# retoor import os import re import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] EXPECTED_KEYS = [ "SECRET_KEY", "PLAYWRIGHT_HEADLESS", "PLAYWRIGHT_SLOW_MO", "MOLODETZ_ADMIN_USERNAME", "MOLODETZ_ADMIN_EMAIL", "MOLODETZ_ADMIN_PASSWORD", "MOLODETZ_PORT", "MOLODETZ_TEST_PORT", "MOLODETZ_SITE_URL", "MOLODETZ_DATA_DIR", "MOLODETZ_DATABASE_URL", "MOLODETZ_INTERNAL_BASE_URL", "MOLODETZ_DISABLE_SERVICES", "MOLODETZ_DISABLE_RATE_LIMIT", "MOLODETZ_RATE_LIMIT", "MOLODETZ_WEB_WORKERS", "MOLODETZ_TEMPLATE_AUTO_RELOAD", "MOLODETZ_STATIC_VERSION", "MOLODETZ_LOG_LEVEL", "MOLODETZ_PRESENCE_TIMEOUT_SECONDS", "MOLODETZ_PRESENCE_ONLINE_LIMIT", "MOLODETZ_PRESENCE_TRACK_LIMIT", "MOLODETZ_PRESENCE_ONLINE_MARGIN_SECONDS", "MOLODETZ_OUTBOUND_PROXY_URL", "MOLODETZ_RCLONE_BIN", "MOLODETZ_RCLONE_CONFIG", "MOLODETZ_BACKUP_OFFLOAD_REMOTE", "MOLODETZ_SITEMAP_TTL", "MOLODETZ_LANDING_TTL", "MOLODETZ_UNREAD_TTL", ] NONEMPTY_PATH_KEYS = [ "MOLODETZ_DATA_DIR", "MOLODETZ_DATABASE_URL", "MOLODETZ_INTERNAL_BASE_URL", "MOLODETZ_RCLONE_BIN", "MOLODETZ_RCLONE_CONFIG", ] def read_example(): values = {} for line in (ROOT / ".env.example").read_text().splitlines(): match = re.match(r"^([A-Z][A-Z0-9_]*)=(.*)$", line) if match: values[match.group(1)] = match.group(2) return values def test_env_example_lists_every_key(): values = read_example() assert sorted(values) == sorted(EXPECTED_KEYS) def test_env_example_keeps_path_values_nonempty(): values = read_example() for key in NONEMPTY_PATH_KEYS: assert values[key].strip() != "" def test_config_reads_no_unknown_keys(): source = (ROOT / "molodetz" / "config.py").read_text() prefixed = set(re.findall(r'_env(?:_int)?\("([A-Z_]+)"', source)) assert set(re.findall(r'os\.environ\.get\("([A-Z_]+)"', source)) <= {"SECRET_KEY", "PLAYWRIGHT_HEADLESS", "PLAYWRIGHT_SLOW_MO"} assert {f"MOLODETZ_{name}" for name in prefixed} <= set(EXPECTED_KEYS) def run_config_import(data_dir, database_url): env = {**os.environ, "MOLODETZ_DATA_DIR": data_dir, "MOLODETZ_DATABASE_URL": database_url} return subprocess.run( [sys.executable, "-c", "from molodetz import config"], cwd=ROOT, env=env, capture_output=True, text=True, ) def test_data_dir_outside_root_refused(): result = run_config_import("/tmp/evil", "sqlite:////tmp/evil/molodetz.db") assert result.returncode != 0 assert "outside" in result.stderr def test_data_dir_inside_root_allowed(): target = ROOT / "data" / ".tmp-guard-probe" result = run_config_import(str(target), f"sqlite:///{target / 'molodetz.db'}") assert result.returncode == 0 def test_database_url_outside_data_dir_refused(): target = ROOT / "data" / ".tmp-guard-probe" result = run_config_import(str(target), "sqlite:////tmp/evil/molodetz.db") assert result.returncode != 0 assert "outside" in result.stderr