From e25acd736df1fb2ec18de11143f7f67709b484d3 Mon Sep 17 00:00:00 2001
From: Hangzhi Yu <hangzhi@protonmail.com>
Date: Fri, 8 Mar 2024 16:03:44 +0100
Subject: [PATCH] Fix permissions

---
 aleksis/apps/alsijil/rules.py           | 12 ++++-
 aleksis/apps/alsijil/util/predicates.py | 58 ++++++++++++++++++++++---
 2 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py
index 9e39fb276..e3d9e43a6 100644
--- a/aleksis/apps/alsijil/rules.py
+++ b/aleksis/apps/alsijil/rules.py
@@ -16,6 +16,8 @@ from .util.predicates import (
     has_lesson_group_object_perm,
     has_person_group_object_perm,
     has_personal_note_group_perm,
+    is_course_group_owner,
+    is_course_member,
     is_course_teacher,
     is_group_member,
     is_group_owner,
@@ -363,12 +365,18 @@ view_documentation_predicate = has_person & (
 add_perm("alsijil.view_documentation_rule", view_documentation_predicate)
 
 view_documentations_for_course_predicate = has_person & (
-    has_global_perm("alsijil.view_documentation") | is_course_teacher
+    has_global_perm("alsijil.view_documentation")
+    | is_course_teacher
+    | is_course_member
+    | is_course_group_owner
 )
 add_perm("alsijil.view_documentations_for_course_rule", view_documentations_for_course_predicate)
 
 view_documentations_for_group_predicate = has_person & (
-    has_global_perm("alsijil.view_documentation") | is_group_owner
+    has_global_perm("alsijil.view_documentation")
+    | is_group_owner
+    | is_group_member
+    | is_parent_group_owner
 )
 add_perm("alsijil.view_documentations_for_group_rule", view_documentations_for_group_predicate)
 
diff --git a/aleksis/apps/alsijil/util/predicates.py b/aleksis/apps/alsijil/util/predicates.py
index d984fafc0..dff299faf 100644
--- a/aleksis/apps/alsijil/util/predicates.py
+++ b/aleksis/apps/alsijil/util/predicates.py
@@ -329,19 +329,55 @@ def is_course_member(user: User, obj: Course):
     return False
 
 
+@predicate
+def is_course_group_owner(user: User, obj: Course):
+    """Predicate for group owners of a course.
+
+    Checks whether the person linked to the user is a owner of any group (and their parent groups) linked to the course.
+    """
+    if obj:
+        for g in obj.groups.all():
+            if user.person in g.owners.all():
+                return True
+            for pg in g.parent_groups.all():
+                if user.person in pg.owners.all():
+                    return True
+    return False
+
+
 @predicate
 def is_lesson_event_member(user: User, obj: LessonEvent):
     """Predicate for members of a lesson event.
 
-    Checks whether the person linked to the user is a members in the lesson event,
+    Checks whether the person linked to the user is a member in the lesson event,
     or a members of the course, if the lesson event has one.
     """
     if obj:
-        if obj.course and is_course_member(user, obj):
+        if obj.course and is_course_member(user, obj.course):
             return True
         for g in obj.groups.all():
             if user.person in g.members.all():
                 return True
+
+    return False
+
+
+@predicate
+def is_lesson_event_group_owner(user: User, obj: LessonEvent):
+    """Predicate for group owners of a lesson event.
+
+    Checks whether the person linked to the user is a owner of some group linked to the lesson event,
+    or a owner of some group linked to the course, if the lesson event has one.
+    """
+    if obj:
+        if obj.course and is_course_group_owner(user, obj.course):
+            return True
+        for g in obj.groups.all():
+            if user.person in g.owners.all():
+                return True
+            for pg in g.parent_groups.all():
+                if user.person in pg.owners.all():
+                    return True
     return False
 
 
@@ -350,10 +386,16 @@ def can_view_documentation(user: User, obj: Documentation):
     """Predicate which checks if the user is allowed to view a documentation."""
     if obj:
         if obj.course:
-            return is_course_teacher(user, obj.course) | is_course_member(user, obj.course)
+            return (
+                is_course_teacher(user, obj.course)
+                | is_course_member(user, obj.course)
+                | is_course_group_owner(user, obj.course)
+            )
         if obj.lesson_event:
-            return is_lesson_event_teacher(user, obj.course) | is_lesson_event_member(
-                user, obj.course
+            return (
+                is_lesson_event_teacher(user, obj.lesson_event)
+                | is_lesson_event_member(user, obj.lesson_event)
+                | is_lesson_event_group_owner(user, obj.lesson_event)
             )
     return False
 
@@ -363,7 +405,9 @@ def can_edit_documentation(user: User, obj: Documentation):
     """Predicate which checks if the user is allowed to edit or delete a documentation."""
     if obj:
         if obj.course:
-            return is_course_teacher(user, obj.course)
+            return is_course_teacher(user, obj.course) | is_course_group_owner(user, obj.course)
         if obj.lesson_event:
-            return is_lesson_event_teacher(user, obj.course)
+            return is_lesson_event_teacher(user, obj.lesson_event) | is_lesson_event_group_owner(
+                user, obj.lesson_event
+            )
     return False
-- 
GitLab