[bug] handle path exceptions using twisted failures
authordrebs <drebs@leap.se>
Sat, 9 Dec 2017 15:44:29 +0000 (13:44 -0200)
committerdrebs <drebs@leap.se>
Wed, 13 Dec 2017 15:49:28 +0000 (13:49 -0200)
src/leap/soledad/server/_blobs.py
tests/blobs/test_fs_backend.py

index cb72678..554fe5a 100644 (file)
@@ -95,13 +95,19 @@ class FilesystemBlobsBackend(object):
 
     def read_blob(self, user, blob_id, namespace=''):
         logger.info('reading blob: %s - %s@%s' % (user, blob_id, namespace))
-        path = self._get_path(user, blob_id, namespace)
+        try:
+            path = self._get_path(user, blob_id, namespace)
+        except Exception as e:
+            return defer.fail(e)
         logger.debug('blob path: %s' % path)
         fd = open(path)
         return defer.succeed(fd)
 
     def get_flags(self, user, blob_id, namespace=''):
-        path = self._get_path(user, blob_id, namespace)
+        try:
+            path = self._get_path(user, blob_id, namespace)
+        except Exception as e:
+            return defer.fail(e)
         if not os.path.isfile(path):
             return defer.fail(BlobNotFound())
         if not os.path.isfile(path + '.flags'):
@@ -111,7 +117,10 @@ class FilesystemBlobsBackend(object):
             return defer.succeed(flags)
 
     def set_flags(self, user, blob_id, flags, namespace=''):
-        path = self._get_path(user, blob_id, namespace)
+        try:
+            path = self._get_path(user, blob_id, namespace)
+        except Exception as e:
+            return defer.fail(e)
         if not os.path.isfile(path):
             return defer.fail(BlobNotFound())
         for flag in flags:
@@ -142,7 +151,10 @@ class FilesystemBlobsBackend(object):
         yield self.semaphore.release()
 
     def delete_blob(self, user, blob_id, namespace=''):
-        blob_path = self._get_path(user, blob_id, namespace)
+        try:
+            blob_path = self._get_path(user, blob_id, namespace)
+        except Exception as e:
+            return defer.fail(e)
         if not os.path.isfile(blob_path):
             return defer.fail(BlobNotFound())
         self.__touch(blob_path + '.deleted')
@@ -154,12 +166,18 @@ class FilesystemBlobsBackend(object):
         return defer.succeed(None)
 
     def get_blob_size(self, user, blob_id, namespace=''):
-        blob_path = self._get_path(user, blob_id, namespace)
+        try:
+            blob_path = self._get_path(user, blob_id, namespace)
+        except Exception as e:
+            return defer.fail(e)
         size = os.stat(blob_path).st_size
         return defer.succeed(size)
 
     def count(self, user, namespace=''):
-        base_path = self._get_path(user, namespace=namespace)
+        try:
+            base_path = self._get_path(user, namespace=namespace)
+        except Exception as e:
+            return defer.fail(e)
         count = 0
         for _, _, filenames in os.walk(base_path):
             count += len(filter(lambda i: not i.endswith('.flags'), filenames))
@@ -169,7 +187,10 @@ class FilesystemBlobsBackend(object):
                    filter_flag=False):
         namespace = namespace or 'default'
         blob_ids = []
-        base_path = self._get_path(user, namespace=namespace)
+        try:
+            base_path = self._get_path(user, namespace=namespace)
+        except Exception as e:
+            return defer.fail(e)
 
         def match(name):
             if deleted:
@@ -202,10 +223,17 @@ class FilesystemBlobsBackend(object):
                 yield blob_path
 
     def get_total_storage(self, user):
-        return self._get_disk_usage(self._get_path(user))
+        try:
+            path = self._get_path(user)
+        except Exception as e:
+            return defer.fail(e)
+        return self._get_disk_usage(path)
 
     def get_tag(self, user, blob_id, namespace=''):
-        blob_path = self._get_path(user, blob_id, namespace)
+        try:
+            blob_path = self._get_path(user, blob_id, namespace)
+        except Exception as e:
+            return defer.fail(e)
         if not os.path.isfile(blob_path):
             return defer.fail(BlobNotFound())
         with open(blob_path) as doc_file:
@@ -236,8 +264,11 @@ class FilesystemBlobsBackend(object):
         return desired_path
 
     def exists(self, user, blob_id, namespace):
-        return os.path.isfile(
-            self._get_path(user, blob_id=blob_id, namespace=namespace))
+        try:
+            path = self._get_path(user, blob_id=blob_id, namespace=namespace)
+        except Exception as e:
+            return defer.fail(e)
+        return os.path.isfile(path)
 
     def _get_path(self, user, blob_id='', namespace=''):
         parts = [user]
index 28be483..5b3ff30 100644 (file)
@@ -142,18 +142,19 @@ class FilesystemBackendTestCase(unittest.TestCase):
         target_dir = os.path.join(self.tempdir, 'user', 'incoming')
         walk_mock.assert_called_once_with(target_dir)
 
+    @defer.inlineCallbacks
     @pytest.mark.usefixtures("method_tmpdir")
     def test_path_validation_on_read_blob(self):
         blobs_path, request = self.tempdir, DummyRequest([''])
         backend = _blobs.FilesystemBlobsBackend(blobs_path=blobs_path)
         with pytest.raises(Exception):
-            backend.read_blob('..', '..', request)
+            yield backend.read_blob('..', '..', request)
         with pytest.raises(Exception):
-            backend.read_blob('user', '../../../', request)
+            yield backend.read_blob('user', '../../../', request)
         with pytest.raises(Exception):
-            backend.read_blob('../../../', 'blob_id', request)
+            yield backend.read_blob('../../../', 'blob_id', request)
         with pytest.raises(Exception):
-            backend.read_blob('user', 'blob_id', request, namespace='..')
+            yield backend.read_blob('user', 'blob_id', request, namespace='..')
 
     @pytest.mark.usefixtures("method_tmpdir")
     @defer.inlineCallbacks