"""Application configuration using environment variables""" import secrets from pydantic_settings import BaseSettings from pydantic import model_validator from typing import List class Settings(BaseSettings): """Application settings loaded from environment variables""" # Application app_name: str = "Ohm Stream Downloader" app_version: str = "2.2" debug: bool = False # Server host: str = "0.0.0.0" port: int = 3000 reload: bool = True # Authentication jwt_secret_key: str = "dev-secret-change-in-production" jwt_algorithm: str = "HS256" access_token_expire_minutes: int = 60 * 24 # 24 hours (short-lived for security) refresh_token_expire_days: int = 30 @model_validator(mode="after") def validate_jwt_secret_key(self) -> "Settings": """Validate JWT_SECRET_KEY is not the default or too short""" default_secret = "dev-secret-change-in-production" if self.jwt_secret_key == default_secret: raise ValueError( f"JWT_SECRET_KEY cannot be the default value '{default_secret}'. " f"Please set a secure secret in your .env file. " f"Use Settings.generate_secret() to generate a secure secret." ) if len(self.jwt_secret_key) < 32: raise ValueError( f"JWT_SECRET_KEY must be at least 32 characters long. " f"Current length: {len(self.jwt_secret_key)} characters. " f"Use Settings.generate_secret() to generate a secure secret." ) return self @staticmethod def generate_secret() -> str: """Generate a cryptographically secure JWT secret key""" return secrets.token_urlsafe(32) # Downloads download_dir: str = "downloads" max_parallel_downloads: int = 3 chunk_size: int = 1024 * 1024 # 1MB chunks # CORS cors_origins: List[str] = [ "http://localhost:3000", "http://127.0.0.1:3000", "http://192.168.1.204:3000", "http://192.168.1.204", ] # Storage favorites_storage_path: str = "favorites.json" # Sonarr sonarr_config_path: str = "config/sonarr.json" sonarr_mappings_path: str = "config/sonarr_mappings.json" # API Timeouts http_timeout: float = 10.0 download_timeout: int = 300 # 5 minutes # Logging log_level: str = "INFO" class Config: env_file = ".env" env_file_encoding = "utf-8" case_sensitive = False # Global settings instance settings = Settings() def get_settings() -> Settings: """Get the global settings instance""" return settings