host: discoverable log in / log out footer link
Login had no visible entry point — you could only reach it by hitting a guard. Add an auth footer the pages splice in: "log in" when logged out, "signed in as <user> · log out" when logged in. - host/auth-footer: SX fragment reading the session principal; guards a session-less request so it's safe to call anywhere. - GET /logout added alongside POST so the footer link is a plain <a> (logout is low-harm; GET is acceptable). Clears the session, redirects home. - home and post pages splice (host/auth-footer req) into their footer. Tests: home + post footers show a login link when anonymous; GET /logout -> 303. 221/221. Verified live: anonymous shows "log in"; logged in shows "signed in as admin · log out"; /logout reverts it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -73,7 +73,8 @@
|
||||
(dream-html-status 401
|
||||
(host/-login-form next-path "Invalid credentials — try again."))))))
|
||||
|
||||
;; ── POST /logout — clear the session, redirect home ─────────────────
|
||||
;; ── /logout — clear the session, redirect home. Allowed on GET too so a plain
|
||||
;; footer link can log out (logout is low-harm, so GET is acceptable here). ─────
|
||||
(define host/logout-submit
|
||||
(fn (req)
|
||||
(begin
|
||||
@@ -85,8 +86,22 @@
|
||||
(list
|
||||
(dream-get "/login" host/login-page)
|
||||
(dream-post "/login" host/login-submit)
|
||||
(dream-get "/logout" host/logout-submit)
|
||||
(dream-post "/logout" host/logout-submit)))
|
||||
|
||||
;; ── auth footer fragment ────────────────────────────────────────────
|
||||
;; A small SX node pages splice into their footer: "log in" when logged out,
|
||||
;; "signed in as <user> · log out" when logged in. Guards a session-less request
|
||||
;; (no middleware) so it's safe to call anywhere. Reads the session principal.
|
||||
(define host/auth-footer
|
||||
(fn (req)
|
||||
(let ((who (if (get req :dream-session) (host/current-principal req) nil)))
|
||||
(if (and who (not (= who "")))
|
||||
(quasiquote
|
||||
(span (unquote (str "signed in as " who)) " · "
|
||||
(a :href "/logout" "log out")))
|
||||
(quote (a :href "/login" "log in"))))))
|
||||
|
||||
;; The authenticated principal for a request, or nil: a logged-in session takes
|
||||
;; precedence, else a Bearer token resolved by `resolve` (the API fallback).
|
||||
(define host/-principal-of
|
||||
|
||||
@@ -115,7 +115,9 @@
|
||||
" · "
|
||||
(a :href (unquote (str "/" slug "/edit")) "edit")
|
||||
" · "
|
||||
(a :href "/" "all posts"))))))
|
||||
(a :href "/" "all posts")
|
||||
" · "
|
||||
(unquote (host/auth-footer req)))))))
|
||||
(dream-html-status 404
|
||||
(host/blog--page "Not found"
|
||||
(quasiquote
|
||||
@@ -140,7 +142,9 @@
|
||||
(quasiquote
|
||||
(div (h1 "Posts")
|
||||
(unquote listing)
|
||||
(p (a :href "/new" "+ New post")))))))))))
|
||||
(p (a :href "/new" "+ New post"))
|
||||
(p :style "margin-top:2em;font-size:0.9em;opacity:0.8"
|
||||
(unquote (host/auth-footer req))))))))))))
|
||||
|
||||
(define host/blog-index (fn (req) (host/ok (host/blog-list))))
|
||||
|
||||
|
||||
@@ -203,6 +203,14 @@
|
||||
(host-bl-test "edit missing post -> 404"
|
||||
(dream-status (host-bl-wapp (host-bl-send "GET" "/ghost/edit" "Bearer good" "" ""))) 404)
|
||||
|
||||
;; -- auth footer (discoverable login/logout) --
|
||||
(host-bl-test "home footer shows a log in link when anonymous"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/"))) ">log in</a>") true)
|
||||
(host-bl-test "post footer shows a log in link when anonymous"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/my-first-post/"))) ">log in</a>") true)
|
||||
(host-bl-test "GET /logout -> 303"
|
||||
(dream-status (host-bl-app (host-bl-req "/logout"))) 303)
|
||||
|
||||
;; -- experimental unguarded create-only route (POST /new, no auth) --
|
||||
(define host-bl-oapp (host/make-app (list host/blog-open-create-routes host/blog-routes)))
|
||||
(host/blog-use-store! (persist/open))
|
||||
|
||||
Reference in New Issue
Block a user