Merge SEC-09: hide admin nav links from non-admin users
# Conflicts: # internal/ui/ui_test.go
This commit is contained in:
@@ -631,3 +631,121 @@ func TestLoginLockedAccountShowsInvalidCredentials(t *testing.T) {
|
||||
t.Error("wrong password response does not contain 'invalid credentials'")
|
||||
}
|
||||
}
|
||||
|
||||
// ---- SEC-09: admin nav link visibility tests ----
|
||||
|
||||
// issueUserSession creates a human account with the "user" role (non-admin),
|
||||
// issues a JWT, tracks it, and returns the raw token string.
|
||||
func issueUserSession(t *testing.T, u *UIServer) string {
|
||||
t.Helper()
|
||||
acct, err := u.db.CreateAccount("regular-user", model.AccountTypeHuman, "")
|
||||
if err != nil {
|
||||
t.Fatalf("CreateAccount: %v", err)
|
||||
}
|
||||
if err := u.db.SetRoles(acct.ID, []string{"user"}, nil); err != nil {
|
||||
t.Fatalf("SetRoles: %v", err)
|
||||
}
|
||||
tok, claims, err := token.IssueToken(u.privKey, testIssuer, acct.UUID, []string{"user"}, time.Hour)
|
||||
if err != nil {
|
||||
t.Fatalf("IssueToken: %v", err)
|
||||
}
|
||||
if err := u.db.TrackToken(claims.JTI, acct.ID, claims.IssuedAt, claims.ExpiresAt); err != nil {
|
||||
t.Fatalf("TrackToken: %v", err)
|
||||
}
|
||||
return tok
|
||||
}
|
||||
|
||||
// TestNonAdminDashboardHidesAdminNavLinks verifies that a non-admin user's
|
||||
// dashboard does not contain links to admin-only pages (SEC-09).
|
||||
func TestNonAdminDashboardHidesAdminNavLinks(t *testing.T) {
|
||||
u := newTestUIServer(t)
|
||||
mux := http.NewServeMux()
|
||||
u.Register(mux)
|
||||
|
||||
userToken := issueUserSession(t, u)
|
||||
|
||||
req := authenticatedGET(t, userToken, "/dashboard")
|
||||
rr := httptest.NewRecorder()
|
||||
mux.ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200; body: %s", rr.Code, rr.Body.String())
|
||||
}
|
||||
|
||||
body := rr.Body.String()
|
||||
for _, adminPath := range []string{
|
||||
`href="/accounts"`,
|
||||
`href="/audit"`,
|
||||
`href="/policies"`,
|
||||
`href="/pgcreds"`,
|
||||
} {
|
||||
if strings.Contains(body, adminPath) {
|
||||
t.Errorf("non-admin dashboard contains admin link %s — SEC-09 violation", adminPath)
|
||||
}
|
||||
}
|
||||
|
||||
// Dashboard link should still be present.
|
||||
if !strings.Contains(body, `href="/dashboard"`) {
|
||||
t.Error("dashboard link missing from non-admin nav")
|
||||
}
|
||||
}
|
||||
|
||||
// TestAdminDashboardShowsAdminNavLinks verifies that an admin user's
|
||||
// dashboard contains all admin navigation links.
|
||||
func TestAdminDashboardShowsAdminNavLinks(t *testing.T) {
|
||||
u := newTestUIServer(t)
|
||||
mux := http.NewServeMux()
|
||||
u.Register(mux)
|
||||
|
||||
adminToken, _, _ := issueAdminSession(t, u)
|
||||
|
||||
req := authenticatedGET(t, adminToken, "/dashboard")
|
||||
rr := httptest.NewRecorder()
|
||||
mux.ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200; body: %s", rr.Code, rr.Body.String())
|
||||
}
|
||||
|
||||
body := rr.Body.String()
|
||||
for _, adminPath := range []string{
|
||||
`href="/accounts"`,
|
||||
`href="/audit"`,
|
||||
`href="/policies"`,
|
||||
`href="/pgcreds"`,
|
||||
} {
|
||||
if !strings.Contains(body, adminPath) {
|
||||
t.Errorf("admin dashboard missing admin link %s", adminPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestNonAdminProfileHidesAdminNavLinks verifies that the profile page
|
||||
// also hides admin nav links for non-admin users (SEC-09).
|
||||
func TestNonAdminProfileHidesAdminNavLinks(t *testing.T) {
|
||||
u := newTestUIServer(t)
|
||||
mux := http.NewServeMux()
|
||||
u.Register(mux)
|
||||
|
||||
userToken := issueUserSession(t, u)
|
||||
|
||||
req := authenticatedGET(t, userToken, "/profile")
|
||||
rr := httptest.NewRecorder()
|
||||
mux.ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200; body: %s", rr.Code, rr.Body.String())
|
||||
}
|
||||
|
||||
body := rr.Body.String()
|
||||
for _, adminPath := range []string{
|
||||
`href="/accounts"`,
|
||||
`href="/audit"`,
|
||||
`href="/policies"`,
|
||||
`href="/pgcreds"`,
|
||||
} {
|
||||
if strings.Contains(body, adminPath) {
|
||||
t.Errorf("non-admin profile page contains admin link %s — SEC-09 violation", adminPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user