fargo: prevent pushing the same file many times (#22682)

Bug was discovered because we added the creation_date non-null field as
content_hash is the primary key. When saving a Document with the same
content_hash, Django try to update the existing document by setting
creation_date to NULL which fails.
This commit is contained in:
Benjamin Dauvergne 2018-03-27 13:08:06 +02:00
parent 7089a0fa7e
commit 2db8756f48
3 changed files with 9 additions and 2 deletions

View File

@ -10,6 +10,7 @@ class APIError(ValidationError):
NOT_STRING = {'code': 'not-string', 'msg': _('data is not a string')}
TOO_BIG = {'code': 'too-big', 'msg': _('file is too big (limit is {limit})')}
BOX_IS_FULL = {'code': 'box-is-full', 'msg': _('box is full (limit is {limit})')}
DOCUMENT_EXISTS = {'code': 'document-exists', 'msg': _('user already have this document')}
def __init__(self, kind, **kwargs):
assert hasattr(self, kind), 'error %s is not defined' % kind

View File

@ -121,8 +121,12 @@ class PushDocument(CommonAPIMixin, GenericAPIView):
document_file = data['file_b64_content']
if data.get('file_name'):
document_file.name = data.get('file_name')
document = Document(content=document_file)
document.save()
content_hash = utils.sha256_of_file(document_file)
document, created = Document.objects.get_or_create(
content_hash=content_hash,
defaults={'content': document_file})
if not created:
raise api_errors.APIError('DOCUMENT_EXISTS')
user_document = UserDocument(
user=data.get('user'),

View File

@ -83,6 +83,7 @@ def test_push_document(app, admin_user, john_doe):
assert (models.UserDocument.objects.get().origin
== models.Origin.objects.get())
data['file_b64_content'] = base64.b64encode('coin2')
data['deletable_by_user'] = False
response = app.post_json(url, params=data, status=200)
assert response.json['result'] == 1
@ -90,6 +91,7 @@ def test_push_document(app, admin_user, john_doe):
assert models.UserDocument.objects.count() == 2 # new document
assert models.UserDocument.objects.filter(deletable_by_user=False).count() == 1
data['file_b64_content'] = base64.b64encode('coin3')
data['deletable_by_user'] = True
response = app.post_json(url, params=data, status=200)
assert response.json['result'] == 1