From 26a65d100f91883027c17c219d018461968eda65 Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Thu, 23 Mar 2017 20:33:20 -0300 Subject: [feature] add blobs listing --- client/src/leap/soledad/client/_blobs.py | 6 ++++++ server/src/leap/soledad/server/_blobs.py | 17 +++++++++++++++++ testing/tests/blobs/test_fs_backend.py | 9 +++++++++ testing/tests/server/test_blobs_server.py | 11 +++++++++++ 4 files changed, 43 insertions(+) diff --git a/client/src/leap/soledad/client/_blobs.py b/client/src/leap/soledad/client/_blobs.py index 7ecd4a4d..f9f1515b 100644 --- a/client/src/leap/soledad/client/_blobs.py +++ b/client/src/leap/soledad/client/_blobs.py @@ -157,6 +157,12 @@ class BlobManager(object): if hasattr(self, 'local') and self.local: return self.local.close() + @defer.inlineCallbacks + def list(self): + uri = urljoin(self.remote, self.user + '/') + data = yield self._client.get(uri) + defer.returnValue((yield data.json())) + @defer.inlineCallbacks def put(self, doc, size): fd = doc.blob_fd diff --git a/server/src/leap/soledad/server/_blobs.py b/server/src/leap/soledad/server/_blobs.py index 25266b18..3eac536e 100644 --- a/server/src/leap/soledad/server/_blobs.py +++ b/server/src/leap/soledad/server/_blobs.py @@ -27,6 +27,7 @@ environments. import commands import os import base64 +import json from twisted.logger import Logger from twisted.web import static @@ -65,6 +66,13 @@ class IBlobsBackend(Interface): :returns: a deferred that fires upon finishing. """ + def list_blobs(user, request): + """ + Returns a json-encoded list of ids from user's blob. + + :returns: a deferred that fires upon finishing. + """ + def tag_header(user, blob_id, request): """ Adds a header 'Tag' with the last 20 bytes of the encoded file, @@ -101,6 +109,13 @@ class FilesystemBlobsBackend(object): os.makedirs(blobs_path) self.path = blobs_path + def list_blobs(self, user, request): + blob_ids = [] + base_path = os.path.join(self.path, user) + for _, _, filenames in os.walk(base_path): + blob_ids += filenames + return json.dumps(blob_ids) + def tag_header(self, user, blob_id, request): with open(self._get_path(user, blob_id)) as doc_file: doc_file.seek(-16, 2) @@ -185,6 +200,8 @@ class BlobsResource(resource.Resource): def render_GET(self, request): logger.info("http get: %s" % request.path) user, blob_id = request.postpath + if not blob_id: + return self._handler.list_blobs(user, request) self._handler.tag_header(user, blob_id, request) return self._handler.read_blob(user, blob_id, request) diff --git a/testing/tests/blobs/test_fs_backend.py b/testing/tests/blobs/test_fs_backend.py index ce82fce0..5be6c17d 100644 --- a/testing/tests/blobs/test_fs_backend.py +++ b/testing/tests/blobs/test_fs_backend.py @@ -25,6 +25,7 @@ from mock import Mock import mock import os import base64 +import json import pytest @@ -86,3 +87,11 @@ class FilesystemBackendTestCase(unittest.TestCase): backend.path = '/somewhere/' path = backend._get_path('user', 'blob_id') assert path == '/somewhere/user/b/blo/blob_i/blob_id' + + @pytest.mark.usefixtures("method_tmpdir") + @mock.patch('leap.soledad.server._blobs.os.walk') + def test_list_blobs(self, walk_mock): + backend, _ = _blobs.FilesystemBlobsBackend(self.tempdir), None + walk_mock.return_value = [(_, _, ['blob_0']), (_, _, ['blob_1'])] + result = json.loads(backend.list_blobs('user', DummyRequest(['']))) + assert result == ['blob_0', 'blob_1'] diff --git a/testing/tests/server/test_blobs_server.py b/testing/tests/server/test_blobs_server.py index 1f35c285..3c534c0c 100644 --- a/testing/tests/server/test_blobs_server.py +++ b/testing/tests/server/test_blobs_server.py @@ -51,6 +51,17 @@ class BlobServerTestCase(unittest.TestCase): 'mydoc', '1') assert blob.getvalue() == "save me" + @defer.inlineCallbacks + @pytest.mark.usefixtures("method_tmpdir") + def test_upload_list(self): + manager = BlobManager('', self.uri, self.secret, + self.secret, 'user') + yield manager._encrypt_and_upload('blob_id1', '1', '1', BytesIO("1")) + yield manager._encrypt_and_upload('blob_id2', '2', '2', BytesIO("2")) + blobs_list = yield manager.list() + assert len(blobs_list) == 2 + assert 'blob_id1' in blobs_list and 'blob_id2' in blobs_list + @defer.inlineCallbacks @pytest.mark.usefixtures("method_tmpdir") def test_upload_deny_duplicates(self): -- cgit v1.2.3