From 1aa9dee0ce87434188d37c821617caeff24fd70f Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Fri, 7 Jul 2017 02:58:09 -0300 Subject: [feature] add namespace support for BlobsManager 'namespace' argument is supported by backend but not yet exposed on API for clients. Since IncomingBox makes heavy usage of it, this commit exposes the argument as a query string for clients to use it. --- src/leap/soledad/client/_db/blobs.py | 4 ++-- src/leap/soledad/server/_blobs.py | 20 ++++++++++++-------- testing/tests/server/test_blobs_server.py | 12 ++++++++++++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/leap/soledad/client/_db/blobs.py b/src/leap/soledad/client/_db/blobs.py index 8f9f4769..604d4bef 100644 --- a/src/leap/soledad/client/_db/blobs.py +++ b/src/leap/soledad/client/_db/blobs.py @@ -240,7 +240,7 @@ class BlobManager(object): logger.error('sorry, dunno what happened') @defer.inlineCallbacks - def _encrypt_and_upload(self, blob_id, fd): + def _encrypt_and_upload(self, blob_id, fd, **params): # TODO ------------------------------------------ # this is wrong, is doing 2 stages. # the crypto producer can be passed to @@ -254,7 +254,7 @@ class BlobManager(object): crypter = BlobEncryptor(doc_info, fd, secret=self.secret, armor=False) fd = yield crypter.encrypt() - response = yield self._client.put(uri, data=fd) + response = yield self._client.put(uri, data=fd, params=params) check_http_status(response.code) logger.info("Finished upload: %s" % (blob_id,)) diff --git a/src/leap/soledad/server/_blobs.py b/src/leap/soledad/server/_blobs.py index 793149cd..7648e18e 100644 --- a/src/leap/soledad/server/_blobs.py +++ b/src/leap/soledad/server/_blobs.py @@ -184,23 +184,24 @@ class BlobsResource(resource.Resource): def render_GET(self, request): logger.info("http get: %s" % request.path) - user, blob_id = self._validate(request) + user, blob_id, namespace = self._validate(request) if not blob_id: order = request.args.get('order_by', [None])[0] - return self._handler.list_blobs(user, request, order_by=order) + return self._handler.list_blobs(user, request, namespace, + order_by=order) self._handler.add_tag_header(user, blob_id, request) - return self._handler.read_blob(user, blob_id, request) + return self._handler.read_blob(user, blob_id, request, namespace) def render_DELETE(self, request): logger.info("http put: %s" % request.path) - user, blob_id = self._validate(request) - self._handler.delete_blob(user, blob_id) + user, blob_id, namespace = self._validate(request) + self._handler.delete_blob(user, blob_id, namespace) return '' def render_PUT(self, request): logger.info("http put: %s" % request.path) - user, blob_id = self._validate(request) - d = self._handler.write_blob(user, blob_id, request) + user, blob_id, namespace = self._validate(request) + d = self._handler.write_blob(user, blob_id, request, namespace) d.addCallback(lambda _: request.finish()) d.addErrback(self._error, request) return NOT_DONE_YET @@ -214,7 +215,10 @@ class BlobsResource(resource.Resource): for arg in request.postpath: if arg and not VALID_STRINGS.match(arg): raise Exception('Invalid blob resource argument: %s' % arg) - return request.postpath + namespace = request.args.get('namespace', [''])[0] + if namespace and not VALID_STRINGS.match(namespace): + raise Exception('Invalid blob namespace: %s' % namespace) + return request.postpath + [namespace] if __name__ == '__main__': diff --git a/testing/tests/server/test_blobs_server.py b/testing/tests/server/test_blobs_server.py index bbb1b6d5..f4c9119b 100644 --- a/testing/tests/server/test_blobs_server.py +++ b/testing/tests/server/test_blobs_server.py @@ -80,6 +80,18 @@ class BlobServerTestCase(unittest.TestCase): blobs_list = yield manager.remote_list(order_by='-date') self.assertEquals(['blob_id1', 'blob_id2'], blobs_list) + @defer.inlineCallbacks + @pytest.mark.usefixtures("method_tmpdir") + def test_list_restricted_by_namespace(self): + manager = BlobManager('', self.uri, self.secret, + self.secret, 'user') + namespace = 'incoming' + yield manager._encrypt_and_upload('blob_id1', BytesIO("1"), + namespace=namespace) + yield manager._encrypt_and_upload('blob_id2', BytesIO("2")) + blobs_list = yield manager.remote_list(namespace=namespace) + self.assertEquals(['blob_id1'], blobs_list) + def __touch(self, *args): path = os.path.join(*args) with open(path, 'a'): -- cgit v1.2.3