docs: add AI code generation requirements and comprehensive Google-style docstrings
- Add AI code generation requirements to AGENTS.md - Add module-level docstrings to all 46 Python modules - Add detailed Google-style docstrings to all classes and functions - Remove all inline comments following self-documenting code principle - Include Args, Returns, Raises sections in function docstrings - Add Attributes and Examples sections to class docstrings
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
"""Keycloak authentication client."""
|
||||
"""Keycloak authentication client.
|
||||
|
||||
This module provides a client for Keycloak authentication operations
|
||||
including token introspection and user info retrieval.
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
@@ -9,10 +13,30 @@ from app.infrastructure.config.settings import Settings
|
||||
|
||||
|
||||
class KeycloakAuthClient:
|
||||
"""Client for Keycloak authentication operations."""
|
||||
"""Client for Keycloak authentication operations.
|
||||
|
||||
Handles token validation via introspection and user info retrieval.
|
||||
Implements token caching to reduce Keycloak server load.
|
||||
|
||||
Attributes:
|
||||
_settings: Application settings with Keycloak config.
|
||||
_base_url: Keycloak realm base URL.
|
||||
_client_id: OAuth client identifier.
|
||||
_client_secret: OAuth client secret.
|
||||
_cache: Token info cache for performance.
|
||||
_cache_ttl: Cache time-to-live in seconds.
|
||||
|
||||
Example:
|
||||
>>> client = KeycloakAuthClient(settings)
|
||||
>>> token_info = await client.introspect_token(token)
|
||||
"""
|
||||
|
||||
def __init__(self, settings: Settings) -> None:
|
||||
"""Initialize Keycloak client with settings."""
|
||||
"""Initialize Keycloak client with settings.
|
||||
|
||||
Args:
|
||||
settings: Application settings with Keycloak configuration.
|
||||
"""
|
||||
self._settings = settings
|
||||
self._base_url = f"{settings.kc.server_url}/realms/{settings.kc.realm}"
|
||||
self._client_id = settings.kc.client_id
|
||||
@@ -21,15 +45,30 @@ class KeycloakAuthClient:
|
||||
self._cache_ttl = settings.kc.token_cache_ttl
|
||||
|
||||
def _get_introspection_url(self) -> str:
|
||||
"""Get token introspection endpoint URL."""
|
||||
"""Get token introspection endpoint URL.
|
||||
|
||||
Returns:
|
||||
Full URL for token introspection endpoint.
|
||||
"""
|
||||
return f"{self._base_url}/protocol/openid-connect/token/introspection"
|
||||
|
||||
def _get_userinfo_url(self) -> str:
|
||||
"""Get userinfo endpoint URL."""
|
||||
"""Get userinfo endpoint URL.
|
||||
|
||||
Returns:
|
||||
Full URL for userinfo endpoint.
|
||||
"""
|
||||
return f"{self._base_url}/protocol/openid-connect/userinfo"
|
||||
|
||||
def _get_cached_token(self, token: str) -> TokenInfo | None:
|
||||
"""Get cached token info if valid."""
|
||||
"""Get cached token info if valid.
|
||||
|
||||
Args:
|
||||
token: Access token string.
|
||||
|
||||
Returns:
|
||||
Cached TokenInfo if valid and not expired, None otherwise.
|
||||
"""
|
||||
if token not in self._cache:
|
||||
return None
|
||||
|
||||
@@ -41,9 +80,13 @@ class KeycloakAuthClient:
|
||||
return token_info
|
||||
|
||||
def _cache_token(self, token: str, token_info: TokenInfo) -> None:
|
||||
"""Cache token info."""
|
||||
"""Cache token info.
|
||||
|
||||
Args:
|
||||
token: Access token string as cache key.
|
||||
token_info: TokenInfo to cache.
|
||||
"""
|
||||
self._cache[token] = (token_info, time.time())
|
||||
# Simple cleanup of old entries
|
||||
current_time = time.time()
|
||||
expired_keys = [
|
||||
k for k, (_, t) in self._cache.items() if current_time - t > self._cache_ttl
|
||||
@@ -52,13 +95,21 @@ class KeycloakAuthClient:
|
||||
del self._cache[k]
|
||||
|
||||
async def introspect_token(self, token: str) -> TokenInfo:
|
||||
"""Introspect access token using Keycloak."""
|
||||
# Check cache first
|
||||
"""Introspect access token using Keycloak.
|
||||
|
||||
Validates token with Keycloak server and extracts user information.
|
||||
Uses cache to reduce server requests for recently validated tokens.
|
||||
|
||||
Args:
|
||||
token: Access token to validate.
|
||||
|
||||
Returns:
|
||||
TokenInfo with validation result and user claims.
|
||||
"""
|
||||
cached = self._get_cached_token(token)
|
||||
if cached:
|
||||
return cached
|
||||
|
||||
# Prepare introspection request
|
||||
data = {
|
||||
"token": token,
|
||||
"client_id": self._client_id,
|
||||
@@ -81,7 +132,6 @@ class KeycloakAuthClient:
|
||||
if not result.get("active", False):
|
||||
return TokenInfo(active=False, raw_claims=result)
|
||||
|
||||
# Extract roles from realm_access or resource_access
|
||||
roles: list[str] = []
|
||||
realm_access = result.get("realm_access", {})
|
||||
if isinstance(realm_access, dict):
|
||||
@@ -96,13 +146,21 @@ class KeycloakAuthClient:
|
||||
raw_claims=result,
|
||||
)
|
||||
|
||||
# Cache valid token
|
||||
self._cache_token(token, token_info)
|
||||
|
||||
return token_info
|
||||
|
||||
async def get_userinfo(self, token: str) -> KeycloakUser | None:
|
||||
"""Get user information from Keycloak using access token."""
|
||||
"""Get user information from Keycloak using access token.
|
||||
|
||||
Fetches detailed user profile from Keycloak userinfo endpoint.
|
||||
|
||||
Args:
|
||||
token: Valid access token.
|
||||
|
||||
Returns:
|
||||
KeycloakUser with profile data, or None on error.
|
||||
"""
|
||||
try:
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(
|
||||
|
||||
Reference in New Issue
Block a user