internal/rbac: drei Grundrollen (superadmin, tenant_admin, user) mit Hierarchie ueber eine einfache Eltern-Map (tenant_admin erbt von user, superadmin erbt von tenant_admin) — EffectivePermissions loest die volle vererbte Rechtemenge auf (Akzeptanzkriterium 2). Policy-Modell bewusst als reine Go-Datenstruktur getrennt von der Durchsetzung (RBAC-02), nach Casbin-Prinzip. Store verwaltet Rollenzuweisungen innerhalb EINER Tenant-Datenbank (Modell C, analog internal/user.TenantUserStore) — nur 'user' und 'tenant_admin' sind hier zuweisbar (assignableRoles-Matrix). Ein Zuweisungsversuch fuer 'superadmin' wird abgewiesen, da diese Rolle mandantenuebergreifend ist und bereits durch die Existenz eines Kontos in IAM-01s SuperadminStore repraesentiert wird — keine doppelte Modellierung. Jede Zuweisung schreibt zusaetzlich einen Historieneintrag (role_assignment_history) mit grantedBy/grantedAt, atomar in derselben Transaktion (Akzeptanzkriterium 3). Pruefungen (ausgefuehrt auf root@192.168.1.131, go build/vet/test PASS): 1. Zuweisung ausserhalb der erlaubten Matrix abgewiesen — TestStore_RejectsSuperadminOutsideAllowedMatrix und TestStore_RejectsUnknownRole: beide ErrRoleNotAssignableInTenantScope, kein Datensatz hinterlassen. PASS. 2. Rollenhierarchie liefert erwartete effektive Rechtemenge — TestEffectivePermissions_Inheritance: tenant_admin hat geerbte user-Rechte + eigene, aber nicht platform.manage_tenants; superadmin hat die volle Kette. PASS. 3. Datenmodell von zweiter Person gegen Dokumentation geprueft — NICHT durchgefuehrt (keine zweite Person in dieser Session verfuegbar). Offen. Zusaetzlich automatisiert getestet (Akzeptanzkriterium 3): TestStore_HistoryTracksWhoAndWhen — zwei aufeinanderfolgende Zuweisungen, Historie liefert beide mit korrektem grantedBy in chronologischer Reihenfolge. PASS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
49 lines
1.6 KiB
Go
49 lines
1.6 KiB
Go
package rbac
|
|
|
|
import "testing"
|
|
|
|
func contains(perms []Permission, p Permission) bool {
|
|
for _, x := range perms {
|
|
if x == p {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Akzeptanzkriterium 2 + Pruefung 2: Rollenhierarchie liefert die erwartete
|
|
// effektive Rechtemenge.
|
|
func TestEffectivePermissions_Inheritance(t *testing.T) {
|
|
userPerms := EffectivePermissions(RoleUser)
|
|
if !contains(userPerms, PermSelfRead) || !contains(userPerms, PermSelfUpdate) {
|
|
t.Fatalf("user sollte self.read/self.update haben, habe %v", userPerms)
|
|
}
|
|
if contains(userPerms, PermManageUsers) {
|
|
t.Fatal("user sollte KEIN tenant.manage_users haben")
|
|
}
|
|
|
|
adminPerms := EffectivePermissions(RoleTenantAdmin)
|
|
if !contains(adminPerms, PermSelfRead) || !contains(adminPerms, PermManageUsers) || !contains(adminPerms, PermManageSettings) {
|
|
t.Fatalf("tenant_admin sollte geerbte user-rechte + eigene rechte haben, habe %v", adminPerms)
|
|
}
|
|
if contains(adminPerms, PermManageTenants) {
|
|
t.Fatal("tenant_admin sollte KEIN platform.manage_tenants haben")
|
|
}
|
|
|
|
superPerms := EffectivePermissions(RoleSuperadmin)
|
|
for _, want := range []Permission{PermSelfRead, PermSelfUpdate, PermManageUsers, PermManageSettings, PermManageTenants} {
|
|
if !contains(superPerms, want) {
|
|
t.Fatalf("superadmin sollte %q haben (volle vererbte kette), habe %v", want, superPerms)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHasPermission(t *testing.T) {
|
|
if !HasPermission(RoleTenantAdmin, PermSelfRead) {
|
|
t.Fatal("tenant_admin sollte geerbtes self.read haben")
|
|
}
|
|
if HasPermission(RoleUser, PermManageTenants) {
|
|
t.Fatal("user sollte platform.manage_tenants nicht haben")
|
|
}
|
|
}
|