from fastapi import APIRouter, Depends, HTTPException, Request, Response from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from ..core.authx import auth from ..core.db import get_db from ..core.security import hash_password, verify_password from ..models.users import User from ..schemas.user_schema import UserCreate, UserLogin, UserRead router = APIRouter(prefix="/auth", tags=["auth"]) @router.post("/register", response_model=UserRead, status_code=201) async def register( data: UserCreate, response: Response, db: AsyncSession = Depends(get_db), # noqa: B008 ): existing = await db.execute(select(User).where(User.username == data.username)) if existing.scalar_one_or_none(): raise HTTPException(400, "Username already taken") user = User( username=data.username, hashed_password=hash_password(data.password), isAdmin=False, ) db.add(user) await db.commit() await db.refresh(user) access = auth.create_access_token(uid=user.username) refresh = auth.create_refresh_token(uid=user.username) auth.set_access_cookies(access, response) auth.set_refresh_cookies(refresh, response) return user @router.post("/login", response_model=UserRead) async def login( data: UserLogin, response: Response, db: AsyncSession = Depends(get_db), # noqa: B008 ): result = await db.execute(select(User).where(User.username == data.username)) user = result.scalar_one_or_none() if not user or not verify_password(data.password, user.hashed_password): raise HTTPException(401, "Invalid credentials") access = auth.create_access_token(uid=user.username) refresh = auth.create_refresh_token(uid=user.username) auth.set_access_cookies(access, response) auth.set_refresh_cookies(refresh, response) return user @router.post("/refresh") async def refresh( request: Request, response: Response, db: AsyncSession = Depends(get_db), # noqa: B008 ): payload = await auth.get_refresh_token_from_request(request) result = await db.execute(select(User).where(User.username == payload.sub)) user = result.scalar_one_or_none() if not user: raise HTTPException(401, "User not found") new_access = auth.create_access_token(uid=user.username) auth.set_access_cookies(new_access, response) return {"status": "ok"} @router.post("/logout") async def logout(response: Response): auth.unset_cookies(response) return {"status": "ok"}