From 27e3ca71f920083e8bf1599facc2cc4638f8efcf Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Mon, 23 Nov 2015 19:51:12 -0300 Subject: Return 422 if deletion failed This is needed for protecting against concurrent saves on drafts. --Issue #512 --- service/pixelated/adapter/mailstore/leap_mailstore.py | 2 ++ service/pixelated/adapter/mailstore/searchable_mailstore.py | 3 ++- service/pixelated/adapter/services/draft_service.py | 7 ++++--- service/pixelated/resources/mails_resource.py | 8 +++++++- service/test/unit/adapter/test_draft_service.py | 1 + 5 files changed, 16 insertions(+), 5 deletions(-) (limited to 'service') diff --git a/service/pixelated/adapter/mailstore/leap_mailstore.py b/service/pixelated/adapter/mailstore/leap_mailstore.py index f59034b8..3bf27bbf 100644 --- a/service/pixelated/adapter/mailstore/leap_mailstore.py +++ b/service/pixelated/adapter/mailstore/leap_mailstore.py @@ -291,6 +291,8 @@ class LeapMailStore(MailStore): message = yield self._fetch_msg_from_soledad(mail_id) if message and message.get_wrapper().mdoc.doc_id: yield message.get_wrapper().delete(self.soledad) + defer.returnValue(True) + defer.returnValue(False) @defer.inlineCallbacks def get_mailbox_mail_ids(self, mailbox_name): diff --git a/service/pixelated/adapter/mailstore/searchable_mailstore.py b/service/pixelated/adapter/mailstore/searchable_mailstore.py index 0c5310eb..07e99ba7 100644 --- a/service/pixelated/adapter/mailstore/searchable_mailstore.py +++ b/service/pixelated/adapter/mailstore/searchable_mailstore.py @@ -39,8 +39,9 @@ class SearchableMailStore(object): # implementes MailStore @defer.inlineCallbacks def delete_mail(self, mail_id): - yield self._delegate.delete_mail(mail_id) + removed = yield self._delegate.delete_mail(mail_id) self._search_engine.remove_from_index(mail_id) + defer.returnValue(removed) @defer.inlineCallbacks def update_mail(self, mail): diff --git a/service/pixelated/adapter/services/draft_service.py b/service/pixelated/adapter/services/draft_service.py index 70cc9136..98444442 100644 --- a/service/pixelated/adapter/services/draft_service.py +++ b/service/pixelated/adapter/services/draft_service.py @@ -29,6 +29,7 @@ class DraftService(object): @defer.inlineCallbacks def update_draft(self, ident, input_mail): - yield self._mail_store.delete_mail(ident) - new_draft = yield self.create_draft(input_mail) - defer.returnValue(new_draft) + removed = yield self._mail_store.delete_mail(ident) + if removed: + new_draft = yield self.create_draft(input_mail) + defer.returnValue(new_draft) diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index 201350b6..34dd042a 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -183,11 +183,17 @@ class MailsResource(Resource): err(error, 'error saving draft') respond_json_deferred("", request, status_code=422) + def updateCallback(pixelated_mail): + if not pixelated_mail: + respond_json_deferred("", request, status_code=422) + else: + respond_json_deferred({'ident': pixelated_mail.ident}, request) + if draft_id: deferred = self._draft_service.update_draft(draft_id, _mail) else: deferred = self._draft_service.create_draft(_mail) - deferred.addCallback(lambda pixelated_mail: respond_json_deferred({'ident': pixelated_mail.ident}, request)) + deferred.addCallback(updateCallback) deferred.addErrback(onError) return server.NOT_DONE_YET diff --git a/service/test/unit/adapter/test_draft_service.py b/service/test/unit/adapter/test_draft_service.py index 628b95d4..bf5e18c5 100644 --- a/service/test/unit/adapter/test_draft_service.py +++ b/service/test/unit/adapter/test_draft_service.py @@ -23,6 +23,7 @@ class DraftServiceTest(unittest.TestCase): def test_update_draft(self): mail = InputMail.from_dict(test_helper.mail_dict()) + when(self.mail_store).delete_mail(mail.ident).thenReturn(defer.succeed(True)) when(self.mail_store).add_mail('DRAFTS', mail.raw).thenReturn(defer.succeed(LeapMail('id', 'DRAFTS'))) self.draft_service.update_draft(mail.ident, mail) -- cgit v1.2.3