pdf-tei-editor / docs /development /configuration.md
cmboulanger's picture
disaster-recovery deploy of pdf-tei-editor
6a49f21 verified
|
Raw
History Blame Contribute Delete
6.77 kB

Configuration Management

The PDF-TEI-Editor uses JSON configuration files to manage application settings. Configuration can be managed via the command-line interface.

For programmatic use, see Configuration Processing Architecture.

Configuration Files

  • data/db/config.json - Runtime configuration (user-specific, gitignored)
  • config/config.json - Default configuration (version-controlled)

Configuration Processing Architecture

Backend Processing

Configuration values are processed through a high-level API that abstracts storage details.

fastapi_app/lib/utils/config_utils.py

Provides a Config class and module-level configuration instance:

High-Level API (recommended):

from fastapi_app.lib.utils.config_utils import get_config

# Get config instance (lazy initialization)
config = get_config()

# Get configuration values
value = config.get('session.timeout', default=3600)

# Set configuration values (with validation)
success, message = config.set('session.timeout', 7200)

# Delete configuration keys
success, message = config.delete('old.key')

# Load complete configuration
config_data = config.load()

The get_config() function returns a module-level config instance preconfigured with settings.db_dir, so you don't need to pass directory paths.

Alternative - Custom Config Instance:

For testing or custom db_dir:

from fastapi_app.lib.utils.config_utils import Config
from pathlib import Path

custom_config = Config(Path('/custom/db/dir'))
value = custom_config.get('key')

Configuration Features:

  • Type validation: If <key>.type exists, validates value matches required JSON type
  • Values constraints: If <key>.values exists, validates value is in allowed values
  • Auto-typing: New keys automatically get a .type constraint based on value's JSON type
  • Thread-safe: Uses cross-platform file locking (fcntl on Unix, msvcrt on Windows)
  • Dot notation: Supports keys like session.timeout and session.cookie.name

Using Configuration in Backend Routes

Configuration is accessed via get_config():

from fastapi import APIRouter
from fastapi_app.lib.utils.config_utils import get_config

router = APIRouter()

@router.get("/my-endpoint")
async def my_endpoint():
    # Get config instance
    config = get_config()

    # Get configuration values
    timeout = config.get('session.timeout', default=3600)
    mode = config.get('application.mode', default='production')

    return {
        "timeout": timeout,
        "mode": mode
    }

For Settings Properties:

Access environment variables and static settings via the Settings object:

from fastapi_app.config import get_settings

settings = get_settings()
host = settings.HOST
port = settings.PORT
data_root = settings.data_root  # Path property
db_dir = settings.db_dir        # Path property

Settings Properties:

  • Environment variables: HOST, PORT, DATA_ROOT, WEBDAV_ENABLED, LOG_LEVEL, etc.
  • Path properties: data_root, db_dir, upload_dir, config_dir
  • Dynamic properties: session_timeout (checks environment, then config.json, then default)
  • The Settings class is cached via @lru_cache, so get_settings() returns the same instance

Setting Config Values:

from fastapi_app.lib.utils.config_utils import get_config
from fastapi import HTTPException

@router.post("/custom-config")
async def set_custom(key: str, value: str):
    # Get config instance
    config = get_config()

    # Write custom config value (validates constraints)
    success, message = config.set(key, value)

    if not success:
        raise HTTPException(status_code=400, detail=message)

    return {"result": message}

fastapi_app/api/config.py

REST API endpoints for configuration access:

  • GET /api/v1/config/list: Returns complete configuration object
  • GET /api/v1/config/get/{key}: Returns specific configuration value by key
  • POST /api/v1/config/set: Sets a configuration value (requires authentication)
    • Request body: {"key": "config.key", "value": <json_value>}
    • Validates user authentication via session
    • Calls set_config_value() which performs validation
    • Logs the configuration change with username

Frontend Integration

app/src/plugins/config.js

The config plugin provides client-side access to configuration:

  • API Methods:

    • get(key, defaultValue, updateFirst=false): Retrieves a configuration value. If updateFirst is true, fetches fresh data from server before returning.
    • set(key, value): Sets a configuration value on the server. Validates the key exists before attempting to set.
    • load(): Fetches configuration data from server and updates local cache.
    • toMap(): Returns configuration as a Map object.
  • Usage Pattern:

    import { api as config } from './plugins/config.js';
    
    // Get a value (uses cached data)
    const mode = await config.get('application.mode');
    
    // Get with fresh data from server
    const interval = await config.get('heartbeat.interval', 30, true);
    
    // Set a value (updates server)
    await config.set('application.mode', 'production');
    
    // Reload configuration cache
    await config.load();
    
  • Internal State:

    • Maintains a local configMap object cached from server
    • Automatically loads config on first get() call if not already loaded
    • Uses client.getConfigData() to fetch from /api/v1/config/list
    • Uses client.setConfigValue(key, value) to update via /api/v1/config/set

Configuration Flow

  1. Initial Load:

    • Frontend calls config.get() for the first time
    • Plugin fetches complete config via GET /api/v1/config/list
    • Backend calls config.load() to read data/db/config.json
    • Data is cached in configMap object
  2. Reading Values:

    • Frontend calls config.get(key) using cached data
    • Or config.get(key, default, true) to force server refresh
    • Backend uses config.get(key, default) for server-side reads
  3. Writing Values:

    • Frontend calls config.set(key, value)
    • Validates key exists in cached config (throws error if not)
    • Sends POST /api/v1/config/set with JSON body
    • Backend validates authentication and session
    • Backend calls config.set(key, value) which:
      • Acquires file lock on config.json
      • Loads current config
      • Validates value constraints and type
      • Writes updated config
      • Releases file lock
  4. CLI Usage:

    • CLI calls Python functions from bin/manage.py
    • Uses low-level config_utils.py functions directly
    • No authentication required for CLI access