From a106ee5597c7aaf752e37df20aa7423af8a6d3e1 Mon Sep 17 00:00:00 2001
From: Hangzhi Yu <hangzhi@protonmail.com>
Date: Fri, 3 Jan 2025 15:50:13 +0100
Subject: [PATCH] Add permission check to participation status type

---
 aleksis/apps/alsijil/rules.py                 | 24 ++++++++++++++++---
 aleksis/apps/alsijil/schema/documentation.py  | 12 +++++-----
 .../alsijil/schema/participation_status.py    |  8 +++++++
 aleksis/apps/alsijil/util/predicates.py       | 22 ++++++++++++++---
 4 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py
index 054669388..a65c4ca9e 100644
--- a/aleksis/apps/alsijil/rules.py
+++ b/aleksis/apps/alsijil/rules.py
@@ -13,11 +13,13 @@ from aleksis.core.util.predicates import (
 from .util.predicates import (
     can_edit_documentation,
     can_edit_participation_status,
+    can_edit_participation_status_for_documentation,
     can_edit_personal_note,
     can_register_absence_for_at_least_one_group,
     can_register_absence_for_person,
     can_view_documentation,
     can_view_participation_status,
+    can_view_participation_status_for_documentation,
     can_view_personal_note,
     can_view_statistics_for_person,
     has_person_group_object_perm,
@@ -196,7 +198,7 @@ add_perm("alsijil.edit_documentation_rule", edit_documentation_predicate)
 add_perm("alsijil.delete_documentation_rule", edit_documentation_predicate)
 
 view_participation_status_for_documentation_predicate = has_person & (
-    has_global_perm("alsijil.change_participationstatus") | can_view_participation_status
+    has_global_perm("alsijil.change_participationstatus") | can_view_participation_status_for_documentation
 )
 add_perm(
     "alsijil.view_participation_status_for_documentation_rule",
@@ -205,7 +207,7 @@ add_perm(
 
 edit_participation_status_for_documentation_with_time_range_predicate = (
     has_person
-    & (has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status)
+    & (has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status_for_documentation)
     & is_in_allowed_time_range_for_participation_status
 )
 add_perm(
@@ -214,13 +216,29 @@ add_perm(
 )
 
 edit_participation_status_for_documentation_predicate = has_person & (
-    has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status
+    has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status_for_documentation
 )
 add_perm(
     "alsijil.edit_participation_status_for_documentation_rule",
     edit_participation_status_for_documentation_predicate,
 )
 
+view_participation_status_predicate = has_person & (
+    has_global_perm("alsijil.view_participationstatus") | can_view_participation_status
+)
+add_perm(
+    "alsijil.view_participation_status_rule",
+    view_participation_status_predicate,
+)
+
+edit_participation_status_predicate = has_person & (
+    has_global_perm("alsijil.change_participationstatus") | can_edit_participation_status
+)
+add_perm(
+    "alsijil.edit_participation_status_rule",
+    edit_participation_status_predicate,
+)
+
 view_personal_note_predicate = has_person & (
     has_global_perm("alsijil.change_newpersonalnote") | can_view_personal_note
 )
diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py
index 6b0c3e1ff..d3da77dbb 100644
--- a/aleksis/apps/alsijil/schema/documentation.py
+++ b/aleksis/apps/alsijil/schema/documentation.py
@@ -11,7 +11,7 @@ from aleksis.apps.alsijil.util.predicates import (
     is_in_allowed_time_range_for_participation_status,
 )
 from aleksis.apps.alsijil.util.predicates import (
-    can_edit_participation_status as can_edit_participation_status_predicate,
+    can_edit_participation_status_for_documentation as can_edit_participation_status_for_documentation_predicate,
 )
 from aleksis.apps.chronos.schema import LessonEventType
 from aleksis.apps.cursus.models import Subject
@@ -56,8 +56,8 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp
     future_notice = graphene.Boolean(required=False)
     future_notice_participation_status = graphene.Boolean(required=False)
 
-    can_edit_participation_status = graphene.Boolean(required=False)
-    can_view_participation_status = graphene.Boolean(required=False)
+    can_edit_participation_status_for_documentation = graphene.Boolean(required=False)
+    can_view_participation_status_for_documentation = graphene.Boolean(required=False)
 
     old_id = graphene.ID(required=False)
 
@@ -96,12 +96,12 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp
         return not is_in_allowed_time_range_for_participation_status(info.context.user, root)
 
     @staticmethod
-    def resolve_can_edit_participation_status(root: Documentation, info, **kwargs):
+    def resolve_can_edit_participation_status_for_documentation(root: Documentation, info, **kwargs):
         """Shows whether the user can edit all participation statuses of the documentation"""
-        return can_edit_participation_status_predicate(info.context.user, root)
+        return can_edit_participation_status_for_documentation_predicate(info.context.user, root)
 
     @staticmethod
-    def resolve_can_view_participation_status(root: Documentation, info, **kwargs):
+    def resolve_can_view_participation_status_for_documentation(root: Documentation, info, **kwargs):
         """Shows whether the user can view all participation statuses of the documentation"""
         return info.context.user.has_perm(
             "alsijil.view_participation_status_for_documentation_rule", root
diff --git a/aleksis/apps/alsijil/schema/participation_status.py b/aleksis/apps/alsijil/schema/participation_status.py
index 2f6a830e2..bb90b9bea 100644
--- a/aleksis/apps/alsijil/schema/participation_status.py
+++ b/aleksis/apps/alsijil/schema/participation_status.py
@@ -68,6 +68,14 @@ class ParticipationStatusType(
             note__isnull=False,
         ).exclude(note="")
 
+    @staticmethod
+    def resolve_can_edit(root: ParticipationStatus, info, **kwargs):
+        return info.context.user.has_perm("alsijil.edit_participation_status_rule", root)
+
+    @staticmethod
+    def resolve_can_delete(root: ParticipationStatus, info, **kwargs):
+        return info.context.user.has_perm("alsijil.edit_participation_status_rule", root)
+
 
 class ParticipationStatusBatchPatchMutation(BaseBatchPatchMutation):
     class Meta:
diff --git a/aleksis/apps/alsijil/util/predicates.py b/aleksis/apps/alsijil/util/predicates.py
index 41f8dbe02..e33b7fafe 100644
--- a/aleksis/apps/alsijil/util/predicates.py
+++ b/aleksis/apps/alsijil/util/predicates.py
@@ -12,7 +12,7 @@ from aleksis.core.models import Group, Person
 from aleksis.core.util.core_helpers import get_site_preferences
 from aleksis.core.util.predicates import check_object_permission
 
-from ..models import Documentation, NewPersonalNote
+from ..models import Documentation, NewPersonalNote, ParticipationStatus
 
 
 @predicate
@@ -277,7 +277,7 @@ def can_edit_documentation(user: User, obj: Documentation):
 
 
 @predicate
-def can_view_participation_status(user: User, obj: Documentation):
+def can_view_participation_status_for_documentation(user: User, obj: Documentation):
     """Predicate which checks if the user is allowed to view participation for a documentation."""
     if obj:
         if obj.amends and obj.amends.cancelled:
@@ -294,7 +294,7 @@ def can_view_participation_status(user: User, obj: Documentation):
 
 
 @predicate
-def can_edit_participation_status(user: User, obj: Documentation):
+def can_edit_participation_status_for_documentation(user: User, obj: Documentation):
     """Predicate which checks if the user is allowed to edit participation for a documentation."""
     if obj:
         if obj.amends and obj.amends.cancelled:
@@ -308,6 +308,22 @@ def can_edit_participation_status(user: User, obj: Documentation):
     return False
 
 
+@predicate
+def can_view_participation_status(user: User, obj: ParticipationStatus):
+    """Predicate which checks if the user is allowed to view participation."""
+    if obj.related_documentation:
+        return can_view_participation_status_for_documentation(user, obj.related_documentation)
+    return False
+
+
+@predicate
+def can_edit_participation_status(user: User, obj: ParticipationStatus):
+    """Predicate which checks if the user is allowed to edit participation."""
+    if obj.related_documentation:
+        return can_edit_participation_status_for_documentation(user, obj.related_documentation)
+    return False
+
+
 @predicate
 def is_in_allowed_time_range(user: User, obj: Union[Documentation, NewPersonalNote]):
     """Predicate for documentations or new personal notes with linked documentation.
-- 
GitLab