"""API dependencies module.""" from typing import Generator from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt from pydantic import ValidationError from sqlalchemy.orm import Session from app.core.config import settings from app.core.security import verify_password from app.db.session import get_db from app.models.user import User from app.schemas.token import TokenPayload # OAuth2 token URL oauth2_scheme = OAuth2PasswordBearer(tokenUrl=f"{settings.API_V1_STR}/auth/login") def get_current_user( db: Session = Depends(get_db), token: str = Depends(oauth2_scheme) ) -> User: """ Get the current user from the token. Args: db: Database session token: JWT token Returns: User: The authenticated user Raises: HTTPException: If the token is invalid or the user doesn't exist """ try: payload = jwt.decode( token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM] ) token_data = TokenPayload(**payload) except (JWTError, ValidationError): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) user = db.query(User).filter(User.id == token_data.sub).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found" ) return user def get_current_active_user( current_user: User = Depends(get_current_user), ) -> User: """ Get the current active user. Args: current_user: The authenticated user Returns: User: The active authenticated user Raises: HTTPException: If the user is inactive """ if not current_user.is_active: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Inactive user" ) return current_user def get_current_active_superuser( current_user: User = Depends(get_current_active_user), ) -> User: """ Get the current active superuser. Args: current_user: The authenticated active user Returns: User: The active superuser Raises: HTTPException: If the user is not a superuser """ if not current_user.is_superuser: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions" ) return current_user def authenticate_user(db: Session, email: str, password: str) -> Optional[User]: """ Authenticate a user by email and password. Args: db: Database session email: User email password: User password Returns: Optional[User]: The authenticated user or None if authentication fails """ user = db.query(User).filter(User.email == email).first() if not user: return None if not verify_password(password, user.hashed_password): return None return user