""" FastAPI dependencies for API routes. Provides reusable dependencies for: - Database session management - Authentication/authorization """ from typing import Generator, Optional from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from sqlalchemy.orm import Session from app.database import get_session_factory from app.security import verify_api_token # HTTP Bearer token security scheme security = HTTPBearer(auto_error=False) def get_db_session() -> Generator[Session, None, None]: """ Dependency to get a database session. Yields: SQLAlchemy database session Example: @app.get("/items") def read_items(db: Session = Depends(get_db_session)): items = db.query(Item).all() return items """ session_factory = get_session_factory() if session_factory is None: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Database not initialized" ) session = session_factory() try: yield session finally: session.close() def require_auth( credentials: Optional[HTTPAuthorizationCredentials] = Depends(security) ) -> None: """ Dependency to require authentication for protected endpoints. Args: credentials: HTTP Bearer token credentials Raises: HTTPException: If authentication fails (401 Unauthorized) Example: @app.get("/protected") def protected_route(auth: None = Depends(require_auth)): return {"message": "authenticated"} """ if credentials is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing authentication credentials", headers={"WWW-Authenticate": "Bearer"}, ) authorization = f"Bearer {credentials.credentials}" if not verify_api_token(authorization): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid authentication token", headers={"WWW-Authenticate": "Bearer"}, ) # Return None to indicate successful authentication return None async def require_auth_optional( credentials: Optional[HTTPAuthorizationCredentials] = Depends(security) ) -> bool: """ Optional authentication dependency. Returns True if authenticated, False otherwise. This is useful for endpoints that have different behavior based on authentication status but don't require it. Args: credentials: HTTP Bearer token credentials Returns: bool: True if authenticated, False otherwise Example: @app.get("/public") def public_route(authenticated: bool = Depends(require_auth_optional)): if authenticated: return {"message": "authenticated user"} return {"message": "anonymous user"} """ if credentials is None: return False authorization = f"Bearer {credentials.credentials}" return verify_api_token(authorization)