1
0
forked from baron/baron-sso

super admin 일반설정 제한 문제 수정

This commit is contained in:
2026-05-27 14:19:11 +09:00
parent 939bf68f85
commit 262c5959cf
3 changed files with 285 additions and 10 deletions

View File

@@ -1958,7 +1958,8 @@ func (h *DevHandler) UpdateClient(c *fiber.Ctx) error {
return errorJSON(c, fiber.StatusForbidden, "forbidden")
}
if !h.canOperateClientByPermit(c, profile, currentSummary, "edit_config") {
isSuperAdmin := role == domain.RoleSuperAdmin
if !isSuperAdmin && !h.canOperateClientByPermit(c, profile, currentSummary, "edit_config") {
return errorJSON(c, fiber.StatusForbidden, "forbidden: edit_config permission is required")
}
@@ -1971,7 +1972,7 @@ func (h *DevHandler) UpdateClient(c *fiber.Ctx) error {
}
// [Security] Check permission for private clients (both current and new type)
if currentSummary.Type == "private" || clientType == "private" {
if !isSuperAdmin && (currentSummary.Type == "private" || clientType == "private") {
if !h.canBypassPrivateClientRestriction(c, profile, currentSummary, "edit_config") {
return errorJSON(c, fiber.StatusForbidden, "forbidden: insufficient permissions for private client")
}
@@ -2072,19 +2073,48 @@ func (h *DevHandler) UpdateClient(c *fiber.Ctx) error {
}
tenantPolicyChanged := tenantAccessPolicyChanged(current.Metadata, updated.Metadata)
beforeScopes := strings.Fields(current.Scope)
afterScopes := strings.Fields(updated.Scope)
beforeAllowedTenants := readStringSliceMetadata(current.Metadata, "allowed_tenants")
afterAllowedTenants := readStringSliceMetadata(metadata, "allowed_tenants")
beforeIDTokenClaims := readMetadataValueOrNil(current.Metadata, "id_token_claims")
afterIDTokenClaims := readMetadataValueOrNil(metadata, "id_token_claims")
h.setAuditDetailsExtra(c, map[string]any{
"action": "UPDATE_CLIENT",
"target_id": clientID,
"tenant_id": tenantID,
"before": map[string]any{
"name": currentSummary.Name,
"type": currentSummary.Type,
"status": currentSummary.Status,
"name": currentSummary.Name,
"type": currentSummary.Type,
"status": currentSummary.Status,
"scopes": beforeScopes,
"tenant_access_restricted": readMetadataBoolValue(current.Metadata, "tenant_access_restricted"),
"allowed_tenants": beforeAllowedTenants,
"id_token_claims": beforeIDTokenClaims,
"token_endpoint_auth_method": current.TokenEndpointAuthMethod,
"jwks_uri": current.JWKSUri,
"backchannel_logout_uri": strings.TrimSpace(current.BackchannelLogoutURI()),
"backchannel_logout_session_required": current.BackchannelLogoutSessionRequiredValue(),
"headless_login_enabled": readMetadataBoolValue(current.Metadata, domain.MetadataHeadlessLoginEnabled),
"headless_token_endpoint_auth_method": readMetadataStringValue(current.Metadata, domain.MetadataHeadlessTokenEndpointAuthMethod),
"headless_jwks_uri": readMetadataStringValue(current.Metadata, domain.MetadataHeadlessJWKSURI),
},
"after": map[string]any{
"name": strings.TrimSpace(updated.ClientName),
"type": clientTypeOrDefault(updated.TokenEndpointAuthMethod),
"status": resolveStatusFromMetadata(updated.Metadata),
"name": strings.TrimSpace(updated.ClientName),
"type": clientTypeOrDefault(updated.TokenEndpointAuthMethod),
"status": resolveStatusFromMetadata(updated.Metadata),
"scopes": afterScopes,
"tenant_access_restricted": readMetadataBoolValue(metadata, "tenant_access_restricted"),
"allowed_tenants": afterAllowedTenants,
"id_token_claims": afterIDTokenClaims,
"token_endpoint_auth_method": resolvedTokenAuthMethod,
"jwks_uri": resolvedJWKSURI,
"backchannel_logout_uri": strings.TrimSpace(resolvedBackchannelLogoutURI),
"backchannel_logout_session_required": resolvedBackchannelLogoutSessionRequired,
"headless_login_enabled": readMetadataBoolValue(metadata, domain.MetadataHeadlessLoginEnabled),
"headless_token_endpoint_auth_method": readMetadataStringValue(metadata, domain.MetadataHeadlessTokenEndpointAuthMethod),
"headless_jwks_uri": readMetadataStringValue(metadata, domain.MetadataHeadlessJWKSURI),
},
})
@@ -2934,6 +2964,49 @@ func readMetadataBoolValue(metadata map[string]interface{}, key string) bool {
return value
}
func readStringSliceMetadata(metadata map[string]interface{}, key string) []string {
if metadata == nil {
return nil
}
raw, ok := metadata[key]
if !ok || raw == nil {
return nil
}
switch typed := raw.(type) {
case []string:
result := make([]string, 0, len(typed))
for _, item := range typed {
if trimmed := strings.TrimSpace(item); trimmed != "" {
result = append(result, trimmed)
}
}
return result
case []interface{}:
result := make([]string, 0, len(typed))
for _, item := range typed {
if str, ok := item.(string); ok {
if trimmed := strings.TrimSpace(str); trimmed != "" {
result = append(result, trimmed)
}
}
}
return result
default:
return nil
}
}
func readMetadataValueOrNil(metadata map[string]interface{}, key string) interface{} {
if metadata == nil {
return nil
}
value, ok := metadata[key]
if !ok {
return nil
}
return value
}
func normalizeBackchannelLogoutMetadata(metadata map[string]interface{}, logoutURI string, sessionRequired bool) (map[string]interface{}, error) {
if metadata == nil {
metadata = map[string]interface{}{}