import os from pathlib import Path import urllib.parse # Base directory for the project BASE_DIR = Path(__file__).parent.parent.parent class Config: """Base configuration class.""" # Database Configuration SQLALCHEMY_DATABASE_URI = os.getenv( "DATABASE_URL", f"sqlite:///{BASE_DIR}/data/scriptsmanager.db" ) SQLALCHEMY_TRACK_MODIFICATIONS = False # PostgreSQL-specific database configuration SQLALCHEMY_ENGINE_OPTIONS = { 'pool_size': 10, 'pool_timeout': 20, 'pool_recycle': -1, 'max_overflow': 0, 'pool_pre_ping': True, } # Additional database settings for PostgreSQL SQLALCHEMY_ECHO = os.getenv("SQLALCHEMY_ECHO", "False").lower() == "true" @staticmethod def get_database_config(): """Get database configuration based on DATABASE_URL.""" database_url = os.getenv("DATABASE_URL", f"sqlite:///{BASE_DIR}/data/scriptsmanager.db") if database_url.startswith('postgresql://'): # Parse PostgreSQL URL parsed = urllib.parse.urlparse(database_url) return { 'engine': 'postgresql', 'host': parsed.hostname, 'port': parsed.port or 5432, 'database': parsed.path[1:], # Remove leading slash 'username': parsed.username, 'password': parsed.password, 'url': database_url } else: # SQLite configuration (fallback) return { 'engine': 'sqlite', 'url': database_url, 'file': database_url.replace('sqlite:///', '') } # Application Settings SECRET_KEY = os.getenv("SECRET_KEY", "your-secret-key-change-in-production") DEBUG = os.getenv("DEBUG", "False").lower() == "true" # Multi-user Settings BASE_DATA_PATH = Path(os.getenv("BASE_DATA_PATH", "./data")) MAX_PROJECTS_PER_USER = int(os.getenv("MAX_PROJECTS_PER_USER", "50")) # Port Management PORT_RANGE_START = int(os.getenv("PORT_RANGE_START", "5200")) PORT_RANGE_END = int(os.getenv("PORT_RANGE_END", "5400")) # Backup Configuration BACKUP_ENABLED = os.getenv("BACKUP_ENABLED", "True").lower() == "true" BACKUP_SCHEDULE_TIME = os.getenv("BACKUP_SCHEDULE_TIME", "02:00") BACKUP_RETENTION_DAYS = int(os.getenv("BACKUP_RETENTION_DAYS", "30")) # Conda Environment CONDA_AUTO_DETECT = os.getenv("CONDA_AUTO_DETECT", "True").lower() == "true" # Supported Languages SUPPORTED_LANGUAGES = ["en", "es", "it", "fr"] DEFAULT_LANGUAGE = os.getenv("DEFAULT_LANGUAGE", "en") # Web Interface Management WEB_INTERFACE_CONFIG = { "port_range": {"start": PORT_RANGE_START, "end": PORT_RANGE_END}, "session_timeout": 1800, "heartbeat_interval": 30, "cleanup_interval": 300, "max_concurrent_interfaces": 20, "max_interfaces_per_user": 5, } # Documentation Settings DOCUMENTATION_CONFIG = { "markdown_extensions": ["codehilite", "tables", "toc", "math"], "supported_languages": SUPPORTED_LANGUAGES, "default_language": DEFAULT_LANGUAGE, "enable_math_rendering": True, "enable_diagram_rendering": False, } # Tagging Configuration TAGGING_CONFIG = { "max_tags_per_script": 20, "max_tag_length": 30, "allowed_tag_chars": "alphanumeric_underscore_dash", "enable_tag_suggestions": True, } # Security Settings SECURITY_CONFIG = { "data_directory_permissions": "755", "config_file_permissions": "644", "enable_project_sharing": False, "admin_can_access_all_data": True, } class DevelopmentConfig(Config): """Development configuration.""" DEBUG = True # Development-specific database settings SQLALCHEMY_ENGINE_OPTIONS = { 'pool_size': 5, 'pool_timeout': 10, 'pool_recycle': 300, 'max_overflow': 0, 'pool_pre_ping': True, 'echo': True, # Log SQL queries in development } class ProductionConfig(Config): """Production configuration.""" DEBUG = False # Production-specific database settings with connection pooling SQLALCHEMY_ENGINE_OPTIONS = { 'pool_size': 20, 'pool_timeout': 30, 'pool_recycle': 3600, # Recycle connections every hour 'max_overflow': 10, 'pool_pre_ping': True, 'echo': False, # Disable SQL logging in production } # Production security enhancements SECURITY_CONFIG = { **Config.SECURITY_CONFIG, "enable_project_sharing": True, # Enable in production "session_cookie_secure": True, "session_cookie_httponly": True, "session_cookie_samesite": "Lax", } class TestingConfig(Config): """Testing configuration.""" TESTING = True SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:" # Testing-specific settings SQLALCHEMY_ENGINE_OPTIONS = { 'pool_size': 1, 'pool_timeout': 5, 'pool_recycle': -1, 'max_overflow': 0, 'pool_pre_ping': False, } # Disable backup in testing BACKUP_ENABLED = False # Configuration dictionary config = { "development": DevelopmentConfig, "production": ProductionConfig, "testing": TestingConfig, "default": DevelopmentConfig, }