From 0722d2a6e9243e760233c8a9c6a50a19624432bf Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Wed, 5 Feb 2020 08:03:57 +0100 Subject: [PATCH] Add ComposedMessageAttachment model --- apimail/admin.py | 13 ++++++++-- .../0015_composedmessageattachment.py | 24 +++++++++++++++++++ apimail/models/__init__.py | 2 +- apimail/models/composed_message.py | 20 ++++++++++++++++ apimail/views.py | 13 +++++++--- 5 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 apimail/migrations/0015_composedmessageattachment.py diff --git a/apimail/admin.py b/apimail/admin.py index b0d30561c..a9382eb59 100644 --- a/apimail/admin.py +++ b/apimail/admin.py @@ -6,7 +6,7 @@ from django.contrib import admin from .models import ( EmailAccount, EmailAccountAccess, - ComposedMessage, ComposedMessageAPIResponse, + ComposedMessage, ComposedMessageAPIResponse, ComposedMessageAttachment, Event, StoredMessage, StoredMessageAttachment, UserTag) @@ -29,8 +29,17 @@ class ComposedMessageAPIResponseInline(admin.StackedInline): extra = 0 min_num = 0 + +class ComposedMessageAttachmentInline(admin.StackedInline): + model = ComposedMessageAttachment + extra = 0 + min_num = 0 + + class ComposedMessageAdmin(admin.ModelAdmin): - inlines = [ComposedMessageAPIResponseInline,] + inlines = [ + ComposedMessageAttachmentInline, + ComposedMessageAPIResponseInline,] admin.site.register(ComposedMessage, ComposedMessageAdmin) diff --git a/apimail/migrations/0015_composedmessageattachment.py b/apimail/migrations/0015_composedmessageattachment.py new file mode 100644 index 000000000..098215a09 --- /dev/null +++ b/apimail/migrations/0015_composedmessageattachment.py @@ -0,0 +1,24 @@ +# Generated by Django 2.1.8 on 2020-02-05 07:02 + +import apimail.validators +from django.db import migrations, models +import django.db.models.deletion +import scipost.storage + + +class Migration(migrations.Migration): + + dependencies = [ + ('apimail', '0014_auto_20200131_0956'), + ] + + operations = [ + migrations.CreateModel( + name='ComposedMessageAttachment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('_file', models.FileField(storage=scipost.storage.SecureFileStorage(), upload_to='uploads/mail/composed_messages/attachments/%Y/%m/%d/', validators=[apimail.validators.validate_max_email_attachment_file_size])), + ('message', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='apimail.ComposedMessage')), + ], + ), + ] diff --git a/apimail/models/__init__.py b/apimail/models/__init__.py index f211191ef..07d51db2e 100644 --- a/apimail/models/__init__.py +++ b/apimail/models/__init__.py @@ -4,7 +4,7 @@ __license__ = "AGPL v3" from .account import EmailAccount, EmailAccountAccess -from .composed_message import ComposedMessage, ComposedMessageAPIResponse +from .composed_message import ComposedMessage, ComposedMessageAPIResponse, ComposedMessageAttachment from .event import Event diff --git a/apimail/models/composed_message.py b/apimail/models/composed_message.py index 1d3a22ec6..2e2e32a5f 100644 --- a/apimail/models/composed_message.py +++ b/apimail/models/composed_message.py @@ -7,9 +7,13 @@ import uuid as uuid_lib from django.conf import settings from django.contrib.postgres.fields import ArrayField, JSONField from django.db import models +from django.urls import reverse from django.utils import timezone +from scipost.storage import SecureFileStorage + from ..managers import ComposedMessageQuerySet +from ..validators import validate_max_email_attachment_file_size class ComposedMessage(models.Model): @@ -88,3 +92,19 @@ class ComposedMessageAPIResponse(models.Model): class Meta: ordering = ['-datetime'] + + +class ComposedMessageAttachment(models.Model): + message = models.ForeignKey( + 'apimail.ComposedMessage', + on_delete=models.CASCADE, + related_name='attachments' + ) + _file = models.FileField( + upload_to='uploads/mail/composed_messages/attachments/%Y/%m/%d/', + validators=[validate_max_email_attachment_file_size,], + storage=SecureFileStorage()) + + def get_absolute_url(self): + return reverse('apimail:composed_message_attachment', + kwargs={'uuid': self.message.uuid, 'pk': self.id}) diff --git a/apimail/views.py b/apimail/views.py index 1a61e6857..67825ad1e 100644 --- a/apimail/views.py +++ b/apimail/views.py @@ -7,12 +7,19 @@ import mimetypes from django.http import HttpResponse from django.shortcuts import get_object_or_404 -from .models import StoredMessage, StoredMessageAttachment +from .models import ComposedMessageAttachment, StoredMessageAttachment def attachment_file(request, uuid, pk): - att = get_object_or_404(StoredMessageAttachment, - message__uuid=uuid, id=pk) + """ + Return an attachment to either a Composed Message or a StoredMessage. + """ + try: + att = ComposedMessageAttachment.objects.get( + message__uuid=uuid, id=pk) + except ComposedMessageAttachment.DoesNotExist: + att = get_object_or_404(StoredMessageAttachment, + message__uuid=uuid, id=pk) content_type, encoding = mimetypes.guess_type(att._file.path) content_type = content_type or 'application/octet-stream' response = HttpResponse(att._file.read(), content_type=content_type) -- GitLab