"""Session-cookie dependencies. Handlers stay thin; DB via get_session.""" from __future__ import annotations from collections.abc import Iterator from typing import Annotated from fastapi import Depends, HTTPException, Request from sqlmodel import Session from app.db import get_session from app.models import User from . import service SESSION_COOKIE = "kirche_session" SESSION_MAX_AGE = int(service.SESSION_TTL.total_seconds()) def get_db() -> Iterator[Session]: yield from get_session() def get_optional_user( request: Request, session: Annotated[Session, Depends(get_db)] ) -> User | None: session_id = request.cookies.get(SESSION_COOKIE) if not session_id: return None record = service.get_valid_session(session, session_id) if record is None: return None return service.get_user(session, record.user_id) def get_current_user(request: Request, session: Annotated[Session, Depends(get_db)]) -> User: user = get_optional_user(request, session) if user is None: raise HTTPException(status_code=401, detail="not authenticated") return user def require_admin(user: Annotated[User, Depends(get_current_user)]) -> User: if user.role != "admin": raise HTTPException(status_code=403, detail="admin only") return user def resolve_tenant(user: User | None, explicit: str | None, default: str = "default") -> str: """Tenant comes from the session; the body/query param is a deprecated fallback for unauthenticated callers.""" if user is not None: return user.tenant_id return explicit or default