NextMyDay/internal/core/server/roles_test.go
Claus Lohmar d11e14295b feat(core): add the store, identity plumbing and the door (SPEC-003/004)
- store: SQLite (WAL, foreign keys ON, CGO-free driver) + the embedded
  migration runner; each module's migrations are name-prefixed (D-012)
- audit: the append-only audit log; the actor threads via context (R-1)
- users: the user_id/GUID/email anchors (D-013)
- config: the YAML settings file (D-035) + validation
- httpx: cookies · loopback detection · trusted-proxy XFF · CSRF · security
  headers · redaction
- middleware: correlation id · audit · rate limiting
- mail: the invite/recovery mailer seam
- server: the core DOOR — the resolution switch, the dispatch registry
  (RegisterModule), the role gates, /setup · enroll/login · recovery flows,
  the reserved `static` workflow, and the loopback-only bootstrap (D-025)
2026-10-14 10:53:51 +00:00

49 lines
1.6 KiB
Go

package server
import (
"testing"
"git.lohmar.co.uk/cclohmar/NextMyDay/internal/core/users"
)
// TestTiersRippleDown proves the D-034 role gate: simple tiers, one role per
// user, and a role implies every role below it.
func TestTiersRippleDown(t *testing.T) {
g := NewTiers()
// No explicit requirement -> the floor (team): every authenticated role is
// admitted.
for _, r := range []users.Role{users.RoleTeam, users.RoleManager, users.RoleDirector, users.RoleAdmin} {
if !g.Allowed(r, "home", "dashboard") {
t.Errorf("%s was denied an unlisted function (floor = team)", r)
}
}
// An invalid/empty role fails closed.
if g.Allowed(users.Role("boss"), "home", "dashboard") {
t.Error("an invalid role was admitted by the tier gate")
}
if g.Allowed(users.Role(""), "home", "dashboard") {
t.Error("an empty role was admitted by the tier gate")
}
// A function requiring manager: team is denied, manager and above pass
// (ripple-down).
g.Require("users", "create", users.RoleManager)
if g.Allowed(users.RoleTeam, "users", "create") {
t.Error("team was admitted to a manager function")
}
for _, r := range []users.Role{users.RoleManager, users.RoleDirector, users.RoleAdmin} {
if !g.Allowed(r, "users", "create") {
t.Errorf("%s was denied a manager function (ripple-down)", r)
}
}
// A director function: only director and admin pass.
g.Require("users", "promote", users.RoleDirector)
if g.Allowed(users.RoleManager, "users", "promote") {
t.Error("manager was admitted to a director function")
}
if !g.Allowed(users.RoleAdmin, "users", "promote") {
t.Error("admin was denied a director function")
}
}