Skip to content
Snippets Groups Projects
Verified Commit 6b0eedfd authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Fix lint issues and reformat files

parent 95f16ef8
No related branches found
No related tags found
1 merge request!49Resolve "Add rules and permissions"
Pipeline #2759 passed
...@@ -93,12 +93,29 @@ def get_personal_notes(self, persons: QuerySet, wanted_week: CalendarWeek): ...@@ -93,12 +93,29 @@ def get_personal_notes(self, persons: QuerySet, wanted_week: CalendarWeek):
lesson_period=self, week=wanted_week.week lesson_period=self, week=wanted_week.week
) )
# Dynamically add extra permissions to Group and Person models in core, requires migration afterwards
Group.add_permission("view_week_class_register_group", _("Can view week overview of group class register")) # Dynamically add extra permissions to Group and Person models in core
Group.add_permission("view_personalnote_group", _("Can view all personal notes of a group")) # Note: requires migrate afterwards
Group.add_permission("edit_personalnote_group", _("Can edit all personal notes of a group")) Group.add_permission(
Group.add_permission("view_lessondocumentation_group", _("Can view all lesson documentation of a group")) "view_week_class_register_group",
Group.add_permission("edit_lessondocumentation_group", _("Can edit all lesson documentation of a group")) _("Can view week overview of group class register"),
)
Group.add_permission(
"view_personalnote_group", _("Can view all personal notes of a group")
)
Group.add_permission(
"edit_personalnote_group", _("Can edit all personal notes of a group")
)
Group.add_permission(
"view_lessondocumentation_group", _("Can view all lesson documentation of a group")
)
Group.add_permission(
"edit_lessondocumentation_group", _("Can edit all lesson documentation of a group")
)
Group.add_permission("view_full_register_group", _("Can view full register of a group")) Group.add_permission("view_full_register_group", _("Can view full register of a group"))
Group.add_permission("register_absence_group", _("Can register an absence for all members of a group")) Group.add_permission(
Person.add_permission("register_absence_person", _("Can register an absence for a person")) "register_absence_group", _("Can register an absence for all members of a group")
)
Person.add_permission(
"register_absence_person", _("Can register an absence for a person")
)
...@@ -92,6 +92,7 @@ class PersonalNoteFilter(ExtensibleModel): ...@@ -92,6 +92,7 @@ class PersonalNoteFilter(ExtensibleModel):
verbose_name_plural = _("Personal note filters") verbose_name_plural = _("Personal note filters")
ordering = ["identifier"] ordering = ["identifier"]
class AlsijilGlobalPermissions(ExtensibleModel): class AlsijilGlobalPermissions(ExtensibleModel):
class Meta: class Meta:
managed = False managed = False
......
from rules import add_perm from rules import add_perm
from aleksis.core.util.predicates import ( from aleksis.core.util.predicates import (
has_any_object,
has_global_perm, has_global_perm,
has_object_perm, has_object_perm,
has_person, has_person,
...@@ -9,91 +8,100 @@ from aleksis.core.util.predicates import ( ...@@ -9,91 +8,100 @@ from aleksis.core.util.predicates import (
) )
from .util.predicates import ( from .util.predicates import (
is_lesson_teacher,
is_lesson_participant,
is_lesson_parent_group_owner,
has_lesson_group_object_perm, has_lesson_group_object_perm,
has_person_group_object_perm,
is_group_member, is_group_member,
is_group_owner, is_group_owner,
has_person_group_object_perm, is_lesson_parent_group_owner,
is_lesson_participant,
is_lesson_teacher,
is_person_group_owner, is_person_group_owner,
) )
# View lesson # View lesson
view_lesson_predicate = has_person & ( view_lesson_predicate = has_person & (
has_global_perm("alsijil.view_lesson") | is_lesson_teacher | is_lesson_participant | is_lesson_parent_group_owner | has_lesson_group_object_perm("alsijil.view_lesson") has_global_perm("alsijil.view_lesson")
| is_lesson_teacher
| is_lesson_participant
| is_lesson_parent_group_owner
| has_lesson_group_object_perm("alsijil.view_lesson")
) )
add_perm("alsijil.view_lesson", view_lesson_predicate) add_perm("alsijil.view_lesson", view_lesson_predicate)
# View lesson personal notes # View lesson personal notes
view_lesson_personal_notes_predicate = has_person & ( view_lesson_personal_notes_predicate = has_person & (
has_global_perm("alsijil.view_personalnote") | has_global_perm("alsijil.view_personalnote")
has_lesson_group_object_perm("core.view_personalnote_group") | | has_lesson_group_object_perm("core.view_personalnote_group")
is_lesson_teacher | | is_lesson_teacher
is_lesson_parent_group_owner | is_lesson_parent_group_owner
) )
add_perm("alsijil.view_lesson_personalnote", view_lesson_personal_notes_predicate) add_perm("alsijil.view_lesson_personalnote", view_lesson_personal_notes_predicate)
# Edit lesson personal notes # Edit lesson personal notes
edit_lesson_personal_notes_predicate = has_person & ( edit_lesson_personal_notes_predicate = has_person & (
has_global_perm("alsijil.change_personalnote") | has_global_perm("alsijil.change_personalnote")
has_lesson_group_object_perm("core.edit_personalnote_group") | | has_lesson_group_object_perm("core.edit_personalnote_group")
is_lesson_teacher | is_lesson_teacher
) )
add_perm("alsijil.edit_personalnote", edit_lesson_personal_notes_predicate) add_perm("alsijil.edit_personalnote", edit_lesson_personal_notes_predicate)
# View lesson documentation # View lesson documentation
view_lesson_documentation_predicate = has_person & ( view_lesson_documentation_predicate = has_person & (
has_global_perm("alsijil.view_lessondocumentation") | has_global_perm("alsijil.view_lessondocumentation")
has_lesson_group_object_perm("core.view_lessondocumentation_group") | | has_lesson_group_object_perm("core.view_lessondocumentation_group")
is_lesson_teacher | | is_lesson_teacher
is_lesson_parent_group_owner | | is_lesson_parent_group_owner
is_lesson_participant | is_lesson_participant
) )
add_perm("alsijil.view_lessondocumentation", view_lesson_documentation_predicate) add_perm("alsijil.view_lessondocumentation", view_lesson_documentation_predicate)
# Edit lesson documentation # Edit lesson documentation
edit_lesson_documentation_predicate = has_person & ( edit_lesson_documentation_predicate = has_person & (
has_global_perm("alsijil.change_lessondocumentation") | has_global_perm("alsijil.change_lessondocumentation")
has_lesson_group_object_perm("core.edit_lessondocumentation_group") | | has_lesson_group_object_perm("core.edit_lessondocumentation_group")
is_lesson_teacher | is_lesson_teacher
) )
add_perm("alsijil.edit_lessondocumentation", edit_lesson_documentation_predicate) add_perm("alsijil.edit_lessondocumentation", edit_lesson_documentation_predicate)
# View week overview # View week overview
view_week_predicate = has_person & ( view_week_predicate = has_person & (
has_global_perm("alsijil.view_week") | has_object_perm("core.view_week_class_register_group") | is_group_member | is_group_owner | is_current_person has_global_perm("alsijil.view_week")
| has_object_perm("core.view_week_class_register_group")
| is_group_member
| is_group_owner
| is_current_person
) )
add_perm("alsijil.view_week", view_week_predicate) add_perm("alsijil.view_week", view_week_predicate)
# View week personal notes # View week personal notes
view_week_personal_notes_predicate = has_person & ( view_week_personal_notes_predicate = has_person & (
has_global_perm("alsijil.view_personalnote") | has_global_perm("alsijil.view_personalnote")
has_object_perm("alsijil.view_personalnote") | | has_object_perm("alsijil.view_personalnote")
is_group_owner | is_group_owner
) )
add_perm("alsijil.view_week_personalnote", view_week_personal_notes_predicate) add_perm("alsijil.view_week_personalnote", view_week_personal_notes_predicate)
# Register absence # Register absence
register_absence_predicate = has_person & ( register_absence_predicate = has_person & (
has_global_perm("alsijil.register_absence") | has_global_perm("alsijil.register_absence")
has_person_group_object_perm("core.register_absence_group") | | has_person_group_object_perm("core.register_absence_group")
has_global_perm("core.register_absence_person") | | has_global_perm("core.register_absence_person")
is_person_group_owner | is_person_group_owner
) )
add_perm("alsijil.register_absence", register_absence_predicate) add_perm("alsijil.register_absence", register_absence_predicate)
# View full register for group # View full register for group
view_full_register_predicate = has_person & ( view_full_register_predicate = has_person & (
has_global_perm("alsijil.view_full_register") | has_global_perm("alsijil.view_full_register")
has_object_perm("core.view_full_register_group") | | has_object_perm("core.view_full_register_group")
is_group_owner | is_group_owner
) )
add_perm("alsijil.view_full_register", view_full_register_predicate) add_perm("alsijil.view_full_register", view_full_register_predicate)
# View all personal note filters # View all personal note filters
list_personal_note_filters_predicate = has_person & has_global_perm("alsijil.view_personal_note_filter") list_personal_note_filters_predicate = has_person & has_global_perm(
"alsijil.view_personal_note_filter"
)
add_perm("alsijil.view_personal_note_filters", list_personal_note_filters_predicate) add_perm("alsijil.view_personal_note_filters", list_personal_note_filters_predicate)
# Edit personal note filter # Edit personal note filter
......
from typing import Optional from typing import Optional
from django.db.models import Count, Exists, OuterRef, Q, Sum from django.http import HttpRequest
from django.http import HttpRequest, HttpResponseNotFound
from django.shortcuts import get_object_or_404
from calendarweek import CalendarWeek
from aleksis.apps.chronos.managers import TimetableType
from aleksis.apps.chronos.models import LessonPeriod from aleksis.apps.chronos.models import LessonPeriod
from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk
from ..models import LessonDocumentation
def get_lesson_period_by_pk( def get_lesson_period_by_pk(
...@@ -23,9 +17,17 @@ def get_lesson_period_by_pk( ...@@ -23,9 +17,17 @@ def get_lesson_period_by_pk(
lesson_period = LessonPeriod.objects.get(pk=period_id) lesson_period = LessonPeriod.objects.get(pk=period_id)
elif hasattr(request, "user") and hasattr(request.user, "person"): elif hasattr(request, "user") and hasattr(request.user, "person"):
if request.user.person.lessons_as_teacher.exists(): if request.user.person.lessons_as_teacher.exists():
lesson_period = LessonPeriod.objects.at_time().filter_teacher(request.user.person).first() lesson_period = (
LessonPeriod.objects.at_time()
.filter_teacher(request.user.person)
.first()
)
else: else:
lesson_period = LessonPeriod.objects.at_time().filter_participant(request.user.person).first() lesson_period = (
LessonPeriod.objects.at_time()
.filter_participant(request.user.person)
.first()
)
else: else:
lesson_period = None lesson_period = None
return lesson_period return lesson_period
...@@ -42,4 +44,4 @@ def get_instance_by_pk( ...@@ -42,4 +44,4 @@ def get_instance_by_pk(
if type_ and id_: if type_ and id_:
return get_el_by_pk(request, type_, id_) return get_el_by_pk(request, type_, id_)
elif hasattr(request, "user") and hasattr(request.user, "person"): elif hasattr(request, "user") and hasattr(request.user, "person"):
return request.user.person return request.user.person
\ No newline at end of file
...@@ -11,36 +11,66 @@ from aleksis.core.util.predicates import check_object_permission ...@@ -11,36 +11,66 @@ from aleksis.core.util.predicates import check_object_permission
@predicate @predicate
def is_lesson_teacher(user: User, obj: LessonPeriod) -> bool: def is_lesson_teacher(user: User, obj: LessonPeriod) -> bool:
"""Predicate which checks whether the person linked to the user is a teacher in the lesson linked to the given LessonPeriod.""" """Predicate for teachers of a lesson.
Checks whether the person linked to the user is a teacher
in the lesson linked to the given LessonPeriod.
"""
return user.person in obj.lesson.teachers return user.person in obj.lesson.teachers
@predicate @predicate
def is_lesson_participant(user: User, obj: LessonPeriod) -> bool: def is_lesson_participant(user: User, obj: LessonPeriod) -> bool:
"""Predicate which checks whether the person linked to the user is a member in the groups linked to the given LessonPeriod.""" """Predicate for participants of a lesson.
Checks whether the person linked to the user is a member in
the groups linked to the given LessonPeriod.
"""
return obj.lesson.groups.filter(members=user.person).exists() return obj.lesson.groups.filter(members=user.person).exists()
@predicate @predicate
def is_lesson_parent_group_owner(user: User, obj: LessonPeriod) -> bool: def is_lesson_parent_group_owner(user: User, obj: LessonPeriod) -> bool:
"""Predicate which checks whether the person linked to the user is the owner of any parent groups of any groups of the given LessonPeriods lesson.""" """
Predicate for parent group owners of a lesson.
Checks whether the person linked to the user is the owner of
any parent groups of any groups of the given LessonPeriods lesson.
"""
return obj.lesson.groups.filter(parent_groups__owners=user.person).exists() return obj.lesson.groups.filter(parent_groups__owners=user.person).exists()
@predicate @predicate
def is_group_owner(user: User, obj: Union[Group, Person]) -> bool: def is_group_owner(user: User, obj: Union[Group, Person]) -> bool:
"""Predicate which checks whether the person linked to the user is the owner of the given group.""" """Predicate for group owners of a given group.
Checks whether the person linked to the user is the owner of the given group.
If there isn't provided a group, it will return `False`.
"""
if isinstance(obj, Group): if isinstance(obj, Group):
if obj.owners.filter(pk=user.person.pk).exists(): if obj.owners.filter(pk=user.person.pk).exists():
return True return True
return False return False
@predicate @predicate
def is_person_group_owner(user: User, obj: Person) -> bool: def is_person_group_owner(user: User, obj: Person) -> bool:
"""Predicate which checks whether the person linked to the user is the owner of any group of the given person.""" """
Predicate for group owners of any group.
Checks whether the person linked to the user is
the owner of any group of the given person.
"""
return obj.filter(member_of__owners=user.person).exists() return obj.filter(member_of__owners=user.person).exists()
@predicate @predicate
def has_person_group_object_perm(perm: str): def has_person_group_object_perm(perm: str):
"""Predicate which checks whether a user has a permission on any group of a person.""" """Predicate builder for permissions on a set of member groups.
Checks whether a user has a permission on any group of a person.
"""
name = f"has_person_group_object_perm:{perm}" name = f"has_person_group_object_perm:{perm}"
@predicate(name) @predicate(name)
...@@ -52,9 +82,14 @@ def has_person_group_object_perm(perm: str): ...@@ -52,9 +82,14 @@ def has_person_group_object_perm(perm: str):
return fn return fn
@predicate @predicate
def is_group_member(user: User, obj: Union[Group, Person]) -> bool: def is_group_member(user: User, obj: Union[Group, Person]) -> bool:
"""Predicate which checks whether the person linked to the user is a member of the given group.""" """Predicate for group membership.
Checks whether the person linked to the user is a member of the given group.
If there isn't provided a group, it will return `False`.
"""
if isinstance(obj, Group): if isinstance(obj, Group):
if obj.members.filter(pk=user.person.pk).exists(): if obj.members.filter(pk=user.person.pk).exists():
return True return True
...@@ -63,7 +98,10 @@ def is_group_member(user: User, obj: Union[Group, Person]) -> bool: ...@@ -63,7 +98,10 @@ def is_group_member(user: User, obj: Union[Group, Person]) -> bool:
def has_lesson_group_object_perm(perm: str): def has_lesson_group_object_perm(perm: str):
"""Build predicate which checks whether a user has a permission on any group of a LessonPeriod.""" """Predicate builder for permissions on lesson groups.
Checks whether a user has a permission on any group of a LessonPeriod.
"""
name = f"has_lesson_group_object_perm:{perm}" name = f"has_lesson_group_object_perm:{perm}"
@predicate(name) @predicate(name)
......
...@@ -2,7 +2,7 @@ from datetime import date, datetime, timedelta ...@@ -2,7 +2,7 @@ from datetime import date, datetime, timedelta
from typing import Optional from typing import Optional
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db.models import Count, Exists, F, OuterRef, Q, Subquery, Sum from django.db.models import Count, Exists, OuterRef, Q, Subquery, Sum
from django.http import Http404, HttpRequest, HttpResponse, HttpResponseNotFound from django.http import Http404, HttpRequest, HttpResponse, HttpResponseNotFound
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse from django.urls import reverse
...@@ -14,10 +14,10 @@ from rules.contrib.views import permission_required ...@@ -14,10 +14,10 @@ from rules.contrib.views import permission_required
from aleksis.apps.chronos.managers import TimetableType from aleksis.apps.chronos.managers import TimetableType
from aleksis.apps.chronos.models import LessonPeriod from aleksis.apps.chronos.models import LessonPeriod
from aleksis.apps.chronos.util.chronos_helpers import get_el_by_pk
from aleksis.core.models import Group, Person, SchoolTerm from aleksis.core.models import Group, Person, SchoolTerm
from aleksis.core.util import messages from aleksis.core.util import messages
from aleksis.core.util.core_helpers import objectgetter_optional from aleksis.core.util.core_helpers import objectgetter_optional
from .forms import ( from .forms import (
LessonDocumentationForm, LessonDocumentationForm,
PersonalNoteFilterForm, PersonalNoteFilterForm,
...@@ -27,7 +27,7 @@ from .forms import ( ...@@ -27,7 +27,7 @@ from .forms import (
) )
from .models import LessonDocumentation, PersonalNoteFilter from .models import LessonDocumentation, PersonalNoteFilter
from .tables import PersonalNoteFilterTable from .tables import PersonalNoteFilterTable
from .util.alsijil_helpers import get_lesson_period_by_pk, get_instance_by_pk from .util.alsijil_helpers import get_instance_by_pk, get_lesson_period_by_pk
@permission_required("alsijil.view_lesson", fn=get_lesson_period_by_pk) @permission_required("alsijil.view_lesson", fn=get_lesson_period_by_pk)
...@@ -102,10 +102,14 @@ def lesson( ...@@ -102,10 +102,14 @@ def lesson(
) )
if request.method == "POST": if request.method == "POST":
if lesson_documentation_form.is_valid() and request.user.has_perm("alsijil.edit_lessondocumentation", lesson_period): if lesson_documentation_form.is_valid() and request.user.has_perm(
"alsijil.edit_lessondocumentation", lesson_period
):
lesson_documentation_form.save() lesson_documentation_form.save()
if personal_note_formset.is_valid() and request.user.has_perm("alsijil.edit_personalnote", lesson_period): if personal_note_formset.is_valid() and request.user.has_perm(
"alsijil.edit_personalnote", lesson_period
):
instances = personal_note_formset.save() instances = personal_note_formset.save()
# Iterate over personal notes and carry changed absences to following lessons # Iterate over personal notes and carry changed absences to following lessons
...@@ -196,13 +200,13 @@ def week_view( ...@@ -196,13 +200,13 @@ def week_view(
# Aggregate all personal notes for this group and week # Aggregate all personal notes for this group and week
lesson_periods_pk = lesson_periods.values_list("pk", flat=True) lesson_periods_pk = lesson_periods.values_list("pk", flat=True)
persons = Person.objects.filter(is_active=True) persons = Person.objects.filter(is_active=True)
if not request.user.has_perm("alsijil.view_week_personalnote", instance): if not request.user.has_perm("alsijil.view_week_personalnote", instance):
persons = persons.filter(pk=request.user.pk) persons = persons.filter(pk=request.user.pk)
persons = (persons.filter(member_of__lessons__lesson_periods__in=lesson_periods_pk) persons = (
persons.filter(member_of__lessons__lesson_periods__in=lesson_periods_pk)
.distinct() .distinct()
.prefetch_related("personal_notes") .prefetch_related("personal_notes")
.annotate( .annotate(
...@@ -266,7 +270,9 @@ def week_view( ...@@ -266,7 +270,9 @@ def week_view(
return render(request, "alsijil/class_register/week_view.html", context) return render(request, "alsijil/class_register/week_view.html", context)
@permission_required("alsijil.view_full_register", fn=objectgetter_optional(Group, None, False)) @permission_required(
"alsijil.view_full_register", fn=objectgetter_optional(Group, None, False)
)
def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: def full_register_group(request: HttpRequest, id_: int) -> HttpResponse:
context = {} context = {}
...@@ -355,7 +361,9 @@ def register_absence(request: HttpRequest) -> HttpResponse: ...@@ -355,7 +361,9 @@ def register_absence(request: HttpRequest) -> HttpResponse:
register_absence_form = RegisterAbsenceForm(request.POST or None) register_absence_form = RegisterAbsenceForm(request.POST or None)
if request.method == "POST": if request.method == "POST":
if register_absence_form.is_valid() and request.user.has_perm("alsijil.register_absence", register_absence_form.cleaned_data["person"]): if register_absence_form.is_valid() and request.user.has_perm(
"alsijil.register_absence", register_absence_form.cleaned_data["person"]
):
# Get data from form # Get data from form
person = register_absence_form.cleaned_data["person"] person = register_absence_form.cleaned_data["person"]
start_date = register_absence_form.cleaned_data["date_start"] start_date = register_absence_form.cleaned_data["date_start"]
...@@ -395,7 +403,10 @@ def list_personal_note_filters(request: HttpRequest) -> HttpResponse: ...@@ -395,7 +403,10 @@ def list_personal_note_filters(request: HttpRequest) -> HttpResponse:
return render(request, "alsijil/personal_note_filter/list.html", context) return render(request, "alsijil/personal_note_filter/list.html", context)
@permission_required("alsijil.edit_personal_note_filter", fn=objectgetter_optional(PersonalNoteFilter, None, False)) @permission_required(
"alsijil.edit_personal_note_filter",
fn=objectgetter_optional(PersonalNoteFilter, None, False),
)
def edit_personal_note_filter( def edit_personal_note_filter(
request: HttpRequest, id_: Optional["int"] = None request: HttpRequest, id_: Optional["int"] = None
) -> HttpResponse: ) -> HttpResponse:
...@@ -422,7 +433,10 @@ def edit_personal_note_filter( ...@@ -422,7 +433,10 @@ def edit_personal_note_filter(
return render(request, "alsijil/personal_note_filter/manage.html", context) return render(request, "alsijil/personal_note_filter/manage.html", context)
@permission_required("alsijil.delete_personal_note_filter", fn=objectgetter_optional(PersonalNoteFilter, None, False)) @permission_required(
"alsijil.delete_personal_note_filter",
fn=objectgetter_optional(PersonalNoteFilter, None, False),
)
def delete_personal_note_filter(request: HttpRequest, id_: int) -> HttpResponse: def delete_personal_note_filter(request: HttpRequest, id_: int) -> HttpResponse:
context = {} context = {}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment