import json import os import secrets import logging class Settings: _instance = None def __new__(cls, config_file=None): if cls._instance is None: cls._instance = super(Settings, cls).__new__(cls) if config_file is None: config_file = os.path.join(os.path.dirname(__file__), '..', 'appsettings.json') cls._instance.config_file = config_file cls._instance.load_settings() return cls._instance def load_settings(self): """Load settings from the JSON file, providing defaults if necessary, and save them.""" try: if os.path.exists(self.config_file): with open(self.config_file, 'r') as file: self.settings = json.load(file) else: self.settings = {} self.validate_settings() self.save_settings() except Exception as e: logging.error(f"Failed to load settings: {e}") self.settings = {} self.validate_settings() self.save_settings() def validate_settings(self): """Ensure all necessary settings are present, set defaults if not.""" default_values = { 'host': 'localhost', 'port': 8000, 'reload': False, 'api_key': None # Default API key is None which will trigger generation } # Check for presence and validity of each setting for key, default in default_values.items(): if key == 'api_key': # Special handling for API key if key not in self.settings or not self.is_valid_api_key(self.settings[key]): self.settings[key] = self.generate_api_key() else: if key not in self.settings: logging.info(key) self.settings[key] = default self.save_settings() def is_valid_api_key(self, api_key): """Check if the API key is valid.""" if api_key is None or not isinstance(api_key, str) or len(api_key) < 20: return False return True def generate_api_key(self): """Generate a new API key.""" return secrets.token_urlsafe(32) def save_settings(self): """Save the current settings back to the JSON file.""" try: with open(self.config_file, 'w') as file: json.dump(self.settings, file, indent=4) logging.info("Settings saved successfully.") except Exception as e: logging.error(f"Failed to save settings: {e}") def get_api_key(self): """Retrieve or generate an API key.""" api_key = self.settings.get('api_key') if not self.is_valid_api_key(api_key): logging.error("Invalid API key found, generating a new one.") api_key = self.generate_api_key() self.settings['api_key'] = api_key self.save_settings() return api_key def generate_api_key(self): """Generate a new API key.""" return secrets.token_urlsafe(32) def is_valid_api_key(self, api_key): """Check if the API key is valid.""" if not api_key or not isinstance(api_key, str) or len(api_key) < 20: return False return True # Initialize logging logging.basicConfig(level=logging.INFO) settings = Settings()