from datetime import timedelta from typing import Any from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy.orm import Session from app.api import deps from app.db.session import get_db from app.models.user import User from app.schemas.user import Token, UserLogin, User as UserSchema from app.services.auth import ( authenticate_user, create_access_token, get_user_by_username, get_user_by_email, create_user as create_user_service, ) from app.schemas.user import UserCreate from app.core.config import settings router = APIRouter() @router.post("/login", response_model=Token) def login_for_access_token( db: Session = Depends(get_db), form_data: OAuth2PasswordRequestForm = Depends() ) -> Any: """ OAuth2 compatible token login, get an access token for future requests. """ user = authenticate_user(db, form_data.username, form_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) return { "access_token": create_access_token( user.username, expires_delta=access_token_expires ), "token_type": "bearer", } @router.post("/login/json", response_model=Token) def login_json( db: Session = Depends(get_db), user_login: UserLogin = None ) -> Any: """ JSON login endpoint. """ user = authenticate_user(db, user_login.username, user_login.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) return { "access_token": create_access_token( user.username, expires_delta=access_token_expires ), "token_type": "bearer", } @router.get("/me", response_model=UserSchema) def read_users_me( current_user: User = Depends(deps.get_current_active_user), ) -> Any: """ Get current user. """ return current_user @router.post("/register", response_model=UserSchema) def register_user( *, db: Session = Depends(get_db), user_in: UserCreate, ) -> Any: """ Register a new user. """ # Check if user already exists user = get_user_by_username(db, username=user_in.username) if user: raise HTTPException( status_code=400, detail="The user with this username already exists in the system.", ) user = get_user_by_email(db, email=user_in.email) if user: raise HTTPException( status_code=400, detail="The user with this email already exists in the system.", ) user = create_user_service(db, user_in) return user