summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2016-12-19 09:43:03 -0200
committerKali Kaneko <kali@leap.se>2017-02-09 17:41:37 +0100
commit6043f7966b64d6922987bca9137a524fb06a3379 (patch)
tree70f5416685405c084fbc5e4451565c460cb2203e
parent994eaa79b274c3c37af42cb343c41b5dec6e8d19 (diff)
[refactor] separate url mapper, avoid hanging tests
Because the wsgi resource has its own threadpool, tests might get confused when shutting down and the reactor may get clogged waiting for the threadpool to be stopped. By refactoring the URLMapper to its own module, server tests can avoid loading the resource module, where the wsgi threadpool resides, so the threapool will not be started.
-rw-r--r--server/src/leap/soledad/server/auth.py68
-rw-r--r--server/src/leap/soledad/server/session.py17
-rw-r--r--server/src/leap/soledad/server/url_mapper.py74
-rw-r--r--testing/tests/server/test_server.py2
4 files changed, 90 insertions, 71 deletions
diff --git a/server/src/leap/soledad/server/auth.py b/server/src/leap/soledad/server/auth.py
index c5b90359..13245cfe 100644
--- a/server/src/leap/soledad/server/auth.py
+++ b/server/src/leap/soledad/server/auth.py
@@ -21,7 +21,6 @@ import binascii
import time
from hashlib import sha512
-from routes.mapper import Mapper
from zope.interface import implementer
from twisted.cred import error
@@ -33,9 +32,7 @@ from twisted.cred.portal import Portal
from twisted.web.iweb import ICredentialFactory
from twisted.web.resource import IResource
-from leap.soledad.common import SHARED_DB_NAME
from leap.soledad.common.couch import couch_server
-from leap.soledad.common.l2db import DBNAME_CONSTRAINTS
from leap.soledad.server.resource import SoledadResource
from leap.soledad.server.application import get_config
@@ -119,68 +116,3 @@ class TokenCredentialFactory(object):
portal = Portal(SoledadRealm(), [TokenChecker()])
credentialFactory = TokenCredentialFactory()
-
-
-class URLMapper(object):
- """
- Maps the URLs users can access.
- """
-
- def __init__(self):
- self._map = Mapper(controller_scan=None)
- self._connect_urls()
- self._map.create_regs()
-
- def match(self, path, method):
- environ = {'PATH_INFO': path, 'REQUEST_METHOD': method}
- return self._map.match(environ=environ)
-
- def _connect(self, pattern, http_methods):
- self._map.connect(
- None, pattern, http_methods=http_methods,
- conditions=dict(method=http_methods),
- requirements={'dbname': DBNAME_CONSTRAINTS})
-
- def _connect_urls(self):
- """
- Register the authorization info in the mapper using C{SHARED_DB_NAME}
- as the user's database name.
-
- This method sets up the following authorization rules:
-
- URL path | Authorized actions
- --------------------------------------------------
- / | GET
- /shared-db | GET
- /shared-db/docs | -
- /shared-db/doc/{any_id} | GET, PUT, DELETE
- /shared-db/sync-from/{source} | -
- /user-db | -
- /user-db/docs | -
- /user-db/doc/{id} | -
- /user-db/sync-from/{source} | GET, PUT, POST
- """
- # auth info for global resource
- self._connect('/', ['GET'])
- # auth info for shared-db database resource
- self._connect('/%s' % SHARED_DB_NAME, ['GET'])
- # auth info for shared-db doc resource
- self._connect('/%s/doc/{id:.*}' % SHARED_DB_NAME,
- ['GET', 'PUT', 'DELETE'])
- # auth info for user-db sync resource
- self._connect('/user-{uuid}/sync-from/{source_replica_uid}',
- ['GET', 'PUT', 'POST'])
-
-
-@implementer(IResource)
-class UnauthorizedResource(object):
- isLeaf = True
-
- def render(self, request):
- request.setResponseCode(401)
- if request.method == b'HEAD':
- return b''
- return b'Unauthorized'
-
- def getChildWithDefault(self, path, request):
- return self
diff --git a/server/src/leap/soledad/server/session.py b/server/src/leap/soledad/server/session.py
index 75440089..1ef5b6a6 100644
--- a/server/src/leap/soledad/server/session.py
+++ b/server/src/leap/soledad/server/session.py
@@ -30,10 +30,9 @@ from twisted.web.server import Session
from zope.interface import Interface
from zope.interface import Attribute
-from leap.soledad.server.auth import URLMapper
from leap.soledad.server.auth import portal
from leap.soledad.server.auth import credentialFactory
-from leap.soledad.server.auth import UnauthorizedResource
+from leap.soledad.server.urlmapper import URLMapper
from leap.soledad.server.resource import SoledadResource
@@ -59,6 +58,20 @@ def _sessionData(request):
@implementer(IResource)
+class UnauthorizedResource(object):
+ isLeaf = True
+
+ def render(self, request):
+ request.setResponseCode(401)
+ if request.method == b'HEAD':
+ return b''
+ return b'Unauthorized'
+
+ def getChildWithDefault(self, path, request):
+ return self
+
+
+@implementer(IResource)
class SoledadSession(HTTPAuthSessionWrapper):
def __init__(self):
diff --git a/server/src/leap/soledad/server/url_mapper.py b/server/src/leap/soledad/server/url_mapper.py
new file mode 100644
index 00000000..483f7e87
--- /dev/null
+++ b/server/src/leap/soledad/server/url_mapper.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+# url_mapper.py
+# Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
+"""
+An URL mapper that represents authorized paths.
+"""
+from routes.mapper import Mapper
+
+from leap.soledad.common import SHARED_DB_NAME
+from leap.soledad.common.l2db import DBNAME_CONSTRAINTS
+
+
+class URLMapper(object):
+ """
+ Maps the URLs users can access.
+ """
+
+ def __init__(self):
+ self._map = Mapper(controller_scan=None)
+ self._connect_urls()
+ self._map.create_regs()
+
+ def match(self, path, method):
+ environ = {'PATH_INFO': path, 'REQUEST_METHOD': method}
+ return self._map.match(environ=environ)
+
+ def _connect(self, pattern, http_methods):
+ self._map.connect(
+ None, pattern, http_methods=http_methods,
+ conditions=dict(method=http_methods),
+ requirements={'dbname': DBNAME_CONSTRAINTS})
+
+ def _connect_urls(self):
+ """
+ Register the authorization info in the mapper using C{SHARED_DB_NAME}
+ as the user's database name.
+
+ This method sets up the following authorization rules:
+
+ URL path | Authorized actions
+ --------------------------------------------------
+ / | GET
+ /shared-db | GET
+ /shared-db/docs | -
+ /shared-db/doc/{any_id} | GET, PUT, DELETE
+ /shared-db/sync-from/{source} | -
+ /user-db | -
+ /user-db/docs | -
+ /user-db/doc/{id} | -
+ /user-db/sync-from/{source} | GET, PUT, POST
+ """
+ # auth info for global resource
+ self._connect('/', ['GET'])
+ # auth info for shared-db database resource
+ self._connect('/%s' % SHARED_DB_NAME, ['GET'])
+ # auth info for shared-db doc resource
+ self._connect('/%s/doc/{id:.*}' % SHARED_DB_NAME,
+ ['GET', 'PUT', 'DELETE'])
+ # auth info for user-db sync resource
+ self._connect('/user-{uuid}/sync-from/{source_replica_uid}',
+ ['GET', 'PUT', 'POST'])
diff --git a/testing/tests/server/test_server.py b/testing/tests/server/test_server.py
index 12f6fb20..39d8e8c3 100644
--- a/testing/tests/server/test_server.py
+++ b/testing/tests/server/test_server.py
@@ -43,7 +43,7 @@ from leap.soledad.client import _crypto
from leap.soledad.client import Soledad
from leap.soledad.server.config import load_configuration
from leap.soledad.server.config import CONFIG_DEFAULTS
-from leap.soledad.server.auth import URLMapper
+from leap.soledad.server.url_mapper import URLMapper
class ServerAuthorizationTestCase(BaseSoledadTest):