Files
ctms/backend/app/core/deps.py
T

55 lines
1.7 KiB
Python

from typing import Annotated, AsyncGenerator, Callable, Iterable
import uuid
from fastapi import Depends, HTTPException, status
from pydantic import ValidationError
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.security import decode_token, oauth2_scheme
from app.crud import user as user_crud
from app.db.session import SessionLocal
from app.schemas.user import TokenPayload
async def get_db_session() -> AsyncGenerator[AsyncSession, None]:
async with SessionLocal() as session:
yield session
async def get_current_user(
token: Annotated[str, Depends(oauth2_scheme)],
db: Annotated[AsyncSession, Depends(get_db_session)],
):
payload = decode_token(token)
try:
token_data = TokenPayload(**payload)
except ValidationError as exc:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
) from exc
user = await user_crud.get_by_id(db, uuid.UUID(str(token_data.sub)))
if not user or not user.is_active:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Inactive or missing user",
headers={"WWW-Authenticate": "Bearer"},
)
return user
def require_roles(roles: Iterable[str]) -> Callable:
roles_set = set(roles)
async def dependency(current_user=Depends(get_current_user)):
if current_user.role not in roles_set:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Insufficient permissions",
)
return current_user
return dependency