forked from baron/baron-sso
super admin 일반설정 제한 문제 수정
This commit is contained in:
@@ -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{}{}
|
||||
|
||||
Reference in New Issue
Block a user