From 9a542b4ef77774df7a3b3d8f75031b61837c918c Mon Sep 17 00:00:00 2001
From: Hangzhi Yu <hangzhi@protonmail.com>
Date: Fri, 7 Jun 2024 16:30:42 +0200
Subject: [PATCH] Add global permission to manage substitutions

---
 ...0017_add_substitution_global_permission.py | 17 ++++++++++++++
 aleksis/apps/chronos/models.py                | 13 ++++++++---
 aleksis/apps/chronos/rules.py                 | 23 ++++++++++++++-----
 3 files changed, 44 insertions(+), 9 deletions(-)
 create mode 100644 aleksis/apps/chronos/migrations/0017_add_substitution_global_permission.py

diff --git a/aleksis/apps/chronos/migrations/0017_add_substitution_global_permission.py b/aleksis/apps/chronos/migrations/0017_add_substitution_global_permission.py
new file mode 100644
index 00000000..1c34d2ef
--- /dev/null
+++ b/aleksis/apps/chronos/migrations/0017_add_substitution_global_permission.py
@@ -0,0 +1,17 @@
+# Generated by Django 5.0.6 on 2024-06-07 14:19
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('chronos', '0016_lessonevent'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='chronosglobalpermissions',
+            options={'managed': False, 'permissions': (('view_all_room_timetables', 'Can view all room timetables'), ('view_all_group_timetables', 'Can view all group timetables'), ('view_all_person_timetables', 'Can view all person timetables'), ('view_timetable_overview', 'Can view timetable overview'), ('view_lessons_day', 'Can view all lessons per day'), ('view_supervisions_day', 'Can view all supervisions per day'), ('manage_substitutions', 'Can manage all substitutions'))},
+        ),
+    ]
diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index 685544c7..7f4b3595 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -1281,6 +1281,7 @@ class ChronosGlobalPermissions(GlobalPermissionModel):
             ("view_timetable_overview", _("Can view timetable overview")),
             ("view_lessons_day", _("Can view all lessons per day")),
             ("view_supervisions_day", _("Can view all supervisions per day")),
+            ("manage_substitutions", _("Can manage all substitutions")),
         )
 
 
@@ -1540,6 +1541,7 @@ class LessonEvent(CalendarEvent):
             not_amended = params.get("not_amended", False)
             not_amending = params.get("not_amending", False)
             own = params.get("own", False)
+            all = params.get("all", False)
 
             if prefetch_absences:
                 objs = objs.prefetch_related("teachers__kolego_absences")
@@ -1570,7 +1572,7 @@ class LessonEvent(CalendarEvent):
                 elif type_ == "OWNER":
                     return objs.for_owner(obj_id)
 
-            if "own" in params:
+            if "own" in params or all:
                 return objs
         if request:
             return objs.for_person(request.user.person)
@@ -1593,10 +1595,15 @@ class LessonEvent(CalendarEvent):
 
         # 1. Find all LessonEvents for all Lessons of this Group in this date range and which are not themselves amending another lessonEvent
         event_params = {
-            "own": False,
             "not_amending": True,
             "prefetch_absences": True,
         }
+
+        if request.user.has_perm("chronos.manage_substitutions"):
+            event_params["all"] = True
+        else:
+            event_params["own"] = False
+
         if obj_type is not None and obj_id is not None:
             event_params.update(
                 {
@@ -1604,7 +1611,7 @@ class LessonEvent(CalendarEvent):
                     "id": obj_id,
                 }
             )
-        else:
+        elif not request.user.has_perm("chronos.manage_substitutions"):
             event_params.update(
                 {
                     "type": "OWNER",
diff --git a/aleksis/apps/chronos/rules.py b/aleksis/apps/chronos/rules.py
index 65659458..df016622 100644
--- a/aleksis/apps/chronos/rules.py
+++ b/aleksis/apps/chronos/rules.py
@@ -35,16 +35,23 @@ view_lessons_day_predicate = has_person & has_global_perm("chronos.view_lessons_
 add_perm("chronos.view_lessons_day_rule", view_lessons_day_predicate)
 
 # View substitution management overview page
-view_substitution_overview_predicate = has_person & has_any_group_substitution_perm
+view_substitution_overview_predicate = has_person & (
+    has_global_perm("chronos.manage_substitutions")
+    | has_any_group_substitution_perm
+)
 add_perm("chronos.view_substitution_overview_rule", view_substitution_overview_predicate)
 
 # Manage substitutions for a group
-manage_substitutions_for_group_predicate = has_person & has_group_substitution_perm
+manage_substitutions_for_group_predicate = has_person & (
+    has_global_perm("chronos.manage_substitutions")
+    | has_group_substitution_perm
+)
 add_perm("chronos.manage_substitutions_for_group_rule", manage_substitutions_for_group_predicate)
 
 # Add substitution
 add_substitution_predicate = has_person & (
-    has_substitution_perm_by_group
+    has_global_perm("chronos.manage_substitutions")
+    | has_substitution_perm_by_group
     | has_global_perm("chronos.add_lessonsubstitution")
     | has_object_perm("chronos.add_lessonsubstitution")
 )
@@ -52,7 +59,8 @@ add_perm("chronos.add_substitution_rule", add_substitution_predicate)
 
 # Edit substition
 edit_substitution_predicate = has_person & (
-    has_substitution_perm_by_group
+    has_global_perm("chronos.manage_substitutions")
+    | has_substitution_perm_by_group
     | has_global_perm("chronos.change_lessonsubstitution")
     | has_object_perm("chronos.change_lessonsubstitution")
 )
@@ -60,14 +68,17 @@ add_perm("chronos.edit_substitution_rule", edit_substitution_predicate)
 
 # Delete substitution
 delete_substitution_predicate = has_person & (
-    has_global_perm("chronos.delete_lessonsubstitution")
+    has_global_perm("chronos.manage_substitutions")
+    | has_substitution_perm_by_group
+    | has_global_perm("chronos.delete_lessonsubstitution")
     | has_object_perm("chronos.delete_lessonsubstitution")
 )
 add_perm("chronos.delete_substitution_rule", delete_substitution_predicate)
 
 # View substitutions
 view_substitutions_predicate = has_person & (
-    has_global_perm("chronos.view_lessonsubstitution")
+    has_global_perm("chronos.manage_substitutions")
+    | has_global_perm("chronos.view_lessonsubstitution")
     | has_any_object("chronos.view_lessonsubstitution", LessonSubstitution)
 )
 add_perm("chronos.view_substitutions_rule", view_substitutions_predicate)
-- 
GitLab