From 80d113cd1d7d6b3976b885dcfed8084aebf07638 Mon Sep 17 00:00:00 2001
From: Tom Teichler <tom.teichler@teckids.org>
Date: Sat, 18 Apr 2020 15:17:48 +0200
Subject: [PATCH] Add rules for all views

---
 aleksis/core/rules.py           | 60 +++++++++++++++++++++++++++++----
 aleksis/core/util/predicates.py |  2 +-
 aleksis/core/views.py           | 51 ++++++++++++++++++----------
 3 files changed, 89 insertions(+), 24 deletions(-)

diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py
index dd969838d..f890be5f5 100644
--- a/aleksis/core/rules.py
+++ b/aleksis/core/rules.py
@@ -1,6 +1,6 @@
 from rules import add_perm, always_allow
 
-from aleksis.core.models import Person, Group
+from aleksis.core.models import Person, Group, Announcement
 from aleksis.core.util.predicates import (
     has_person_predicate,
     has_global_perm,
@@ -48,11 +48,15 @@ view_groups_predicate = has_person_predicate & (
 )
 add_perm("core.view_person_groups", view_groups_predicate)
 
-# Change person
-change_person_predicate = has_person_predicate & (
-    has_global_perm("core.change_person") | has_object_perm("core.change_person")
+# Edit person
+edit_person_predicate = has_person_predicate & (
+    has_global_perm("core.edit_person") | has_object_perm("core.edit_person")
 )
-add_perm("core.change_person", change_person_predicate)
+add_perm("core.edit_person", edit_person_predicate)
+
+# Link persons with accounts
+link_persons_accounts_predicate = has_person_predicate & has_global_perm("core.link_persons_accounts")
+add_perm("core.link_persons_accounts", link_persons_accounts_predicate)
 
 # View groups
 view_groups_predicate = has_person_predicate & (
@@ -66,5 +70,49 @@ view_group_predicate = has_person_predicate & (
 )
 add_perm("core.view_group", view_group_predicate)
 
-# People menu (persons + objects)
+# Edit group
+edit_group_predicate = has_person_predicate & (
+    has_global_perm("core.edit_person") | has_object_perm("core.edit_person")
+)
+add_perm("core.edit_group", edit_group_predicate)
+
+# Edit school information
+edit_school_information_predicate = has_person_predicate & has_global_perm("core.edit_school_information")
+add_perm("core.edit_school_information", edit_school_information_predicate)
+
+# Edit school term
+edit_school_term_predicate = has_person_predicate & has_global_perm("core.edit_school_term")
+add_perm("core.edit_school_term", edit_school_term_predicate)
+
+# Manage school
+manage_school_predicate = edit_school_information_predicate | edit_school_term_predicate
+add_perm("core.manage_school", manage_school_predicate)
+
+# Manage data
+manage_data_predicate = has_person_predicate & has_global_perm("core.manage_data")
+add_perm("core.manage_data", manage_data_predicate)
+
+# View announcements
+view_announcements_predicate = has_person_predicate & (
+    has_global_perm("core.view_announcements") | has_any_object("core.view_announcements", Announcement)
+)
+add_perm("core.view_announcements", view_announcements_predicate)
+
+# Create or edit announcements
+create_or_edit_announcement_predicate = has_person_predicate & (
+    has_global_perm("core.create_or_edit_announcement") | has_object_perm("core.create_or_edit_announcement")
+)
+add_perm("core.create_or_edit_announcement", create_or_edit_announcement_predicate)
+
+# Delete announcement
+delete_announcement_predicate = has_person_predicate & (
+    has_global_perm("core.delete_announcement") | has_object_perm("core.delete_announcement")
+)
+add_perm("core.delete_announcement", delete_announcement_predicate)
+
+# View people menu (persons + objects)
 add_perm("core.view_people_menu", has_person_predicate & (view_persons_predicate | view_groups_predicate))
+
+# View system status
+view_system_status_predicate = has_person_predicate & has_global_perm("core.view_system_status")
+add_perm("core.view_system_status", view_system_status_predicate)
diff --git a/aleksis/core/util/predicates.py b/aleksis/core/util/predicates.py
index 7195cd451..7a209b048 100644
--- a/aleksis/core/util/predicates.py
+++ b/aleksis/core/util/predicates.py
@@ -79,7 +79,7 @@ def has_person_predicate(user: User) -> bool:
     return has_person(user)
 
 
-@predicate()
+@predicate
 def is_person(user: User, obj: Model) -> bool:
     """ Predicate which checks if the provided object is the person linked to the user object """
 
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index f64602d3b..35b39df20 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -12,7 +12,7 @@ from haystack.inputs import AutoQuery
 from haystack.query import SearchQuerySet
 from rules.contrib.views import permission_required, objectgetter
 
-from .decorators import admin_required, person_required
+from .decorators import person_required
 from .forms import (
     EditGroupForm,
     EditPersonForm,
@@ -147,7 +147,7 @@ def groups(request: HttpRequest) -> HttpResponse:
     return render(request, "core/groups.html", context)
 
 
-@admin_required
+@permission_required("core.link_persons_accounts")
 def persons_accounts(request: HttpRequest) -> HttpResponse:
     context = {}
 
@@ -163,11 +163,15 @@ def persons_accounts(request: HttpRequest) -> HttpResponse:
     return render(request, "core/persons_accounts.html", context)
 
 
-@permission_required("core.change_person", fn=objectgetter(Person, "id_"))
+def get_person_by_id(request: HttpRequest, id_:int):
+    return get_object_or_404(Person, id=id_)
+
+
+@permission_required("core.edit_person", fn=get_person_by_id)
 def edit_person(request: HttpRequest, id_: int) -> HttpResponse:
     context = {}
 
-    person = get_object_or_404(Person, id=id_)
+    person = get_person_by_id(request, id_)
 
     edit_person_form = EditPersonForm(request.POST or None, request.FILES or None, instance=person)
 
@@ -185,15 +189,22 @@ def edit_person(request: HttpRequest, id_: int) -> HttpResponse:
     return render(request, "core/edit_person.html", context)
 
 
-@admin_required
+def get_group_by_id(request: HttpRequest, id_: Optional[int] = None):
+    if id_:
+        return get_object_or_404(Group, id=id_)
+    else:
+        return None
+
+
+@permission_required("core.edit_group", fn=get_group_by_id)
 def edit_group(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
     context = {}
 
+    group = get_group_by_id(request, id_)
+
     if id_:
-        group = get_object_or_404(Group, id=id_)
         edit_group_form = EditGroupForm(request.POST or None, instance=group)
     else:
-        group = None
         edit_group_form = EditGroupForm(request.POST or None)
 
     if request.method == "POST":
@@ -209,26 +220,26 @@ def edit_group(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
     return render(request, "core/edit_group.html", context)
 
 
-@admin_required
+@permission_required("core.manage_data")
 def data_management(request: HttpRequest) -> HttpResponse:
     context = {}
     return render(request, "core/data_management.html", context)
 
 
-@admin_required
+@permission_required("core.view_system_status")
 def system_status(request: HttpRequest) -> HttpResponse:
     context = {}
 
     return render(request, "core/system_status.html", context)
 
 
-@admin_required
+@permission_required("core.manage_school")
 def school_management(request: HttpRequest) -> HttpResponse:
     context = {}
     return render(request, "core/school_management.html", context)
 
 
-@admin_required
+@permission_required("core.edit_school_information")
 def edit_school(request: HttpRequest) -> HttpResponse:
     context = {}
 
@@ -249,7 +260,7 @@ def edit_school(request: HttpRequest) -> HttpResponse:
     return render(request, "core/edit_school.html", context)
 
 
-@admin_required
+@permission_required("core.edit_school_term")
 def edit_schoolterm(request: HttpRequest) -> HttpResponse:
     context = {}
 
@@ -282,7 +293,7 @@ def notification_mark_read(request: HttpRequest, id_: int) -> HttpResponse:
     return redirect("index")
 
 
-@admin_required
+@permission_required("core.view_announcements")
 def announcements(request: HttpRequest) -> HttpResponse:
     context = {}
 
@@ -293,12 +304,18 @@ def announcements(request: HttpRequest) -> HttpResponse:
     return render(request, "core/announcement/list.html", context)
 
 
-@admin_required
+def get_announcement_by_pk(request: HttpRequest, id_: Optional[int] = None):
+    if id_:
+        return get_object_or_404(Announcement, pk=id_)
+
+
+@permission_required("core.create_or_edit_announcement", fn=get_announcement_by_pk)
 def announcement_form(request: HttpRequest, pk: Optional[int] = None) -> HttpResponse:
     context = {}
 
+    announcement = get_announcement_by_pk(request, pk)
+
     if pk:
-        announcement = get_object_or_404(Announcement, pk=pk)
         form = AnnouncementForm(
             request.POST or None,
             instance=announcement
@@ -320,10 +337,10 @@ def announcement_form(request: HttpRequest, pk: Optional[int] = None) -> HttpRes
     return render(request, "core/announcement/form.html", context)
 
 
-@admin_required
+@permission_required("core.delete_announcement", fn=get_announcement_by_pk)
 def delete_announcement(request: HttpRequest, pk: int) -> HttpResponse:
     if request.method == "POST":
-        announcement = get_object_or_404(Announcement, pk=pk)
+        announcement = get_announcement_by_pk(request, pk)
         announcement.delete()
         messages.success(request, _("The announcement has been deleted."))
 
-- 
GitLab