dockerized läuft
This commit is contained in:
1 parent
a8c95e9df5
commit
1c789aa8d5
10 files changed
+735
-286
No files matched your search
+178
@@ -0,0 +1,178 @@
|
||||
# ==============================================================================
|
||||
# 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
|
||||
|
||||
|
||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
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',
|
||||
f'sqlite:///{os.path.join(BASE_DIR, "instance", "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
|
||||
}
|
||||
Reference in new issue
Block a user