From 92283ca678fac2e03f98c23d0eda4c8b4ce047c1 Mon Sep 17 00:00:00 2001 From: George Katsikas <giorgakis.katsikas@gmail.com> Date: Mon, 18 Mar 2024 16:02:21 +0100 Subject: [PATCH] add notes managers --- scipost_django/pins/managers.py | 54 +++++++++++++++++++++++++++++++++ scipost_django/pins/models.py | 4 +++ 2 files changed, 58 insertions(+) create mode 100644 scipost_django/pins/managers.py diff --git a/scipost_django/pins/managers.py b/scipost_django/pins/managers.py new file mode 100644 index 000000000..483504b96 --- /dev/null +++ b/scipost_django/pins/managers.py @@ -0,0 +1,54 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + +from typing import Optional +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType +from django.db import models + + +class NotesQuerySet(models.QuerySet): + + def visible_to( + self, + user: Optional[User] = None, + model: Optional[models.Model] = None, + ): + """ + Filter out notes which are not visible to the given user. + """ + + if user is None: + # Without specifying a user, only public notes are visible + return self.filter(visibility=self.model.VISIBILITY_PUBLIC) + else: + # Filter non-author users from viewing private notes + self = self.exclude( + models.Q(visibility=self.model.VISIBILITY_PRIVATE) + & ~models.Q(author=user.contributor) + ) + + # Filter out internal notes unless the user has the default "manager" + # permission for the given object, e.g. "can_manage_subsidies" + # If no model is given, just filter out all of them + model_plural = str(model._meta.verbose_name_plural).lower() if model else "" + if model is None or not user.has_perm(f"pins.can_manage_{model_plural}"): + self = self.exclude(visibility=self.model.VISIBILITY_INTERNAL) + + return self + + def for_object(self, content_type, object_id): + """ + Filter notes for a given object. + """ + return self.filter( + regarding_content_type=content_type, + regarding_object_id=object_id, + ) + + def visible_for(self, user, content_type, object_id): + """ + Filter notes for a given object, accessible to the given user. + """ + model = ContentType.objects.get_for_id(content_type) + return self.for_object(content_type, object_id).visible_to(user, model) diff --git a/scipost_django/pins/models.py b/scipost_django/pins/models.py index 88a7ff9ed..63904dedf 100644 --- a/scipost_django/pins/models.py +++ b/scipost_django/pins/models.py @@ -4,6 +4,8 @@ __license__ = "AGPL v3" from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey +from .managers import NotesQuerySet + class Note(models.Model): """ @@ -46,6 +48,8 @@ class Note(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) + objects = NotesQuerySet.as_manager() + def __str__(self): return self.title -- GitLab