import secrets from pathlib import Path from typing import Literal from fastapi.templating import Jinja2Templates from pydantic import BaseSettings # Directories file_dir = Path(__file__).parent templates_dir = str(file_dir.parent / 'templates') static_dir = str(file_dir.parent / 'static') # Main configuration class Settings(BaseSettings): version: str = '1.0.0' debug: bool = False session_key: str = 'secret' csrf_key: str = 'secret' app_host: str = '127.0.0.1' app_port: int = 8000 # Type alias for secret keys settings fields SecretKey = Literal['session_key', 'csrf_key'] # Settings class instantiating settings = Settings() # Jinja templates handler templates = Jinja2Templates( directory=templates_dir, ) def secret_key_check(name: SecretKey) -> None: """Generates a secret key automatically if an environment variable is not set or contains text `secret`""" settings_dict = settings.dict() if settings_dict.get(name) != 'secret': return key_file = Path(f'/tmp/{name}') if key_file.exists(): with key_file.open('rt', encoding='utf-8') as f: key = f.read() else: key = secrets.token_hex(32) with key_file.open('wt', encoding='utf-8') as f: f.write(key) settings_dict[name] = key # Calling the function # for session and CSRF keys secret_key_check('session_key') secret_key_check('csrf_key')