I'm working on fastapi web app and currently strugling with one thing.
I'm working on google auth system and my dependency injection does not work as expected.
Here are my endpoints:
@app.route('/login')
async def login(request: Request):
redirect_uri = request.url_for('auth')
return await oauth.google.authorize_redirect(request, redirect_uri)
@app.route('/auth')
async def auth(request: Request):
try:
access_token = await oauth.google.authorize_access_token(request)
except OAuthError as e:
raise CREDENTIALS_EXCEPTION
_data = access_token["userinfo"]
if get_or_create_user(data = _data):
return JSONResponse({'result': True, 'access_token': create_token(_data['email'])})
raise CREDENTIALS_EXCEPTION
The problem lies in get_or_create_user
function.
@validate_payload
def get_or_create_user(data: USER_GOOGLE_DATA, users_repo: UsersRepository = Depends(SQLUsersRepository)) -> model.User:
_email: str = data.get("email")
if not _email:
raise AttributeError("Payload is missing data")
user: model.User = users_repo.get_by_email(email=_email)
if not user:
_user = model.User(**dict(data))
user = users_repo.add(model.User(_user))
return user
data
is dict with required info to create user and users_repo
is crud class. Decorator is just to check if data
contains all required keys.
PAYLOAD_KEYS: Tuple[str] = ("email",)
def validate_payload(func: Callable[[USER_GOOGLE_DATA, UsersRepository], model.User]):
def decorator(*args, **kwargs):
_data: USER_GOOGLE_DATA = kwargs.get("data")
for _key in PAYLOAD_KEYS:
if _key not in _data:
return None
return func(_data)
return decorator
My crud class looks like following:
class SQLUsersRepository(input_boundries.UsersRepository):
def __init__(self, db: Session or RawDBConnection = Depends(get_db)):
self._db = db
def get(self, user_id: UserId) -> model.User:
user_db = self._db.query(model.User).filter(model.User.id == user_id).first()
if not user_db:
raise DBRecordNotFound(f"User with id: '{user_id}' not found.")
return user_db
def get_by_email(self, email: str) -> model.User:
user_db = self._db.query(model.User).filter(model.User.email == email).first()
if not user_db:
raise DBRecordNotFound(f"User with email: '{email}' not found.")
return user_db
def add(self, user: model.User) -> model.User:
self._db.add(user)
self._db.commit()
self._db.refresh(user)
return user
def save(self, user: model.User) -> None:
user_db = self._db.query(model.User).filter(model.User.id == user.id).first()
self.add(user=user_db)
def remove(self, user_id: UserId) -> None:
user_db = self._db.query(model.User).filter(model.User.id == user_id).first()
if not user_db:
raise DBRecordNotFound(f"User with id: '{user_id}' not found.")
user_db.delete()
self._db.commit()
The error I receive AttributeError: 'Depends' object has no attribute 'get_by_email'
What's wrong with these dependiences? As far as I remember Depends() works similar to decorator (it triggers first).