feat(api): Core-API mit Authentifizierung, CRUD und Monatsreport
- Anmeldung über Argon2id und JWT in httpOnly-Cookies, Refresh mit echter Rotation über die neue Tabelle refresh_token - AuthProvider-Protokoll als Vorbereitung für OIDC, Administrator-Anlage beim Erststart mit erzwungenem Passwortwechsel - CRUD für Konten, Kategorien (zweistufiger Baum), Firmen, Recurrences, Preisversionen, Buchungen, Budgets, Vorlagen und Sparziele - Fälligkeiten mit Overlay-Logik: abrufen, bestätigen, auslassen, zurücksetzen - Kontosalden zum Stichtag, Monatsübersicht mit Plan-Ist-Vergleich - SECRET_KEY jetzt mindestens 32 Zeichen; Platzhalter in Produktion abgelehnt - 61 neue Integrationstests, insgesamt 148 grün Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
This commit is contained in:
@@ -10,6 +10,8 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from app.api.router import api_router
|
||||
from app.core.config import settings
|
||||
from app.core.errors import register_exception_handlers
|
||||
from app.db.session import SessionLocal, engine
|
||||
from app.services.auth import ensure_admin_user, purge_expired_refresh_tokens
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG if settings.debug else logging.INFO,
|
||||
@@ -22,11 +24,30 @@ logger = logging.getLogger("moneyfy")
|
||||
async def lifespan(_: FastAPI) -> AsyncGenerator[None, None]:
|
||||
"""Start- und Stopplogik der Anwendung."""
|
||||
settings.logo_storage_dir.mkdir(parents=True, exist_ok=True)
|
||||
await _bootstrap()
|
||||
logger.info("moneyfy %s gestartet (%s)", settings.app_version, settings.environment)
|
||||
yield
|
||||
await engine.dispose()
|
||||
logger.info("moneyfy wird beendet")
|
||||
|
||||
|
||||
async def _bootstrap() -> None:
|
||||
"""Erststart: Administrator anlegen und abgelaufene Sitzungen aufräumen.
|
||||
|
||||
Fehler werden protokolliert, beenden die Anwendung aber nicht – der
|
||||
Health-Check meldet eine nicht erreichbare Datenbank ohnehin.
|
||||
"""
|
||||
try:
|
||||
async with SessionLocal() as session:
|
||||
await ensure_admin_user(session)
|
||||
removed = await purge_expired_refresh_tokens(session)
|
||||
await session.commit()
|
||||
if removed:
|
||||
logger.info("%d abgelaufene Sitzungen entfernt.", removed)
|
||||
except Exception:
|
||||
logger.exception("Start-Initialisierung fehlgeschlagen.")
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
app = FastAPI(
|
||||
title="moneyfy",
|
||||
|
||||
Reference in New Issue
Block a user