I have service ( UserService) where i store all functionality connected to user. How can I use service method like async def get_current_user
as a dependency, in my router function?
from typing import Annotated
from passlib.context import CryptContext
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from src.auth.schemas import UserInDTO
from src.auth.models import User
from src.auth.messages import errors
from src.auth.services.token_service import TokenService
from src.auth.repositories.user_repository import UserRepository
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="users/token")
class UserService:
def __init__(self, repository: UserRepository = Depends()) -> None:
self.repository = repository
async def register_user(self, user: UserInDTO) -> User:
if await self.get_user_by_email(email=user.email):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=errors.USER_EMAIL_ALREADY_EXISTS
)
user.hashed_password = self.hash_password(user.hashed_password)
return await self.repository.create(User(**user.model_dump()))
async def get_current_user(
self,
token: Annotated[str, Depends(oauth2_scheme)],
token_service: TokenService = Depends(),
) -> User:
token_data = token_service.verify_token(token=token)
email = token_data.email
user = await self.get_user_by_email(email=email)
if not email or not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
return user
async def authenticate_user(self, email: str, password: str) -> User | HTTPException:
user = await self.get_user_by_email(email=email)
if not user or not self.verify_password(plain_password=password, hashed_password=user.hashed_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=errors.USER_INCORECT_CREDENTIALS,
headers={"WWW-Authenticate": "Bearer"},
)
return user
async def get_user_by_email(self, email: str) -> User:
return await self.repository.get(identifier=email)
def verify_password(self, plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
def hash_password(self, plain_password: str) -> str:
return pwd_context.hash(plain_password)
I try create specific file for dependencies where i put something like this:
def get_current_user(user_service: UserService = Depends()) -> User:
return user_service.get_current_user
and then in my router function
@router.get("me/")
def test_me(user: Annotated\[UserOutDTO, Depends(get_current_user)\]):
return user
Result:
{'type': 'model_attributes_type', 'loc': ('response',), 'msg': 'Input should be a valid dictionary or object to extract fields from', 'input': \<bound method UserService.get_current_user of \<src.auth.services.user_ser
vice.UserService object at 0x7f2ddd603ed0\>\>, 'url': 'https://errors.pydantic.dev/2.5/v/model_attributes_type'}