first commit

This commit is contained in:
Mateusz Gruszczyński
2026-03-04 15:21:03 +01:00
commit 5429f176c9
53 changed files with 3808 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
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)