ultisuite-backend/internal/permission/permission_test.go
R3D347HR4Y cd0a80f5e8 huhu
2026-05-25 13:52:27 +02:00

237 lines
6.1 KiB
Go

package permission
import "testing"
func TestHasRole(t *testing.T) {
tests := []struct {
groups []string
role Role
want bool
}{
{[]string{"role:admin"}, RoleAdmin, true},
{[]string{"admin"}, RoleAdmin, true},
{[]string{"role:user"}, RoleAdmin, false},
{[]string{" role:service "}, RoleService, true},
}
for _, tt := range tests {
if got := HasRole(tt.groups, tt.role); got != tt.want {
t.Fatalf("HasRole(%v, %q) = %v, want %v", tt.groups, tt.role, got, tt.want)
}
}
}
func TestHasPermissionHierarchy(t *testing.T) {
groups := []string{"drive:write"}
if !HasPermission(groups, ResourceDrive, LevelRead) {
t.Fatal("write should satisfy read")
}
if !HasPermission(groups, ResourceDrive, LevelWrite) {
t.Fatal("write should satisfy write")
}
if HasPermission(groups, ResourceDrive, LevelAdmin) {
t.Fatal("write should not satisfy admin")
}
}
func TestHasPermissionAdminBypass(t *testing.T) {
groups := []string{"role:admin"}
if !HasPermission(groups, ResourcePhotos, LevelAdmin) {
t.Fatal("platform admin should bypass resource checks")
}
}
func TestHasPermissionResourceAdmin(t *testing.T) {
groups := []string{"calendar:admin"}
if !HasPermission(groups, ResourceCalendar, LevelRead) {
t.Fatal("resource admin should satisfy read")
}
if !HasPermission(groups, ResourceCalendar, LevelWrite) {
t.Fatal("resource admin should satisfy write")
}
if !HasPermission(groups, ResourceCalendar, LevelAdmin) {
t.Fatal("resource admin should satisfy admin")
}
}
func TestWithSuiteDefaultsEmptyGroups(t *testing.T) {
groups := WithSuiteDefaults(nil)
if !HasRole(groups, RoleUser) {
t.Fatal("expected role:user")
}
if !HasPermission(groups, ResourceContacts, LevelWrite) {
t.Fatal("expected contacts write")
}
if !HasPermission(groups, ResourceCalendar, LevelWrite) {
t.Fatal("expected calendar write")
}
}
func TestWithSuiteDefaultsPreservesExplicitResource(t *testing.T) {
groups := WithSuiteDefaults([]string{"contacts:read"})
if !HasPermission(groups, ResourceContacts, LevelRead) {
t.Fatal("expected contacts read")
}
if HasPermission(groups, ResourceContacts, LevelWrite) {
t.Fatal("contacts:read must not be upgraded to write")
}
if HasPermission(groups, ResourceDrive, LevelRead) {
t.Fatal("must not grant drive when contacts-only group is present")
}
}
func TestWithSuiteDefaultsUserRoleOnly(t *testing.T) {
groups := WithSuiteDefaults([]string{"role:user"})
if !HasPermission(groups, ResourceContacts, LevelWrite) {
t.Fatal("role:user without resource groups should get suite defaults")
}
}
func TestHasPermissionIsolation(t *testing.T) {
groups := []string{"contacts:read"}
if !HasPermission(groups, ResourceContacts, LevelRead) {
t.Fatal("expected contacts read")
}
if HasPermission(groups, ResourceDrive, LevelRead) {
t.Fatal("contacts permission must not grant drive access")
}
}
func TestAdminScopeString(t *testing.T) {
tests := []struct {
scope AdminScope
want string
}{
{AdminScopeRead, "read"},
{AdminScopeWrite, "write"},
{AdminScope(0), "unknown"},
}
for _, tt := range tests {
if got := tt.scope.String(); got != tt.want {
t.Fatalf("AdminScope(%d).String() = %q, want %q", tt.scope, got, tt.want)
}
}
}
func TestParseAdminScope(t *testing.T) {
tests := []struct {
in string
want AdminScope
ok bool
}{
{"read", AdminScopeRead, true},
{"write", AdminScopeWrite, true},
{" READ ", AdminScopeRead, true},
{"Write", AdminScopeWrite, true},
{"admin", 0, false},
{"", 0, false},
}
for _, tt := range tests {
got, ok := ParseAdminScope(tt.in)
if ok != tt.ok || got != tt.want {
t.Fatalf("ParseAdminScope(%q) = (%v, %v), want (%v, %v)", tt.in, got, ok, tt.want, tt.ok)
}
}
}
func TestHasAdminScopeReadOnly(t *testing.T) {
groups := []string{GroupAdminRead}
if !HasAdminScope(groups, AdminScopeRead) {
t.Fatal("admin:read should satisfy read scope")
}
if HasAdminScope(groups, AdminScopeWrite) {
t.Fatal("admin:read should not satisfy write scope")
}
}
func TestHasAdminScopeWriteImpliesRead(t *testing.T) {
groups := []string{GroupAdminWrite}
if !HasAdminScope(groups, AdminScopeRead) {
t.Fatal("admin:write should satisfy read scope")
}
if !HasAdminScope(groups, AdminScopeWrite) {
t.Fatal("admin:write should satisfy write scope")
}
}
func TestHasAdminScopePlatformAdminBypass(t *testing.T) {
tests := []struct {
name string
groups []string
}{
{"bare admin role", []string{"admin"}},
{"prefixed admin role", []string{"role:admin"}},
{"trimmed prefixed admin role", []string{" role:admin "}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if !HasAdminScope(tt.groups, AdminScopeRead) {
t.Fatal("platform admin should satisfy read scope")
}
if !HasAdminScope(tt.groups, AdminScopeWrite) {
t.Fatal("platform admin should satisfy write scope")
}
if !HasAdminScope(tt.groups, DefaultAdminScope) {
t.Fatal("platform admin should satisfy default admin scope")
}
})
}
}
func TestHasAdminScopeNoAccess(t *testing.T) {
tests := []struct {
name string
groups []string
}{
{"empty groups", nil},
{"unrelated user role", []string{"role:user"}},
{"resource permission only", []string{"drive:admin"}},
{"unknown admin suffix", []string{"admin:unknown"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if HasAdminScope(tt.groups, AdminScopeRead) {
t.Fatal("expected no admin read scope")
}
if HasAdminScope(tt.groups, AdminScopeWrite) {
t.Fatal("expected no admin write scope")
}
})
}
}
func TestHasAdminScopeMaxWins(t *testing.T) {
groups := []string{GroupAdminRead, GroupAdminWrite}
if !HasAdminScope(groups, AdminScopeRead) {
t.Fatal("combined scopes should satisfy read")
}
if !HasAdminScope(groups, AdminScopeWrite) {
t.Fatal("combined scopes should satisfy write")
}
}
func TestHasAdminScopeNormalization(t *testing.T) {
groups := []string{" Admin:Write "}
if !HasAdminScope(groups, AdminScopeWrite) {
t.Fatal("admin scope groups should be case- and whitespace-normalized")
}
if !HasAdminScope(groups, AdminScopeRead) {
t.Fatal("normalized admin:write should still imply read")
}
}