""" 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", "") # ── Standard-Berechtigungen neuer Gruppenmitglieder ─────── INVITE_EXPIRY_HOURS = int(os.getenv("INVITE_EXPIRY_HOURS") or "72") 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))