""" Tool_OCR - Authentication Router JWT login endpoint """ from datetime import timedelta import logging from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.core.config import settings from app.core.deps import get_db from app.core.security import verify_password, create_access_token from app.models.user import User from app.schemas.auth import LoginRequest, Token logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/v1/auth", tags=["Authentication"]) @router.post("/login", response_model=Token, summary="User login") async def login( login_data: LoginRequest, db: Session = Depends(get_db) ): """ User login with username and password Returns JWT access token for authentication - **username**: User's username - **password**: User's password """ # Query user by username user = db.query(User).filter(User.username == login_data.username).first() # Verify user exists and password is correct if not user or not verify_password(login_data.password, user.password_hash): logger.warning(f"Failed login attempt for username: {login_data.username}") raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) # Check if user is active if not user.is_active: logger.warning(f"Inactive user login attempt: {login_data.username}") raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="User account is inactive" ) # Create access token access_token_expires = timedelta(minutes=settings.access_token_expire_minutes) access_token = create_access_token( data={"sub": str(user.id), "username": user.username}, expires_delta=access_token_expires ) logger.info(f"Successful login: {user.username} (ID: {user.id})") return { "access_token": access_token, "token_type": "bearer", "expires_in": settings.access_token_expire_minutes * 60 # Convert to seconds }