257 lines
11 KiB
Python
257 lines
11 KiB
Python
"""Compatible configuration management with MariaDB and Redis support."""
|
|
|
|
import os
|
|
from functools import lru_cache
|
|
from typing import Optional, Dict, Any
|
|
from pydantic import BaseSettings, Field, validator
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Application settings with backward compatibility."""
|
|
|
|
# Application settings
|
|
app_name: str = Field(default="My Uploader Bot", env="APP_NAME")
|
|
debug: bool = Field(default=False, env="DEBUG")
|
|
environment: str = Field(default="production", env="ENVIRONMENT")
|
|
host: str = Field(default="0.0.0.0", env="HOST")
|
|
port: int = Field(default=15100, env="PORT")
|
|
|
|
# Security settings
|
|
secret_key: str = Field(env="SECRET_KEY", default="your-secret-key-change-this")
|
|
jwt_secret_key: str = Field(env="JWT_SECRET_KEY", default="jwt-secret-change-this")
|
|
jwt_algorithm: str = Field(default="HS256", env="JWT_ALGORITHM")
|
|
jwt_expire_minutes: int = Field(default=30, env="JWT_EXPIRE_MINUTES")
|
|
|
|
# MariaDB/MySQL settings (preserving existing configuration)
|
|
mysql_host: str = Field(default="maria_db", env="MYSQL_HOST")
|
|
mysql_port: int = Field(default=3306, env="MYSQL_PORT")
|
|
mysql_user: str = Field(default="myuploader", env="MYSQL_USER")
|
|
mysql_password: str = Field(default="password", env="MYSQL_PASSWORD")
|
|
mysql_database: str = Field(default="myuploader", env="MYSQL_DATABASE")
|
|
mysql_root_password: str = Field(default="password", env="MYSQL_ROOT_PASSWORD")
|
|
|
|
# Database pool settings
|
|
database_pool_size: int = Field(default=20, env="DATABASE_POOL_SIZE")
|
|
database_max_overflow: int = Field(default=30, env="DATABASE_MAX_OVERFLOW")
|
|
database_pool_timeout: int = Field(default=30, env="DATABASE_POOL_TIMEOUT")
|
|
database_pool_recycle: int = Field(default=3600, env="DATABASE_POOL_RECYCLE")
|
|
|
|
# Optional new database URL (for future migration)
|
|
database_url: Optional[str] = Field(default=None, env="DATABASE_URL")
|
|
|
|
# Redis settings (new addition)
|
|
redis_enabled: bool = Field(default=True, env="REDIS_ENABLED")
|
|
redis_host: str = Field(default="redis", env="REDIS_HOST")
|
|
redis_port: int = Field(default=6379, env="REDIS_PORT")
|
|
redis_password: Optional[str] = Field(default=None, env="REDIS_PASSWORD")
|
|
redis_db: int = Field(default=0, env="REDIS_DB")
|
|
redis_max_connections: int = Field(default=50, env="REDIS_MAX_CONNECTIONS")
|
|
redis_socket_timeout: int = Field(default=30, env="REDIS_SOCKET_TIMEOUT")
|
|
redis_socket_connect_timeout: int = Field(default=30, env="REDIS_SOCKET_CONNECT_TIMEOUT")
|
|
|
|
# Cache settings
|
|
cache_enabled: bool = Field(default=True, env="CACHE_ENABLED")
|
|
cache_default_ttl: int = Field(default=300, env="CACHE_DEFAULT_TTL") # 5 minutes
|
|
cache_user_ttl: int = Field(default=600, env="CACHE_USER_TTL") # 10 minutes
|
|
cache_content_ttl: int = Field(default=1800, env="CACHE_CONTENT_TTL") # 30 minutes
|
|
|
|
# Storage settings (preserving existing paths)
|
|
storage_path: str = Field(default="/Storage/storedContent", env="STORAGE_PATH")
|
|
logs_path: str = Field(default="/Storage/logs", env="LOGS_PATH")
|
|
sql_storage_path: str = Field(default="/Storage/sqlStorage", env="SQL_STORAGE_PATH")
|
|
|
|
# File upload settings
|
|
max_file_size: int = Field(default=100 * 1024 * 1024, env="MAX_FILE_SIZE") # 100MB
|
|
allowed_extensions: str = Field(default=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.txt", env="ALLOWED_EXTENSIONS")
|
|
|
|
# Rate limiting
|
|
rate_limit_enabled: bool = Field(default=True, env="RATE_LIMIT_ENABLED")
|
|
rate_limit_requests: int = Field(default=100, env="RATE_LIMIT_REQUESTS")
|
|
rate_limit_window: int = Field(default=3600, env="RATE_LIMIT_WINDOW") # 1 hour
|
|
|
|
# TON Blockchain settings (preserving existing)
|
|
ton_network: str = Field(default="mainnet", env="TON_NETWORK")
|
|
ton_api_key: Optional[str] = Field(default=None, env="TON_API_KEY")
|
|
ton_wallet_address: Optional[str] = Field(default=None, env="TON_WALLET_ADDRESS")
|
|
|
|
# License settings
|
|
license_check_enabled: bool = Field(default=True, env="LICENSE_CHECK_ENABLED")
|
|
license_server_url: Optional[str] = Field(default=None, env="LICENSE_SERVER_URL")
|
|
|
|
# Indexer settings
|
|
indexer_enabled: bool = Field(default=True, env="INDEXER_ENABLED")
|
|
indexer_interval: int = Field(default=300, env="INDEXER_INTERVAL") # 5 minutes
|
|
|
|
# Convert process settings
|
|
convert_enabled: bool = Field(default=True, env="CONVERT_ENABLED")
|
|
convert_queue_size: int = Field(default=10, env="CONVERT_QUEUE_SIZE")
|
|
|
|
# Logging settings
|
|
log_level: str = Field(default="INFO", env="LOG_LEVEL")
|
|
log_format: str = Field(default="json", env="LOG_FORMAT")
|
|
log_file_enabled: bool = Field(default=True, env="LOG_FILE_ENABLED")
|
|
log_file_max_size: int = Field(default=10 * 1024 * 1024, env="LOG_FILE_MAX_SIZE") # 10MB
|
|
log_file_backup_count: int = Field(default=5, env="LOG_FILE_BACKUP_COUNT")
|
|
|
|
# API settings
|
|
api_title: str = Field(default="My Uploader Bot API", env="API_TITLE")
|
|
api_version: str = Field(default="1.0.0", env="API_VERSION")
|
|
api_description: str = Field(default="File upload and management API", env="API_DESCRIPTION")
|
|
cors_enabled: bool = Field(default=True, env="CORS_ENABLED")
|
|
cors_origins: str = Field(default="*", env="CORS_ORIGINS")
|
|
|
|
# Health check settings
|
|
health_check_enabled: bool = Field(default=True, env="HEALTH_CHECK_ENABLED")
|
|
health_check_interval: int = Field(default=60, env="HEALTH_CHECK_INTERVAL")
|
|
|
|
# Metrics settings
|
|
metrics_enabled: bool = Field(default=True, env="METRICS_ENABLED")
|
|
metrics_endpoint: str = Field(default="/metrics", env="METRICS_ENDPOINT")
|
|
|
|
@validator("allowed_extensions")
|
|
def validate_extensions(cls, v):
|
|
"""Validate and normalize file extensions."""
|
|
if isinstance(v, str):
|
|
return [ext.strip().lower() for ext in v.split(",") if ext.strip()]
|
|
return v
|
|
|
|
@validator("cors_origins")
|
|
def validate_cors_origins(cls, v):
|
|
"""Validate and normalize CORS origins."""
|
|
if isinstance(v, str) and v != "*":
|
|
return [origin.strip() for origin in v.split(",") if origin.strip()]
|
|
return v
|
|
|
|
@validator("log_level")
|
|
def validate_log_level(cls, v):
|
|
"""Validate log level."""
|
|
valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
if v.upper() not in valid_levels:
|
|
raise ValueError(f"Log level must be one of: {valid_levels}")
|
|
return v.upper()
|
|
|
|
def get_database_url(self) -> str:
|
|
"""Get complete database URL."""
|
|
if self.database_url:
|
|
return self.database_url
|
|
return f"mysql+aiomysql://{self.mysql_user}:{self.mysql_password}@{self.mysql_host}:{self.mysql_port}/{self.mysql_database}"
|
|
|
|
def get_redis_url(self) -> str:
|
|
"""Get complete Redis URL."""
|
|
if self.redis_password:
|
|
return f"redis://:{self.redis_password}@{self.redis_host}:{self.redis_port}/{self.redis_db}"
|
|
return f"redis://{self.redis_host}:{self.redis_port}/{self.redis_db}"
|
|
|
|
def get_allowed_extensions_set(self) -> set:
|
|
"""Get allowed extensions as a set."""
|
|
if isinstance(self.allowed_extensions, list):
|
|
return set(self.allowed_extensions)
|
|
return set(ext.strip().lower() for ext in self.allowed_extensions.split(",") if ext.strip())
|
|
|
|
def get_cors_origins_list(self) -> list:
|
|
"""Get CORS origins as a list."""
|
|
if self.cors_origins == "*":
|
|
return ["*"]
|
|
if isinstance(self.cors_origins, list):
|
|
return self.cors_origins
|
|
return [origin.strip() for origin in self.cors_origins.split(",") if origin.strip()]
|
|
|
|
def is_development(self) -> bool:
|
|
"""Check if running in development mode."""
|
|
return self.environment.lower() in ["development", "dev", "local"]
|
|
|
|
def is_production(self) -> bool:
|
|
"""Check if running in production mode."""
|
|
return self.environment.lower() in ["production", "prod"]
|
|
|
|
def get_cache_config(self) -> Dict[str, Any]:
|
|
"""Get cache configuration dictionary."""
|
|
return {
|
|
"enabled": self.cache_enabled and self.redis_enabled,
|
|
"default_ttl": self.cache_default_ttl,
|
|
"user_ttl": self.cache_user_ttl,
|
|
"content_ttl": self.cache_content_ttl,
|
|
"redis_url": self.get_redis_url(),
|
|
"max_connections": self.redis_max_connections,
|
|
}
|
|
|
|
def get_database_config(self) -> Dict[str, Any]:
|
|
"""Get database configuration dictionary."""
|
|
return {
|
|
"url": self.get_database_url(),
|
|
"pool_size": self.database_pool_size,
|
|
"max_overflow": self.database_max_overflow,
|
|
"pool_timeout": self.database_pool_timeout,
|
|
"pool_recycle": self.database_pool_recycle,
|
|
}
|
|
|
|
class Config:
|
|
env_file = ".env"
|
|
env_file_encoding = "utf-8"
|
|
case_sensitive = False
|
|
|
|
|
|
@lru_cache()
|
|
def get_settings() -> Settings:
|
|
"""Get cached settings instance."""
|
|
return Settings()
|
|
|
|
|
|
# Backward compatibility functions
|
|
def get_mysql_config() -> Dict[str, Any]:
|
|
"""Get MySQL configuration for backward compatibility."""
|
|
settings = get_settings()
|
|
return {
|
|
"host": settings.mysql_host,
|
|
"port": settings.mysql_port,
|
|
"user": settings.mysql_user,
|
|
"password": settings.mysql_password,
|
|
"database": settings.mysql_database,
|
|
}
|
|
|
|
|
|
def get_storage_config() -> Dict[str, str]:
|
|
"""Get storage configuration for backward compatibility."""
|
|
settings = get_settings()
|
|
return {
|
|
"storage_path": settings.storage_path,
|
|
"logs_path": settings.logs_path,
|
|
"sql_storage_path": settings.sql_storage_path,
|
|
}
|
|
|
|
|
|
def get_redis_config() -> Dict[str, Any]:
|
|
"""Get Redis configuration."""
|
|
settings = get_settings()
|
|
return {
|
|
"enabled": settings.redis_enabled,
|
|
"host": settings.redis_host,
|
|
"port": settings.redis_port,
|
|
"password": settings.redis_password,
|
|
"db": settings.redis_db,
|
|
"max_connections": settings.redis_max_connections,
|
|
"socket_timeout": settings.redis_socket_timeout,
|
|
"socket_connect_timeout": settings.redis_socket_connect_timeout,
|
|
}
|
|
|
|
|
|
# Environment variables validation
|
|
def validate_environment():
|
|
"""Validate required environment variables."""
|
|
settings = get_settings()
|
|
|
|
required_vars = [
|
|
"SECRET_KEY",
|
|
"JWT_SECRET_KEY",
|
|
"MYSQL_PASSWORD",
|
|
]
|
|
|
|
missing_vars = []
|
|
for var in required_vars:
|
|
if not os.getenv(var):
|
|
missing_vars.append(var)
|
|
|
|
if missing_vars:
|
|
raise ValueError(f"Missing required environment variables: {', '.join(missing_vars)}")
|
|
|
|
return True |