From 97e41acf8a0e6437aa7c4cabf25082a9526653e2 Mon Sep 17 00:00:00 2001
From: magicfelix <felix@felix-zauberer.de>
Date: Wed, 30 Aug 2023 21:04:02 +0200
Subject: [PATCH] WIP: Add permissions for Documentation

---
 aleksis/apps/alsijil/rules.py                | 15 ++++
 aleksis/apps/alsijil/schema/documentation.py |  8 +-
 aleksis/apps/alsijil/util/predicates.py      | 82 +++++++++++++++++++-
 3 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py
index e9011c6c2..94fd3aebc 100644
--- a/aleksis/apps/alsijil/rules.py
+++ b/aleksis/apps/alsijil/rules.py
@@ -11,6 +11,8 @@ from aleksis.core.util.predicates import (
 )
 
 from .util.predicates import (
+    can_edit_documentation,
+    can_view_documentation,
     has_lesson_group_object_perm,
     has_person_group_object_perm,
     has_personal_note_group_perm,
@@ -352,3 +354,16 @@ view_register_objects_list_predicate = has_person & (
     | has_global_perm("alsijil.view_full_register")
 )
 add_perm("alsijil.view_register_objects_list_rule", view_register_objects_list_predicate)
+
+view_documentation_predicate = has_person & (
+    has_global_perm("alsijil.view_documentation")
+    | can_view_documentation
+)
+add_perm("alsijil.view_documentation_rule", view_documentation_predicate)
+
+edit_documentation_predicate = has_person & (
+    has_global_perm("alsijil.change_documentation")
+    | can_edit_documentation
+)
+add_perm("alsijil.edit_documentation_rule", edit_documentation_predicate)
+add_perm("alsijil.delete_documentation_rule", edit_documentation_predicate)
diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py
index d4752e09e..384b8863b 100644
--- a/aleksis/apps/alsijil/schema/documentation.py
+++ b/aleksis/apps/alsijil/schema/documentation.py
@@ -34,7 +34,7 @@ class DocumentationCreateMutation(DjangoCreateMutation):
         model = Documentation
         fields = ("course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
         optional_fields = ("course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
-        permissions = ("",)  # FIXME
+        permissions = ("alsijil.add_documentation",)  # FIXME
 
     @classmethod
     def before_mutate(cls, root, info, input):
@@ -49,16 +49,16 @@ class DocumentationBatchCreateMutation(DjangoBatchCreateMutation):
     class Meta:
         model = Documentation
         fields = ("id", "course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
-        permissions = ("",)  # FIXME
+        permissions = ("alsijil.add_documentation",)  # FIXME
 
 
 class DocumentationDeleteMutation(DeleteMutation):
     klass = Documentation
-    permission_required = ""  # FIXME
+    permission_required = "alsijil.delete_documentation_rule"  # FIXME
 
 
 class DocumentationBatchPatchMutation(PermissionBatchPatchMixin, DjangoBatchPatchMutation):
     class Meta:
         model = Documentation
         fields = ("id", "course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
-        permissions = ("",)  # FIXME
+        permissions = ("alsijil.edit_documentation_rule",)  # FIXME
diff --git a/aleksis/apps/alsijil/util/predicates.py b/aleksis/apps/alsijil/util/predicates.py
index c3a450ec9..b261173ab 100644
--- a/aleksis/apps/alsijil/util/predicates.py
+++ b/aleksis/apps/alsijil/util/predicates.py
@@ -4,11 +4,12 @@ from django.contrib.auth.models import User
 
 from rules import predicate
 
-from aleksis.apps.chronos.models import Event, ExtraLesson, LessonPeriod
+from aleksis.apps.chronos.models import Event, ExtraLesson, LessonEvent, LessonPeriod
+from aleksis.apps.cursus.models import Course
 from aleksis.core.models import Group, Person
 from aleksis.core.util.predicates import check_object_permission
 
-from ..models import PersonalNote
+from ..models import Documentation, PersonalNote
 
 
 @predicate
@@ -290,3 +291,80 @@ def is_group_role_assignment_group_owner(user: User, obj: Union[Group, Person])
 def is_owner_of_any_group(user: User, obj):
     """Predicate which checks if the person is group owner of any group."""
     return Group.objects.filter(owners=user.person).exists()
+
+
+@predicate
+def is_course_teacher(user: User, obj: Course):
+    """Predicate for teachers of a course.
+
+    Checks whether the person linked to the user is a teacher in the course.
+    """
+    if obj:
+        return user.person in obj.teachers.all()
+    return False
+
+
+@predicate
+def is_lesson_event_teacher(user: User, obj: LessonEvent):
+    """Predicate for teachers of a lesson event.
+
+    Checks whether the person linked to the user is a teacher in the lesson event,
+    or a teacher of the course, if the lesson event has one.
+    """
+    if obj:
+        return (
+            obj.course and is_course_teacher(user, obj)
+            or user.person in obj.all_teachers()
+        )
+    return False
+
+
+@predicate
+def is_course_member(user: User, obj: Course):
+    """Predicate for members of a course.
+
+    Checks whether the person linked to the user is a member in the course.
+    """
+    if obj:
+        for g in obj.groups.all():
+            if user.person in g.members.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,
+    or a members of the course, if the lesson event has one.
+    """
+    if obj:
+        if obj.course and is_course_member(user, obj):
+            return True
+        for g in obj.groups.all():
+            if user.person in g.members.all():
+                return True
+    return False
+
+
+@predicate
+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)
+        if obj.lesson_event:
+            return is_lesson_event_teacher(user, obj.course) | is_lesson_event_member(user, obj.course)
+    return False
+
+
+@predicate
+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)
+        if obj.lesson_event:
+            return is_lesson_event_teacher(user, obj.course)
+    return False
-- 
GitLab