- recipes/ai.py: Chat Completions with strict JSON schema (Structured Outputs), Pydantic re-validation, plausibility clamping, prompt treats input as data only - "Mit KI aufbereiten" on create/edit form returns an editable draft - Import page: photo/screenshot (vision, downscaled JPEG, not stored) and pasted text; drafts pre-fill the recipe form with a preview - Clear UI messages for timeout, rate limit, quota, auth, model and connection errors; without OPENAI_API_KEY AI features show a notice - Optional per-user and global daily AI limits (default unlimited) - Tests for response parsing, schema strictness, error mapping, views Co-Authored-By: Claude Opus 5.5 <[email protected]>
71 lines
2.8 KiB
Bash
71 lines
2.8 KiB
Bash
# Kopieren nach .env und anpassen: cp .env.example .env
|
|
# Pflichtwerte sind mit [PFLICHT] markiert.
|
|
|
|
# --- Allgemein ---------------------------------------------------------------
|
|
# [PFLICHT] Langer Zufallswert, z. B.: openssl rand -base64 48
|
|
SECRET_KEY=
|
|
# [PFLICHT] Öffentliche Adresse, wie sie im Browser steht (für Einladungslinks, CSRF, Hosts)
|
|
APP_BASE_URL=https://kochbuch.dammann.vip
|
|
# Zusätzliche erlaubte Hostnamen (kommagetrennt), z. B. für direkten LAN-Zugriff
|
|
ALLOWED_HOSTS=
|
|
TIME_ZONE=Europe/Berlin
|
|
# Nur für lokale Entwicklung auf true setzen
|
|
DEBUG=false
|
|
|
|
# --- Netzwerk / Reverse Proxy ------------------------------------------------
|
|
# Port auf dem Host, auf dem die App erreichbar ist (HTTP, ohne TLS)
|
|
APP_PORT=8000
|
|
# Adresse, an die der Port gebunden wird (127.0.0.1 = nur lokal, 0.0.0.0 = alle Interfaces)
|
|
APP_BIND_ADDRESS=0.0.0.0
|
|
# IPs/Netze (CIDR, kommagetrennt), deren X-Forwarded-For/-Proto-Header vertraut wird.
|
|
# Standard: private Netze. Am besten auf die IP deines Nginx eingrenzen.
|
|
TRUSTED_PROXIES=127.0.0.1/32,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
|
# Optional: Header mit der echten Client-IP, gesetzt von einem vertrauenswürdigen Proxy,
|
|
# z. B. CF-Connecting-IP bei Cloudflare. Leer = X-Forwarded-For auswerten.
|
|
CLIENT_IP_HEADER=
|
|
# Cookies nur über HTTPS senden. Nur für Tests ohne HTTPS auf false setzen.
|
|
COOKIE_SECURE=true
|
|
# HSTS-Dauer in Sekunden (0 = aus)
|
|
HSTS_SECONDS=31536000
|
|
|
|
# --- Erster Admin (wird beim Start angelegt, falls die E-Mail noch nicht existiert) ---
|
|
ADMIN_EMAIL=
|
|
ADMIN_PASSWORD=
|
|
ADMIN_NAME=Admin
|
|
|
|
# --- Datenbank ---------------------------------------------------------------
|
|
POSTGRES_DB=kochbuch
|
|
POSTGRES_USER=kochbuch
|
|
# [PFLICHT] z. B.: openssl rand -base64 32
|
|
POSTGRES_PASSWORD=
|
|
|
|
# --- Server-Ressourcen ---------------------------------------------------------
|
|
GUNICORN_WORKERS=2
|
|
GUNICORN_THREADS=4
|
|
GUNICORN_TIMEOUT=120
|
|
|
|
# --- Anmelde-Schutz ------------------------------------------------------------
|
|
# Fehlversuche pro E-Mail bzw. pro IP innerhalb des Zeitfensters (Minuten)
|
|
LOGIN_MAX_FAILURES_PER_EMAIL=5
|
|
LOGIN_MAX_FAILURES_PER_IP=30
|
|
LOGIN_LOCKOUT_MINUTES=15
|
|
|
|
# --- Fotos ---------------------------------------------------------------------
|
|
IMAGE_MAX_UPLOAD_MB=15
|
|
IMAGE_MAX_PER_RECIPE=10
|
|
|
|
# --- Kommentare ------------------------------------------------------------------
|
|
# Maximal so viele Kommentare pro Nutzer und Stunde (0 = unbegrenzt)
|
|
COMMENT_RATE_LIMIT_PER_HOUR=30
|
|
|
|
# --- KI (OpenAI) -------------------------------------------------------------------
|
|
# Ohne Key funktioniert alles außer den KI-Funktionen.
|
|
OPENAI_API_KEY=
|
|
OPENAI_MODEL=gpt-5-mini
|
|
# Nur für Reasoning-Modelle (gpt-5*, o*): minimal|low|medium|high. Für andere Modelle leer lassen.
|
|
OPENAI_REASONING_EFFORT=low
|
|
OPENAI_TIMEOUT=90
|
|
# Optionale Kostenbremse: KI-Aufrufe pro Tag (0 = unbegrenzt)
|
|
AI_RATE_LIMIT_PER_USER_PER_DAY=0
|
|
AI_RATE_LIMIT_GLOBAL_PER_DAY=0
|