"""API dependencies.""" from typing import Annotated from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.services.auth import AuthService from app.models.user import User # Security scheme security = HTTPBearer() async def get_current_user( credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)], db: Annotated[AsyncSession, Depends(get_db)], ) -> User: """Get current authenticated user from JWT token.""" credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) token = credentials.credentials payload = AuthService.decode_token(token) if payload is None: raise credentials_exception user_id_str = payload.get("sub") if user_id_str is None: raise credentials_exception try: user_id = int(user_id_str) except (ValueError, TypeError): raise credentials_exception user = await AuthService.get_user_by_id(db, user_id) if user is None: raise credentials_exception if not user.is_active: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="User account is disabled", ) return user async def get_current_active_user( current_user: Annotated[User, Depends(get_current_user)], ) -> User: """Ensure user is active.""" if not current_user.is_active: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Inactive user", ) return current_user # Type aliases for cleaner annotations CurrentUser = Annotated[User, Depends(get_current_user)] ActiveUser = Annotated[User, Depends(get_current_active_user)] Database = Annotated[AsyncSession, Depends(get_db)]