import os from datetime import timedelta class Config: """Base configuration""" SECRET_KEY = os.environ.get("SECRET_KEY") or "dev-secret-key-change-in-production" SQLALCHEMY_TRACK_MODIFICATIONS = False JWT_SECRET_KEY = os.environ["JWT_SECRET_KEY"] JWT_ACCESS_TOKEN_EXPIRES = timedelta(hours=12) JWT_REFRESH_TOKEN_EXPIRES = timedelta(days=30) CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "*") # Celery Configuration CELERY = { "broker_url": os.environ.get("CELERY_BROKER_URL", "redis://redis:6379/0"), "result_backend": os.environ.get( "CELERY_RESULT_BACKEND", "redis://redis:6379/0" ), "task_serializer": "json", "result_serializer": "json", "accept_content": ["json"], "timezone": "UTC", "enable_utc": True, "task_track_started": True, "task_time_limit": 30 * 60, # 30 minutes "task_soft_time_limit": 25 * 60, # 25 minutes "worker_prefetch_multiplier": 1, "worker_max_tasks_per_child": 100, "broker_connection_retry_on_startup": True, } SQLALCHEMY_ENGINE_OPTIONS = { "pool_size": 20, # Reduce from default "max_overflow": 10, # Reduce overflow "pool_timeout": 30, "pool_recycle": 1800, # Recycle connections after 30 minutes "pool_pre_ping": True, # Verify connections before using } # MinIO Configuration MINIO_ENDPOINT = os.environ.get("MINIO_ENDPOINT", "minio:9000") MINIO_ACCESS_KEY = os.environ.get("MINIO_ACCESS_KEY", "minioadmin") MINIO_SECRET_KEY = os.environ.get("MINIO_SECRET_KEY", "minioadmin") MINIO_REGION = os.environ.get("MINIO_REGION", "garage") MINIO_USE_SSL = os.environ.get("MINIO_USE_SSL", "true").lower() == "true" # MinIO Buckets MINIO_IMAGES_BUCKET = "kanban-images" MINIO_DOCUMENTS_BUCKET = "kanban-documents" MINIO_THUMBNAILS_BUCKET = "kanban-thumbnails" class DevelopmentConfig(Config): """Development configuration""" DEBUG = True SQLALCHEMY_DATABASE_URI = os.environ["DATABASE_URL"] # MinIO Configuration for Development MINIO_ENDPOINT = os.environ.get("MINIO_ENDPOINT", "minio:9000") MINIO_ACCESS_KEY = os.environ.get("MINIO_ACCESS_KEY", "minioadmin") MINIO_SECRET_KEY = os.environ.get("MINIO_SECRET_KEY", "minioadmin") MINIO_USE_SSL = os.environ.get("MINIO_USE_SSL", "false").lower() == "true" MINIO_IMAGES_BUCKET = "kanban-images" MINIO_DOCUMENTS_BUCKET = "kanban-documents" MINIO_THUMBNAILS_BUCKET = "kanban-thumbnails" MAX_UPLOAD_SIZE_IMAGE = 10 * 1024 * 1024 MAX_UPLOAD_SIZE_DOCUMENT = 50 * 1024 * 1024 ALLOWED_IMAGE_TYPES = [ "image/jpeg", "image/png", "image/gif", "image/svg+xml", "image/webp", ] ALLOWED_DOCUMENT_TYPES = ["application/pdf"] class TestingConfig(Config): """Testing configuration""" TESTING = True USE_MOCK_STORAGE = True # Use in-memory mock storage for tests SQLALCHEMY_DATABASE_URI = os.environ.get("TEST_DATABASE_URL") WTF_CSRF_ENABLED = False # Conservative connection pool settings for testing SQLALCHEMY_ENGINE_OPTIONS = { "pool_size": 4, # Only one connection in the pool "max_overflow": 0, # No overflow connections allowed "pool_timeout": 30, "pool_recycle": 3600, # Recycle after 1 hour "pool_pre_ping": True, # Verify connections before using } # MinIO configuration (not used in tests due to USE_MOCK_STORAGE=True) MINIO_ENDPOINT = "minio:9000" MINIO_ACCESS_KEY = os.environ.get("MINIO_ACCESS_KEY", "minioadmin") MINIO_SECRET_KEY = os.environ.get("MINIO_SECRET_KEY", "minioadmin") MINIO_USE_SSL = os.environ.get("MINIO_USE_SSL", "false").lower() == "true" # Bucket names (required for FileService even with mock storage) MINIO_IMAGES_BUCKET = "kanban-images" MINIO_DOCUMENTS_BUCKET = "kanban-documents" MINIO_THUMBNAILS_BUCKET = "kanban-thumbnails" # File upload limits MAX_UPLOAD_SIZE_IMAGE = 10 * 1024 * 1024 # 10MB MAX_UPLOAD_SIZE_DOCUMENT = 50 * 1024 * 1024 # 50MB # Allowed file types ALLOWED_IMAGE_TYPES = [ "image/jpeg", "image/png", "image/gif", "image/svg+xml", "image/webp", ] ALLOWED_DOCUMENT_TYPES = ["application/pdf"] class ProductionConfig(Config): """Production configuration""" DEBUG = False SQLALCHEMY_DATABASE_URI = os.environ["DATABASE_URL"] # Security headers SESSION_COOKIE_SECURE = True SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" # MinIO Configuration MINIO_ENDPOINT = os.environ.get("MINIO_ENDPOINT", "minio:9000") MINIO_ACCESS_KEY = os.environ.get("MINIO_ACCESS_KEY", "minioadmin") MINIO_SECRET_KEY = os.environ.get("MINIO_SECRET_KEY", "minioadmin") MINIO_USE_SSL = os.environ.get("MINIO_USE_SSL", "true").lower() == "true" # MinIO Buckets MINIO_IMAGES_BUCKET = "kanban-images" MINIO_DOCUMENTS_BUCKET = "kanban-documents" MINIO_THUMBNAILS_BUCKET = "kanban-thumbnails" # File Upload Limits (in bytes) MAX_UPLOAD_SIZE_IMAGE = 10 * 1024 * 1024 # 10MB MAX_UPLOAD_SIZE_DOCUMENT = 50 * 1024 * 1024 # 50MB # Allowed File Types ALLOWED_IMAGE_TYPES = [ "image/jpeg", "image/png", "image/gif", "image/svg+xml", "image/webp", ] ALLOWED_DOCUMENT_TYPES = ["application/pdf"] config_by_name = { "dev": DevelopmentConfig, "test": TestingConfig, "prod": ProductionConfig, }