Sync site-role assignments to Keycloak group role mappings
This commit is contained in:
@@ -413,6 +413,65 @@ class ProviderAdminService:
|
||||
return client_uuid
|
||||
raise HTTPException(status_code=404, detail="provider_client_not_found")
|
||||
|
||||
def _get_client_role_representation(self, client: httpx.Client, *, client_uuid: str, role_name: str) -> dict:
|
||||
resp = client.get(f"/admin/realms/{self.realm}/clients/{client_uuid}/roles/{role_name}")
|
||||
if resp.status_code == 404:
|
||||
raise HTTPException(status_code=404, detail=f"provider_role_not_found:{role_name}")
|
||||
if resp.status_code >= 400:
|
||||
raise HTTPException(status_code=502, detail="idp_lookup_failed")
|
||||
payload = resp.json() if resp.content else {}
|
||||
if not isinstance(payload, dict):
|
||||
raise HTTPException(status_code=502, detail="idp_lookup_failed")
|
||||
return payload
|
||||
|
||||
def set_group_client_roles(self, *, group_id: str, provider_client_id: str, role_names: list[str]) -> None:
|
||||
if not group_id:
|
||||
raise HTTPException(status_code=400, detail="provider_group_id_required")
|
||||
|
||||
desired_names = [name.strip() for name in role_names if isinstance(name, str) and name.strip()]
|
||||
desired_name_set = set(desired_names)
|
||||
|
||||
with self._client() as client:
|
||||
client_uuid = self._resolve_client_uuid(client, provider_client_id)
|
||||
|
||||
current_resp = client.get(f"/admin/realms/{self.realm}/groups/{group_id}/role-mappings/clients/{client_uuid}")
|
||||
if current_resp.status_code >= 400:
|
||||
raise HTTPException(status_code=502, detail="idp_group_role_mapping_lookup_failed")
|
||||
current_payload = current_resp.json() if current_resp.content else []
|
||||
current_rows = current_payload if isinstance(current_payload, list) else []
|
||||
current_map: dict[str, dict] = {}
|
||||
for row in current_rows:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
name = str(row.get("name", "")).strip()
|
||||
if name:
|
||||
current_map[name] = row
|
||||
|
||||
to_add_names = sorted(desired_name_set - set(current_map.keys()))
|
||||
to_remove_names = sorted(set(current_map.keys()) - desired_name_set)
|
||||
|
||||
if to_add_names:
|
||||
add_payload = [
|
||||
self._get_client_role_representation(client, client_uuid=client_uuid, role_name=role_name)
|
||||
for role_name in to_add_names
|
||||
]
|
||||
add_resp = client.post(
|
||||
f"/admin/realms/{self.realm}/groups/{group_id}/role-mappings/clients/{client_uuid}",
|
||||
json=add_payload,
|
||||
)
|
||||
if add_resp.status_code >= 400:
|
||||
raise HTTPException(status_code=502, detail="idp_group_role_mapping_add_failed")
|
||||
|
||||
if to_remove_names:
|
||||
remove_payload = [current_map[name] for name in to_remove_names]
|
||||
remove_resp = client.request(
|
||||
"DELETE",
|
||||
f"/admin/realms/{self.realm}/groups/{group_id}/role-mappings/clients/{client_uuid}",
|
||||
json=remove_payload,
|
||||
)
|
||||
if remove_resp.status_code >= 400:
|
||||
raise HTTPException(status_code=502, detail="idp_group_role_mapping_remove_failed")
|
||||
|
||||
def ensure_client_role(
|
||||
self,
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user