From a7d6e0ccd864b9ed2ba3734ae8ad9adfc27ccf8e Mon Sep 17 00:00:00 2001
From: George Katsikas <giorgakis.katsikas@gmail.com>
Date: Thu, 28 Mar 2024 16:07:53 +0100
Subject: [PATCH] add internal note viewing permissions

---
 scipost_django/pins/managers.py                  | 13 +++++++------
 scipost_django/pins/views.py                     |  6 ------
 .../commands/add_groups_and_permissions.py       | 16 ++++++++++++++++
 3 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/scipost_django/pins/managers.py b/scipost_django/pins/managers.py
index 4387f4e2d..4dd664ab7 100644
--- a/scipost_django/pins/managers.py
+++ b/scipost_django/pins/managers.py
@@ -1,7 +1,6 @@
 __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
@@ -11,8 +10,8 @@ class NotesQuerySet(models.QuerySet):
 
     def visible_to(
         self,
-        user: Optional[User] = None,
-        model: Optional[models.Model] = None,
+        user: User | None = None,
+        model: type[models.Model] | None = None,
     ):
         """
         Filter out notes which are not visible to the given user.
@@ -31,8 +30,10 @@ class NotesQuerySet(models.QuerySet):
         # 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}"):
+        model_name = str(model._meta.verbose_name).lower() if model else ""
+        can_view_internal_notes = f"scipost.can_view_internal_{model_name}_notes"
+
+        if not (model and user.has_perm(can_view_internal_notes)):
             self = self.exclude(visibility=self.model.VISIBILITY_INTERNAL)
 
         return self
@@ -50,5 +51,5 @@ class NotesQuerySet(models.QuerySet):
         """
         Filter notes for a given object, accessible to the given user.
         """
-        model = ContentType.objects.get_for_id(content_type)
+        model = ContentType.objects.get_for_id(content_type).model_class()
         return self.for_object(content_type, object_id).visible_to(user, model)
diff --git a/scipost_django/pins/views.py b/scipost_django/pins/views.py
index 1f56bd61c..ae0209ab9 100644
--- a/scipost_django/pins/views.py
+++ b/scipost_django/pins/views.py
@@ -72,12 +72,6 @@ def _hx_notes_list(request, regarding_content_type, regarding_object_id):
     # Filter according to the visibility of the notes
     notes = notes.visible_to(request.user, object)
 
-    # Filter out internal notes unless the user has the default "manager"
-    # permission for the given object, e.g. "can_manage_subsidies"
-    model_plural = (object._meta.verbose_name_plural or "").lower()
-    if not request.user.has_perm(f"pins.can_manage_{model_plural}"):
-        notes = notes.exclude(visibility=Note.VISIBILITY_INTERNAL)
-
     context = {
         "object": object,
         "can_create_notes": can_create_notes,
diff --git a/scipost_django/scipost/management/commands/add_groups_and_permissions.py b/scipost_django/scipost/management/commands/add_groups_and_permissions.py
index c11951c9b..b004030f3 100644
--- a/scipost_django/scipost/management/commands/add_groups_and_permissions.py
+++ b/scipost_django/scipost/management/commands/add_groups_and_permissions.py
@@ -477,6 +477,18 @@ class Command(BaseCommand):
             name="Can add notes",
             content_type=content_type,
         )
+        can_view_internal_subsidy_notes, created = Permission.objects.get_or_create(
+            codename="can_view_internal_subsidy_notes",
+            name="Can view internal subsidy notes",
+            content_type=content_type,
+        )
+        can_view_internal_organization_notes, created = (
+            Permission.objects.get_or_create(
+                codename="can_view_internal_organization_notes",
+                name="Can view internal organization notes",
+                content_type=content_type,
+            )
+        )
 
         # Assign permissions to groups
         SciPostAdmin.permissions.set(
@@ -523,6 +535,8 @@ class Command(BaseCommand):
                 can_view_all_nomination_voting_rounds,
                 can_view_fellowships_monitor,
                 can_add_notes,
+                can_view_internal_subsidy_notes,
+                can_view_internal_organization_notes,
             ]
         )
 
@@ -532,6 +546,8 @@ class Command(BaseCommand):
                 can_manage_subsidies,
                 can_view_timesheets,
                 can_add_notes,
+                can_view_internal_subsidy_notes,
+                can_view_internal_organization_notes,
             ]
         )
 
-- 
GitLab