from fastapi import Depends, HTTPException, status from app.core.config import get_settings from app.schemas.auth import KeycloakPrincipal from app.security.idp_jwt import require_authenticated_principal def _expand_group_aliases(groups: set[str]) -> set[str]: expanded: set[str] = set() for group in groups: value = group.strip().lower() if not value: continue expanded.add(value) stripped = value.lstrip("/") if stripped: expanded.add(stripped) if "/" in stripped: expanded.add(stripped.rsplit("/", 1)[-1]) return expanded def require_admin_principal( principal: KeycloakPrincipal = Depends(require_authenticated_principal), ) -> KeycloakPrincipal: settings = get_settings() required_groups = _expand_group_aliases(set(settings.admin_required_groups)) if not required_groups: raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="admin_policy_not_configured") principal_groups = _expand_group_aliases(set(principal.groups)) group_ok = bool(required_groups.intersection(principal_groups)) if not group_ok: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="admin_forbidden") return principal