1
0
forked from baron/baron-sso

feat: simplify RBAC roles and remove dev role switcher

- Simplified RBAC system to two roles: super_admin and user.
- Removed tenant_admin and rp_admin roles across backend and frontend.
- Removed Dev Role Switcher feature from adminfront.
- Updated all handlers, middlewares, and navigation to reflect the new role model.
- Fixed backend build errors and updated tests.
This commit is contained in:
2026-06-02 18:29:18 +09:00
parent 57f05e2694
commit 802bf3e91d
32 changed files with 487 additions and 938 deletions

View File

@@ -252,21 +252,13 @@ func normalizeUserRole(role string) string {
}
func isDevConsoleRoleAllowed(role string) bool {
switch normalizeUserRole(role) {
case domain.RoleSuperAdmin, domain.RoleTenantAdmin, domain.RoleRPAdmin, domain.RoleUser:
return true
default:
return false
}
r := normalizeUserRole(role)
return r == domain.RoleSuperAdmin || r == domain.RoleUser
}
func isDevConsoleViewerRole(role string) bool {
switch normalizeUserRole(role) {
case domain.RoleSuperAdmin, domain.RoleTenantAdmin, domain.RoleRPAdmin, domain.RoleUser:
return true
default:
return false
}
r := normalizeUserRole(role)
return r == domain.RoleSuperAdmin || r == domain.RoleUser
}
func setCurrentProfileContext(c *fiber.Ctx, profile *domain.UserProfileResponse) {
@@ -538,7 +530,7 @@ func mergeStringSets(dst map[string]struct{}, src map[string]struct{}) map[strin
func shouldScopeDashboardToExplicitClients(role string) bool {
switch normalizeUserRole(role) {
case domain.RoleRPAdmin, domain.RoleUser:
case "rp_admin", domain.RoleUser:
return true
default:
return false
@@ -562,20 +554,7 @@ func canAccessClientByLegacyScope(profile *domain.UserProfileResponse, summary c
}
role := normalizeUserRole(profile.Role)
if role == domain.RoleSuperAdmin {
return true
}
if !isDevConsoleRoleAllowed(role) {
return false
}
userTenantID := tenantIDFromProfile(profile)
clientTenantID := resolveClientTenantID(summary)
if userTenantID != "" && clientTenantID != "" && clientTenantID != userTenantID {
return false
}
return isRPAdminClientAllowed(profile, summary.ID)
return role == domain.RoleSuperAdmin
}
func resolveClientTenantID(summary clientSummary) string {
@@ -587,19 +566,10 @@ func resolveClientTenantID(summary clientSummary) string {
}
func isRPAdminClientAllowed(profile *domain.UserProfileResponse, clientID string) bool {
// [Deprecated] isRPAdminClientAllowed is now simplified.
// Non-superadmins are already checked by tenant in canAccessClientByLegacyScope.
role := normalizeUserRole(profileRole(profile))
if role == domain.RoleUser {
return false
}
if role != domain.RoleRPAdmin {
return true
}
allowed := managedClientIDsFromProfile(profile)
if len(allowed) == 0 {
return false
}
_, ok := allowed[strings.TrimSpace(clientID)]
return ok
return role == domain.RoleSuperAdmin || role == domain.RoleUser
}
func manageableTenantKeysFromProfile(profile *domain.UserProfileResponse) map[string]struct{} {
@@ -927,18 +897,12 @@ func (h *DevHandler) checkAppManagerPermission(c *fiber.Ctx) (bool, error) {
if ok && profile != nil {
setCurrentProfileContext(c, profile)
role := normalizeUserRole(profile.Role)
switch role {
case domain.RoleSuperAdmin:
if role == domain.RoleSuperAdmin {
slog.Info("Dev private permission granted by super_admin role", "user_id", profile.ID)
return true, nil
case domain.RoleTenantAdmin, domain.RoleRPAdmin:
slog.Info("Dev private permission granted by role", "user_id", profile.ID, "role", role)
return true, nil
case domain.RoleUser:
return false, nil
}
// Super Admin bypass
// Super Admin bypass by email
if isAdminEmail(profile.Email) {
slog.Info("Dev private permission granted by ADMIN_EMAIL match", "email", profile.Email)
return true, nil
@@ -997,13 +961,6 @@ func (h *DevHandler) checkAppManagerPermission(c *fiber.Ctx) (bool, error) {
slog.Info("Dev private permission granted by token role", "role", tokenRole)
return true, nil
}
if tokenRole == domain.RoleTenantAdmin || tokenRole == domain.RoleRPAdmin {
slog.Info("Dev private permission granted by token role", "role", tokenRole)
return true, nil
}
if tokenRole == domain.RoleUser {
return false, nil
}
if isAdminEmail(tokenEmail) {
slog.Info("Dev private permission granted by token email", "email", tokenEmail)
return true, nil
@@ -1067,7 +1024,6 @@ func (h *DevHandler) listVisibleClientSummaries(
userTenantID := tenantIDFromProfile(profile)
isSuperAdmin := role == domain.RoleSuperAdmin
allowedClientIDs := managedClientIDsFromProfile(profile)
isAppManager, err := h.checkAppManagerPermission(c)
if err != nil {
@@ -1099,12 +1055,6 @@ func (h *DevHandler) listVisibleClientSummaries(
}
}
if role == domain.RoleRPAdmin && len(allowedClientIDs) > 0 {
if _, ok := allowedClientIDs[summary.ID]; !ok && !canViewByPermit {
continue
}
}
if !isSuperAdmin && !canAccessClientByLegacyScope(profile, summary) && !canViewByPermit {
continue
}
@@ -1737,7 +1687,7 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error {
if tenantID == "" && profile.TenantID != nil {
tenantID = *profile.TenantID
}
if (role == domain.RoleRPAdmin || role == domain.RoleUser) && !h.canManageTenantClientsByPermit(c, profile, tenantID) {
if (role == "rp_admin" || role == domain.RoleUser) && !h.canManageTenantClientsByPermit(c, profile, tenantID) {
return errorJSON(c, fiber.StatusForbidden, "forbidden: tenant grant permission is required")
}
@@ -2672,7 +2622,7 @@ func (h *DevHandler) ListAuditLogs(c *fiber.Ctx) error {
statusFilter := strings.ToLower(strings.TrimSpace(c.Query("status")))
allowedClientIDs := managedClientIDsFromProfile(profile)
allowedClientIDs = mergeStringSets(allowedClientIDs, h.auditClientIDsByPermit(c, profile, clientFilter))
if role != domain.RoleSuperAdmin && len(allowedClientIDs) == 0 && (role == domain.RoleRPAdmin || role == domain.RoleUser) {
if role != domain.RoleSuperAdmin && len(allowedClientIDs) == 0 && (role == "rp_admin" || role == domain.RoleUser) {
return c.JSON(devAuditListResponse{
Items: []domain.AuditLog{},
Limit: limit,