from fastapi import APIRouter, Depends, Response, HTTPException, Request from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.api.deps import db_session, get_current_user from app.core.config import settings from app.core.security import ( verify_password, create_session_token, new_csrf_token, SESSION_COOKIE, CSRF_COOKIE ) from app.models.user import User from app.schemas.user import LoginIn, UserOut router = APIRouter() @router.post("/login") async def login(payload: LoginIn, response: Response, session: AsyncSession = Depends(db_session)): res = await session.execute(select(User).where(User.email == payload.email)) user = res.scalar_one_or_none() if not user or not verify_password(payload.password, user.password_hash): raise HTTPException(status_code=401, detail="Bad credentials") if not user.is_active: raise HTTPException(status_code=403, detail="Inactive") token = create_session_token(user.id) csrf = new_csrf_token() response.set_cookie( key=SESSION_COOKIE, value=token, httponly=True, secure=settings.COOKIE_SECURE, samesite=settings.COOKIE_SAMESITE, max_age=60 * 60 * 24 * 7, path="/", ) # CSRF token czytelny dla JS (nie httponly) response.set_cookie( key=CSRF_COOKIE, value=csrf, httponly=False, secure=settings.COOKIE_SECURE, samesite=settings.COOKIE_SAMESITE, max_age=60 * 60 * 24 * 7, path="/", ) return {"ok": True} @router.post("/logout") async def logout(response: Response): response.delete_cookie(SESSION_COOKIE, path="/") response.delete_cookie(CSRF_COOKIE, path="/") return {"ok": True} @router.get("/me", response_model=UserOut) async def me(user: User = Depends(get_current_user)): return UserOut(id=user.id, email=user.email, role=user.role)