99 lines
2.6 KiB
Python
99 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Generator
|
|
|
|
from fastapi import Depends, HTTPException, Request, status
|
|
|
|
from config.settings import Settings, get_settings
|
|
from models import User
|
|
from services.security import JWTSettings
|
|
from services.session import (
|
|
AuthSession,
|
|
SessionStrategy,
|
|
SessionTokens,
|
|
build_session_strategy,
|
|
extract_session_tokens,
|
|
)
|
|
from services.unit_of_work import UnitOfWork
|
|
|
|
|
|
def get_unit_of_work() -> Generator[UnitOfWork, None, None]:
|
|
"""FastAPI dependency yielding a unit-of-work instance."""
|
|
|
|
with UnitOfWork() as uow:
|
|
yield uow
|
|
|
|
|
|
def get_application_settings() -> Settings:
|
|
"""Provide cached application settings instance."""
|
|
|
|
return get_settings()
|
|
|
|
|
|
def get_jwt_settings() -> JWTSettings:
|
|
"""Provide JWT runtime configuration derived from settings."""
|
|
|
|
return get_settings().jwt_settings()
|
|
|
|
|
|
def get_session_strategy(
|
|
settings: Settings = Depends(get_application_settings),
|
|
) -> SessionStrategy:
|
|
"""Yield configured session transport strategy."""
|
|
|
|
return build_session_strategy(settings.session_settings())
|
|
|
|
|
|
def get_session_tokens(
|
|
request: Request,
|
|
strategy: SessionStrategy = Depends(get_session_strategy),
|
|
) -> SessionTokens:
|
|
"""Extract raw session tokens from the incoming request."""
|
|
|
|
existing = getattr(request.state, "auth_session", None)
|
|
if isinstance(existing, AuthSession):
|
|
return existing.tokens
|
|
|
|
tokens = extract_session_tokens(request, strategy)
|
|
request.state.auth_session = AuthSession(tokens=tokens)
|
|
return tokens
|
|
|
|
|
|
def get_auth_session(
|
|
request: Request,
|
|
tokens: SessionTokens = Depends(get_session_tokens),
|
|
) -> AuthSession:
|
|
"""Provide authentication session context for the current request."""
|
|
|
|
existing = getattr(request.state, "auth_session", None)
|
|
if isinstance(existing, AuthSession):
|
|
return existing
|
|
|
|
if tokens.is_empty:
|
|
session = AuthSession.anonymous()
|
|
else:
|
|
session = AuthSession(tokens=tokens)
|
|
request.state.auth_session = session
|
|
return session
|
|
|
|
|
|
def get_current_user(
|
|
session: AuthSession = Depends(get_auth_session),
|
|
) -> User | None:
|
|
"""Return the current authenticated user if present."""
|
|
|
|
return session.user
|
|
|
|
|
|
def require_current_user(
|
|
session: AuthSession = Depends(get_auth_session),
|
|
) -> User:
|
|
"""Ensure that a request is authenticated and return the user context."""
|
|
|
|
if session.user is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Authentication required.",
|
|
)
|
|
return session.user
|