| 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): |
| |
| 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 |
| ) |
| |
| |
| 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 |
|
|