from typing import Optional from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import jwt, JWTError from pydantic import ValidationError from sqlalchemy.orm import Session from app.db.session import get_db from app.core.config import settings from app.core.security import ALGORITHM from app.models.user import User from app.schemas.user import TokenPayload from app import crud oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login", auto_error=False) def get_current_user( db: Session = Depends(get_db), token: Optional[str] = Depends(oauth2_scheme) ) -> Optional[User]: """ Get the current user from the provided JWT token. Returns None if no token is provided or the token is invalid. """ if not token: return None try: payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM]) token_data = TokenPayload(**payload) except (JWTError, ValidationError): return None user = crud.user.get(db, id=token_data.sub) if not user: return None return user def get_current_active_user( current_user: User = Depends(get_current_user), ) -> User: """ Get the current active user and raise an exception if the user is not authenticated or inactive. """ if not current_user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated", headers={"WWW-Authenticate": "Bearer"}, ) if not crud.user.is_active(current_user): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Inactive user" ) return current_user