diff --git a/src/xmpp_api/config/config.py b/src/xmpp_api/config/config.py index 69cfb47..0ae6472 100644 --- a/src/xmpp_api/config/config.py +++ b/src/xmpp_api/config/config.py @@ -1,11 +1,16 @@ import os -from typing import Annotated +from typing import Annotated, Self import logging -from pydantic import BaseModel +from pydantic import BaseModel, Field, model_validator from pydantic_yaml import parse_yaml_file_as from fastapi import Depends +from xmpp_api.exceptions.base import ConfigurationException + + +log = logging.getLogger("config") + class _ComponentConfig(BaseModel): # The JID of the component @@ -15,7 +20,20 @@ class _ComponentConfig(BaseModel): server: str # The component's secret. - secret: str + secret: str | None = Field(default=None) + + # Optional file to read the secret from + secret_file: str | None = Field(default=None) + + @model_validator(mode="after") + def validate_secret(self) -> Self: + if self.secret is None and self.secret_file is None: + raise ConfigurationException("No component secret is specified") + if self.secret is not None and self.secret_file is not None: + log.warn( + "Both secret and secret_file specified! secret_file takes precedence" + ) + return self class _Config(BaseModel): @@ -26,9 +44,6 @@ class _Config(BaseModel): component: _ComponentConfig -log = logging.getLogger("config") - - def load_config() -> _Config: """ Load the application config @@ -40,7 +55,15 @@ def load_config() -> _Config: log.info(f"Reading configuration from {config_path}") with open(config_path, "r", encoding="utf8") as f: - return parse_yaml_file_as(_Config, f) + config = parse_yaml_file_as(_Config, f) + + # Read the secret from a file, if specified + if config.component.secret_file is not None: + log.info("Reading component secret from %s", config.component.secret_file) + with open(config.component.secret_file, "r", encoding="utf8") as f: + config.component.secret = f.read().strip().replace("\n", "") + + return config ConfigDep = Annotated[_Config, Depends(load_config)] diff --git a/src/xmpp_api/exceptions/base.py b/src/xmpp_api/exceptions/base.py new file mode 100644 index 0000000..fbebae8 --- /dev/null +++ b/src/xmpp_api/exceptions/base.py @@ -0,0 +1,8 @@ +class ConfigurationException(Exception): + """ + Exception that is raised when there is an issue with + the configuration. + """ + + def __init__(self, msg: str): + super().__init__(msg)