Fix SEC-09: hide admin nav links from non-admin users

- Add IsAdmin bool to PageData (embedded in all page view structs)
- Remove redundant IsAdmin from DashboardData
- Add isAdmin() helper to derive admin status from request claims
- Set IsAdmin in all page-level handlers that populate PageData
- Wrap admin-only nav links in base.html with {{if .IsAdmin}}
- Add tests: non-admin dashboard/profile hide admin links,
  admin dashboard shows them

Security: navigation links to /accounts, /audit, /policies,
and /pgcreds are now only rendered for admin users. Server-side
authorization (requireAdminRole middleware) was already in place;
this change removes the information leak of showing links that
return 403 to non-admin users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 00:44:30 -07:00
parent 586d4e3355
commit d7d7ba21d9
8 changed files with 142 additions and 14 deletions

View File

@@ -17,15 +17,13 @@ func (u *UIServer) handleDashboard(w http.ResponseWriter, r *http.Request) {
return
}
claims := claimsFromContext(r.Context())
isAdmin := claims != nil && claims.HasRole("admin")
admin := isAdmin(r)
data := DashboardData{
PageData: PageData{CSRFToken: csrfToken, ActorName: u.actorName(r)},
IsAdmin: isAdmin,
PageData: PageData{CSRFToken: csrfToken, ActorName: u.actorName(r), IsAdmin: admin},
}
if isAdmin {
if admin {
accounts, err := u.db.ListAccounts()
if err != nil {
u.renderError(w, r, http.StatusInternalServerError, "failed to load accounts")