NextMyDay/internal/modules/home/handlers.go
Claus Lohmar b8ead2bf2d feat(web): role-gate the nav and show the post-setup passkey banner
The shell now renders the CORE nav entries — Home · Account for everyone,
Users · Modules only for an admin — alongside the registry entries, with the
discovered `home` dashboard collapsed onto the core Home entry (SPEC-010 §3).

A signed-in user with no passkey, who has not opted out and is not on a
loopback origin, now sees a prominent "Add a passkey" banner linking to the
Account page (SPEC-010 §6). This closes the D-041 gap where the wizard's
direct session mint bypasses the TOTP-login nudge, so the admin was never
prompted.

The door computes (admin, banner) in serveGUID — it already holds the
session, identity and user — and attaches it to the request context; the new
web.PageFor copies it onto every authenticated page (RequestContext is
untouched, so identification stays separate from authorisation, D-003).
2026-10-15 07:58:09 +00:00

27 lines
930 B
Go

package home
import (
"net/http"
"git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/server"
"git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/web"
)
// dashboard renders the user's landing page inside the core shell (SPEC-009
// §4/§7). The door has already resolved identity and gated the session/role, so
// rc carries the authenticated user — the handler never parses a raw path (the
// rule of the door).
//
// It is the reference for the module view contract: a module supplies its
// CONTENT; the shell owns the header, the nav (from Registry.Nav, D-038) and
// the flash area.
func dashboard(w http.ResponseWriter, r *http.Request, rc *server.RequestContext) error {
w.Header().Set("Cache-Control", "no-store")
return web.Render(w, http.StatusOK, web.PageFor(r, web.Page{
Title: "MyDay",
GUID: rc.Workflow,
Active: "home",
Content: web.Markup(`<h1>MyDay</h1>
<p>Your day, at a glance.</p>`),
}))
}