118 lines
4.7 KiB
Python
118 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Configuration Management for Chat Server
|
|
Supports both environment variables and .env files
|
|
"""
|
|
|
|
import os
|
|
from typing import Optional, Any, cast
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from dotenv import load_dotenv # type: ignore
|
|
load_dotenv(override=True)
|
|
DOTENV_AVAILABLE = True
|
|
except ImportError:
|
|
DOTENV_AVAILABLE = False
|
|
|
|
|
|
class Config:
|
|
"""Configuration class with environment variable support"""
|
|
|
|
# Server Configuration
|
|
HOST: str = os.getenv('HOST', '127.0.0.1')
|
|
PORT: int = int(os.getenv('PORT', '8765'))
|
|
MAX_HISTORY: int = int(os.getenv('MAX_HISTORY', '100'))
|
|
|
|
# Admin Configuration
|
|
ADMIN_PASSWORD: str = os.getenv('ADMIN_PASSWORD', '') # Should be set in environment
|
|
|
|
# SSL Configuration
|
|
USE_SSL: bool = os.getenv('USE_SSL', 'false').lower() == 'true'
|
|
SSL_CERT_PATH: Optional[str] = os.getenv('SSL_CERT_PATH')
|
|
SSL_KEY_PATH: Optional[str] = os.getenv('SSL_KEY_PATH')
|
|
|
|
# Database Configuration
|
|
DB_PATH: str = os.getenv('DB_PATH', 'data/chat.db')
|
|
|
|
# Logging Configuration
|
|
LOG_LEVEL: str = os.getenv('LOG_LEVEL', 'INFO')
|
|
LOG_FILE: Optional[str] = os.getenv('LOG_FILE', 'logs/chat_server.log')
|
|
|
|
# Security Configuration
|
|
MAX_MESSAGE_LENGTH: int = int(os.getenv('MAX_MESSAGE_LENGTH', '4096'))
|
|
MAX_NICKNAME_LENGTH: int = int(os.getenv('MAX_NICKNAME_LENGTH', '32'))
|
|
RATE_LIMIT_MESSAGES: int = int(os.getenv('RATE_LIMIT_MESSAGES', '120'))
|
|
RATE_LIMIT_WINDOW: int = int(os.getenv('RATE_LIMIT_WINDOW', '60'))
|
|
|
|
# Session Configuration
|
|
SESSION_TIMEOUT: int = int(os.getenv('SESSION_TIMEOUT', '3600'))
|
|
KEEPALIVE_INTERVAL: int = int(os.getenv('KEEPALIVE_INTERVAL', '30'))
|
|
RECONNECT_TIMEOUT: int = int(os.getenv('RECONNECT_TIMEOUT', '300'))
|
|
|
|
# Backup Configuration
|
|
BACKUP_DIR: str = os.getenv('BACKUP_DIR', './backups')
|
|
AUTO_BACKUP_ENABLED: bool = os.getenv('AUTO_BACKUP_ENABLED', 'false').lower() == 'true'
|
|
AUTO_BACKUP_INTERVAL: int = int(os.getenv('AUTO_BACKUP_INTERVAL', '86400')) # 24 hours
|
|
|
|
# Room Configuration
|
|
ROOM_EXPIRATION_HOURS: int = int(os.getenv('ROOM_EXPIRATION_HOURS', '24'))
|
|
AUTO_HISTORY_CLEAR: bool = os.getenv('AUTO_HISTORY_CLEAR', 'false').lower() == 'true'
|
|
|
|
@classmethod
|
|
def validate(cls) -> bool:
|
|
"""Validate configuration"""
|
|
errors = []
|
|
|
|
# Validate port range
|
|
if not (1 <= cls.PORT <= 65535):
|
|
errors.append(f"Invalid PORT: {cls.PORT}. Must be between 1-65535")
|
|
|
|
# Validate SSL configuration
|
|
if cls.USE_SSL:
|
|
if not cls.SSL_CERT_PATH or not cls.SSL_KEY_PATH:
|
|
errors.append("SSL enabled but SSL_CERT_PATH or SSL_KEY_PATH not set")
|
|
elif not Path(cast(str, cls.SSL_CERT_PATH)).exists():
|
|
errors.append(f"SSL certificate not found: {cls.SSL_CERT_PATH}")
|
|
elif not Path(cast(str, cls.SSL_KEY_PATH)).exists():
|
|
errors.append(f"SSL key not found: {cls.SSL_KEY_PATH}")
|
|
|
|
# Validate positive integers
|
|
if cls.MAX_HISTORY < 1:
|
|
errors.append(f"MAX_HISTORY must be positive, got {cls.MAX_HISTORY}")
|
|
if cls.MAX_MESSAGE_LENGTH < 1:
|
|
errors.append(f"MAX_MESSAGE_LENGTH must be positive, got {cls.MAX_MESSAGE_LENGTH}")
|
|
if cls.MAX_NICKNAME_LENGTH < 1:
|
|
errors.append(f"MAX_NICKNAME_LENGTH must be positive, got {cls.MAX_NICKNAME_LENGTH}")
|
|
|
|
# Print errors
|
|
if errors:
|
|
print("[ERROR] Configuration errors:")
|
|
for error in errors:
|
|
print(f" - {error}")
|
|
return False
|
|
|
|
return True
|
|
|
|
@classmethod
|
|
def display(cls):
|
|
"""Display current configuration"""
|
|
print("\n" + "=" * 70)
|
|
print("CHAT SERVER CONFIGURATION")
|
|
print("=" * 70)
|
|
print(f"Server: {cls.HOST}:{cls.PORT}")
|
|
print(f"SSL: {'Enabled' if cls.USE_SSL else 'Disabled'}")
|
|
print(f"Database: {cls.DB_PATH}")
|
|
print(f"Log Level: {cls.LOG_LEVEL}")
|
|
print(f"Log File: {cls.LOG_FILE or 'Console only'}")
|
|
print(f"Max History: {cls.MAX_HISTORY} messages")
|
|
print(f"Rate Limit: {cls.RATE_LIMIT_MESSAGES} msg/{cls.RATE_LIMIT_WINDOW}s")
|
|
print(f"Auto Backup: {'Enabled' if cls.AUTO_BACKUP_ENABLED else 'Disabled'}")
|
|
print("=" * 70 + "\n")
|
|
|
|
|
|
# Validate configuration on import
|
|
if __name__ != "__main__":
|
|
if not Config.validate():
|
|
raise ValueError("Invalid configuration. Please check your environment variables or .env file")
|