f1tness_parser/backend/app/api/deps.py

61 lines
2 KiB
Python

import jwt
from fastapi import Depends, HTTPException
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database.connection import get_session
from app.core.database.repository import TrainingRepository
from app.core.database.token_repository import RefreshTokenRepository
from app.core.database.user_repository import UserRepository
from app.core.dto.user import UserDTO
from app.core.security import decode_access_token
# auto_error=False: a missing header gets the same 401 as a bad token
bearer_scheme = HTTPBearer(auto_error=False)
def get_training_repository(
session: AsyncSession = Depends(get_session),
) -> TrainingRepository:
return TrainingRepository(session)
def get_user_repository(
session: AsyncSession = Depends(get_session),
) -> UserRepository:
return UserRepository(session)
def get_token_repository(
session: AsyncSession = Depends(get_session),
) -> RefreshTokenRepository:
return RefreshTokenRepository(session)
async def get_current_user(
credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme),
repository: UserRepository = Depends(get_user_repository),
) -> UserDTO:
"""The user of the access token. The user is read from the database on every request, so
a deactivated user loses access at once, not when the token expires."""
unauthorized = HTTPException(
status_code=401,
detail="Not authenticated",
headers={"WWW-Authenticate": "Bearer"},
)
if credentials is None:
raise unauthorized
try:
user_id = int(decode_access_token(credentials.credentials)["sub"])
except (jwt.PyJWTError, ValueError):
raise unauthorized
user = await repository.get(user_id)
if user is None or not user.is_active:
raise unauthorized
return user
async def require_superuser(user: UserDTO = Depends(get_current_user)) -> UserDTO:
if not user.is_superuser:
raise HTTPException(status_code=403, detail="Superuser only")
return user