61 lines
2 KiB
Python
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
|