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

Add permissions for everything

parent 521544b0
No related branches found
No related tags found
1 merge request!14Resolve "Not mensa-specific"
Pipeline #20367 failed
......@@ -17,9 +17,15 @@ def _get_menu_entries() -> List[Dict[str, Any]]:
"name": group.name,
"url": reverse("poster_show_current", args=[group.slug]),
"icon": "picture_as_pdf",
"validators": ["menu_generator.validators.is_authenticated"],
"validators": [
(
"aleksis.apps.resint.rules.permission_validator",
"resint.view_poster_pdf_menu",
group,
),
],
}
for group in PosterGroup.objects.filter(show_in_menu=True)
for group in PosterGroup.objects.all()
]
......@@ -32,22 +38,34 @@ MENUS = {
"url": "#",
"icon": "open_in_browser",
"root": True,
"validators": ["menu_generator.validators.is_authenticated",],
"validators": [
("aleksis.core.util.predicates.permission_validator", "resint.view_poster_menu",),
],
"submenu": [
{
"name": _("Manage posters"),
"url": "poster_index",
"icon": "file_upload",
"validators": ["menu_generator.validators.is_authenticated"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"resint.view_posters_rule",
),
],
},
{
"name": _("Poster groups"),
"url": "poster_group_list",
"icon": "topic",
"validators": ["menu_generator.validators.is_authenticated"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"resint.view_postergroups_rule",
),
],
},
]
+ get_menu_entries_lazy(),
],
}
]
+ get_menu_entries_lazy(),
}
# Generated by Django 3.2.5 on 2021-07-03 09:20
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('resint', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='postergroup',
options={'permissions': [('view_poster_of_group', 'Can view all posters of this group'), ('upload_poster_to_group', 'Can upload new posters to this group'), ('delete_poster_of_group', 'Can delete all posters of this group')], 'verbose_name': 'Poster group', 'verbose_name_plural': 'Poster groups'},
),
]
......@@ -41,6 +41,11 @@ class PosterGroup(ExtensibleModel):
models.UniqueConstraint(fields=["site_id", "name"], name="unique_site_name"),
models.UniqueConstraint(fields=["site_id", "slug"], name="unique_site_slug"),
]
permissions = [
("view_poster_of_group", _("Can view all posters of this group")),
("upload_poster_to_group", _("Can upload new posters to this group")),
("delete_poster_of_group", _("Can delete all posters of this group")),
]
def __str__(self) -> str:
return f"{self.name} ({self.publishing_day_name}, {self.publishing_time})"
......
from django.contrib.auth.models import User
from django.http import HttpRequest
from rules import add_perm, predicate
from aleksis.apps.resint.models import Poster, PosterGroup
from aleksis.core.util.predicates import (
check_object_permission,
has_any_object,
has_global_perm,
has_object_perm,
has_person,
)
def has_poster_group_object_perm(perm: str):
name = f"has_poster_group_object_perm:{perm}"
@predicate(name)
def fn(user: User, obj: Poster) -> bool:
return check_object_permission(user, perm, obj.group, checker_obj=obj)
return fn
def permission_validator(request: HttpRequest, perm: str, obj) -> bool:
"""Check whether the request user has a permission."""
print("Am I executed?")
if request.user:
print("And I", request, request.user, perm, obj)
print(request.user.has_perm(perm, obj))
return request.user.has_perm(perm, obj)
return False
@predicate
def is_public_poster_group(user: User, obj: PosterGroup):
return obj.public
@predicate
def show_poster_group_in_menu(user: User, obj: PosterGroup):
return obj.show_in_menu
# View poster group list
view_poster_groups_predicate = has_person & (
has_global_perm("resint.view_postergroup")
| has_any_object("resint.view_postergroup", PosterGroup)
)
add_perm("resint.view_postergroups_rule", view_poster_groups_predicate)
# Add poster group
add_poster_group_predicate = view_poster_groups_predicate & has_global_perm(
"resint.add_postergroup"
)
add_perm("resint.add_postergroup_rule", add_poster_group_predicate)
# Edit poster group
edit_poster_group_predicate = view_poster_groups_predicate & (
has_global_perm("resint.change_postergroup") | has_object_perm("resint.change_postergroup")
)
add_perm("resint.edit_postergroup_rule", edit_poster_group_predicate)
# Delete poster group
delete_poster_group_predicate = view_poster_groups_predicate & (
has_global_perm("resint.delete_postergroup") | has_object_perm("resint.delete_postergroup")
)
add_perm("resint.delete_postergroup_rule", delete_poster_group_predicate)
view_posters_predicate = has_person & (
has_global_perm("resint.view_poster")
| has_any_object("resint.view_poster", Poster)
| has_any_object("resint.view_poster_of_group", PosterGroup)
)
add_perm("resint.view_posters_rule", view_posters_predicate)
# Upload poster
upload_poster_predicate = view_posters_predicate & (
has_global_perm("resint.add_poster") | has_any_object("resint.add_poster_to_group", PosterGroup)
) # FIXME FIlter on form
add_perm("resint.upload_poster_rule", upload_poster_predicate)
# Delete poster
delete_poster_predicate = view_posters_predicate & (
has_global_perm("resint.delete_poster")
| has_object_perm("resint.delete_poster")
| has_poster_group_object_perm("resint.delete_poster_of_group")
)
add_perm("resint.delete_poster_rule", delete_poster_predicate)
# View poster PDF file
view_poster_pdf_predicate = is_public_poster_group | (
has_person
& (has_global_perm("resint.view_postergroup") | has_global_perm("resint.view_poster"))
)
add_perm("resint.view_poster_pdf", view_poster_pdf_predicate)
# View menu entry for single posters
view_poster_pdf_menu_predicate = show_poster_group_in_menu & view_poster_pdf_predicate
add_perm("resint.view_poster_pdf_menu", view_poster_pdf_menu_predicate)
# Show the poster manage menu
view_poster_menu_predicate = view_posters_predicate | view_poster_groups_predicate
add_perm("resint.view_poster_menu", view_poster_menu_predicate)
{% extends 'core/base.html' %}
{% load material_form i18n %}
{% load material_form i18n rules %}
{% block browser_title %}{% blocktrans %}Poster groups{% endblocktrans %}{% endblock %}
{% block content %}
<a class="waves-effect waves-light btn green modal-trigger right" href="{% url "create_poster_group" %}">
<i class="material-icons left">add</i>{% blocktrans %}Create new poster group{% endblocktrans %}
</a>
{% has_perm "resint.add_postergroup" user as can_add_poster_group %}
{% if can_add_poster_group %}
<a class="waves-effect waves-light btn green modal-trigger right" href="{% url "create_poster_group" %}">
<i class="material-icons left">add</i>{% blocktrans %}Create new poster group{% endblocktrans %}
</a>
{% endif %}
<h1>{% blocktrans %}Poster groups{% endblocktrans %}</h1>
......@@ -37,16 +40,23 @@
</a>
</td>
<td>
<a href="{% url 'edit_poster_group' poster_group.id %}"
class="waves-effect waves-light btn-flat orange-text">
<i class="material-icons left">edit</i>
{% trans "Edit" %}
</a>
<a href="{% url 'delete_poster_group' poster_group.id %}"
class="waves-effect waves-light btn-flat red-text">
<i class="material-icons left">delete</i>
{% trans "Delete" %}
</a>
{% has_perm "resint.edit_postergroup" user poster_group as can_edit_poster_group %}
{% if can_edit_poster_group %}
<a href="{% url 'edit_poster_group' poster_group.id %}"
class="waves-effect waves-light btn-flat orange-text">
<i class="material-icons left">edit</i>
{% trans "Edit" %}
</a>
{% endif %}
{% has_perm "resint.delete_postergroup" user poster_group as can_delete_poster_group %}
{% if can_delete_poster_group %}
<a href="{% url 'delete_poster_group' poster_group.id %}"
class="waves-effect waves-light btn-flat red-text">
<i class="material-icons left">delete</i>
{% trans "Delete" %}
</a>
{% endif %}
</td>
</tr>
{% empty %}
......
{% extends "core/base.html" %}
{% load static i18n %}
{% load static i18n rules %}
{% block content %}
......@@ -42,10 +42,15 @@
</div>
{% endfor %}
</div>
<a class="waves-effect waves-light btn green right" href="{% url "poster_upload" %}">
<i class="material-icons left">add</i>
{% trans "Upload new poster" %}
</a>
{% has_perm "resint.upload_poster" user as can_upload_poster %}
{% if can_upload_poster %}
<a class="waves-effect waves-light btn green right" href="{% url "poster_upload" %}">
<i class="material-icons left">add</i>
{% trans "Upload new poster" %}
</a>
{% endif %}
<h2>{% trans "All uploaded posters" %}</h2>
<table>
<thead>
......@@ -65,9 +70,13 @@
<a class="btn-flat waves-effect waves-green" href="{{ poster.pdf.url }}" target="_blank">
<i class="material-icons left">picture_as_pdf</i> {% trans "Show" %}
</a>
<a class="btn-flat red-text waves-effect waves-red" href="{% url "poster_delete" poster.id %}">
<i class="material-icons left">delete</i> {% trans "Delete" %}
</a>
{% has_perm "resint.delete_poster" user poster as can_delete_poster %}
{% if can_delete_poster %}
<a class="btn-flat red-text waves-effect waves-red" href="{% url "poster_delete" poster.id %}">
<i class="material-icons left">delete</i> {% trans "Delete" %}
</a>
{% endif %}
</td>
</tr>
{% endfor %}
......
......@@ -8,20 +8,30 @@ from django.views import View
from django.views.generic.detail import SingleObjectMixin
from django.views.generic.list import ListView
from guardian.shortcuts import get_objects_for_user
from rules.contrib.views import PermissionRequiredMixin
from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView
from .forms import PosterGroupForm, PosterUploadForm
from .models import Poster, PosterGroup
class PosterGroupListView(ListView):
class PosterGroupListView(PermissionRequiredMixin, ListView):
"""Show a list of all poster groups."""
template_name = "resint/group/list.html"
model = PosterGroup
permission_required = "resint.view_postergroups_rule"
def get_queryset(self) -> QuerySet:
qs = super().get_queryset()
if self.request.user.has_perm("resint.view_postergroup"):
return qs
return get_objects_for_user(self.request.user, "resint.view_postergroup", qs)
class PosterGroupCreateView(AdvancedCreateView):
class PosterGroupCreateView(PermissionRequiredMixin, AdvancedCreateView):
"""Create a new poster group."""
model = PosterGroup
......@@ -29,9 +39,10 @@ class PosterGroupCreateView(AdvancedCreateView):
template_name = "resint/group/create.html"
success_message = _("The poster group has been saved.")
form_class = PosterGroupForm
permission_required = "resint.create_postergroup_rule"
class PosterGroupEditView(AdvancedEditView):
class PosterGroupEditView(PermissionRequiredMixin, AdvancedEditView):
"""Edit an existing poster group."""
model = PosterGroup
......@@ -39,25 +50,36 @@ class PosterGroupEditView(AdvancedEditView):
template_name = "resint/group/edit.html"
success_message = _("The poster group has been saved.")
form_class = PosterGroupForm
permission_required = "resint.edit_postergroup_rule"
class PosterGroupDeleteView(AdvancedDeleteView):
class PosterGroupDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
"""Delete a poster group."""
model = PosterGroup
success_url = reverse_lazy("poster_group_list")
success_message = _("The poster group has been deleted.")
template_name = "core/pages/delete.html"
permission_required = "resint.delete_postergroup_rule"
class PosterListView(ListView):
class PosterListView(PermissionRequiredMixin, ListView):
"""Show a list of all uploaded posters."""
template_name = "resint/poster/list.html"
model = Poster
permission_required = "resint.view_posters_rule"
def get_queryset(self) -> QuerySet:
return Poster.objects.all().order_by("-year", "-week")
qs = Poster.objects.all().order_by("-year", "-week")
if self.request.user.has_perm("resint.view_poster"):
return qs
allowed_groups = get_objects_for_user(self.request.user, "resint.view_poster_of_group", PosterGroup)
posters = get_objects_for_user(self.request.user, "resint.view_poster", qs)
return qs.filter(group__in=allowed_groups) | posters
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
context = super().get_context_data(**kwargs)
......@@ -65,7 +87,7 @@ class PosterListView(ListView):
return context
class PosterUploadView(AdvancedCreateView):
class PosterUploadView(PermissionRequiredMixin, AdvancedCreateView):
"""Upload a new poster."""
model = Poster
......@@ -73,21 +95,24 @@ class PosterUploadView(AdvancedCreateView):
template_name = "resint/poster/upload.html"
success_message = _("The poster has been uploaded.")
form_class = PosterUploadForm
permission_required = "resint.upload_poster_rule"
class PosterDeleteView(AdvancedDeleteView):
class PosterDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
"""Delete an uploaded poster."""
model = Poster
success_url = reverse_lazy("poster_index")
success_message = _("The poster has been deleted.")
template_name = "core/pages/delete.html"
permission_required = "resint.delete_poster_rule"
class PosterCurrentView(SingleObjectMixin, View):
class PosterCurrentView(PermissionRequiredMixin, SingleObjectMixin, View):
"""Show the poster which is currently valid."""
model = PosterGroup
permission_required = "resint.view_poster_pdf"
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> FileResponse:
group = self.get_object()
......
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