From b73185d27fe5d59d64b0759c1efbbcdf89086d11 Mon Sep 17 00:00:00 2001 From: mnandri Date: Fri, 18 Dec 2015 11:21:48 +0100 Subject: ensuring the same file is not saved twice Issue #548 --- .../adapter/mailstore/leap_attachment_store.py | 10 +++++++--- .../adapter/mailstore/test_leap_attachment_store.py | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'service') diff --git a/service/pixelated/adapter/mailstore/leap_attachment_store.py b/service/pixelated/adapter/mailstore/leap_attachment_store.py index 86121db9..982d9222 100644 --- a/service/pixelated/adapter/mailstore/leap_attachment_store.py +++ b/service/pixelated/adapter/mailstore/leap_attachment_store.py @@ -17,7 +17,7 @@ class LeapAttachmentStore(object): @defer.inlineCallbacks def get_mail_attachment(self, attachment_id): results = yield self.soledad.get_from_index('by-type-and-payloadhash', 'cnt', attachment_id) if attachment_id else [] - if len(results): + if results: content = ContentDocWrapper(**results[0].content) defer.returnValue({'content-type': content.content_type, 'content': self._try_decode( content.raw, content.content_transfer_encoding)}) @@ -27,8 +27,12 @@ class LeapAttachmentStore(object): @defer.inlineCallbacks def add_attachment(self, content, content_type): cdoc = self._attachment_to_cdoc(content, content_type) - yield self.soledad.create_doc(cdoc.serialize(), doc_id=cdoc.phash) - defer.returnValue(cdoc.phash) + attachment_id = cdoc.phash + try: + yield self.get_mail_attachment(attachment_id) + except ValueError: + yield self.soledad.create_doc(cdoc.serialize(), doc_id=attachment_id) + defer.returnValue(attachment_id) def _try_decode(self, raw, encoding): encoding = encoding.lower() diff --git a/service/test/unit/adapter/mailstore/test_leap_attachment_store.py b/service/test/unit/adapter/mailstore/test_leap_attachment_store.py index 172cceb6..4e9b56b1 100644 --- a/service/test/unit/adapter/mailstore/test_leap_attachment_store.py +++ b/service/test/unit/adapter/mailstore/test_leap_attachment_store.py @@ -16,6 +16,7 @@ # along with Pixelated. If not, see . import json from uuid import uuid4 +import u1db from leap.mail.adaptors.soledad_indexes import MAIL_INDEXES from leap.soledad.common.document import SoledadDocument @@ -67,6 +68,26 @@ class TestLeapAttachmentStore(TestCase): verify(self.soledad).create_doc(cdoc_serialized, doc_id=attachment_id) + @defer.inlineCallbacks + def test_store_attachment_twice_does_not_cause_exception(self): + attachment_id = '9863729729D2E2EE8E52F0A7115CE33AD18DDA4B58E49AE08DD092D1C8E699B0' + content = 'this is some attachment content' + content_type = 'text/plain' + cdoc_serialized = {'content_transfer_encoding': 'base64', 'lkf': [], 'content_disposition': 'attachment', + 'ctype': '', 'raw': 'dGhpcyBpcyBzb21lIGF0dGFjaG1lbnQgY29udGVudA==', + 'phash': '9863729729D2E2EE8E52F0A7115CE33AD18DDA4B58E49AE08DD092D1C8E699B0', + 'content_type': 'text/plain', 'type': 'cnt'} + doc = SoledadDocument(json=json.dumps({'content_type': content_type, 'raw': content})) + when(self.soledad).get_from_index('by-type-and-payloadhash', 'cnt', attachment_id).thenReturn(defer.succeed([doc])) + + store = LeapAttachmentStore(self.soledad) + + when(self.soledad).create_doc(cdoc_serialized, doc_id=attachment_id).thenRaise(u1db.errors.RevisionConflict()) + + actual_attachment_id = yield store.add_attachment(content, content_type) + + self.assertEqual(attachment_id, actual_attachment_id) + @defer.inlineCallbacks def test_get_mail_attachment_different_content_encodings(self): attachment_id = '1B0A9AAD9E153D24265395203C53884506ABA276394B9FEC02B214BF9E77E48E' -- cgit v1.2.3