feat: Phase 0 – Gerüst (FastAPI+SQLite, Multi-User-Login, React-App-Shell, Deploy)

Grundgerüst für Certain Finance:
- Backend: FastAPI + SQLAlchemy + SQLite, Alembic-Migrationen (Batch-Mode),
  argon2-Passwort-Hashing, server-seitige Sitzungen im Cookie, Erst-Admin,
  Benutzerverwaltung mit Temporär-Passwort, Einstellungen je Benutzer.
- Ein Prozess, ein Port: uvicorn liefert API (/api) und gebautes SPA aus,
  inkl. SPA-Deeplink-Fallback.
- Frontend: React 18 + Vite + JSX, Design-Tokens (Light/Dark), i18n DE/EN,
  Inline-SVG-Icons (keine Emojis), Login, Passwort-ändern, Dashboard-Platzhalter,
  Benutzer- und Einstellungsseiten.
- Deploy: nativer LXC-Installer + Update-Skript (systemd), env-Vorlage, Doku.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-08-19 18:27:42 +02:00
co-authored by Claude Opus 4.8
commit 2c795a57c8
59 changed files with 6419 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
"""Konfiguration über Umgebungsvariablen (Präfix ``APP_``).
Beispiel: ``APP_DATA_DIR=/var/lib/certain-finance`` setzt ``data_dir``.
Die Standardwerte sind bewusst entwicklungsfreundlich (relatives Datenverzeichnis,
unsichere Cookies erlaubt). Für den Produktivbetrieb setzt das Install-Skript die
sicheren Werte in ``/etc/certain-finance/env`` (siehe ``deploy/env.example``).
"""
from functools import lru_cache
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_prefix="APP_", env_file=".env", extra="ignore")
# --- Ablageort für Datenbank und Backups ---------------------------------
# Produktiv per Env auf einen absoluten Pfad setzen (z. B. /var/lib/...).
data_dir: str = "./data"
# Leer = SQLite-Datei unter data_dir/app.db. Sonst vollständige URL.
database_url: str = ""
# --- Sitzungen / Cookies -------------------------------------------------
session_secret: str = "change-me-in-production"
session_ttl_days: int = 30
cookie_name: str = "cf_session"
# Standard False, damit die Anmeldung auch über http://localhost im Dev
# funktioniert. Produktiv hinter HTTPS (Nginx Proxy Manager) auf true setzen.
cookie_secure: bool = False
cookie_samesite: str = "lax"
# --- Erster Admin, nur beim allerersten Start angelegt -------------------
admin_username: str = "admin"
admin_password: str = "changeme"
# --- Währung -------------------------------------------------------------
default_base_currency: str = "EUR"
# Beim Start die aktuellen EZB-Kurse nachladen (benötigt Internet).
ecb_fetch_on_start: bool = True
# --- CORS ----------------------------------------------------------------
# Leer = kein Cross-Origin (gleiche Herkunft, da FastAPI das SPA selbst
# ausliefert). Kommagetrennte Liste oder "*" nur bei Bedarf.
cors_origins: str = ""
@property
def effective_database_url(self) -> str:
if self.database_url:
return self.database_url
return f"sqlite:///{self.data_dir.rstrip('/')}/app.db"
@lru_cache
def get_settings() -> Settings:
return Settings()