summary refs log tree commit diff
diff options
context:
space:
mode:
authorJorik Schellekens <joriks@matrix.org>2019-08-23 16:33:47 +0100
committerJorik Schellekens <joriks@matrix.org>2019-08-28 15:59:54 +0100
commitd63a58462f4c0e6b0d7a8f34390b8bed63fe2b08 (patch)
treea5a51845467e187ae0e87bc8c871b70cd8f14f4d
parentWe're not using these (diff)
downloadsynapse-d63a58462f4c0e6b0d7a8f34390b8bed63fe2b08.tar.xz
Make the model stateless.
-rw-r--r--synapse_topology/model/__init__.py136
-rw-r--r--synapse_topology/model/constants.py5
-rw-r--r--synapse_topology/model/errors.py7
-rw-r--r--synapse_topology/model/util.py9
-rw-r--r--synapse_topology/server/error_handlers.py6
5 files changed, 83 insertions, 80 deletions
diff --git a/synapse_topology/model/__init__.py b/synapse_topology/model/__init__.py
index 3e3e2de3d2..eb91917935 100644
--- a/synapse_topology/model/__init__.py
+++ b/synapse_topology/model/__init__.py
@@ -1,7 +1,7 @@
 import yaml
 import subprocess
 
-from os.path import abspath, join
+from os.path import abspath, join, exists, isdir
 
 from synapse.config.homeserver import HomeServerConfig
 
@@ -12,83 +12,81 @@ from .constants import (
     DATA_SUBDIR,
     SERVER_NAME,
 )
-from .errors import BasConfigInUseError, BaseConfigNotFoundError, ConfigNotFoundError
+from .errors import BaseConfigInUseError, ConfigNotFoundError, ServernameNotSetError
 from .config import create_config
+from .util import is_subpath
 
+from synapse.config import find_config_files, read_config_files
 
-def set_config_dir(conf_dir):
-    global config_dir
-    global data_dir
-    config_dir = abspath(conf_dir)
-    data_dir = abspath(join(config_dir, "./data"))
 
+class Model:
+    """
+    The Model brokers modification of the config file and signing keys in the config
+    directory.
+    """
+
+    def __init__(self, config_dir):
+        self.config_dir = abspath(config_dir)
+        self.data_dir = abspath(join(self.config_dir, DATA_SUBDIR))
+        if not isdir(self.config_dir) or not isdir(self.data_dir):
+            raise FileNotFoundError()
 
-def get_config_dir():
-    return config_dir
+    def get_config(self, config_path):
+        """
+        Retrieves a config from the config directory. Any path can be provided
+        but it must be a subdirectory of self.config_dir
 
+        Args:
+            config_path (str): path to the config
 
-def get_data_dir():
-    return data_dir
+        Returns:
+            dict: the yaml parse of the config file
+        """
+        conf_path = abspath(join(self.config_dir, config_path))
 
+        if not is_subpath(config_dir, conf_path):
+            raise FileNotFoundError()
 
-def get_config():
-    conf_path = join(config_dir, BASE_CONFIG)
-    try:
         with open(conf_path, "r") as f:
             return yaml.safe_load(f)
-    except FileNotFoundError:
-        raise BaseConfigNotFoundError()
-
-
-def set_config(config):
-    if config_in_use():
-        raise BasConfigInUseError()
 
-    for conf_name, conf in create_config(config_dir, data_dir, config).items():
-        with open(abspath(join(get_config_dir(), conf_name)), "w") as f:
-            f.write(conf)
-
-
-def config_in_use():
-    """
-    Checks if we set whether the config is in use. If it was set up by the system
-    but synapse wasn't launched yet we will have set this to False. However if
-    it's not present we assume someone else has set up synapse before so we assume
-    the config is in use.
-    """
-    try:
-        return get_config().get(CONFIG_LOCK, True)
-    except FileNotFoundError:
-        return False
-
-
-def generate_base_config(server_name, report_stats):
-    if config_in_use():
-        raise BasConfigInUseError()
-
-    conf = HomeServerConfig().generate_config(
-        config_dir,
-        join(config_dir, DATA_SUBDIR),
-        server_name,
-        generate_secrets=True,
-        report_stats=report_stats,
-    )
-
-    with open(join(config_dir, BASE_CONFIG), "w") as f:
-        f.write(conf)
-        f.write(CONFIG_LOCK_DATA)
-
-
-def get_server_name():
-    config = get_config()
-    if config:
-        return config.get(SERVER_NAME)
-
-
-def get_secret_key():
-    config = get_config()
-    server_name = config.get(SERVER_NAME)
-    signing_key_path = join(config_dir, server_name + ".signing.key")
-    subprocess.run(["generate_signing_key.py", "-o", signing_key_path])
-    with open(signing_key_path, "r") as f:
-        return f.read()
+    def write_config(self, config):
+        """
+        Given a config generates a templated config from synapse and writes it
+        out to the config dir. It will raise an exception if the config in
+        the config directory is in use.
+
+        Args:
+            config (dict): The configuration to template out.
+        """
+        if self.config_in_use():
+            raise BaseConfigInUseError()
+
+        for conf_name, conf in create_config(
+            self.config_dir, self.data_dir, config
+        ).items():
+            with open(abspath(join(self.config_dir, conf_name)), "w") as f:
+                f.write(conf)
+
+    def config_in_use(self):
+        """
+        Checks if we set whether the config is in use. If it was set up by the system
+        but synapse wasn't launched yet we will have set this to False. However if
+        it's not present we assume someone else has set up synapse before so we assume
+        the config is in use.
+        """
+        try:
+            return read_config_files(find_config_files(self.config_dir)).get(
+                CONFIG_LOCK, True
+            )
+        except FileNotFoundError:
+            return False
+
+    def generate_secret_key(self, server_name):
+        if self.config_in_use():
+            raise BaseConfigInUseError()
+
+        signing_key_path = join(self.config_dir, server_name + ".signing.key")
+        subprocess.run(["generate_signing_key.py", "-o", signing_key_path])
+        with open(signing_key_path, "r") as f:
+            return f.read()
diff --git a/synapse_topology/model/constants.py b/synapse_topology/model/constants.py
index a3b4d2240b..f847083db6 100644
--- a/synapse_topology/model/constants.py
+++ b/synapse_topology/model/constants.py
@@ -1,7 +1,4 @@
 # Paths
-BASE_CONFIG = "homeserver.yaml"
-# TODO: fill in further configs
-CONFIGS = [BASE_CONFIG, "user.yaml", "optimizations.yaml", "something.yaml"]
 DATA_SUBDIR = "data"
 
 # Config options
@@ -17,7 +14,7 @@ CONFIG_LOCK_DATA = """
 # Specifies whether synapse has been started with this config.
 # If set to True the setup util will not go through the initialization
 # phase which sets the server name and server keys.
-{}: False
+{}: {{}}
 
 
 """.format(
diff --git a/synapse_topology/model/errors.py b/synapse_topology/model/errors.py
index 4a36752d95..cbe9c5d819 100644
--- a/synapse_topology/model/errors.py
+++ b/synapse_topology/model/errors.py
@@ -9,10 +9,9 @@ class ConfigNotFoundError(FileNotFoundError):
         return self.config_name
 
 
-class BaseConfigNotFoundError(ConfigNotFoundError):
-    def __init__(self):
-        super().__init__(BASE_CONFIG)
+class ServernameNotSetError(Exception):
+    pass
 
 
-class BasConfigInUseError(Exception):
+class BaseConfigInUseError(Exception):
     pass
diff --git a/synapse_topology/model/util.py b/synapse_topology/model/util.py
new file mode 100644
index 0000000000..aad2de4efe
--- /dev/null
+++ b/synapse_topology/model/util.py
@@ -0,0 +1,9 @@
+from os.path import realpath, pardir, sep, relpath
+
+
+def is_subpath(superpath, subpath):
+    subpath = realpath(subpath)
+    superpath = realpath(superpath)
+    relative = relpath(subpath, superpath)
+    return not relative.startswith(pardir + sep)
+
diff --git a/synapse_topology/server/error_handlers.py b/synapse_topology/server/error_handlers.py
index 22825159d0..f43083322d 100644
--- a/synapse_topology/server/error_handlers.py
+++ b/synapse_topology/server/error_handlers.py
@@ -2,8 +2,8 @@ from jsonschema import ValidationError
 from simplejson.errors import JSONDecodeError
 from synapse_topology.model.errors import (
     BasConfigInUseError,
-    BaseConfigNotFoundError,
     ConfigNotFoundError,
+    ServernameNotSetError,
 )
 
 from . import app
@@ -22,8 +22,8 @@ def json_decode_error(request, failure):
     return "Invalid post json"
 
 
-@app.handle_errors(BaseConfigNotFoundError)
-def base_config_not_found(request, failure):
+@app.handle_errors(ServernameNotSetError)
+def not_initialised(request, failure):
     request.setResponseCode(500)
     return "Config file not setup, please initialise it using the /servername endpoint"