* Improves document display
* Adds Roles * Adds Role based auth
This commit is contained in:
parent
aa940cc42a
commit
68cbb94977
9 changed files with 114 additions and 24 deletions
|
@ -1,8 +1,11 @@
|
||||||
package net.h34t.filemure
|
package net.h34t.filemure
|
||||||
|
|
||||||
import io.javalin.Javalin
|
import io.javalin.Javalin
|
||||||
|
import io.javalin.http.UnauthorizedResponse
|
||||||
import net.h34t.filemure.controller.*
|
import net.h34t.filemure.controller.*
|
||||||
import net.h34t.filemure.repository.SqliteRepository
|
import net.h34t.filemure.repository.SqliteRepository
|
||||||
|
import net.h34t.filemure.tpl.Frame
|
||||||
|
import net.h34t.filemure.tpl.Unauthorized
|
||||||
|
|
||||||
class FilemureApp(repository: SqliteRepository) {
|
class FilemureApp(repository: SqliteRepository) {
|
||||||
|
|
||||||
|
@ -16,20 +19,36 @@ class FilemureApp(repository: SqliteRepository) {
|
||||||
private val documentController = DocumentController(modifiers, repository)
|
private val documentController = DocumentController(modifiers, repository)
|
||||||
|
|
||||||
fun register(server: Javalin) {
|
fun register(server: Javalin) {
|
||||||
server.get("/") { ctx ->
|
server.beforeMatched { ctx ->
|
||||||
if (ctx.getSession() != null) {
|
val userRole = getUserRole(ctx)
|
||||||
overviewController.overview(ctx)
|
if (!ctx.routeRoles().contains(userRole)) {
|
||||||
} else {
|
|
||||||
ctx.redirectPRG("/login")
|
ctx.redirectPRG("/login")
|
||||||
|
throw UnauthorizedResponse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server.get("/login", loginPageController::formLogin)
|
|
||||||
server.post("/login", loginPageController::doLogin)
|
|
||||||
server.post("/logout", loginPageController::doLogout)
|
|
||||||
|
|
||||||
server.post("/upload", uploadController::upload)
|
server.get("/", overviewController::overview, Role.USER)
|
||||||
server.get("/limbo", limboController::formLimbo)
|
server.get("/login", loginPageController::formLogin, Role.ANON, Role.USER)
|
||||||
server.get("/document/new", documentController::createDocumentForm)
|
server.post("/login", loginPageController::doLogin, Role.ANON, Role.USER)
|
||||||
server.post("/document/new", documentController::createDocument)
|
server.post("/logout", loginPageController::doLogout, Role.USER)
|
||||||
|
|
||||||
|
server.post("/upload", uploadController::upload, Role.USER)
|
||||||
|
server.get("/limbo", limboController::formLimbo, Role.USER)
|
||||||
|
|
||||||
|
server.get("/document/new", documentController::createDocumentForm, Role.USER)
|
||||||
|
server.post("/document/new", documentController::createDocument, Role.USER)
|
||||||
|
server.get("/document/{extId}", documentController::documentDetail, Role.USER)
|
||||||
|
|
||||||
|
|
||||||
|
server.exception(UnauthorizedResponse::class.java) { e, ctx ->
|
||||||
|
ctx.tempolin(
|
||||||
|
Frame(
|
||||||
|
modifiers = modifiers,
|
||||||
|
title = "unauthorized",
|
||||||
|
isTarget = false,
|
||||||
|
content = Unauthorized()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
18
app/src/main/kotlin/net/h34t/filemure/Role.kt
Normal file
18
app/src/main/kotlin/net/h34t/filemure/Role.kt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package net.h34t.filemure
|
||||||
|
|
||||||
|
import io.javalin.http.Context
|
||||||
|
import io.javalin.security.RouteRole
|
||||||
|
|
||||||
|
enum class Role : RouteRole {
|
||||||
|
ANON, USER, ADMIN
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserRole(ctx: Context): Role {
|
||||||
|
val session = ctx.getSession()
|
||||||
|
|
||||||
|
return if (session == null) {
|
||||||
|
Role.ANON
|
||||||
|
} else {
|
||||||
|
Role.USER
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
package net.h34t.filemure
|
package net.h34t.filemure
|
||||||
|
|
||||||
import net.h34t.filemure.tpl.Frame
|
import net.h34t.filemure.tpl.*
|
||||||
import net.h34t.filemure.tpl.Limbo
|
|
||||||
import net.h34t.filemure.tpl.NewDocumentForm
|
|
||||||
import org.apache.commons.text.StringEscapeUtils
|
import org.apache.commons.text.StringEscapeUtils
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
|
||||||
class TemplateModifiers : Frame.Modifiers, Limbo.Modifiers, NewDocumentForm.Modifiers {
|
class TemplateModifiers : Frame.Modifiers, Limbo.Modifiers, NewDocumentForm.Modifiers, Overview.Modifiers,
|
||||||
|
Document.Modifiers {
|
||||||
|
|
||||||
fun hashPrefix(arg: String): String {
|
fun hashPrefix(arg: String): String {
|
||||||
return URLEncoder.encode(arg, Charsets.UTF_8)
|
return URLEncoder.encode(arg, Charsets.UTF_8)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import io.javalin.http.Context
|
||||||
import io.javalin.http.ForbiddenResponse
|
import io.javalin.http.ForbiddenResponse
|
||||||
import net.h34t.filemure.*
|
import net.h34t.filemure.*
|
||||||
import net.h34t.filemure.repository.SqliteRepository
|
import net.h34t.filemure.repository.SqliteRepository
|
||||||
|
import net.h34t.filemure.tpl.Document
|
||||||
import net.h34t.filemure.tpl.Frame
|
import net.h34t.filemure.tpl.Frame
|
||||||
import net.h34t.filemure.tpl.NewDocumentForm
|
import net.h34t.filemure.tpl.NewDocumentForm
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
@ -21,6 +22,31 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
|
||||||
val session = ctx.requireSession()
|
val session = ctx.requireSession()
|
||||||
val extId = ctx.pathParam("extId")
|
val extId = ctx.pathParam("extId")
|
||||||
|
|
||||||
|
val document = repository.getDocumentByExtId(accountId = session.id, extId = extId)
|
||||||
|
|
||||||
|
ctx.tempolin(
|
||||||
|
Frame(
|
||||||
|
modifiers = modifiers,
|
||||||
|
title = document.title,
|
||||||
|
isTarget = true,
|
||||||
|
content = Document(
|
||||||
|
modifiers = modifiers,
|
||||||
|
title = document.title,
|
||||||
|
referenceDate = dtf.format(document.referenceDate),
|
||||||
|
tags = { document.tags.map { TagsBlock(tag = it.value) }.asSequence() },
|
||||||
|
description = document.description,
|
||||||
|
files = {
|
||||||
|
document.files.map { file ->
|
||||||
|
FilesBlock(
|
||||||
|
extId = file.extId,
|
||||||
|
filename = file.filename,
|
||||||
|
contentType = file.contentType ?: "?"
|
||||||
|
)
|
||||||
|
}.asSequence()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,37 @@ import net.h34t.filemure.requireSession
|
||||||
import net.h34t.filemure.tempolin
|
import net.h34t.filemure.tempolin
|
||||||
import net.h34t.filemure.tpl.Frame
|
import net.h34t.filemure.tpl.Frame
|
||||||
import net.h34t.filemure.tpl.Overview
|
import net.h34t.filemure.tpl.Overview
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.format.FormatStyle
|
||||||
|
|
||||||
class OverviewController(val modifiers: TemplateModifiers, val repository: SqliteRepository) {
|
class OverviewController(val modifiers: TemplateModifiers, val repository: SqliteRepository) {
|
||||||
|
|
||||||
|
val dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.SHORT)
|
||||||
|
|
||||||
fun overview(ctx: Context) {
|
fun overview(ctx: Context) {
|
||||||
val session = ctx.requireSession()
|
val session = ctx.requireSession()
|
||||||
|
|
||||||
val limboFileCount = repository.getLimboFileCount(accountId = session.id)
|
val limboFileCount = repository.getLimboFileCount(accountId = session.id)
|
||||||
|
|
||||||
|
val documents = repository.getDocuments(accountId = session.id)
|
||||||
|
|
||||||
ctx.tempolin(
|
ctx.tempolin(
|
||||||
Frame(
|
Frame(
|
||||||
modifiers = modifiers,
|
modifiers = modifiers,
|
||||||
title = "Filemure Overview",
|
title = "Filemure Overview",
|
||||||
isTarget = true,
|
isTarget = true,
|
||||||
content = Overview(
|
content = Overview(
|
||||||
limboFileCount = limboFileCount.toString()
|
modifiers = modifiers,
|
||||||
|
limboFileCount = limboFileCount.toString(),
|
||||||
|
document = {
|
||||||
|
documents.map { document ->
|
||||||
|
DocumentBlock(
|
||||||
|
extId = document.extId,
|
||||||
|
referenceDate = dtf.format(document.referenceDate),
|
||||||
|
title = document.title.ifBlank { "untitled" },
|
||||||
|
)
|
||||||
|
}.asSequence()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<h1>{*$title}</h1>
|
<h1>{*$title}</h1>
|
||||||
|
|
||||||
<p>Date: {*$referenceDate}"></p>
|
<p>Date: {*$referenceDate}</p>
|
||||||
|
|
||||||
<p>Tags: <span id="tags">{for $tags}<span>{*$tag}</span>{/for}</span></p>
|
<p>Tags: <span id="tags">{for $tags}<span>{*$tag}</span>{/for}</span></p>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
<h1>Hello to Filemure</h1>
|
<h1>Hello to Filemure</h1>
|
||||||
|
|
||||||
Files in <a href="/limbo">limbo: {$limboFileCount}</a>.
|
<p>Files in <a href="/limbo">limbo: {$limboFileCount}</a>.</p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
{for $document}
|
||||||
|
<tr>
|
||||||
|
<td>{*$referenceDate}</td>
|
||||||
|
<td>{*$title}</td>
|
||||||
|
<td><a href="/document/{*$extId}">details</a></td>
|
||||||
|
</tr>
|
||||||
|
{/for}
|
||||||
|
</table>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>Unauthorized</h1>
|
||||||
|
|
||||||
|
<p><a href="/login">Please log in</a>.</p>
|
|
@ -1,7 +1,6 @@
|
||||||
package net.h34t.filemure.core.entity
|
package net.h34t.filemure.core.entity
|
||||||
|
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class Document(
|
class Document(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
|
@ -11,7 +10,7 @@ class Document(
|
||||||
val tags: List<Tag>,
|
val tags: List<Tag>,
|
||||||
val created: LocalDateTime,
|
val created: LocalDateTime,
|
||||||
val referenceDate: LocalDateTime,
|
val referenceDate: LocalDateTime,
|
||||||
val files: List<DocFile>,
|
val files: List<FileRef>,
|
||||||
)
|
)
|
||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
|
@ -25,10 +24,11 @@ value class MimeType(val value: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class DocFile(
|
data class FileRef(
|
||||||
val id: UUID,
|
val id: Long,
|
||||||
|
val extId: String,
|
||||||
val filename: String,
|
val filename: String,
|
||||||
val mimeType: MimeType,
|
val contentType: String?,
|
||||||
val created: LocalDateTime,
|
val created: LocalDateTime,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue