Files
formeleon/config.py
T

177 lines
6.5 KiB
Python

# ==============================================================================
# Formeleon - Multi-tenant Form Generator
# Author: Björn Runden <br@runden.net>
# Module: config.py
# Description: Application configuration with environment variable support.
# Handles development mode, reCAPTCHA, Zitadel OIDC, and database settings.
# ==============================================================================
"""
Application configuration module for Formeleon.
This module centralizes all configuration settings for the Flask application,
loading from environment variables with sensible defaults for development.
Environment Variables:
- DEV_MODE: Enable development mode (default: False)
- SECRET_KEY: Flask secret key for session management
- SQLALCHEMY_DATABASE_URI: Database connection string
- SQLALCHEMY_TRACK_MODIFICATIONS: Track modifications (default: False)
- ZITADEL_ISSUER: OIDC issuer URL for Zitadel
- ZITADEL_CLIENT_ID: OIDC client ID
- ZITADEL_CLIENT_SECRET: OIDC client secret
- ZITADEL_REDIRECT_URI: OIDC redirect URI
- RECAPTCHA_SECRET_KEY: reCAPTCHA v3 secret key
- RECAPTCHA_SITE_KEY: reCAPTCHA v3 site key
- RECAPTCHA_THRESHOLD: Minimum score threshold (default: 0.5)
- MOCK_RECAPTCHA_SCORE: Mock score for dev mode (default: 0.9)
- DEV_USER_ROLE: Role for dev mode user (default: 'admin')
- DEV_TENANT_ID: Tenant ID for dev mode (default: 'tenant_dev_123')
- DEV_USER_NAME: Username for dev mode (default: 'Dev Admin')
- DEV_USER_EMAIL: Email for dev mode (default: 'dev@formeleon.local')
"""
import os
from typing import Optional
class Config:
"""
Base configuration class with default values.
All configuration values can be overridden via environment variables.
"""
# Flask Core Settings
SECRET_KEY: str = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production')
DEBUG: bool = os.environ.get('FLASK_DEBUG', 'false').lower() == 'true'
TESTING: bool = os.environ.get('FLASK_TESTING', 'false').lower() == 'true'
# Development Mode
DEV_MODE: bool = os.environ.get('DEV_MODE', 'false').lower() == 'true'
# Dev User Settings
DEV_USER_ROLE: str = os.environ.get('DEV_USER_ROLE', 'admin')
DEV_TENANT_ID: str = os.environ.get('DEV_TENANT_ID', 'tenant_dev_123')
DEV_USER_NAME: str = os.environ.get('DEV_USER_NAME', 'Dev Admin')
DEV_USER_EMAIL: str = os.environ.get('DEV_USER_EMAIL', 'dev@formeleon.local')
# Database Configuration
SQLALCHEMY_DATABASE_URI: str = os.environ.get(
'SQLALCHEMY_DATABASE_URI',
'sqlite:///formeleon.db'
)
SQLALCHEMY_TRACK_MODIFICATIONS: bool = False
SQLALCHEMY_ECHO: bool = os.environ.get('SQLALCHEMY_ECHO', 'false').lower() == 'true'
# Zitadel OIDC Configuration
ZITADEL_ISSUER: Optional[str] = os.environ.get('ZITADEL_ISSUER')
ZITADEL_CLIENT_ID: Optional[str] = os.environ.get('ZITADEL_CLIENT_ID')
ZITADEL_CLIENT_SECRET: Optional[str] = os.environ.get('ZITADEL_CLIENT_SECRET')
ZITADEL_REDIRECT_URI: Optional[str] = os.environ.get(
'ZITADEL_REDIRECT_URI',
'http://localhost:5000/auth/callback'
)
ZITADEL_SCOPES: list = ['openid', 'profile', 'email']
# reCAPTCHA v3 Configuration
RECAPTCHA_SECRET_KEY: Optional[str] = os.environ.get('RECAPTCHA_SECRET_KEY')
RECAPTCHA_SITE_KEY: Optional[str] = os.environ.get('RECAPTCHA_SITE_KEY')
RECAPTCHA_THRESHOLD: float = float(os.environ.get('RECAPTCHA_THRESHOLD', '0.5'))
MOCK_RECAPTCHA_SCORE: float = float(os.environ.get('MOCK_RECAPTCHA_SCORE', '0.9'))
RECAPTCHA_VERIFY_URL: str = 'https://www.google.com/recaptcha/api/siteverify'
# Application Settings
DEFAULT_PAGE_SIZE: int = 20
MAX_PAGE_SIZE: int = 100
# Form Submission Settings
ALLOWED_ORIGINS: list = os.environ.get('ALLOWED_ORIGINS', '*').split(',')
ENABLE_CORS: bool = os.environ.get('ENABLE_CORS', 'true').lower() == 'true'
# File Upload Settings
MAX_CONTENT_LENGTH: int = 16 * 1024 * 1024 # 16MB
UPLOAD_FOLDER: str = os.environ.get('UPLOAD_FOLDER', '/tmp/formeleon_uploads')
ALLOWED_EXTENSIONS: set = {'png', 'jpg', 'jpeg', 'gif', 'pdf', 'txt'}
# Session Configuration
SESSION_COOKIE_SECURE: bool = os.environ.get('SESSION_COOKIE_SECURE', 'false').lower() == 'true'
SESSION_COOKIE_HTTPONLY: bool = True
SESSION_COOKIE_SAMESITE: str = os.environ.get('SESSION_COOKIE_SAMESITE', 'Lax')
PERMANENT_SESSION_LIFETIME: int = 3600 # 1 hour in seconds
def is_dev_mode(self) -> bool:
"""
Check if application is running in development mode.
:return: True if DEV_MODE is enabled, False otherwise.
"""
return self.DEV_MODE
def is_recaptcha_enabled(self) -> bool:
"""
Check if reCAPTCHA is properly configured.
:return: True if both secret and site keys are configured, False otherwise.
"""
return (self.RECAPTCHA_SECRET_KEY is not None and
self.RECAPTCHA_SITE_KEY is not None)
def is_zitadel_enabled(self) -> bool:
"""
Check if Zitadel OIDC is properly configured.
:return: True if all required Zitadel settings are present, False otherwise.
"""
return (self.ZITADEL_ISSUER is not None and
self.ZITADEL_CLIENT_ID is not None and
self.ZITADEL_CLIENT_SECRET is not None)
class DevelopmentConfig(Config):
"""
Development-specific configuration.
Overrides base configuration with development-friendly settings.
"""
DEBUG: bool = True
DEV_MODE: bool = True
SQLALCHEMY_ECHO: bool = True
SESSION_COOKIE_SECURE: bool = False
class ProductionConfig(Config):
"""
Production-specific configuration.
Overrides base configuration with production-safe settings.
"""
DEBUG: bool = False
DEV_MODE: bool = False
SQLALCHEMY_ECHO: bool = False
SESSION_COOKIE_SECURE: bool = True
SESSION_COOKIE_SAMESITE: str = 'Strict'
class TestingConfig(Config):
"""
Testing-specific configuration.
Overrides base configuration with test-friendly settings.
"""
TESTING: bool = True
SQLALCHEMY_DATABASE_URI: str = 'sqlite:///:memory:'
WTF_CSRF_ENABLED: bool = False
# Configuration mapping for easy access
config_map: dict = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'testing': TestingConfig,
'default': DevelopmentConfig if os.environ.get('FLASK_ENV', 'development') == 'development' else ProductionConfig
}