From 0e12cd3eb1e20bb867f34e0bf60f280d93b6182d Mon Sep 17 00:00:00 2001 From: drebs Date: Wed, 18 Jan 2017 17:28:01 -0200 Subject: [feature] add server config option for blobs --- server/src/leap/soledad/server/_blobs.py | 34 ++++++++++++ server/src/leap/soledad/server/_config.py | 81 ++++++++++++++++++++++++++++ server/src/leap/soledad/server/_resource.py | 22 ++++++-- server/src/leap/soledad/server/_wsgi.py | 18 ++----- server/src/leap/soledad/server/auth.py | 2 +- server/src/leap/soledad/server/config.py | 67 ----------------------- server/src/leap/soledad/server/entrypoint.py | 4 +- testing/tests/server/test_server.py | 3 +- 8 files changed, 140 insertions(+), 91 deletions(-) create mode 100644 server/src/leap/soledad/server/_blobs.py create mode 100644 server/src/leap/soledad/server/_config.py delete mode 100644 server/src/leap/soledad/server/config.py diff --git a/server/src/leap/soledad/server/_blobs.py b/server/src/leap/soledad/server/_blobs.py new file mode 100644 index 00000000..0424aae0 --- /dev/null +++ b/server/src/leap/soledad/server/_blobs.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# _blobs.py +# Copyright (C) 2017 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Blobs Server implementation. +""" +from twisted.web import resource + + +__all__ = ['blobs_resource'] + + +class BlobsResource(resource.Resource): + + isLeaf = True + + def render_GET(self, request): + return 'blobs is not implemented yet!' + + +blobs_resource = BlobsResource() diff --git a/server/src/leap/soledad/server/_config.py b/server/src/leap/soledad/server/_config.py new file mode 100644 index 00000000..2c7f530d --- /dev/null +++ b/server/src/leap/soledad/server/_config.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# config.py +# Copyright (C) 2016 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +import configparser + + +__all__ = ['get_config'] + + +CONFIG_DEFAULTS = { + 'soledad-server': { + 'couch_url': 'http://localhost:5984', + 'create_cmd': None, + 'admin_netrc': '/etc/couchdb/couchdb-admin.netrc', + 'batching': True, + 'blobs': False, + }, + 'database-security': { + 'members': ['soledad'], + 'members_roles': [], + 'admins': [], + 'admins_roles': [] + } +} + + +_config = None + + +def get_config(): + global _config + if not _config: + _config = _load_config('/etc/soledad/soledad-server.conf') + return _config['soledad-server'] + + +def _load_config(file_path): + """ + Load server configuration from file. + + @param file_path: The path to the configuration file. + @type file_path: str + + @return: A dictionary with the configuration. + @rtype: dict + """ + conf = dict(CONFIG_DEFAULTS) + config = configparser.SafeConfigParser() + config.read(file_path) + for section in conf: + if not config.has_section(section): + continue + for key, value in conf[section].items(): + if not config.has_option(section, key): + continue + elif type(value) == bool: + conf[section][key] = config.getboolean(section, key) + elif type(value) == list: + values = config.get(section, key).split(',') + values = [v.strip() for v in values] + conf[section][key] = values + else: + conf[section][key] = config.get(section, key) + # TODO: implement basic parsing/sanitization of options comming from + # config file. + return conf diff --git a/server/src/leap/soledad/server/_resource.py b/server/src/leap/soledad/server/_resource.py index 4070d786..4f8e98df 100644 --- a/server/src/leap/soledad/server/_resource.py +++ b/server/src/leap/soledad/server/_resource.py @@ -17,8 +17,10 @@ """ A twisted resource that serves the Soledad Server. """ +from twisted.web.error import Error from twisted.web.resource import Resource +from ._blobs import blobs_resource from ._wsgi import get_sync_resource @@ -33,11 +35,21 @@ class SoledadResource(Resource): def __init__(self, sync_pool=None): sync_resource = get_sync_resource(sync_pool) - self.children = {'': sync_resource} + self.children = { + 'sync': sync_resource, + 'blobs': blobs_resource, + } def getChild(self, path, request): - # for now, just "rewind" the path and serve the wsgi resource for all - # requests. In the future, we might look into the request path to - # decide which child resources should serve each request. + """ + Decide which child resource to serve based on the given path. + """ + if path == 'blobs': + if not self._blobs_enabled: + msg = 'Blobs feature is disabled in this server.' + raise Error(403, message=msg) + return self.children['blobs'] + + # rewind the path and serve the wsgi sync resource request.postpath.insert(0, request.prepath.pop()) - return self.children[''] + return self.children['sync'] diff --git a/server/src/leap/soledad/server/_wsgi.py b/server/src/leap/soledad/server/_wsgi.py index 3e30d560..c00d00ae 100644 --- a/server/src/leap/soledad/server/_wsgi.py +++ b/server/src/leap/soledad/server/_wsgi.py @@ -27,7 +27,6 @@ from twisted.web.wsgi import WSGIResource from leap.soledad.server import SoledadApp from leap.soledad.server.gzip_middleware import GzipMiddleware -from leap.soledad.server.config import load_configuration from leap.soledad.common.backend import SoledadBackend from leap.soledad.common.couch.state import CouchServerState from leap.soledad.common.log import getLogger @@ -36,18 +35,7 @@ from leap.soledad.common.log import getLogger __all__ = ['init_couch_state', 'get_sync_resource'] -_config = None - - -def get_config(): - global _config - if not _config: - _config = load_configuration('/etc/soledad/soledad-server.conf') - return _config['soledad-server'] - - -def _get_couch_state(): - conf = get_config() +def _get_couch_state(conf): state = CouchServerState(conf['couch_url'], create_cmd=conf['create_cmd'], check_schema_versions=True) SoledadBackend.BATCH_SUPPORT = conf.get('batching', False) @@ -67,9 +55,9 @@ wsgi_application = GzipMiddleware(_app) # work. Because of that, we delay couch state initialization until the reactor # is running. -def init_couch_state(_app): +def init_couch_state(conf): try: - _app.state = _get_couch_state() + _app.state = _get_couch_state(conf) except Exception as e: logger = getLogger() logger.error(str(e)) diff --git a/server/src/leap/soledad/server/auth.py b/server/src/leap/soledad/server/auth.py index a5d90c46..d7ccdeb9 100644 --- a/server/src/leap/soledad/server/auth.py +++ b/server/src/leap/soledad/server/auth.py @@ -36,7 +36,7 @@ from twisted.web.resource import IResource from leap.soledad.common.couch import couch_server from ._resource import SoledadResource -from ._wsgi import get_config +from ._config import get_config @implementer(IRealm) diff --git a/server/src/leap/soledad/server/config.py b/server/src/leap/soledad/server/config.py deleted file mode 100644 index 3c17ec19..00000000 --- a/server/src/leap/soledad/server/config.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# config.py -# Copyright (C) 2016 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -import configparser - - -CONFIG_DEFAULTS = { - 'soledad-server': { - 'couch_url': 'http://localhost:5984', - 'create_cmd': None, - 'admin_netrc': '/etc/couchdb/couchdb-admin.netrc', - 'batching': True - }, - 'database-security': { - 'members': ['soledad'], - 'members_roles': [], - 'admins': [], - 'admins_roles': [] - } -} - - -def load_configuration(file_path): - """ - Load server configuration from file. - - @param file_path: The path to the configuration file. - @type file_path: str - - @return: A dictionary with the configuration. - @rtype: dict - """ - defaults = dict(CONFIG_DEFAULTS) - config = configparser.SafeConfigParser() - config.read(file_path) - for section in defaults: - if not config.has_section(section): - continue - for key, value in defaults[section].items(): - if not config.has_option(section, key): - continue - elif type(value) == bool: - defaults[section][key] = config.getboolean(section, key) - elif type(value) == list: - values = config.get(section, key).split(',') - values = [v.strip() for v in values] - defaults[section][key] = values - else: - defaults[section][key] = config.get(section, key) - # TODO: implement basic parsing/sanitization of options comming from - # config file. - return defaults diff --git a/server/src/leap/soledad/server/entrypoint.py b/server/src/leap/soledad/server/entrypoint.py index 7501a447..714490ae 100644 --- a/server/src/leap/soledad/server/entrypoint.py +++ b/server/src/leap/soledad/server/entrypoint.py @@ -19,13 +19,13 @@ The entrypoint for Soledad server. """ from twisted.internet import reactor -from .config import load_configuration +from ._config import get_config from ._session import SoledadSession from ._wsgi import init_couch_state # load configuration from file -conf = load_configuration('/etc/soledad/soledad-server.conf') +conf = get_config class SoledadEntrypoint(SoledadSession): diff --git a/testing/tests/server/test_server.py b/testing/tests/server/test_server.py index da69c423..866d9eab 100644 --- a/testing/tests/server/test_server.py +++ b/testing/tests/server/test_server.py @@ -379,5 +379,6 @@ class ConfigurationParsingTest(unittest.TestCase): 'sudo -u soledad-admin /usr/bin/create-user-db', 'admin_netrc': '/etc/couchdb/couchdb-soledad-admin.netrc', - 'batching': False} + 'batching': False, + 'blobs': False} self.assertDictEqual(expected, config['soledad-server']) -- cgit v1.2.3