admin → RBAC group migration: grant-based access replaces role check
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 19s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m14s
CI/CD / test-sqlite (pull_request) Successful in 2m56s
CI/CD / build-and-deploy (pull_request) Successful in 1m21s
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 19s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m14s
CI/CD / test-sqlite (pull_request) Successful in 2m56s
CI/CD / build-and-deploy (pull_request) Successful in 1m21s
surface.admin.access permission + seeded Admins system group replaces hardcoded role == "admin" middleware checks. Admin bypass removed from RequirePermission — all permissions flow through group membership. Bootstrap, seed, OIDC, and admin handlers sync group membership on role changes. Demotion/deletion safeguards use group member count. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -507,6 +507,7 @@ func BootstrapAdmin(cfg *config.Config, s store.Stores, uekCache ...*crypto.UEKC
|
||||
cache = uekCache[0]
|
||||
}
|
||||
ProbeAndRepairVault(ctx, s, existing.ID, cfg.AdminPassword, cache)
|
||||
ensureAdminsGroupMember(ctx, s, existing.ID)
|
||||
log.Printf(" ✅ Admin user '%s' updated", cfg.AdminUsername)
|
||||
return
|
||||
}
|
||||
@@ -531,6 +532,7 @@ func BootstrapAdmin(cfg *config.Config, s store.Stores, uekCache ...*crypto.UEKC
|
||||
log.Printf("⚠ Failed to create admin user: %v", err)
|
||||
return
|
||||
}
|
||||
ensureAdminsGroupMember(ctx, s, user.ID)
|
||||
log.Printf(" ✅ Admin user '%s' created", cfg.AdminUsername)
|
||||
}
|
||||
|
||||
@@ -601,6 +603,9 @@ func SeedUsers(cfg *config.Config, s store.Stores, uekCache ...*crypto.UEKCache)
|
||||
cache = uekCache[0]
|
||||
}
|
||||
ProbeAndRepairVault(ctx, s, existing.ID, password, cache)
|
||||
if role == models.UserRoleAdmin {
|
||||
ensureAdminsGroupMember(ctx, s, existing.ID)
|
||||
}
|
||||
log.Printf(" 🌱 Seed user '%s' updated (role=%s)", username, role)
|
||||
continue
|
||||
}
|
||||
@@ -620,10 +625,20 @@ func SeedUsers(cfg *config.Config, s store.Stores, uekCache ...*crypto.UEKCache)
|
||||
log.Printf("⚠ Seed user '%s' failed: %v", username, err)
|
||||
continue
|
||||
}
|
||||
if role == models.UserRoleAdmin {
|
||||
ensureAdminsGroupMember(ctx, s, user.ID)
|
||||
}
|
||||
log.Printf(" 🌱 Seed user '%s' created (role=%s, active=true)", username, role)
|
||||
}
|
||||
}
|
||||
|
||||
// ensureAdminsGroupMember adds userID to the Admins system group (idempotent).
|
||||
// Used by BootstrapAdmin and SeedUsers so that admin users receive
|
||||
// surface.admin.access through the normal permission resolution path.
|
||||
func ensureAdminsGroupMember(ctx context.Context, s store.Stores, userID string) {
|
||||
auth.SyncAdminsGroupMembership(ctx, s, userID, models.UserRoleAdmin)
|
||||
}
|
||||
|
||||
// IsRegistrationEnabled checks the platform policy.
|
||||
func IsRegistrationEnabled(s store.Stores) bool {
|
||||
val, _ := s.Policies.GetBool(context.Background(), "allow_registration")
|
||||
|
||||
Reference in New Issue
Block a user