From f0c7f630b2e7dfcf6a7bda913dbd21ebd6c4ec12 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Sun, 25 Oct 2020 10:53:18 +0100 Subject: [PATCH] Turn apimail.views into a package --- apimail/api/serializers/composed_message.py | 5 +- apimail/api/views/__init__.py | 21 +++ apimail/api/views/account.py | 32 ++++ apimail/api/views/attachment.py | 17 ++ apimail/api/views/composed_message.py | 78 ++++++++ apimail/api/views/event.py | 23 +++ .../api/{views.py => views/stored_message.py} | 166 +----------------- apimail/api/views/tag.py | 44 +++++ apimail/models/account.py | 2 + apimail/models/composed_message.py | 1 + 10 files changed, 225 insertions(+), 164 deletions(-) create mode 100644 apimail/api/views/__init__.py create mode 100644 apimail/api/views/account.py create mode 100644 apimail/api/views/attachment.py create mode 100644 apimail/api/views/composed_message.py create mode 100644 apimail/api/views/event.py rename apimail/api/{views.py => views/stored_message.py} (53%) create mode 100644 apimail/api/views/tag.py diff --git a/apimail/api/serializers/composed_message.py b/apimail/api/serializers/composed_message.py index 705b46219..827ae4f05 100644 --- a/apimail/api/serializers/composed_message.py +++ b/apimail/api/serializers/composed_message.py @@ -9,10 +9,7 @@ from ...models import ( ComposedMessage, ComposedMessageAPIResponse, AttachmentFile, ) -from ..serializers import ( - ComposedMessageAPIResponseSerializer, - AttachmentFileSerializer -) +from ..serializers import AttachmentFileSerializer class ComposedMessageAPIResponseSerializer(serializers.ModelSerializer): diff --git a/apimail/api/views/__init__.py b/apimail/api/views/__init__.py new file mode 100644 index 000000000..e14b3a275 --- /dev/null +++ b/apimail/api/views/__init__.py @@ -0,0 +1,21 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from .account import EmailAccountListAPIView, UserEmailAccountAccessListAPIView + +from .attachment import AttachmentFileCreateAPIView + +from .event import EventListAPIView, EventRetrieveAPIView + +from .tag import UserTagCreateAPIView, UserTagDestroyAPIView, UserTagListAPIView + +from .composed_message import ( + ComposedMessageCreateAPIView, ComposedMessageUpdateAPIView, + ComposedMessageDestroyAPIView, ComposedMessageListAPIView +) + +from .stored_message import ( + StoredMessageListAPIView, StoredMessageRetrieveAPIView, + StoredMessageUpdateReadAPIView, StoredMessageUpdateTagAPIView +) diff --git a/apimail/api/views/account.py b/apimail/api/views/account.py new file mode 100644 index 000000000..1c91dbbf8 --- /dev/null +++ b/apimail/api/views/account.py @@ -0,0 +1,32 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + +from rest_framework.generics import ListAPIView +from rest_framework.permissions import IsAdminUser, IsAuthenticated + +from ...models import EmailAccount + +from ..serializers import EmailAccountSerializer, EmailAccountAccessSerializer + + +class EmailAccountListAPIView(ListAPIView): + permission_classes = (IsAdminUser,) + queryset = EmailAccount.objects.all() + serializer_class = EmailAccountSerializer + + +class UserEmailAccountAccessListAPIView(ListAPIView): + """ + ListAPIView returning request.user's email account accesses. + """ + + permission_classes = (IsAuthenticated,) + serializer_class = EmailAccountAccessSerializer + + def get_queryset(self): + queryset = self.request.user.email_account_accesses.all() + if self.request.query_params.get('current', None) == 'true': + queryset = queryset.current() + if self.request.query_params.get('cansend', None) == 'true': + queryset = queryset.can_send() + return queryset diff --git a/apimail/api/views/attachment.py b/apimail/api/views/attachment.py new file mode 100644 index 000000000..95b70db84 --- /dev/null +++ b/apimail/api/views/attachment.py @@ -0,0 +1,17 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from rest_framework.generics import CreateAPIView +from rest_framework.parsers import FormParser, MultiPartParser +from rest_framework.permissions import IsAuthenticated + +from ...models import AttachmentFile +from ..serializers import AttachmentFileSerializer + + +class AttachmentFileCreateAPIView(CreateAPIView): + permission_classes = (IsAuthenticated,) + queryset = AttachmentFile.objects.all() + serializer_class = AttachmentFileSerializer + parser_classes = [FormParser, MultiPartParser,] diff --git a/apimail/api/views/composed_message.py b/apimail/api/views/composed_message.py new file mode 100644 index 000000000..3a4584c6f --- /dev/null +++ b/apimail/api/views/composed_message.py @@ -0,0 +1,78 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from rest_framework.generics import ( + CreateAPIView, ListAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView +) + +from rest_framework.permissions import IsAdminUser, IsAuthenticated +from rest_framework.response import Response +from rest_framework import status + +from ...models import ComposedMessage +from ..serializers import ComposedMessageSerializer +from ...permissions import CanHandleComposedMessage + + +class ComposedMessageCreateAPIView(CreateAPIView): + permission_classes = (IsAuthenticated,) + queryset = ComposedMessage.objects.all() + serializer_class = ComposedMessageSerializer + lookup_field = 'uuid' + + def create(self, request, *args, **kwargs): + # Override rest_framework.mixins.CreateModelMixin.create in order + # to include request.user in data, and attachment_uuids for serializer.create + data = request.data + data['author'] = request.user.id + serializer = self.get_serializer(data=data) + serializer.is_valid(raise_exception=True) + # Attachment uuids passed as extra args to be popped in serializer.create + serializer.save(attachment_uuids=request.data['attachment_uuids']) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + + +class ComposedMessageUpdateAPIView(UpdateAPIView): + permission_classes = (IsAuthenticated, CanHandleComposedMessage,) + queryset = ComposedMessage.objects.all() + serializer_class = ComposedMessageSerializer + lookup_field = 'uuid' + + def update(self, request, *args, **kwargs): + # Override rest_framework.mixins.CreateModelMixin.update in order + # to include request.user in data, and attachment_uuids for serializer.update + partial = kwargs.pop('partial', False) + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=partial) + serializer.is_valid(raise_exception=True) + serializer.save(attachment_uuids=request.data['attachment_uuids']) + + if getattr(instance, '_prefetched_objects_cache', None): + # If 'prefetch_related' has been applied to a queryset, we need to + # forcibly invalidate the prefetch cache on the instance. + instance._prefetched_objects_cache = {} + + return Response(serializer.data) + + +class ComposedMessageDestroyAPIView(DestroyAPIView): + permission_classes = (IsAuthenticated, CanHandleComposedMessage,) + serializer_class = ComposedMessageSerializer + lookup_field = 'uuid' + + def get_queryset(self): + return ComposedMessage.objects.filter_for_user(self.request.user) + + +class ComposedMessageListAPIView(ListAPIView): + permission_classes = (IsAuthenticated,) + serializer_class = ComposedMessageSerializer + lookup_field = 'uuid' + + def get_queryset(self): + queryset = ComposedMessage.objects.filter_for_user(self.request.user) + if self.request.query_params.get('status', None) == 'draft': + queryset = queryset.filter(status=ComposedMessage.STATUS_DRAFT) + return queryset diff --git a/apimail/api/views/event.py b/apimail/api/views/event.py new file mode 100644 index 000000000..cd62ead41 --- /dev/null +++ b/apimail/api/views/event.py @@ -0,0 +1,23 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from rest_framework.generics import ListAPIView, RetrieveAPIView +from rest_framework.permissions import IsAdminUser + +from ...models import Event +from ..serializers import EventSerializer + + +class EventListAPIView(ListAPIView): + permission_classes = (IsAdminUser,) + queryset = Event.objects.all() + serializer_class = EventSerializer + lookup_field = 'uuid' + + +class EventRetrieveAPIView(RetrieveAPIView): + permission_classes = (IsAdminUser,) + queryset = Event.objects.all() + serializer_class = EventSerializer + lookup_field = 'uuid' diff --git a/apimail/api/views.py b/apimail/api/views/stored_message.py similarity index 53% rename from apimail/api/views.py rename to apimail/api/views/stored_message.py index 05fc3b93a..ffb01b783 100644 --- a/apimail/api/views.py +++ b/apimail/api/views/stored_message.py @@ -8,139 +8,16 @@ from django.db.models import Q from django.shortcuts import get_object_or_404 from django.utils import timezone -from rest_framework.generics import ( - CreateAPIView, DestroyAPIView, ListAPIView, - RetrieveAPIView, UpdateAPIView) -from rest_framework.parsers import FormParser, MultiPartParser -from rest_framework.permissions import IsAdminUser, IsAuthenticated +from rest_framework.generics import ListAPIView, RetrieveAPIView, UpdateAPIView +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from rest_framework import filters, status +from rest_framework import filters -from ..models import ( - EmailAccount, - AttachmentFile, - ComposedMessage, - Event, - StoredMessage, UserTag) -from ..permissions import ( - CanHandleComposedMessage, - CanHandleStoredMessage, CanReadStoredMessage) +from ...models import StoredMessage, UserTag +from ..serializers import StoredMessageSerializer -from .serializers import ( - EmailAccountSerializer, EmailAccountAccessSerializer, - AttachmentFileSerializer, - ComposedMessageSerializer, - EventSerializer, - StoredMessageSerializer, - UserTagSerializer) - - -class EmailAccountListAPIView(ListAPIView): - permission_classes = (IsAdminUser,) - queryset = EmailAccount.objects.all() - serializer_class = EmailAccountSerializer - - -class UserEmailAccountAccessListAPIView(ListAPIView): - """ - ListAPIView returning request.user's email account accesses. - """ - - permission_classes = (IsAuthenticated,) - serializer_class = EmailAccountAccessSerializer - - def get_queryset(self): - queryset = self.request.user.email_account_accesses.all() - if self.request.query_params.get('current', None) == 'true': - queryset = queryset.current() - if self.request.query_params.get('cansend', None) == 'true': - queryset = queryset.can_send() - return queryset - - -class AttachmentFileCreateAPIView(CreateAPIView): - permission_classes = (IsAuthenticated,) - queryset = AttachmentFile.objects.all() - serializer_class = AttachmentFileSerializer - parser_classes = [FormParser, MultiPartParser,] - - -class ComposedMessageCreateAPIView(CreateAPIView): - permission_classes = (IsAuthenticated,) - queryset = ComposedMessage.objects.all() - serializer_class = ComposedMessageSerializer - lookup_field = 'uuid' - - def create(self, request, *args, **kwargs): - # Override rest_framework.mixins.CreateModelMixin.create in order - # to include request.user in data, and attachment_uuids for serializer.create - data = request.data - data['author'] = request.user.id - serializer = self.get_serializer(data=data) - serializer.is_valid(raise_exception=True) - # Attachment uuids passed as extra args to be popped in serializer.create - serializer.save(attachment_uuids=request.data['attachment_uuids']) - headers = self.get_success_headers(serializer.data) - return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) - - -class ComposedMessageUpdateAPIView(UpdateAPIView): - permission_classes = (IsAuthenticated, CanHandleComposedMessage,) - queryset = ComposedMessage.objects.all() - serializer_class = ComposedMessageSerializer - lookup_field = 'uuid' - - def update(self, request, *args, **kwargs): - # Override rest_framework.mixins.CreateModelMixin.update in order - # to include request.user in data, and attachment_uuids for serializer.update - partial = kwargs.pop('partial', False) - instance = self.get_object() - serializer = self.get_serializer(instance, data=request.data, partial=partial) - serializer.is_valid(raise_exception=True) - serializer.save(attachment_uuids=request.data['attachment_uuids']) - - if getattr(instance, '_prefetched_objects_cache', None): - # If 'prefetch_related' has been applied to a queryset, we need to - # forcibly invalidate the prefetch cache on the instance. - instance._prefetched_objects_cache = {} - - return Response(serializer.data) - - -class ComposedMessageDestroyAPIView(DestroyAPIView): - permission_classes = (IsAuthenticated, CanHandleComposedMessage,) - serializer_class = ComposedMessageSerializer - lookup_field = 'uuid' - - def get_queryset(self): - return ComposedMessage.objects.filter_for_user(self.request.user) - - -class ComposedMessageListAPIView(ListAPIView): - permission_classes = (IsAuthenticated,) - serializer_class = ComposedMessageSerializer - lookup_field = 'uuid' - - def get_queryset(self): - queryset = ComposedMessage.objects.filter_for_user(self.request.user) - if self.request.query_params.get('status', None) == 'draft': - queryset = queryset.filter(status=ComposedMessage.STATUS_DRAFT) - return queryset - - -class EventListAPIView(ListAPIView): - permission_classes = (IsAdminUser,) - queryset = Event.objects.all() - serializer_class = EventSerializer - lookup_field = 'uuid' - - -class EventRetrieveAPIView(RetrieveAPIView): - permission_classes = (IsAdminUser,) - queryset = Event.objects.all() - serializer_class = EventSerializer - lookup_field = 'uuid' +from ...permissions import CanReadStoredMessage class StoredMessageFilterBackend(filters.BaseFilterBackend): @@ -275,37 +152,6 @@ class StoredMessageUpdateReadAPIView(UpdateAPIView): return Response() -class UserTagCreateAPIView(CreateAPIView): - permission_classes = (IsAuthenticated,) - queryset = UserTag.objects.all() - serializer_class = UserTagSerializer - - def create(self, request, *args, **kwargs): - data = request.data - data['user'] = request.user.id - serializer = self.get_serializer(data=data) - serializer.is_valid(raise_exception=True) - self.perform_create(serializer) - headers = self.get_success_headers(serializer.data) - return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) - - -class UserTagDestroyAPIView(DestroyAPIView): - permission_classes = (IsAuthenticated,) - serializer_class = UserTagSerializer - - def get_queryset(self): - return UserTag.objects.filter(user=self.request.user) - - -class UserTagListAPIView(ListAPIView): - permission_classes = (IsAuthenticated,) - serializer_class = UserTagSerializer - - def get_queryset(self): - return self.request.user.email_tags.all() - - class StoredMessageUpdateTagAPIView(UpdateAPIView): """ Adds or removes a user tag on a StoredMessage. diff --git a/apimail/api/views/tag.py b/apimail/api/views/tag.py new file mode 100644 index 000000000..772ab4395 --- /dev/null +++ b/apimail/api/views/tag.py @@ -0,0 +1,44 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from rest_framework.generics import ( + CreateAPIView, DestroyAPIView, ListAPIView, +) +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework import status + +from ...models import UserTag +from ..serializers import UserTagSerializer + + +class UserTagCreateAPIView(CreateAPIView): + permission_classes = (IsAuthenticated,) + queryset = UserTag.objects.all() + serializer_class = UserTagSerializer + + def create(self, request, *args, **kwargs): + data = request.data + data['user'] = request.user.id + serializer = self.get_serializer(data=data) + serializer.is_valid(raise_exception=True) + self.perform_create(serializer) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + + +class UserTagDestroyAPIView(DestroyAPIView): + permission_classes = (IsAuthenticated,) + serializer_class = UserTagSerializer + + def get_queryset(self): + return UserTag.objects.filter(user=self.request.user) + + +class UserTagListAPIView(ListAPIView): + permission_classes = (IsAuthenticated,) + serializer_class = UserTagSerializer + + def get_queryset(self): + return self.request.user.email_tags.all() diff --git a/apimail/models/account.py b/apimail/models/account.py index fb59da3d1..cb2fb9e66 100644 --- a/apimail/models/account.py +++ b/apimail/models/account.py @@ -2,6 +2,8 @@ _copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" +import pytz + from django.conf import settings from django.core.exceptions import ValidationError from django.db import models diff --git a/apimail/models/composed_message.py b/apimail/models/composed_message.py index 654f911d2..68b123702 100644 --- a/apimail/models/composed_message.py +++ b/apimail/models/composed_message.py @@ -2,6 +2,7 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" +import pytz import uuid as uuid_lib from django.conf import settings -- GitLab