from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from core.security import create_access_token, hash_password, verify_password from database.models import User from database.session import get_db from schemas.user import TokenResponse, UserLoginRequest, UserRegisterRequest, UserResponse router = APIRouter(prefix="/api/auth", tags=["auth"]) @router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def register(body: UserRegisterRequest, db: AsyncSession = Depends(get_db)) -> User: result = await db.execute(select(User).where(User.email == body.email)) if result.scalar_one_or_none() is not None: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="User with this email already exists", ) user = User(email=body.email, hashed_password=hash_password(body.password)) db.add(user) await db.commit() await db.refresh(user) return user @router.post("/login", response_model=TokenResponse) async def login(body: UserLoginRequest, db: AsyncSession = Depends(get_db)) -> TokenResponse: result = await db.execute(select(User).where(User.email == body.email)) user: User | None = result.scalar_one_or_none() if user is None or not verify_password(body.password, user.hashed_password): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid email or password", headers={"WWW-Authenticate": "Bearer"}, ) return TokenResponse(access_token=create_access_token(subject=user.id))