"""API dependencies.""" from typing import Annotated, Optional from fastapi import Depends, Header, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from jose import JWTError from sqlalchemy.ext.asyncio import AsyncSession from app.core.config import settings from app.core.database import get_db from app.core.security import decode_token from app.models.user import User from app.services.auth_service import AuthService # Database session dependency DBSession = Annotated[AsyncSession, Depends(get_db)] # Authentication security = HTTPBearer() async def get_current_user( credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)], db: DBSession, ) -> User: """ Get current authenticated user from JWT token. Args: credentials: HTTP Authorization credentials db: Database session Returns: Current user Raises: HTTPException: If token is invalid or user not found """ credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) try: payload = decode_token(credentials.credentials) user_id: str = payload.get("sub") token_type: str = payload.get("type") if user_id is None or token_type != "access": raise credentials_exception except JWTError: raise credentials_exception auth_service = AuthService(db) user = await auth_service.get_user_by_id(user_id) if user is None: raise credentials_exception return user async def get_current_user_optional( credentials: Annotated[Optional[HTTPAuthorizationCredentials], Depends(security)], db: DBSession, ) -> Optional[User]: """ Get current user if authenticated, otherwise None. Args: credentials: Optional HTTP Authorization credentials db: Database session Returns: Current user or None """ if credentials is None: return None try: return await get_current_user(credentials, db) # type: ignore except HTTPException: return None # Current user dependencies CurrentUser = Annotated[User, Depends(get_current_user)] CurrentUserOptional = Annotated[Optional[User], Depends(get_current_user_optional)] def get_auth_service(db: DBSession) -> AuthService: """Get auth service instance.""" return AuthService(db) AuthServiceDep = Annotated[AuthService, Depends(get_auth_service)]