arbret/backend/main.py
2025-12-18 22:08:31 +01:00

118 lines
3.3 KiB
Python

from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database import engine, get_db, Base
from models import Counter, User
from auth import (
UserCreate,
UserLogin,
UserResponse,
TokenResponse,
get_password_hash,
get_user_by_email,
authenticate_user,
create_access_token,
get_current_user,
)
@asynccontextmanager
async def lifespan(app: FastAPI):
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
app = FastAPI(lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_methods=["*"],
allow_headers=["*"],
allow_credentials=True,
)
# Auth endpoints
@app.post("/api/auth/register", response_model=TokenResponse)
async def register(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
existing_user = await get_user_by_email(db, user_data.email)
if existing_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered",
)
user = User(
email=user_data.email,
hashed_password=get_password_hash(user_data.password),
)
db.add(user)
await db.commit()
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),
)
@app.post("/api/auth/login", response_model=TokenResponse)
async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db)):
user = await authenticate_user(db, user_data.email, user_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect email or password",
)
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),
)
@app.get("/api/auth/me", response_model=UserResponse)
async def get_me(current_user: User = Depends(get_current_user)):
return UserResponse(id=current_user.id, email=current_user.email)
# Counter endpoints
async def get_or_create_counter(db: AsyncSession) -> Counter:
result = await db.execute(select(Counter).where(Counter.id == 1))
counter = result.scalar_one_or_none()
if not counter:
counter = Counter(id=1, value=0)
db.add(counter)
await db.commit()
await db.refresh(counter)
return counter
@app.get("/api/counter")
async def get_counter(
db: AsyncSession = Depends(get_db),
_current_user: User = Depends(get_current_user),
):
counter = await get_or_create_counter(db)
return {"value": counter.value}
@app.post("/api/counter/increment")
async def increment_counter(
db: AsyncSession = Depends(get_db),
_current_user: User = Depends(get_current_user),
):
counter = await get_or_create_counter(db)
counter.value += 1
await db.commit()
return {"value": counter.value}