From 9aeea41478738bf6b6ada387119e0a3e2e334395 Mon Sep 17 00:00:00 2001 From: Siegfried Ehret Date: Mon, 6 Jun 2022 21:01:59 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=96=20add=20auth=20on=20pages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/auth.nim | 21 +++++++++++++++ src/lib/server.nim | 52 +++++++++++++++++++++++--------------- src/routes/token.nim | 1 + src/urlhut.nim | 10 +++++--- src/views/unauthorized.nim | 14 ++++++++++ urlhut.nimble | 2 +- 6 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 src/lib/auth.nim create mode 100644 src/routes/token.nim create mode 100644 src/views/unauthorized.nim diff --git a/src/lib/auth.nim b/src/lib/auth.nim new file mode 100644 index 0000000..b708976 --- /dev/null +++ b/src/lib/auth.nim @@ -0,0 +1,21 @@ +import jester +import karax/vdom +import ../views/[common, unauthorized] + +proc isAuthOK(req: Request, token: string): bool = + if token == "": + return true + + try: + var t = req.cookies["TOKEN"] + if t == token: + return true + except KeyError: + discard + return false + +proc renderWithAuth*(req: Request, token: string, body: VNode): string = + if isAuthOK(req, token): + result = renderPage(body) + else: + result = renderPage(renderUnauthorized()) diff --git a/src/lib/server.nim b/src/lib/server.nim index 4f35bb3..27124d2 100644 --- a/src/lib/server.nim +++ b/src/lib/server.nim @@ -1,28 +1,40 @@ import std/strutils from os import getEnv import jester -import ../routes/[edit, home, new, tags], ../views/[common, forms] +import ../lib/auth, ../routes/[edit, home, new, tags], ../views/[forms] -router hutRouter: - get "/": - resp renderPage(renderHome()) - get "/new": - resp renderPage(renderNew()) - get "/edit/@id": - resp renderPage(renderEdit(@"id")) - get "/tags": - resp renderPage(renderTagsList()) - get "/tags/@name": - resp renderPage(renderTag(@"name")) - post "/api/v1/url": - saveUrl(request) - redirect("/") - post "/api/v1/url/delete": - removeUrl(request) - redirect("/") - -proc startServer*() = +proc startServer*(token: string) = let port = getEnv("PORT", "3000") let settings = newSettings(port = Port(parseInt(port))) + + router hutRouter: + get "/": + resp renderWithAuth(request, token, renderHome()) + get "/new": + resp renderWithAuth(request, token, renderNew()) + get "/edit/@id": + resp renderWithAuth(request, token, renderEdit(@"id")) + get "/tags": + resp renderWithAuth(request, token, renderTagsList()) + get "/tags/@name": + resp renderWithAuth(request, token, renderTag(@"name")) + post "/api/v1/url": + saveUrl(request) + redirect("/") + post "/api/v1/url/delete": + removeUrl(request) + redirect("/") + post "/api/v1/token": + try: + let t = request.formData.getOrDefault("token").body + if t == token: + setCookie("TOKEN", value = t, path = "/", secure = true, + httpOnly = true) + except KeyError: + # TODO show error message + discard + # TODO redirect to requested page. + redirect("/") + var jester = initJester(hutRouter, settings = settings) jester.serve() diff --git a/src/routes/token.nim b/src/routes/token.nim new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/routes/token.nim @@ -0,0 +1 @@ + diff --git a/src/urlhut.nim b/src/urlhut.nim index feb1400..7d56b68 100644 --- a/src/urlhut.nim +++ b/src/urlhut.nim @@ -1,13 +1,18 @@ # This is just an example to get you started. A typical binary package # uses this file as the main entry point of the application. import std/logging +from os import getEnv import dotenv import ./lib/[db, server] proc ctrlc() {.noconv.} = + info("🛖 is stopping") closeDb() + quit() when isMainModule: + info("🛖 is starting") + addHandler(newConsoleLogger()) setLogFilter(lvlError) @@ -15,6 +20,5 @@ when isMainModule: load() initDb() - info("🛖 is starting") - - startServer() + let token = getEnv("TOKEN", "") + startServer(token) diff --git a/src/views/unauthorized.nim b/src/views/unauthorized.nim new file mode 100644 index 0000000..f6e7fbe --- /dev/null +++ b/src/views/unauthorized.nim @@ -0,0 +1,14 @@ +import karax/[karaxdsl, vdom] + +proc renderUnauthorized*(): VNode = + result = buildHtml(tdiv): + p: text "Error 401: unauthorized" + p: text "Do you have a token?" + form(`method` = "post", action = "/api/v1/token", + enctype = "multipart/form-data"): + label(`for` = "token"): + text "Token" + input(`type` = "text", name = "token", id = "token", autofocus = "", + placeholder = "Enter your token...") + button(`type` = "submit"): + text "submit" diff --git a/urlhut.nimble b/urlhut.nimble index 5d63dd3..d654c6c 100644 --- a/urlhut.nimble +++ b/urlhut.nimble @@ -10,7 +10,7 @@ bin = @["urlhut"] # Dependencies -requires "nim >= 1.6.0" +requires "nim >= 1.6.6" requires "jester >= 0.5.0" requires "karax#fa4a2dc" requires "dotenv >= 2.0.0" -- 2.45.2