Skip to content
Snippets Groups Projects
Commit 67685b61 authored by Hangzhi Yu's avatar Hangzhi Yu
Browse files

Add additional rules&permissions in order to differentiate different access to...

Add additional rules&permissions in order to differentiate different access to individual timetables
parent 284b8d33
No related branches found
No related tags found
1 merge request!113Resolve "Review permissions"
Pipeline #5533 failed
...@@ -24,6 +24,8 @@ from .models import ( ...@@ -24,6 +24,8 @@ from .models import (
) )
from .util.format import format_date_period, format_m2m from .util.format import format_date_period, format_m2m
from guardian.admin import GuardedModelAdmin
def colour_badge(fg: str, bg: str, val: str): def colour_badge(fg: str, bg: str, val: str):
html = """ html = """
...@@ -144,7 +146,7 @@ class LessonAdmin(admin.ModelAdmin): ...@@ -144,7 +146,7 @@ class LessonAdmin(admin.ModelAdmin):
admin.site.register(Lesson, LessonAdmin) admin.site.register(Lesson, LessonAdmin)
class RoomAdmin(admin.ModelAdmin): class RoomAdmin(GuardedModelAdmin):
list_display = ("short_name", "name") list_display = ("short_name", "name")
list_display_links = ("short_name", "name") list_display_links = ("short_name", "name")
......
# Generated by Django 3.1.3 on 2020-12-22 12:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('chronos', '0004_substitution_extra_lesson_year'),
]
operations = [
migrations.AlterModelOptions(
name='room',
options={'ordering': ['name', 'short_name'],
'permissions': (('view_room_timetable', 'Can view room timetable'),),
'verbose_name': 'Room', 'verbose_name_plural': 'Rooms'},
),
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'))},
),
]
...@@ -124,3 +124,12 @@ Announcement.field( ...@@ -124,3 +124,12 @@ Announcement.field(
) )
Group.foreign_key("subject", Subject, related_name="groups") Group.foreign_key("subject", Subject, related_name="groups")
# Dynamically add extra permissions to Group and Person models in core
# Note: requires migrate afterwards
Group.add_permission(
"view_group_timetable", _("Can view group timetable"),
)
Person.add_permission(
"view_person_timetable", _("Can view person timetable"),
)
...@@ -317,6 +317,7 @@ class Room(ExtensibleModel): ...@@ -317,6 +317,7 @@ class Room(ExtensibleModel):
return reverse("timetable", args=["room", self.id]) return reverse("timetable", args=["room", self.id])
class Meta: class Meta:
permissions = (("view_room_timetable", _("Can view room timetable")),)
ordering = ["name", "short_name"] ordering = ["name", "short_name"]
verbose_name = _("Room") verbose_name = _("Room")
verbose_name_plural = _("Rooms") verbose_name_plural = _("Rooms")
...@@ -946,7 +947,9 @@ class ChronosGlobalPermissions(ExtensibleModel): ...@@ -946,7 +947,9 @@ class ChronosGlobalPermissions(ExtensibleModel):
class Meta: class Meta:
managed = False managed = False
permissions = ( permissions = (
("view_all_timetables", _("Can view all timetables")), ("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_timetable_overview", _("Can view timetable overview")),
("view_lessons_day", _("Can view all lessons per day")), ("view_lessons_day", _("Can view all lessons per day")),
) )
from rules import add_perm from rules import add_perm
from aleksis.core.models import Group, Person
from aleksis.core.util.predicates import ( from aleksis.core.util.predicates import (
has_any_object, has_any_object,
has_global_perm, has_global_perm,
...@@ -7,20 +8,22 @@ from aleksis.core.util.predicates import ( ...@@ -7,20 +8,22 @@ from aleksis.core.util.predicates import (
has_person, has_person,
) )
from .models import LessonSubstitution from .models import LessonSubstitution, Room
from .util.predicates import has_timetable_perm from .util.predicates import has_timetable_perm
# View timetable overview # View timetable overview
view_timetable_overview_predicate = has_person & has_global_perm("chronos.view_timetable_overview") view_timetable_overview_predicate = has_person & (
has_any_object("chronos.view_timetable", Person)
| has_any_object("chronos.view_timetable", Group)
| has_any_object("chronos.view_timetable", Room)
)
add_perm("chronos.view_timetable_overview", view_timetable_overview_predicate) add_perm("chronos.view_timetable_overview", view_timetable_overview_predicate)
# View my timetable # View my timetable
add_perm("chronos.view_my_timetable", has_person) add_perm("chronos.view_my_timetable", has_person)
# View timetable # View timetable
view_timetable_predicate = has_person & ( view_timetable_predicate = has_person & has_timetable_perm
has_global_perm("chronos.view_all_timetables") | has_timetable_perm
)
add_perm("chronos.view_timetable", view_timetable_predicate) add_perm("chronos.view_timetable", view_timetable_predicate)
# View all lessons per day # View all lessons per day
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
{% extends 'core/base.html' %} {% extends 'core/base.html' %}
{% load i18n static %} {% load i18n static rules %}
{% block extra_head %} {% block extra_head %}
<link rel="stylesheet" href="{% static 'css/chronos/timetable.css' %}"> <link rel="stylesheet" href="{% static 'css/chronos/timetable.css' %}">
...@@ -17,10 +17,13 @@ ...@@ -17,10 +17,13 @@
<h5>{% trans "Teachers" %}</h5> <h5>{% trans "Teachers" %}</h5>
{% for teacher in teachers %} {% for teacher in teachers %}
<a class="waves-effect waves-light btn btn-timetable-quicklaunch primary" {% has_perm "chronos.view_timetable" user teacher as has_teacher_perm %}
href="{% url 'timetable' 'teacher' teacher.pk %}"> {% if has_teacher_perm %}
{{ teacher.short_name }} <a class="waves-effect waves-light btn btn-timetable-quicklaunch primary"
</a> href="{% url 'timetable' 'teacher' teacher.pk %}">
{{ teacher.short_name }}
</a>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
...@@ -28,10 +31,13 @@ ...@@ -28,10 +31,13 @@
<h5>{% trans "Groups" %}</h5> <h5>{% trans "Groups" %}</h5>
{% for class in classes %} {% for class in classes %}
<a class="waves-effect waves-light btn btn-timetable-quicklaunch primary" {% has_perm "chronos.view_timetable" user class as has_class_perm %}
href="{% url 'timetable' 'group' class.pk %}"> {% if has_class_perm %}
{{ class.short_name }} <a class="waves-effect waves-light btn btn-timetable-quicklaunch primary"
</a> href="{% url 'timetable' 'group' class.pk %}">
{{ class.short_name }}
</a>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
...@@ -39,10 +45,13 @@ ...@@ -39,10 +45,13 @@
<h5>{% trans "Rooms" %}</h5> <h5>{% trans "Rooms" %}</h5>
{% for room in rooms %} {% for room in rooms %}
<a class="waves-effect waves-light btn btn-timetable-quicklaunch primary" {% has_perm "chronos.view_timetable" user room as has_room_perm %}
href="{% url 'timetable' 'room' room.pk %}"> {% if has_room_perm %}
{{ room.short_name }} <a class="waves-effect waves-light btn btn-timetable-quicklaunch primary"
</a> href="{% url 'timetable' 'room' room.pk %}">
{{ room.short_name }}
</a>
{% endif %}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
......
...@@ -5,16 +5,29 @@ from rules import predicate ...@@ -5,16 +5,29 @@ from rules import predicate
from aleksis.apps.chronos.models import Room from aleksis.apps.chronos.models import Room
from aleksis.core.models import Group, Person from aleksis.core.models import Group, Person
from aleksis.core.util.predicates import has_global_perm, has_object_perm
@predicate @predicate
def has_timetable_perm(user: User, obj: Model) -> bool: def has_timetable_perm(user: User, obj: Model) -> bool:
"""Predicate which checks whether the user is allowed to access the requested timetable.""" """Predicate which checks whether the user is allowed to access the requested timetable."""
if obj.model is Group: if type(obj) is Group:
return obj in user.person.member_of return (
elif obj.model is Person: user.person.member_of.filter(id=obj.id).exists()
return user.person == obj or user.person.primary_group == obj
elif obj.model is Room: or user.person.owner_of.filter(id=obj.id).exists()
return True or has_global_perm("chronos.view_all_group_timetables")(user)
or has_object_perm("core.view_group_timetable")(user, obj)
)
elif type(obj) is Person:
return (
user.person == obj
or has_global_perm("chronos.view_all_person_timetables")(user)
or has_object_perm("core.view_person_timetable")(user, obj)
)
elif type(obj) is Room:
return has_global_perm("chronos.view_all_room_timetables")(user) or has_object_perm(
"chronos.view_room_timetable"
)(user, obj)
else: else:
return False return False
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