from typing import Annotated import bcrypt from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from fastapi_limiter.depends import RateLimiter from psycopg_pool import AsyncConnectionPool from src.neo_neo_todo.models.member import select_member_by_email from src.neo_neo_todo.utils.database import get_pool router = APIRouter( prefix="/token", tags=["token"], ) @router.post( "", dependencies=[ Depends(RateLimiter(times=100, seconds=600)) ], # rate limit login route status_code=status.HTTP_200_OK, # default status code when login successful ) async def login( form_data: Annotated[OAuth2PasswordRequestForm, Depends()], db_pool: AsyncConnectionPool = Depends(get_pool), ): """ Login to the todo app If successful, save the returned cookie """ member = await select_member_by_email(db_pool, form_data.username) if member is None: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect email or password", ) passwords_match = bcrypt.checkpw( form_data.password.encode("utf-8"), member.password_hash.encode("utf-8"), ) if passwords_match: # to handle login logic here pass else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect email or password", ) return {"access_token": member.email, "token_type": "bearer"}