Files
MClogger/web/config.py
simon 52674fee29 modified: web/app.py
modified:   web/config.py
	modified:   web/templates/privacy_policy.html
2026-04-15 12:09:11 +02:00

110 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
MCLogger Konfiguration
Alle Einstellungen über ENV-Variablen (Coolify-kompatibel).
"""
import os
def _as_bool(value: str | None, default: bool = False) -> bool:
if value is None:
return default
return value.strip().lower() in {"1", "true", "yes", "on"}
class Config:
DEFAULT_SECRET_KEY = "change-me-use-a-long-random-string-min-32-chars"
DEFAULT_PASSWORD_PEPPER = "change-me-global-pepper-secret-never-change"
# ── Flask ──────────────────────────────────────────────────
SECRET_KEY = os.getenv("SECRET_KEY", DEFAULT_SECRET_KEY)
HOST = os.getenv("HOST") or "0.0.0.0"
PORT = int(os.getenv("PORT") or "5000")
DEBUG = _as_bool(os.getenv("DEBUG"), default=False)
# Session-Cookie-Hardening
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = os.getenv("SESSION_COOKIE_SAMESITE") or "Lax"
SESSION_COOKIE_SECURE = _as_bool(os.getenv("SESSION_COOKIE_SECURE"), default=not DEBUG)
# Erzwingt sichere Secrets in Nicht-Debug-Umgebungen
ENFORCE_SECURE_CONFIG = _as_bool(os.getenv("ENFORCE_SECURE_CONFIG"), default=True)
# ── Panel-Datenbank (Nutzer, Gruppen, Mitgliedschaften) ────
PANEL_DB_HOST = os.getenv("PANEL_DB_HOST") or "localhost"
PANEL_DB_PORT = int(os.getenv("PANEL_DB_PORT") or "3306")
PANEL_DB_USER = os.getenv("PANEL_DB_USER") or "root"
PANEL_DB_PASSWORD = os.getenv("PANEL_DB_PASSWORD") or ""
PANEL_DB_NAME = os.getenv("PANEL_DB_NAME") or "mclogger_panel"
# ── Credentials-Datenbank (verschlüsselte MC-DB-Zugangsdaten) ──
CREDS_DB_HOST = os.getenv("CREDS_DB_HOST") or os.getenv("PANEL_DB_HOST") or "localhost"
CREDS_DB_PORT = int(os.getenv("CREDS_DB_PORT") or os.getenv("PANEL_DB_PORT") or "3306")
CREDS_DB_USER = os.getenv("CREDS_DB_USER") or os.getenv("PANEL_DB_USER") or "root"
CREDS_DB_PASSWORD = os.getenv("CREDS_DB_PASSWORD") or os.getenv("PANEL_DB_PASSWORD") or ""
CREDS_DB_NAME = os.getenv("CREDS_DB_NAME") or "mclogger_creds"
# ── Sicherheit ────────────────────────────────────────────
PASSWORD_PEPPER = os.getenv("PASSWORD_PEPPER", DEFAULT_PASSWORD_PEPPER)
# Generieren: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
FERNET_KEY = os.getenv("FERNET_KEY", "")
# ── Mail defaults (can be overridden in admin panel) ─────
MAIL_PORT = int(os.getenv("MAIL_PORT") or "587")
MAIL_USE_TLS = _as_bool(os.getenv("MAIL_USE_TLS"), default=True)
MAIL_TIMEOUT = int(os.getenv("MAIL_TIMEOUT") or "15")
# ── Reverse-Proxy ─────────────────────────────────────────
# Anzahl der vorgelagerten Proxy-Ebenen (z.B. Nginx + Coolify-Traefik).
# ProxyFix liest X-Forwarded-For entsprechend aus und liefert die echte Client-IP.
# Auf 0 setzen, wenn Flask direkt erreichbar ist (kein Proxy).
PROXY_COUNT = int(os.getenv("PROXY_COUNT") or "1")
# ── Datenschutz / DSGVO ───────────────────────────────────
# Version der Datenschutzerklärung. Wird in create_app() automatisch als
# SHA-256-Hash der privacy_policy.html berechnet (erste 6 Zeichen, Großbuchstaben).
# Ändert sich der Seiteninhalt, ändert sich der Hash → alle Nutzer müssen
# beim nächsten Login erneut zustimmen.
# Kann über die ENV-Variable PRIVACY_POLICY_VERSION manuell überschrieben werden.
PRIVACY_POLICY_VERSION = os.getenv("PRIVACY_POLICY_VERSION") or "INIT00"
# ── Standard-Berechtigungen neuer Gruppenmitglieder ───────
INVITE_EXPIRY_HOURS = int(os.getenv("INVITE_EXPIRY_HOURS") or "72")
INVITE_MAX_ACTIVE_PER_GROUP = int(os.getenv("INVITE_MAX_ACTIVE_PER_GROUP") or "200")
INVITE_RESEND_COOLDOWN_SECONDS = int(os.getenv("INVITE_RESEND_COOLDOWN_SECONDS") or "120")
# ── Audit-Log-Aufbewahrung ────────────────────────────────
# Audit-Log-Einträge, die älter als dieser Wert (in Tagen) sind, werden automatisch gelöscht.
# IP-Adressen gelten als personenbezogene Daten (DSGVO Art. 4 Nr. 1); nach 90 Tagen sollten
# diese nicht mehr benötigt werden. Auf 0 setzen, um automatisches Löschen zu deaktivieren.
AUDIT_LOG_RETENTION_DAYS = int(os.getenv("AUDIT_LOG_RETENTION_DAYS") or "90")
DEFAULT_PERMISSIONS = {
"view_dashboard": True,
"view_players": True,
"view_sessions": True,
"view_chat": True,
"view_commands": True,
"view_deaths": True,
"view_blocks": True,
"view_proxy": False,
"view_server_events": False,
"view_perms": False,
}
@classmethod
def validate_security(cls):
"""Fail-fast, damit unsichere Defaults nicht in Produktion laufen."""
if not cls.ENFORCE_SECURE_CONFIG or cls.DEBUG:
return
issues = []
if cls.SECRET_KEY == cls.DEFAULT_SECRET_KEY:
issues.append("SECRET_KEY must be set to a strong random value.")
if cls.PASSWORD_PEPPER == cls.DEFAULT_PASSWORD_PEPPER:
issues.append("PASSWORD_PEPPER must be set to a strong secret value.")
if not cls.FERNET_KEY:
issues.append("FERNET_KEY must be configured.")
if issues:
raise RuntimeError("Invalid security configuration: " + " ".join(issues))