diff --git a/app/api/admin_catalog.py b/app/api/admin_catalog.py index 9209de6..13c5472 100644 --- a/app/api/admin_catalog.py +++ b/app/api/admin_catalog.py @@ -680,6 +680,13 @@ def delete_member( row = users_repo.get_by_sub(authentik_sub) if not row: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="user_not_found") + settings = get_settings() + service = AuthentikAdminService(settings=settings) + service.delete_user( + authentik_user_id=row.authentik_user_id, + email=row.email, + username=row.username, + ) db.execute(delete(PermissionGroupMember).where(PermissionGroupMember.authentik_sub == authentik_sub)) db.delete(row) db.commit() diff --git a/app/services/authentik_admin_service.py b/app/services/authentik_admin_service.py index 20fd938..87b9c99 100644 --- a/app/services/authentik_admin_service.py +++ b/app/services/authentik_admin_service.py @@ -23,6 +23,12 @@ class AuthentikPasswordResetResult: temporary_password: str +@dataclass +class AuthentikDeleteResult: + action: str + user_id: int | None = None + + class AuthentikAdminService: def __init__(self, settings: Settings) -> None: self.base_url = settings.authentik_base_url.rstrip("/") @@ -159,3 +165,30 @@ class AuthentikAdminService: raise HTTPException(status_code=502, detail="authentik_set_password_failed") return AuthentikPasswordResetResult(user_id=user_pk, temporary_password=temp_password) + + def delete_user( + self, + *, + authentik_user_id: int | None, + email: str | None, + username: str | None, + ) -> AuthentikDeleteResult: + with self._client() as client: + existing = None + if authentik_user_id is not None: + existing = self._lookup_user_by_id(client, authentik_user_id) + if existing is None: + existing = self._lookup_user_by_email_or_username(client, email=email, username=username) + if not existing or existing.get("pk") is None: + return AuthentikDeleteResult(action="not_found") + + user_pk = int(existing["pk"]) + delete_resp = client.delete(f"/api/v3/core/users/{user_pk}/") + if delete_resp.status_code in {204, 404}: + return AuthentikDeleteResult( + action="deleted" if delete_resp.status_code == 204 else "not_found", + user_id=user_pk, + ) + if delete_resp.status_code >= 400: + raise HTTPException(status_code=502, detail="authentik_delete_failed") + return AuthentikDeleteResult(action="deleted", user_id=user_pk)