From e55afbbb9323b629e34be0fb7a52dc18a0fd9deb Mon Sep 17 00:00:00 2001 From: "arnaud.morvan@camptocamp.com" Date: Tue, 7 Feb 2017 16:39:17 +0100 Subject: [PATCH] Add view delete --- c2corg_images/__init__.py | 1 + c2corg_images/storage.py | 2 ++ c2corg_images/views.py | 20 ++++++++++++++++++++ tests/inside/test_storage.py | 3 +++ tests/inside/test_views.py | 32 +++++++++++++++++++++++++++++++- 5 files changed, 57 insertions(+), 1 deletion(-) diff --git a/c2corg_images/__init__.py b/c2corg_images/__init__.py index 491a73fd..e145efbd 100644 --- a/c2corg_images/__init__.py +++ b/c2corg_images/__init__.py @@ -31,6 +31,7 @@ def cors_headers(request, response): config.add_route('ping', '/ping') config.add_route('upload', '/upload') config.add_route('publish', '/publish') +config.add_route('delete', '/delete') config.add_static_view(name='active', path=os.environ['ACTIVE_FOLDER']) config.add_subscriber(add_cors_headers_response_callback, NewRequest) diff --git a/c2corg_images/storage.py b/c2corg_images/storage.py index 7559109f..b700084d 100644 --- a/c2corg_images/storage.py +++ b/c2corg_images/storage.py @@ -178,6 +178,8 @@ def put(self, key, path): shutil.copyfile(path, self.object_path(key)) def delete(self, key): + if not self.exists(key): + return os.unlink(self.object_path(key)) def copy(self, key, other_storage): diff --git a/c2corg_images/views.py b/c2corg_images/views.py index a16d8830..9b1f43c2 100644 --- a/c2corg_images/views.py +++ b/c2corg_images/views.py @@ -105,3 +105,23 @@ def publish(request): for key in resized_keys(filename): incoming_storage.move(key, active_storage) return {'success': True} + + +@view_config(route_name='delete', renderer='json') +def delete(request): + if request.POST['secret'] != os.environ['API_SECRET_KEY']: + raise HTTPForbidden('Bad secret key') + filenames = request.POST.getall('filenames') + for filename in filenames: + try: + active_storage.delete(filename) + except Exception: + log.error('Deleting {} failed'.format(filename), exc_info=True) + + for key in resized_keys(filename): + try: + active_storage.delete(key) + except Exception: + log.error('Deleting {} failed'.format(key), exc_info=True) + + return {'success': True} diff --git a/tests/inside/test_storage.py b/tests/inside/test_storage.py index 0acff95f..c6eea190 100644 --- a/tests/inside/test_storage.py +++ b/tests/inside/test_storage.py @@ -52,6 +52,9 @@ def standard_protocol(self): self.active_storage.delete(key) assert not self.active_storage.exists(key) + # delete file that does not exists + self.active_storage.delete('test_not_exists.jpg') + def resizing_protocol(self): # for resizing object is in active storage self.active_storage.put(key, source_file) diff --git a/tests/inside/test_views.py b/tests/inside/test_views.py index 8429cceb..5b421978 100644 --- a/tests/inside/test_views.py +++ b/tests/inside/test_views.py @@ -1,5 +1,5 @@ import unittest -from unittest.mock import patch +from unittest.mock import patch, call from webtest import TestApp from c2corg_images import app @@ -23,3 +23,33 @@ def test_publish_good_secret(self, publish_mock): {'secret': 'good_secret', 'filename': 'test.png'}, status=200) + + @patch('c2corg_images.views.active_storage.delete') + def test_delete_svg(self, delete_mock): + """Test delete with one svg filename""" + self.app.post('/delete', + {'secret': 'good_secret', + 'filenames': ['test.svg']}, + status=200) + delete_mock.assert_has_calls([ + call('test.svg'), + call('testBI.jpg'), + call('testMI.jpg'), + call('testSI.jpg')]) + + @patch('c2corg_images.views.active_storage.delete') + def test_delete_multi(self, delete_mock): + """Test delete with multiple filenames""" + self.app.post('/delete', + {'secret': 'good_secret', + 'filenames': ['test1.jpg', 'test2.jpg']}, + status=200) + delete_mock.assert_has_calls([ + call('test1.jpg'), + call('test1BI.jpg'), + call('test1MI.jpg'), + call('test1SI.jpg'), + call('test2.jpg'), + call('test2BI.jpg'), + call('test2MI.jpg'), + call('test2SI.jpg')])