diff --git a/changelog.d/18784.feature b/changelog.d/18784.feature new file mode 100644 index 000000000..51801e273 --- /dev/null +++ b/changelog.d/18784.feature @@ -0,0 +1 @@ +Support multiple config files in `register_new_matrix_user`. diff --git a/synapse/_scripts/register_new_matrix_user.py b/synapse/_scripts/register_new_matrix_user.py index 1ce822121..ff6e4e297 100644 --- a/synapse/_scripts/register_new_matrix_user.py +++ b/synapse/_scripts/register_new_matrix_user.py @@ -26,7 +26,7 @@ import hashlib import hmac import logging import sys -from typing import Any, Callable +from typing import Any, Callable, Iterable, TextIO import requests import yaml @@ -244,6 +244,7 @@ def main() -> None: group.add_argument( "-c", "--config", + action="append", type=argparse.FileType("r"), help="Path to server config file. Used to read in shared secret.", ) @@ -264,7 +265,7 @@ def main() -> None: config: dict[str, Any] | None = None if "config" in args and args.config: - config = yaml.safe_load(args.config) + config = _read_config_files(args.config) if args.shared_secret: secret = args.shared_secret @@ -326,6 +327,33 @@ def main() -> None: ) +# Adapted from synapse.config._base. +def _read_config_files(config_files: Iterable[TextIO]) -> dict[str, Any]: + """Read the config files and shallowly merge them into a dict. + + Successive configurations are shallowly merged into ones provided earlier, + i.e., entirely replacing top-level sections of the configuration. + + Args: + config_files: A list of the config files to read + + Returns: + The configuration dictionary. + """ + specified_config = {} + for config_file in config_files: + yaml_config = yaml.safe_load(config_file) + + if not isinstance(yaml_config, dict): + err = "File %r is empty or doesn't parse into a key-value map. IGNORING." + print(err % (config_file,)) + continue + + specified_config.update(yaml_config) + + return specified_config + + def _read_file(file_path: Any, config_path: str) -> str: """Check the given file exists, and read it into a string