from fastapi import Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.core.auth import decode_access_token from app.db.database import get_db from app.db.models import User security = HTTPBearer() async def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), db: AsyncSession = Depends(get_db), ) -> User: payload = decode_access_token(credentials.credentials) if payload is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Token invalid or expired", ) user_id = payload.get("sub") if user_id is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token format", ) result = await db.execute(select(User).where(User.id == int(user_id))) user = result.scalar_one_or_none() if user is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found" ) if user.status != "approved": raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Account not approved" ) return user def require_role(*roles: str): """Factory: returns a dependency that checks user role.""" async def _check(user: User = Depends(get_current_user)) -> User: if user.role not in roles: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Insufficient permissions", ) return user return _check