Files
wiki-tcg/backend/main.py
Nikolaj 65b719334f 🐐
2026-03-16 14:01:22 +01:00

85 lines
2.8 KiB
Python

import asyncio
import logging
import uuid
from contextlib import asynccontextmanager
from sqlalchemy.orm import Session
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from database import SessionLocal, get_db
from database_functions import fill_card_pool
from models import Card as CardModel
from models import User as UserModel
from card import _get_cards_async
from auth import hash_password, verify_password, create_access_token, decode_access_token
logger = logging.getLogger("app")
# Auth
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
class RegisterRequest(BaseModel):
username: str
email: str
password: str
def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)) -> UserModel:
user_id = decode_access_token(token)
if not user_id:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
user = db.query(UserModel).filter(UserModel.id == uuid.UUID(user_id)).first()
if not user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="User not found")
return user
@asynccontextmanager
async def lifespan(app: FastAPI):
asyncio.create_task(fill_card_pool())
yield
app = FastAPI(lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173"], # SvelteKit's default dev port
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/pack/{size}")
async def open_pack(size: int = 10, user: UserModel = Depends(get_current_user)):
cards = await _get_cards_async(size)
return [
{**card._asdict(),
"card_type": card.card_type.name,
"card_rarity": card.card_rarity.name}
for card in cards
]
@app.post("/register")
def register(req: RegisterRequest, db: Session = Depends(get_db)):
if db.query(UserModel).filter(UserModel.username == req.username).first():
raise HTTPException(status_code=400, detail="Username already taken")
if db.query(UserModel).filter(UserModel.email == req.email).first():
raise HTTPException(status_code=400, detail="Email already registered")
user = UserModel(
id=uuid.uuid4(),
username=req.username,
email=req.email,
password_hash=hash_password(req.password),
)
db.add(user)
db.commit()
return {"message": "User created"}
@app.post("/login")
def login(form: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
user = db.query(UserModel).filter(UserModel.username == form.username).first()
if not user or not verify_password(form.password, user.password_hash):
raise HTTPException(status_code=400, detail="Invalid username or password")
token = create_access_token(str(user.id))
return {"access_token": token, "token_type": "bearer"}