from fastapi import APIRouter, Depends, HTTPException, status, Request from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from datetime import timedelta from jose import jwt, JWTError from app.core.database import get_db from app.core import security from app.core.config import settings from app.crud import crud from app.schemas import schemas from app.models import models router = APIRouter() @router.post("/login", response_model=schemas.Token) def login( request: Request, form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db) ): user = crud.get_user_by_email(db, email=form_data.username) if not user or not crud.verify_password(form_data.password, user.hashed_password): # Log failed login attempt crud.create_audit_log( db=db, user_id=None, action="Failed Login Attempt", ip_address=request.client.host if request.client else None, user_agent=request.headers.get("user-agent"), details=f"Attempted email: {form_data.username}" ) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect email or password", ) if not user.is_active: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Inactive user account" ) access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) access_token = security.create_access_token( user.email, role=user.role.name, expires_delta=access_token_expires ) refresh_token = security.create_refresh_token( user.email, role=user.role.name ) # Audit log login crud.create_audit_log( db=db, user_id=user.id, action="User Login", ip_address=request.client.host if request.client else None, user_agent=request.headers.get("user-agent"), details=f"Successful login for user email {user.email}" ) return { "access_token": access_token, "refresh_token": refresh_token, "token_type": "bearer" } @router.post("/refresh", response_model=schemas.Token) def refresh_token( refresh_token: str, db: Session = Depends(get_db) ): credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate refresh token", ) try: payload = jwt.decode( refresh_token, settings.JWT_SECRET_KEY, algorithms=[settings.JWT_ALGORITHM] ) email: str = payload.get("sub") token_type: str = payload.get("type") if email is None or token_type != "refresh": raise credentials_exception except JWTError: raise credentials_exception user = crud.get_user_by_email(db, email=email) if user is None or not user.is_active: raise credentials_exception access_token = security.create_access_token( user.email, role=user.role.name ) new_refresh_token = security.create_refresh_token( user.email, role=user.role.name ) return { "access_token": access_token, "refresh_token": new_refresh_token, "token_type": "bearer" } @router.get("/me", response_model=schemas.UserOut) def read_users_me( current_user: models.User = Depends(security.get_current_user) ): return current_user