from fastapi import APIRouter, HTTPException, Request from lib.db import get_connection from models.user import User, UserLogin from lib.helpers import verify_password from lib.logger import logger router = APIRouter(prefix="/auth", tags=["auth"]) @router.post("/token", response_model=User) async def login(user_login: UserLogin, request: Request): logger.debug( f"Login attempt for user: {user_login.username} from IP: {request.client.host}" ) with get_connection() as conn: user_df = conn.execute( 'SELECT * FROM "User" WHERE username = ?', (user_login.username,) ).fetchdf() if user_df.empty: logger.warning( f"Failed login: Username {user_login.username} not found - IP: {request.client.host}" ) raise HTTPException(status_code=401, detail="Invalid username or password") user_data = user_df.to_dict(orient="records")[0] if not verify_password(user_login.password, user_data["hashed_password"]): logger.warning( f"Failed login: Incorrect password for user {user_login.username} - IP: {request.client.host}" ) raise HTTPException(status_code=401, detail="Invalid username or password") # Update the login timestamp in the database with get_connection() as conn: conn.execute( 'UPDATE "User" SET last_login = CURRENT_TIMESTAMP WHERE id = ?', (user_data["id"],), ) # Fetch the updated user data with the new last_login timestamp updated_user = ( conn.execute('SELECT * FROM "User" WHERE id = ?', (user_data["id"],)) .fetchdf() .to_dict(orient="records")[0] ) logger.info( f"Successful login: User {user_login.username} (ID: {user_data['id']}) logged in from {request.client.host}" ) return User(**updated_user)