feat: Migrate to MySQL and add unified environment configuration
## Database Migration (SQLite → MySQL) - Add Alembic migration framework - Add 'tr_' prefix to all tables to avoid conflicts in shared database - Remove SQLite support, use MySQL exclusively - Add pymysql driver dependency - Change ad_token column to Text type for long JWT tokens ## Unified Environment Configuration - Centralize all hardcoded settings to environment variables - Backend: Extend Settings class in app/core/config.py - Frontend: Use Vite environment variables (import.meta.env) - Docker: Move credentials to environment variables - Update .env.example files with comprehensive documentation ## Test Organization - Move root-level test files to tests/ directory: - test_chat_room.py → tests/test_chat_room.py - test_websocket.py → tests/test_websocket.py - test_realtime_implementation.py → tests/test_realtime_implementation.py - Fix path references in test_realtime_implementation.py Breaking Changes: - CORS now requires explicit origins (no more wildcard) - All database tables renamed with 'tr_' prefix - SQLite no longer supported 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
"""Application configuration loaded from environment variables"""
|
||||
from pydantic_settings import BaseSettings
|
||||
from pydantic import field_validator
|
||||
from functools import lru_cache
|
||||
from typing import List
|
||||
import logging
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
@@ -14,6 +17,7 @@ class Settings(BaseSettings):
|
||||
|
||||
# AD API
|
||||
AD_API_URL: str
|
||||
AD_API_TIMEOUT_SECONDS: int = 10 # AD API request timeout
|
||||
|
||||
# Session Settings
|
||||
SESSION_INACTIVITY_DAYS: int = 3
|
||||
@@ -23,7 +27,23 @@ class Settings(BaseSettings):
|
||||
# Server
|
||||
HOST: str = "0.0.0.0"
|
||||
PORT: int = 8000
|
||||
DEBUG: bool = True
|
||||
DEBUG: bool = False # Default to False for security
|
||||
LOG_LEVEL: str = "INFO" # DEBUG, INFO, WARNING, ERROR
|
||||
|
||||
# CORS Configuration
|
||||
CORS_ORIGINS: str = "http://localhost:3000" # Comma-separated list of allowed origins
|
||||
|
||||
# System Admin
|
||||
SYSTEM_ADMIN_EMAIL: str = "" # System administrator email with special permissions
|
||||
|
||||
# Realtime Messaging Settings
|
||||
MESSAGE_EDIT_TIME_LIMIT_MINUTES: int = 15 # Time limit for editing messages
|
||||
TYPING_TIMEOUT_SECONDS: int = 3 # Typing indicator timeout
|
||||
|
||||
# File Upload Size Limits (in MB)
|
||||
IMAGE_MAX_SIZE_MB: int = 10
|
||||
DOCUMENT_MAX_SIZE_MB: int = 20
|
||||
LOG_MAX_SIZE_MB: int = 5
|
||||
|
||||
# MinIO Object Storage
|
||||
MINIO_ENDPOINT: str = "localhost:9000"
|
||||
@@ -41,6 +61,41 @@ class Settings(BaseSettings):
|
||||
REPORT_MAX_MESSAGES: int = 200 # Summarize if exceeded
|
||||
REPORT_STORAGE_PATH: str = "reports" # MinIO path prefix for reports
|
||||
|
||||
@field_validator("LOG_LEVEL")
|
||||
@classmethod
|
||||
def validate_log_level(cls, v: str) -> str:
|
||||
"""Validate log level"""
|
||||
valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
||||
v_upper = v.upper()
|
||||
if v_upper not in valid_levels:
|
||||
raise ValueError(f"LOG_LEVEL must be one of {valid_levels}")
|
||||
return v_upper
|
||||
|
||||
def get_cors_origins(self) -> List[str]:
|
||||
"""Parse CORS_ORIGINS into a list"""
|
||||
if not self.CORS_ORIGINS:
|
||||
return []
|
||||
return [origin.strip() for origin in self.CORS_ORIGINS.split(",") if origin.strip()]
|
||||
|
||||
def get_image_max_size_bytes(self) -> int:
|
||||
"""Get image max size in bytes"""
|
||||
return self.IMAGE_MAX_SIZE_MB * 1024 * 1024
|
||||
|
||||
def get_document_max_size_bytes(self) -> int:
|
||||
"""Get document max size in bytes"""
|
||||
return self.DOCUMENT_MAX_SIZE_MB * 1024 * 1024
|
||||
|
||||
def get_log_max_size_bytes(self) -> int:
|
||||
"""Get log file max size in bytes"""
|
||||
return self.LOG_MAX_SIZE_MB * 1024 * 1024
|
||||
|
||||
def configure_logging(self) -> None:
|
||||
"""Configure application logging based on LOG_LEVEL"""
|
||||
logging.basicConfig(
|
||||
level=getattr(logging, self.LOG_LEVEL),
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
case_sensitive = True
|
||||
|
||||
Reference in New Issue
Block a user