from datetime import datetime, timedelta from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jose import jwt from pydantic import BaseModel from sqlalchemy.orm import Session from ..config import Config from ..db import Connection, schemas router = APIRouter(prefix="/user") SCHEME = OAuth2PasswordBearer( tokenUrl=f".{router.prefix}/token", ) class Token(BaseModel): access_token: str token_type: str def create_access_token( data: dict, expires_delta: timedelta | None = None, config: Config = Depends(Config.get), ): to_encode = data.copy() if expires_delta is None: expires_delta = timedelta(minutes=15) to_encode.update({"exp": datetime.utcnow() + expires_delta}) return jwt.encode( to_encode, config.jwt.secret, algorithm=config.jwt.hash_algorithm, ) @router.post("/auth", response_model=Token) async def login( form_data: OAuth2PasswordRequestForm = Depends(), config: Config = Depends(Config.get), db: Session = Depends(Connection.get), ): credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) user = schemas.User.get(db, form_data.username) if user is None: config.crypt_context.dummy_verify() raise credentials_exception if not user.verify(form_data.password): raise credentials_exception access_token = create_access_token( data={"sub": user.name}, expires_delta=timedelta(minutes=config.jwt.expiry_minutes), ) return {"access_token": access_token, "token_type": "bearer"}