from typing import Annotated from fastapi import Depends, HTTPException from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt from pydantic import ValidationError from setech.utils import get_logger from starlette import status from service.api.models.auth import TokenPayload from service.config import settings from service.constants import security from service.constants.types import PaginationParams from service.database.models import AnonymousUser, User __all__ = ["LoggedInUser", "QueryParams", "CurrentRequestUser", "RequestUser"] _l = get_logger("api") reusable_oauth2 = OAuth2PasswordBearer(tokenUrl=f"{settings.root_path}/login/access-token", auto_error=False) TokenDep = Annotated[str | None, Depends(reusable_oauth2)] RequestUser = User | AnonymousUser async def get_current_user(token: TokenDep) -> User: credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) if token is None: raise credentials_exception try: payload = jwt.decode(token, settings.secret_key, algorithms=[security.ALGORITHM]) token_data = TokenPayload(**payload) except (JWTError, ValidationError, AttributeError): raise credentials_exception user = await User.filter(username=token_data.sub).first() if user is None: raise credentials_exception return user LoggedInUser = Annotated[User, Depends(get_current_user)] async def get_request_user(token: TokenDep) -> RequestUser: if not token: return AnonymousUser() try: user = await get_current_user(token) except HTTPException: return AnonymousUser() return user CurrentRequestUser = Annotated[RequestUser, Depends(get_request_user)] def query_params(q: str | None = None, page: int = 1, limit: int = 10, order: str | None = None) -> PaginationParams: page -= 1 if page < 0: page = 0 if limit < 0: limit = 1 if limit > 250: limit = 250 _l.info(f"Filtering by: {q=}, {page=}, {limit=} | Ordering by: {order}") return PaginationParams(q=q, offset=page * limit, limit=limit, order=order) QueryParams = Annotated[PaginationParams, Depends(query_params)]