import os import json CONFIG_PATH = os.path.join(os.path.expanduser("~"), ".setec-mgr", "config.json") DEFAULTS = { "vps_host": "", "vps_user": "root", "vps_port": 22, "ssh_key_path": "", "domain": "", "hosting_provider": "", "hostinger_api_key": "", "web_root": "/var/www", "compose_path": "/opt/seteclabs/docker-compose.yml", "flask_port": 5000, "flask_secret": "", "setup_complete": False, "tos_accepted": False, "e2e_enabled": False, } # Sensitive fields that should be masked in API responses SENSITIVE_FIELDS = {"hostinger_api_key", "flask_secret", "tunnel_key"} def load(): try: with open(CONFIG_PATH) as f: cfg = json.load(f) for k, v in DEFAULTS.items(): cfg.setdefault(k, v) # Generate and persist flask_secret on first load if empty if not cfg["flask_secret"]: cfg["flask_secret"] = os.urandom(32).hex() save(cfg) return cfg except (FileNotFoundError, json.JSONDecodeError): defaults = dict(DEFAULTS) defaults["flask_secret"] = os.urandom(32).hex() save(defaults) return defaults def save(cfg): os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True) with open(CONFIG_PATH, "w") as f: json.dump(cfg, f, indent=2) def safe_config(): """Return config with sensitive fields masked.""" cfg = load() safe = dict(cfg) for field in SENSITIVE_FIELDS: val = safe.get(field, "") if val and len(val) > 8: safe[field] = val[:8] + "..." elif val: safe[field] = "***" return safe