"""Authentik service definition for read-only directory and access metadata.""" from __future__ import annotations from typing import TYPE_CHECKING, Any from pydantic import Field from media_library_viewer_api.clients.authentik import AuthentikClient from media_library_viewer_api.integrations.base import ( SecretField, ServiceBaseUrl, ServiceConfigBase, ServiceDefinition, TestResult, WidgetConfigBase, translate_connection_error, widget_kind, ) if TYPE_CHECKING: from media_library_viewer_api.services.settings_store import SettingsStore def test_connection(config: dict[str, Any], secrets: dict[str, str], store: SettingsStore) -> TestResult: """Probe the least-expensive Authentik directory endpoint.""" try: client = AuthentikClient( base_url=str(config.get("base_url") or "").rstrip("/"), api_token=str(secrets.get("api_token") or ""), timeout=float(config.get("timeout_seconds") or 60), ) result = client.users(page=1, page_size=1) return TestResult(ok=True, detail="Connected to Authentik.", evidence=f"{result.get('total', 0)} users") except Exception as exc: return translate_connection_error(exc, context="Authentik") class AuthentikConfig(ServiceConfigBase): """Non-secret Authentik connection config.""" base_url: ServiceBaseUrl timeout_seconds: int = Field(default=60, ge=1, le=300) class AuthentikListWidgetConfig(WidgetConfigBase): """Bounded display count for read-only Authentik list widgets.""" limit: int = Field(default=10, ge=1, le=50) DEFINITION = ServiceDefinition( service_type="authentik", name="Authentik", description="Read-only user directory, groups, and application access metadata.", config_model=AuthentikConfig, secret_fields=[SecretField(key="api_token", label="API token", required=True)], widget_kinds=[ widget_kind( kind="access_summary", name="User access summary", description="User group memberships and explicit staff/superuser status; not effective authorization.", model_cls=AuthentikListWidgetConfig, default_config={"limit": 10}, refresh_interval_ms=60_000, ), widget_kind( kind="groups", name="Groups", description="Read-only Authentik group list.", model_cls=AuthentikListWidgetConfig, default_config={"limit": 10}, refresh_interval_ms=60_000, ), widget_kind( kind="applications", name="Applications", description="Read-only Authentik application list.", model_cls=AuthentikListWidgetConfig, default_config={"limit": 10}, refresh_interval_ms=60_000, ), ], test_callable=test_connection, )