teecup/app/main.py
Erol Haagenrud 885dcac4e5 Slag-for-slag GPS-avstandsmåling for org-turneringer (ADR-103)
Ny tournament_round_shot-tabell (org-scopet RLS, FK-et til
tournament_round_participant + hole_number siden tournament_round_hole
kanskje ikke finnes ennå). ShotMeasurementSheet/MapPointPicker gjenbrukt
uendret; ShotMeasurementEntry generalisert fra en lokal round-detail.tsx-
funksjon til en delt, URL-parameterisert komponent. Deling går til den
rundespesifikke kommentartråden (ADR-102) i stedet for Banter Board.
Autorisasjon speiler update_hole (self/org-admin), strengere enn ADR-102s
kommentar-nivå.

Migrasjon 091 IKKE kjørt mot ekte teecup_db ennå -- venter på
brukerbekreftelse før utrulling.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 07:16:14 +02:00

80 lines
2.1 KiB
Python

"""
TeeCup API.
App-factory + livssyklus. All forretningslogikk ligger i app/routers/ — hver
rute der følger samme mønster: Depends(get_authorized_org) verifiserer
medlemskap, org_connection(organization_id) setter RLS-konteksten lokalt for
transaksjonen. Se ARCHITECTURE_DECISIONS.md (ADR-001…014) for reglene bak.
Kjøres i app-containeren (FastAPI + asyncpg + uvicorn):
uvicorn app.main:app --host 0.0.0.0 --port 8000
"""
from contextlib import asynccontextmanager
from fastapi import FastAPI
from .db import init_pool, close_pool
from .routers import (
account_merge,
auth,
courses,
friends,
individual_tournaments,
matches,
messaging,
notifications,
order_of_merit,
organizations,
players,
print_pdf,
registration,
round_messages,
rounds,
scoring,
tournament_round_messages,
tournament_round_shots,
tournaments,
)
from . import storage
@asynccontextmanager
async def lifespan(app: FastAPI):
await init_pool()
await storage.ensure_bucket()
try:
yield
finally:
await close_pool()
app = FastAPI(title="TeeCup API", lifespan=lifespan)
app.include_router(auth.router)
app.include_router(account_merge.router)
app.include_router(organizations.router)
app.include_router(players.router)
app.include_router(courses.router)
app.include_router(tournaments.router)
app.include_router(individual_tournaments.router)
app.include_router(order_of_merit.router)
app.include_router(order_of_merit.public_router)
app.include_router(matches.router)
app.include_router(scoring.router)
app.include_router(registration.router)
app.include_router(registration.org_router)
app.include_router(messaging.router)
app.include_router(messaging.public_router)
app.include_router(rounds.router)
app.include_router(round_messages.router)
app.include_router(tournament_round_messages.router)
app.include_router(tournament_round_shots.router)
app.include_router(friends.router)
app.include_router(notifications.router)
app.include_router(print_pdf.router)
@app.get("/health")
async def health() -> dict[str, str]:
return {"status": "ok"}