87 lines
1.9 KiB
Python
87 lines
1.9 KiB
Python
"""Configuration classes and utilities."""
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
from typing import Dict, List, Optional
|
|
|
|
import toml
|
|
import dacite
|
|
|
|
from flask import current_app
|
|
|
|
|
|
@dataclass
|
|
class CoreConfig:
|
|
"""Core application configuration."""
|
|
|
|
debug: bool = False
|
|
port: int = 5000
|
|
|
|
|
|
@dataclass
|
|
class OidcConfig:
|
|
"""OIDC client configuration."""
|
|
|
|
issuer: str
|
|
client_id: str
|
|
client_secret: Optional[str] = None
|
|
client_secret_file: Optional[str] = None
|
|
scopes: List[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass
|
|
class AppConfig:
|
|
"""App link configuration."""
|
|
|
|
url: str
|
|
name: Optional[str] = None
|
|
image: Optional[str] = None
|
|
description: Optional[str] = None
|
|
groups: List[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass
|
|
class Config:
|
|
"""Top-level configuration."""
|
|
|
|
core: CoreConfig
|
|
oidc: OidcConfig
|
|
apps: Dict[str, AppConfig] = field(default_factory=dict)
|
|
|
|
|
|
class ConfigError(Exception):
|
|
pass
|
|
|
|
|
|
def _validate(config: Config) -> None:
|
|
oidc = config.oidc
|
|
if oidc.client_secret is None and oidc.client_secret_file is None:
|
|
raise ConfigError(
|
|
"exactly one of oidc.client_secret or oidc.client_secret_file is required"
|
|
)
|
|
if oidc.client_secret is not None and oidc.client_secret_file is not None:
|
|
raise ConfigError(
|
|
"exactly one of oidc.client_secret or oidc.client_secret_file is required"
|
|
)
|
|
|
|
|
|
def load(file: str) -> Config:
|
|
"""
|
|
Load the configuration from a `file` path containing a TOML configuration.
|
|
|
|
:param file: a file path to a TOML config
|
|
:return: the configuration object
|
|
"""
|
|
path = Path(file)
|
|
cfg = dacite.from_dict(data_class=Config, data=toml.load(path))
|
|
_validate(cfg)
|
|
return cfg
|
|
|
|
|
|
def current_config() -> Config:
|
|
"""
|
|
Load the configuration from the current Flask app.
|
|
|
|
:return: the configuration object
|
|
"""
|
|
return current_app.config["user_config"]
|