"""Small async client for the internal AuthZ service.""" from __future__ import annotations from typing import Any import httpx class AuthzClient: def __init__(self, base_url: str, timeout_seconds: int = 10) -> None: self.base_url = base_url.rstrip("/") self.timeout_seconds = timeout_seconds async def _request(self, method: str, path: str, *, json_body: dict[str, Any] | None = None) -> Any: async with httpx.AsyncClient( timeout=self.timeout_seconds, follow_redirects=True, trust_env=False, ) as client: response = await client.request(method, f"{self.base_url}{path}", json=json_body) response.raise_for_status() if not response.content: return None return response.json() async def issue_token( self, *, client_id: str, client_secret: str, audience: str, scopes: list[str], ) -> dict[str, Any]: data = await self._request( "POST", "/oauth/token", json_body={ "grant_type": "client_credentials", "client_id": client_id, "client_secret": client_secret, "aud": audience, "scopes": list(scopes), }, ) return data if isinstance(data, dict) else {} async def get_permissions(self, backend_id: str) -> dict[str, Any]: data = await self._request("GET", f"/backends/{backend_id}/permissions") return data if isinstance(data, dict) else {} async def set_permissions(self, backend_id: str, payload: dict[str, Any]) -> dict[str, Any]: data = await self._request("POST", f"/backends/{backend_id}/permissions", json_body=payload) return data if isinstance(data, dict) else {} async def register_user( self, *, username: str, password: str, email: str | None = None, backend_name: str | None = None, backend_id: str | None = None, base_url: str | None = None, frontend_base_url: str | None = None, ) -> dict[str, Any]: payload: dict[str, Any] = { "username": username, "password": password, } optional = { "email": email, "backend_name": backend_name, "backend_id": backend_id, "base_url": base_url, "frontend_base_url": frontend_base_url, } payload.update({key: value for key, value in optional.items() if value}) data = await self._request("POST", "/oauth/register", json_body=payload) return data if isinstance(data, dict) else {} async def register_backend( self, *, name: str, base_url: str, frontend_base_url: str | None = None, backend_id: str | None = None, ) -> dict[str, Any]: payload: dict[str, Any] = { "name": name, "base_url": base_url, } if frontend_base_url: payload["frontend_base_url"] = frontend_base_url if backend_id: payload["backend_id"] = backend_id data = await self._request("POST", "/backends/register", json_body=payload) return data if isinstance(data, dict) else {} async def get_outlook_settings(self, backend_id: str) -> dict[str, Any]: data = await self._request("GET", f"/backends/{backend_id}/settings/outlook") return data if isinstance(data, dict) else {} async def set_outlook_settings(self, backend_id: str, payload: dict[str, Any]) -> dict[str, Any]: data = await self._request("POST", f"/backends/{backend_id}/settings/outlook", json_body=payload) return data if isinstance(data, dict) else {} async def delete_outlook_settings(self, backend_id: str) -> dict[str, Any]: data = await self._request("DELETE", f"/backends/{backend_id}/settings/outlook") return data if isinstance(data, dict) else {} async def get_minio_settings(self, backend_id: str) -> dict[str, Any]: data = await self._request("GET", f"/backends/{backend_id}/settings/minio") return data if isinstance(data, dict) else {} async def set_minio_settings(self, backend_id: str, payload: dict[str, Any]) -> dict[str, Any]: data = await self._request("POST", f"/backends/{backend_id}/settings/minio", json_body=payload) return data if isinstance(data, dict) else {} async def delete_minio_settings(self, backend_id: str) -> dict[str, Any]: data = await self._request("DELETE", f"/backends/{backend_id}/settings/minio") return data if isinstance(data, dict) else {}