first round of review

This commit is contained in:
counterweight 2025-12-18 22:24:46 +01:00
parent 7ebfb7a2dd
commit da5a0d03eb
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
14 changed files with 362 additions and 244 deletions

View file

@ -1,5 +1,5 @@
from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi import FastAPI, Depends, HTTPException, Response, status
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
@ -7,10 +7,11 @@ from sqlalchemy.ext.asyncio import AsyncSession
from database import engine, get_db, Base
from models import Counter, User
from auth import (
ACCESS_TOKEN_EXPIRE_MINUTES,
COOKIE_NAME,
UserCreate,
UserLogin,
UserResponse,
TokenResponse,
get_password_hash,
get_user_by_email,
authenticate_user,
@ -37,9 +38,24 @@ app.add_middleware(
)
def set_auth_cookie(response: Response, token: str) -> None:
response.set_cookie(
key=COOKIE_NAME,
value=token,
httponly=True,
secure=False, # Set to True in production with HTTPS
samesite="lax",
max_age=ACCESS_TOKEN_EXPIRE_MINUTES * 60,
)
# Auth endpoints
@app.post("/api/auth/register", response_model=TokenResponse)
async def register(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
@app.post("/api/auth/register", response_model=UserResponse)
async def register(
user_data: UserCreate,
response: Response,
db: AsyncSession = Depends(get_db),
):
existing_user = await get_user_by_email(db, user_data.email)
if existing_user:
raise HTTPException(
@ -56,15 +72,16 @@ async def register(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
await db.refresh(user)
access_token = create_access_token(data={"sub": str(user.id)})
return TokenResponse(
access_token=access_token,
token_type="bearer",
user=UserResponse(id=user.id, email=user.email),
)
set_auth_cookie(response, access_token)
return UserResponse(id=user.id, email=user.email)
@app.post("/api/auth/login", response_model=TokenResponse)
async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db)):
@app.post("/api/auth/login", response_model=UserResponse)
async def login(
user_data: UserLogin,
response: Response,
db: AsyncSession = Depends(get_db),
):
user = await authenticate_user(db, user_data.email, user_data.password)
if not user:
raise HTTPException(
@ -73,11 +90,14 @@ async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db)):
)
access_token = create_access_token(data={"sub": str(user.id)})
return TokenResponse(
access_token=access_token,
token_type="bearer",
user=UserResponse(id=user.id, email=user.email),
)
set_auth_cookie(response, access_token)
return UserResponse(id=user.id, email=user.email)
@app.post("/api/auth/logout")
async def logout(response: Response):
response.delete_cookie(key=COOKIE_NAME)
return {"ok": True}
@app.get("/api/auth/me", response_model=UserResponse)