diff --git a/app/src/main/kotlin/net/h34t/filemure/FilemureApp.kt b/app/src/main/kotlin/net/h34t/filemure/FilemureApp.kt index c75201f..0c7cd63 100644 --- a/app/src/main/kotlin/net/h34t/filemure/FilemureApp.kt +++ b/app/src/main/kotlin/net/h34t/filemure/FilemureApp.kt @@ -1,8 +1,11 @@ package net.h34t.filemure import io.javalin.Javalin +import io.javalin.http.UnauthorizedResponse import net.h34t.filemure.controller.* import net.h34t.filemure.repository.SqliteRepository +import net.h34t.filemure.tpl.Frame +import net.h34t.filemure.tpl.Unauthorized class FilemureApp(repository: SqliteRepository) { @@ -16,20 +19,36 @@ class FilemureApp(repository: SqliteRepository) { private val documentController = DocumentController(modifiers, repository) fun register(server: Javalin) { - server.get("/") { ctx -> - if (ctx.getSession() != null) { - overviewController.overview(ctx) - } else { + server.beforeMatched { ctx -> + val userRole = getUserRole(ctx) + if (!ctx.routeRoles().contains(userRole)) { 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("/limbo", limboController::formLimbo) - server.get("/document/new", documentController::createDocumentForm) - server.post("/document/new", documentController::createDocument) + server.get("/", overviewController::overview, Role.USER) + server.get("/login", loginPageController::formLogin, Role.ANON, Role.USER) + server.post("/login", loginPageController::doLogin, Role.ANON, Role.USER) + 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() + ) + ) + } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/net/h34t/filemure/Role.kt b/app/src/main/kotlin/net/h34t/filemure/Role.kt new file mode 100644 index 0000000..edb6ad3 --- /dev/null +++ b/app/src/main/kotlin/net/h34t/filemure/Role.kt @@ -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 + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/net/h34t/filemure/TemplateModifiers.kt b/app/src/main/kotlin/net/h34t/filemure/TemplateModifiers.kt index 8599ac2..08f9dcf 100644 --- a/app/src/main/kotlin/net/h34t/filemure/TemplateModifiers.kt +++ b/app/src/main/kotlin/net/h34t/filemure/TemplateModifiers.kt @@ -1,12 +1,11 @@ package net.h34t.filemure -import net.h34t.filemure.tpl.Frame -import net.h34t.filemure.tpl.Limbo -import net.h34t.filemure.tpl.NewDocumentForm +import net.h34t.filemure.tpl.* import org.apache.commons.text.StringEscapeUtils 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 { return URLEncoder.encode(arg, Charsets.UTF_8) diff --git a/app/src/main/kotlin/net/h34t/filemure/controller/DocumentController.kt b/app/src/main/kotlin/net/h34t/filemure/controller/DocumentController.kt index 842b274..f228f5e 100644 --- a/app/src/main/kotlin/net/h34t/filemure/controller/DocumentController.kt +++ b/app/src/main/kotlin/net/h34t/filemure/controller/DocumentController.kt @@ -5,6 +5,7 @@ import io.javalin.http.Context import io.javalin.http.ForbiddenResponse import net.h34t.filemure.* import net.h34t.filemure.repository.SqliteRepository +import net.h34t.filemure.tpl.Document import net.h34t.filemure.tpl.Frame import net.h34t.filemure.tpl.NewDocumentForm import java.io.File @@ -21,6 +22,31 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit val session = ctx.requireSession() 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() + }, + ) + ) + ) } diff --git a/app/src/main/kotlin/net/h34t/filemure/controller/OverviewController.kt b/app/src/main/kotlin/net/h34t/filemure/controller/OverviewController.kt index 63dfca8..076ebc7 100644 --- a/app/src/main/kotlin/net/h34t/filemure/controller/OverviewController.kt +++ b/app/src/main/kotlin/net/h34t/filemure/controller/OverviewController.kt @@ -7,21 +7,37 @@ import net.h34t.filemure.requireSession import net.h34t.filemure.tempolin import net.h34t.filemure.tpl.Frame import net.h34t.filemure.tpl.Overview +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle class OverviewController(val modifiers: TemplateModifiers, val repository: SqliteRepository) { + val dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.SHORT) + fun overview(ctx: Context) { val session = ctx.requireSession() val limboFileCount = repository.getLimboFileCount(accountId = session.id) + val documents = repository.getDocuments(accountId = session.id) + ctx.tempolin( Frame( modifiers = modifiers, title = "Filemure Overview", isTarget = true, 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() + } ) ) ) diff --git a/app/src/main/tpl/net.h34t.filemure.tpl/Document.tpl.html b/app/src/main/tpl/net.h34t.filemure.tpl/Document.tpl.html index ac9306c..1a09e32 100644 --- a/app/src/main/tpl/net.h34t.filemure.tpl/Document.tpl.html +++ b/app/src/main/tpl/net.h34t.filemure.tpl/Document.tpl.html @@ -1,6 +1,6 @@

{*$title}

-

Date: {*$referenceDate}">

+

Date: {*$referenceDate}

Tags: {for $tags}{*$tag}{/for}

diff --git a/app/src/main/tpl/net.h34t.filemure.tpl/Overview.tpl.html b/app/src/main/tpl/net.h34t.filemure.tpl/Overview.tpl.html index 2727cc0..a46ce2b 100644 --- a/app/src/main/tpl/net.h34t.filemure.tpl/Overview.tpl.html +++ b/app/src/main/tpl/net.h34t.filemure.tpl/Overview.tpl.html @@ -1,4 +1,13 @@

Hello to Filemure

-Files in limbo: {$limboFileCount}. +

Files in limbo: {$limboFileCount}.

+ + {for $document} + + + + + + {/for} +
{*$referenceDate}{*$title}details
\ No newline at end of file diff --git a/app/src/main/tpl/net.h34t.filemure.tpl/Unauthorized.tpl.html b/app/src/main/tpl/net.h34t.filemure.tpl/Unauthorized.tpl.html new file mode 100644 index 0000000..e78cf60 --- /dev/null +++ b/app/src/main/tpl/net.h34t.filemure.tpl/Unauthorized.tpl.html @@ -0,0 +1,3 @@ +

Unauthorized

+ +

Please log in.

diff --git a/core/src/main/kotlin/net/h34t/filemure/core/entity/Types.kt b/core/src/main/kotlin/net/h34t/filemure/core/entity/Types.kt index 5f7f1d0..87e362e 100644 --- a/core/src/main/kotlin/net/h34t/filemure/core/entity/Types.kt +++ b/core/src/main/kotlin/net/h34t/filemure/core/entity/Types.kt @@ -1,7 +1,6 @@ package net.h34t.filemure.core.entity import java.time.LocalDateTime -import java.util.* class Document( val id: Long, @@ -11,7 +10,7 @@ class Document( val tags: List, val created: LocalDateTime, val referenceDate: LocalDateTime, - val files: List, + val files: List, ) @JvmInline @@ -25,10 +24,11 @@ value class MimeType(val value: String) { } } -data class DocFile( - val id: UUID, +data class FileRef( + val id: Long, + val extId: String, val filename: String, - val mimeType: MimeType, + val contentType: String?, val created: LocalDateTime, )