import uuid from fastapi import APIRouter, Depends, HTTPException, status from sqlmodel import Session, select from app.database import get_session from app.models.user import User from app.schemas.user import ( UserCreate, UserRead, LoginRequest, TokenResponse, RefreshRequest, ) from app.auth.jwt import ( hash_password, verify_password, create_access_token, create_refresh_token, decode_token, ) router = APIRouter(prefix="/auth", tags=["auth"]) @router.post("/register", response_model=UserRead, status_code=status.HTTP_201_CREATED) def register(body: UserCreate, session: Session = Depends(get_session)): # Check username uniqueness existing = session.exec(select(User).where(User.username == body.username)).first() if existing: raise HTTPException(status_code=400, detail="Username already taken") # Check email uniqueness existing = session.exec(select(User).where(User.email == body.email)).first() if existing: raise HTTPException(status_code=400, detail="Email already registered") user = User( username=body.username, email=body.email, password_hash=hash_password(body.password), ) session.add(user) session.commit() session.refresh(user) return user @router.post("/login", response_model=TokenResponse) def login(body: LoginRequest, session: Session = Depends(get_session)): user = session.exec(select(User).where(User.username == body.username)).first() if not user or not verify_password(body.password, user.password_hash): raise HTTPException(status_code=401, detail="Invalid credentials") access_token = create_access_token({"sub": str(user.id)}) refresh_token = create_refresh_token({"sub": str(user.id)}) return TokenResponse(access_token=access_token, refresh_token=refresh_token) @router.post("/refresh", response_model=TokenResponse) def refresh(body: RefreshRequest, session: Session = Depends(get_session)): try: payload = decode_token(body.refresh_token) if payload.get("type") != "refresh": raise HTTPException(status_code=401, detail="Invalid token type") user_id = uuid.UUID(payload["sub"]) except Exception: raise HTTPException(status_code=401, detail="Invalid refresh token") user = session.get(User, user_id) if not user: raise HTTPException(status_code=401, detail="User not found") access_token = create_access_token({"sub": str(user.id)}) refresh_token = create_refresh_token({"sub": str(user.id)}) return TokenResponse(access_token=access_token, refresh_token=refresh_token)