from datetime import timedelta from fastapi.security import OAuth2PasswordRequestForm from fastapi import APIRouter, Depends, HTTPException, status import pymongo import app.config as config from app.models import User, Token, HTTPError from app.dto import UserRegisterDTO from app.serializers import user_serialize from app.utils import get_current_user, create_access_token, get_password_hash, verify_password # Database setup client = pymongo.MongoClient(config.MONGODB_URL, username=config.MONGODB_USERNAME, password=config.MONGODB_PASSWORD) db = client[config.MONGODB_DATABASE] users_collection = db["users"] auth_router = APIRouter( tags=["Auth"] ) @auth_router.post( path="/register", response_model=Token, responses={409: {"model": HTTPError}} ) async def register(user: UserRegisterDTO): user_exists = users_collection.find_one({"username": user.username}) if user_exists: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Username already used" ) hashed_password = get_password_hash(user.password) user_id = users_collection.insert_one({"username": user.username, "password": hashed_password}) access_token_expires = timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token(data={"sub": user.username}, expires_delta=access_token_expires) return {"access_token": access_token, "token_type": "bearer", "user_id": str(user_id.inserted_id)} @auth_router.post( path="/login", response_model=Token, responses={401: {"model": HTTPError}} ) async def login(form_data: OAuth2PasswordRequestForm = Depends()): user = users_collection.find_one({"username": form_data.username}) if not user or not verify_password(form_data.password, user["password"]): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) access_token_expires = timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token(data={"sub": form_data.username}, expires_delta=access_token_expires) return {"access_token": access_token, "token_type": "bearer", "user_id": str(user["_id"])} @auth_router.get( path="/logout", responses={401: {"model": HTTPError}} ) async def logout(current_user: User = Depends(get_current_user)): return {"message": "Logged out"}