diff --git a/internal/ui/handlers_dashboard.go b/internal/ui/handlers_dashboard.go index b35a2fd..00c05bb 100644 --- a/internal/ui/handlers_dashboard.go +++ b/internal/ui/handlers_dashboard.go @@ -7,7 +7,8 @@ import ( "git.wntrmute.dev/kyle/mcias/internal/model" ) -// handleDashboard renders the main dashboard page with account counts and recent events. +// handleDashboard renders the main dashboard page. Admin users see account +// counts and recent audit events; non-admin users see a welcome page. func (u *UIServer) handleDashboard(w http.ResponseWriter, r *http.Request) { csrfToken, err := u.setCSRFCookies(w) if err != nil { @@ -16,30 +17,35 @@ func (u *UIServer) handleDashboard(w http.ResponseWriter, r *http.Request) { return } - accounts, err := u.db.ListAccounts() - if err != nil { - u.renderError(w, r, http.StatusInternalServerError, "failed to load accounts") - return + claims := claimsFromContext(r.Context()) + isAdmin := claims != nil && claims.HasRole("admin") + + data := DashboardData{ + PageData: PageData{CSRFToken: csrfToken, ActorName: u.actorName(r)}, + IsAdmin: isAdmin, } - var total, active int - for _, a := range accounts { - total++ - if a.Status == model.AccountStatusActive { - active++ + if isAdmin { + accounts, err := u.db.ListAccounts() + if err != nil { + u.renderError(w, r, http.StatusInternalServerError, "failed to load accounts") + return } + + for _, a := range accounts { + data.TotalAccounts++ + if a.Status == model.AccountStatusActive { + data.ActiveAccounts++ + } + } + + events, _, err := u.db.ListAuditEventsPaged(db.AuditQueryParams{Limit: 10, Offset: 0}) + if err != nil { + u.logger.Warn("load recent audit events", "error", err) + events = nil + } + data.RecentEvents = events } - events, _, err := u.db.ListAuditEventsPaged(db.AuditQueryParams{Limit: 10, Offset: 0}) - if err != nil { - u.logger.Warn("load recent audit events", "error", err) - events = nil - } - - u.render(w, "dashboard", DashboardData{ - PageData: PageData{CSRFToken: csrfToken, ActorName: u.actorName(r)}, - TotalAccounts: total, - ActiveAccounts: active, - RecentEvents: events, - }) + u.render(w, "dashboard", data) } diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 549b5b0..d6d13b0 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -314,7 +314,7 @@ func (u *UIServer) Register(mux *http.ServeMux) { return authed(u.requireAdminRole(http.HandlerFunc(h))) } - uiMux.Handle("GET /dashboard", adminGet(u.handleDashboard)) + uiMux.Handle("GET /dashboard", authed(http.HandlerFunc(u.handleDashboard))) uiMux.Handle("GET /accounts", adminGet(u.handleAccountsList)) uiMux.Handle("POST /accounts", admin(u.handleCreateAccount)) uiMux.Handle("GET /accounts/{id}", adminGet(u.handleAccountDetail)) @@ -609,6 +609,7 @@ type LoginData struct { // DashboardData is the view model for the dashboard page. type DashboardData struct { PageData + IsAdmin bool RecentEvents []*db.AuditEventView TotalAccounts int ActiveAccounts int diff --git a/web/templates/dashboard.html b/web/templates/dashboard.html index 7376974..a124adb 100644 --- a/web/templates/dashboard.html +++ b/web/templates/dashboard.html @@ -4,6 +4,7 @@
Welcome, {{.ActorName}}. Use the navigation above to access your profile and credentials.
+