From 88f9ec3c34675c1838410046f31ff9264b78902a Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Thu, 14 Nov 2019 12:09:40 +0100 Subject: [PATCH] Add basic queryset filtering for StoredMessage (not yet good enough) This is not secure. A user might change their email to that of someone else, and then see the messages. Need a verified email class. --- apimail/api/views.py | 4 +++- apimail/managers.py | 37 ++++++++++++++++++++++++++++++++ apimail/models/stored_message.py | 3 +++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 apimail/managers.py diff --git a/apimail/api/views.py b/apimail/api/views.py index 8f64b915b..f5b06b66b 100644 --- a/apimail/api/views.py +++ b/apimail/api/views.py @@ -32,7 +32,9 @@ class StoredMessageListAPIView(ListAPIView): class StoredMessageRetrieveAPIView(RetrieveAPIView): - queryset = StoredMessage.objects.all() permission_classes = (IsAdminUser,) serializer_class = StoredMessageSerializer lookup_field = 'uuid' + + def get_queryset(self): + return StoredMessage.objects.filter_for_user(self.request.user) diff --git a/apimail/managers.py b/apimail/managers.py new file mode 100644 index 000000000..63e1eac12 --- /dev/null +++ b/apimail/managers.py @@ -0,0 +1,37 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django.db import models + + +class StoredMessageQuerySet(models.QuerySet): + """ + All StoredMessage querysets are always filtered for the user. + """ + def filter_for_user(self, request): + """ + Either su or staff, or user's email addresses overlap with sender/recipients. + """ + if not request.user.is_authenticated: + return self.none() + elif request.user.is_superuser or request.user.is_admin: + return self + emails = [request.user.email,] if request.user.email else [] + if request.user.contributor: + for pe in request.user.contributor.profile.emails.all(): + emails.append(pe.email) + return self.filter_for_emails(emails=emails) + + def filter_for_emails(self, emails): + """ + Ensure overlap of the emails in emails kwarg with those in sender or recipients. + """ + emails_used = emails + if not isinstance(emails, list): + emails_used = [emails] + emails_lower = [e.lower() for e in emails_used] + return self.filter( + models.Q(data__sender__in=emails_lower) | + models.Q(data__recipients__in=emails_lower) | # if recipients is a single entry + models.Q(data__recipients__overlap=emails_lower)) # if recipients is a list diff --git a/apimail/models/stored_message.py b/apimail/models/stored_message.py index f3e1bf895..1f5e01b9a 100644 --- a/apimail/models/stored_message.py +++ b/apimail/models/stored_message.py @@ -10,6 +10,7 @@ from django.urls import reverse from scipost.storage import SecureFileStorage +from ..managers import StoredMessageQuerySet from ..validators import validate_max_email_attachment_file_size @@ -23,6 +24,8 @@ class StoredMessage(models.Model): editable=False) data = JSONField(default=dict) + objects = StoredMessageQuerySet.as_manager() + class Meta: ordering = ['-data__Date',] -- GitLab