Improve pedagogy permissions

This commit is contained in:
imperosol 2025-01-16 15:10:46 +01:00
parent 61170c0918
commit 0d95c3b9c9
9 changed files with 167 additions and 210 deletions

View File

@ -256,7 +256,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["request_user"] = self.request.user
kwargs["club"] = self.get_object()
kwargs["club"] = self.object
kwargs["club_members"] = self.members
return kwargs
@ -273,9 +273,9 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
users = data.pop("users", [])
users_old = data.pop("users_old", [])
for user in users:
Membership(club=self.get_object(), user=user, **data).save()
Membership(club=self.object, user=user, **data).save()
for user in users_old:
membership = self.get_object().get_membership_for(user)
membership = self.object.get_membership_for(user)
membership.end_date = timezone.now()
membership.save()
return resp
@ -285,9 +285,7 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
return super().dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs):
return reverse_lazy(
"club:club_members", kwargs={"club_id": self.get_object().id}
)
return reverse_lazy("club:club_members", kwargs={"club_id": self.object.id})
class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView):

View File

@ -895,13 +895,16 @@ Welcome to the wiki page!
subscribers = Group.objects.create(name="Subscribers")
subscribers.permissions.add(
*list(perms.filter(codename__in=["add_news", "add_uvcommentreport"]))
*list(perms.filter(codename__in=["add_news", "add_uvcomment"]))
)
old_subscribers = Group.objects.create(name="Old subscribers")
old_subscribers.permissions.add(
*list(
perms.filter(
codename__in=[
"view_uv",
"view_uvcomment",
"add_uvcommentreport",
"view_user",
"view_picture",
"view_album",
@ -973,9 +976,9 @@ Welcome to the wiki page!
)
pedagogy_admin.permissions.add(
*list(
perms.filter(content_type__app_label="pedagogy").values_list(
"pk", flat=True
)
perms.filter(content_type__app_label="pedagogy")
.exclude(codename__in=["change_uvcomment"])
.values_list("pk", flat=True)
)
)
self.reset_index("core", "auth")

View File

@ -28,8 +28,7 @@ from django.http import (
HttpResponseServerError,
)
from django.shortcuts import render
from django.utils.functional import cached_property
from django.views.generic.detail import SingleObjectMixin
from django.views.generic.detail import BaseDetailView
from django.views.generic.edit import FormView
from sentry_sdk import last_event_id
@ -54,17 +53,12 @@ def internal_servor_error(request):
return HttpResponseServerError(render(request, "core/500.jinja"))
class DetailFormView(SingleObjectMixin, FormView):
class DetailFormView(FormView, BaseDetailView):
"""Class that allow both a detail view and a form view."""
def get_object(self):
"""Get current group from id in url."""
return self.cached_object
@cached_property
def cached_object(self):
"""Optimisation on group retrieval."""
return super().get_object()
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super().post(request, *args, **kwargs)
# F403: those star-imports would be hellish to refactor

View File

@ -66,7 +66,6 @@ from core.views.forms import (
)
from core.views.mixins import QuickNotifMixin, TabedViewMixin
from counter.models import Refilling, Selling
from counter.views.student_card import StudentCardFormView
from eboutic.models import Invoice
from subscription.models import Subscription
from trombi.views import UserTrombiForm
@ -566,6 +565,8 @@ class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView):
if not hasattr(self.object, "trombi_user"):
kwargs["trombi_form"] = UserTrombiForm()
if hasattr(self.object, "customer"):
from counter.views.student_card import StudentCardFormView
kwargs["student_card_fragment"] = StudentCardFormView.get_template_data(
self.object.customer
).render(self.request)

View File

@ -20,10 +20,12 @@
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
from typing import Self
from django.conf import settings
from django.core import validators
from django.db import models
from django.db.models import Exists, OuterRef
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
@ -145,14 +147,6 @@ class UV(models.Model):
def get_absolute_url(self):
return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.id})
def is_owned_by(self, user):
"""Can be created by superuser, root or pedagogy admin user."""
return user.is_in_group(pk=settings.SITH_GROUP_PEDAGOGY_ADMIN_ID)
def can_be_viewed_by(self, user):
"""Only visible by subscribers."""
return user.is_subscribed
def __grade_average_generic(self, field):
comments = self.comments.filter(**{field + "__gte": 0})
if not comments.exists():
@ -191,6 +185,22 @@ class UV(models.Model):
return self.__grade_average_generic("grade_work_load")
class UVCommentQuerySet(models.QuerySet):
def viewable_by(self, user: User) -> Self:
if user.has_perms(["pedagogy.view_uvcomment", "pedagogy.view_uvcommentreport"]):
# the user can view uv comment reports,
# so he can view non-moderated comments
return self
if user.has_perm("pedagogy.view_uvcomment"):
return self.filter(reports=None)
return self.filter(author=user)
def annotate_is_reported(self) -> Self:
return self.annotate(
is_reported=Exists(UVCommentReport.objects.filter(comment=OuterRef("pk")))
)
class UVComment(models.Model):
"""A comment about an UV."""
@ -243,6 +253,8 @@ class UVComment(models.Model):
)
publish_date = models.DateTimeField(_("publish date"), blank=True)
objects = UVCommentQuerySet.as_manager()
def __str__(self):
return f"{self.uv} - {self.author}"
@ -251,15 +263,6 @@ class UVComment(models.Model):
self.publish_date = timezone.now()
super().save(*args, **kwargs)
def is_owned_by(self, user):
"""Is owned by a pedagogy admin, a superuser or the author himself."""
return self.author == user or user.is_owner(self.uv)
@cached_property
def is_reported(self):
"""Return True if someone reported this UV."""
return self.reports.exists()
# TODO : it seems that some views were meant to be implemented
# to use this model.
@ -323,7 +326,3 @@ class UVCommentReport(models.Model):
@cached_property
def uv(self):
return self.comment.uv
def is_owned_by(self, user):
"""Can be created by a pedagogy admin, a superuser or a subscriber."""
return user.is_subscribed or user.is_owner(self.comment.uv)

View File

@ -19,7 +19,7 @@
{% endblock head %}
{% block content %}
{% if can_create_uv %}
{% if user.has_perm("pedagogy.add_uv") %}
<div class="action-bar">
<p>
<a href="{{ url('pedagogy:uv_create') }}">{% trans %}Create UV{% endtrans %}</a>
@ -94,8 +94,10 @@
<td>{% trans %}Credit type{% endtrans %}</td>
<td><i class="fa fa-leaf"></i></td>
<td><i class="fa-regular fa-sun"></i></td>
{% if can_create_uv %}
{%- if user.has_perm("pedagogy.change_uv") -%}
<td>{% trans %}Edit{% endtrans %}</td>
{%- endif -%}
{%- if user.has_perm("pedagogy.delete_uv") -%}
<td>{% trans %}Delete{% endtrans %}</td>
{% endif %}
</tr>
@ -109,8 +111,10 @@
<td x-text="uv.credit_type"></td>
<td><i :class="uv.semester.includes('AUTUMN') && 'fa fa-leaf'"></i></td>
<td><i :class="uv.semester.includes('SPRING') && 'fa-regular fa-sun'"></i></td>
{% if can_create_uv -%}
{%- if user.has_perm("pedagogy.change_uv") -%}
<td><a :href="`/pedagogy/uv/${uv.id}/edit`">{% trans %}Edit{% endtrans %}</a></td>
{%- endif -%}
{%- if user.has_perm("pedagogy.delete_uv") -%}
<td><a :href="`/pedagogy/uv/${uv.id}/delete`">{% trans %}Delete{% endtrans %}</a></td>
{%- endif -%}
</tr>

View File

@ -89,7 +89,7 @@
<div id="leave_comment_not_allowed">
<p>{% trans %}You already posted a comment on this UV. If you want to comment again, please modify or delete your previous comment.{% endtrans %}</p>
</div>
{% else %}
{% elif user.has_perm("pedagogy.add_uvcomment") %}
<div id="leave_comment">
<h2>{% trans %}Leave comment{% endtrans %}</h2>
<div>
@ -146,9 +146,9 @@
{% endif %}
<br>
{% if object.comments.exists() %}
{% if comments %}
<h2>{% trans %}Comments{% endtrans %}</h2>
{% for comment in object.comments.order_by("-publish_date").all() %}
{% for comment in comments %}
<div id="{{ comment.id }}" class="comment-container">
<div class="grade-block">
@ -183,16 +183,28 @@
</p>
{% endif %}
{% if user.is_owner(comment) %}
{% if comment.author_id == user.id or user.has_perm("pedagogy.change_comment") %}
<p class="actions">
<a href="{{ url('pedagogy:comment_update', comment_id=comment.id) }}">{% trans %}Edit{% endtrans %}</a>
<a href="{{ url('pedagogy:comment_delete', comment_id=comment.id) }}">{% trans %}Delete{% endtrans %}</a>
<a href="{{ url('pedagogy:comment_update', comment_id=comment.id) }}">
{% trans %}Edit{% endtrans %}
</a>
{% endif %}
{% if comment.author_id == user.id or user.has_perm("pedagogy.delete_comment") %}
<a href="{{ url('pedagogy:comment_delete', comment_id=comment.id) }}">
{% trans %}Delete{% endtrans %}
</a>
</p>
{% endif %}
</div>
<div class="comment-end-bar">
<div class="report"><p><a href="{{ url('pedagogy:comment_report', comment_id=comment.id) }}">{% trans %}Report this comment{% endtrans %}</a></p></div>
<div class="report">
<p>
<a href="{{ url('pedagogy:comment_report', comment_id=comment.id) }}">
{% trans %}Report this comment{% endtrans %}
</a>
</p>
</div>
<div class="date"><p>{{ comment.publish_date.strftime('%d/%m/%Y') }}</p></div>
@ -209,7 +221,7 @@
<script type="text/javascript">
$("#return_noscript").hide();
$("#return_js").show();
var icons = {
const icons = {
header: "fa fa-toggle-right",
activeHeader: "fa fa-toggle-down"
};

View File

@ -20,14 +20,18 @@
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
from typing import Callable
import pytest
from django.conf import settings
from django.contrib.auth.models import Permission
from django.test import Client, TestCase
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from model_bakery import baker
from pytest_django.asserts import assertRedirects
from core.baker_recipes import old_subscriber_user, subscriber_user
from core.models import Notification, User
from pedagogy.models import UV, UVComment, UVCommentReport
@ -144,17 +148,17 @@ class TestUVCreation(TestCase):
@pytest.mark.django_db
@pytest.mark.parametrize(
("username", "expected_code"),
("user_factory", "expected_code"),
[
("root", 200),
("tutu", 200),
("sli", 200),
("old_subscriber", 200),
("public", 403),
(subscriber_user.make, 200),
(old_subscriber_user.make, 200),
(lambda: baker.make(User), 403),
],
)
def test_guide_permissions(client: Client, username: str, expected_code: int):
client.force_login(User.objects.get(username=username))
def test_guide_permissions(
client: Client, user_factory: Callable[[], User], expected_code: int
):
client.force_login(user_factory())
res = client.get(reverse("pedagogy:guide"))
assert res.status_code == expected_code
@ -190,20 +194,15 @@ class TestUVDelete(TestCase):
def test_uv_delete_pedagogy_unauthorized_fail(self):
# Anonymous user
response = self.client.post(self.delete_uv_url)
assert response.status_code == 403
assertRedirects(response, reverse("core:login") + f"?next={self.delete_uv_url}")
assert UV.objects.filter(pk=self.uv.pk).exists()
# Not subscribed user
self.client.force_login(self.guy)
response = self.client.post(self.delete_uv_url)
assert response.status_code == 403
assert UV.objects.filter(pk=self.uv.pk).exists()
# Simply subscribed user
self.client.force_login(self.sli)
response = self.client.post(self.delete_uv_url)
assert response.status_code == 403
assert UV.objects.filter(pk=self.uv.pk).exists()
for user in baker.make(User), subscriber_user.make():
with self.subTest():
self.client.force_login(user)
response = self.client.post(self.delete_uv_url)
assert response.status_code == 403
assert UV.objects.filter(pk=self.uv.pk).exists()
class TestUVUpdate(TestCase):
@ -249,7 +248,7 @@ class TestUVUpdate(TestCase):
response = self.client.post(
self.update_uv_url, create_uv_template(self.bibou.id, code="PA00")
)
assert response.status_code == 403
assertRedirects(response, reverse("core:login") + f"?next={self.update_uv_url}")
# Not subscribed user
self.client.force_login(self.guy)
@ -312,7 +311,7 @@ class TestUVCommentCreationAndDisplay(TestCase):
response = self.client.post(
self.uv_url, create_uv_comment_template(self.bibou.id)
)
self.assertRedirects(response, self.uv_url)
assertRedirects(response, self.uv_url)
response = self.client.get(self.uv_url)
self.assertContains(response, text="Superbe UV")
@ -338,7 +337,7 @@ class TestUVCommentCreationAndDisplay(TestCase):
nb_comments = self.uv.comments.count()
# Test with anonymous user
response = self.client.post(self.uv_url, create_uv_comment_template(0))
assert response.status_code == 403
assertRedirects(response, reverse("core:login") + f"?next={self.uv_url}")
# Test with non subscribed user
self.client.force_login(self.guy)
@ -405,62 +404,35 @@ class TestUVCommentDelete(TestCase):
@classmethod
def setUpTestData(cls):
cls.bibou = User.objects.get(username="root")
cls.tutu = User.objects.get(username="tutu")
cls.sli = User.objects.get(username="sli")
cls.guy = User.objects.get(username="guy")
cls.krophil = User.objects.get(username="krophil")
cls.comment = baker.make(UVComment)
def setUp(self):
comment_kwargs = create_uv_comment_template(
User.objects.get(username="krophil").id
)
comment_kwargs["author"] = User.objects.get(id=comment_kwargs["author"])
comment_kwargs["uv"] = UV.objects.get(id=comment_kwargs["uv"])
self.comment = UVComment(**comment_kwargs)
self.comment.save()
def test_uv_comment_delete_root_success(self):
self.client.force_login(self.bibou)
self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
assert not UVComment.objects.filter(id=self.comment.id).exists()
def test_uv_comment_delete_pedagogy_admin_success(self):
self.client.force_login(self.tutu)
self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
assert not UVComment.objects.filter(id=self.comment.id).exists()
def test_uv_comment_delete_author_success(self):
self.client.force_login(self.krophil)
self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
assert not UVComment.objects.filter(id=self.comment.id).exists()
def test_uv_comment_delete_success(self):
url = reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
for user in (
baker.make(User, is_superuser=True),
baker.make(
User, user_permissions=[Permission.objects.get(codename="view_uv")]
),
self.comment.author,
):
with self.subTest():
self.client.force_login(user)
self.client.post(url)
assert not UVComment.objects.filter(id=self.comment.id).exists()
def test_uv_comment_delete_unauthorized_fail(self):
url = reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
# Anonymous user
response = self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
assert response.status_code == 403
response = self.client.post(url)
assertRedirects(response, reverse("core:login") + f"?next={url}")
# Unsbscribed user
self.client.force_login(self.guy)
response = self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
assert response.status_code == 403
# Subscribed user (not author of the comment)
self.client.force_login(self.sli)
response = self.client.post(
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
)
assert response.status_code == 403
for user in baker.make(User), subscriber_user.make():
with self.subTest():
self.client.force_login(user)
response = self.client.post(url)
assert response.status_code == 403
# Check that the comment still exists
assert UVComment.objects.filter(id=self.comment.id).exists()
@ -499,16 +471,6 @@ class TestUVCommentUpdate(TestCase):
self.comment.refresh_from_db()
self.assertEqual(self.comment.comment, self.comment_edit["comment"])
def test_uv_comment_update_pedagogy_admin_success(self):
self.client.force_login(self.tutu)
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
assert response.status_code == 302
self.comment.refresh_from_db()
self.assertEqual(self.comment.comment, self.comment_edit["comment"])
def test_uv_comment_update_author_success(self):
self.client.force_login(self.krophil)
response = self.client.post(
@ -520,25 +482,18 @@ class TestUVCommentUpdate(TestCase):
self.assertEqual(self.comment.comment, self.comment_edit["comment"])
def test_uv_comment_update_unauthorized_fail(self):
url = reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id})
# Anonymous user
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
assert response.status_code == 403
response = self.client.post(url, self.comment_edit)
assertRedirects(response, reverse("core:login") + f"?next={url}")
# Unsbscribed user
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
self.client.force_login(baker.make(User))
response = self.client.post(url, self.comment_edit)
assert response.status_code == 403
# Subscribed user (not author of the comment)
response = self.client.post(
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
self.comment_edit,
)
response = self.client.post(url, self.comment_edit)
assert response.status_code == 403
# Check that the comment hasn't change
@ -611,18 +566,19 @@ class TestUVModerationForm(TestCase):
assert response.status_code == 200
def test_access_unauthorized_fail(self):
url = reverse("pedagogy:moderation")
# Test with anonymous user
response = self.client.get(reverse("pedagogy:moderation"))
assert response.status_code == 403
response = self.client.get(url)
assertRedirects(response, reverse("core:login") + f"?next={url}")
# Test with unsubscribed user
self.client.force_login(self.guy)
response = self.client.get(reverse("pedagogy:moderation"))
response = self.client.get(url)
assert response.status_code == 403
# Test with subscribed user
self.client.force_login(self.sli)
response = self.client.get(reverse("pedagogy:moderation"))
response = self.client.get(url)
assert response.status_code == 403
def test_do_nothing(self):

View File

@ -22,8 +22,7 @@
#
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.core.exceptions import PermissionDenied
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db.models import Exists, OuterRef
from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy
@ -35,7 +34,7 @@ from django.views.generic import (
UpdateView,
)
from core.auth.mixins import CanEditPropMixin, CanViewMixin, FormerSubscriberMixin
from core.auth.mixins import PermissionOrAuthorRequiredMixin
from core.models import Notification, User
from core.views import DetailFormView
from pedagogy.forms import (
@ -47,7 +46,7 @@ from pedagogy.forms import (
from pedagogy.models import UV, UVComment, UVCommentReport
class UVDetailFormView(CanViewMixin, DetailFormView):
class UVDetailFormView(PermissionRequiredMixin, DetailFormView):
"""Display every comment of an UV and detailed infos about it.
Allow to comment the UV.
@ -57,11 +56,21 @@ class UVDetailFormView(CanViewMixin, DetailFormView):
pk_url_kwarg = "uv_id"
template_name = "pedagogy/uv_detail.jinja"
form_class = UVCommentForm
permission_required = "pedagogy.view_uv"
def has_permission(self):
if self.request.method == "POST" and not self.request.user.has_perm(
"pedagogy.add_uvcomment"
):
# if it's a POST request, the user is trying to add a new UVComment
# thus he also needs the "add_uvcomment" permission
return False
return super().has_permission()
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["author_id"] = self.request.user.id
kwargs["uv_id"] = self.get_object().id
kwargs["uv_id"] = self.object.id
kwargs["is_creation"] = True
return kwargs
@ -69,66 +78,61 @@ class UVDetailFormView(CanViewMixin, DetailFormView):
form.save()
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy(
"pedagogy:uv_detail", kwargs={"uv_id": self.get_object().id}
)
def get_context_data(self, **kwargs):
user = self.request.user
return super().get_context_data(**kwargs) | {
"can_create_uv": (
user.is_root
or user.is_in_group(pk=settings.SITH_GROUP_PEDAGOGY_ADMIN_ID)
"comments": list(
self.object.comments.viewable_by(self.request.user)
.annotate_is_reported()
.select_related("author")
.order_by("-publish_date")
)
}
def get_success_url(self):
# once the new uv comment has been saved
# redirect to the same page we are currently
return self.request.path
class UVCommentUpdateView(CanEditPropMixin, UpdateView):
class UVCommentUpdateView(PermissionOrAuthorRequiredMixin, UpdateView):
"""Allow edit of a given comment."""
model = UVComment
form_class = UVCommentForm
pk_url_kwarg = "comment_id"
template_name = "core/edit.jinja"
permission_required = "pedagogy.change_uvcomment"
author_field = "author"
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
obj = self.get_object()
kwargs["author_id"] = obj.author.id
kwargs["uv_id"] = obj.uv.id
kwargs["author_id"] = self.object.author_id
kwargs["uv_id"] = self.object.uv_id
kwargs["is_creation"] = False
return kwargs
def get_success_url(self):
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})
return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv_id})
class UVCommentDeleteView(CanEditPropMixin, DeleteView):
class UVCommentDeleteView(PermissionOrAuthorRequiredMixin, DeleteView):
"""Allow delete of a given comment."""
model = UVComment
pk_url_kwarg = "comment_id"
template_name = "core/delete_confirm.jinja"
permission_required = "pedagogy.delete_uvcomment"
author_field = "author"
def get_success_url(self):
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})
return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv_id})
class UVGuideView(LoginRequiredMixin, FormerSubscriberMixin, TemplateView):
class UVGuideView(PermissionRequiredMixin, TemplateView):
"""UV guide main page."""
template_name = "pedagogy/guide.jinja"
def get_context_data(self, **kwargs):
user = self.request.user
return super().get_context_data(**kwargs) | {
"can_create_uv": (
user.is_root
or user.is_in_group(pk=settings.SITH_GROUP_PEDAGOGY_ADMIN_ID)
)
}
permission_required = "pedagogy.view_uv"
class UVCommentReportCreateView(PermissionRequiredMixin, CreateView):
@ -168,21 +172,16 @@ class UVCommentReportCreateView(PermissionRequiredMixin, CreateView):
return resp
def get_success_url(self):
return reverse_lazy(
"pedagogy:uv_detail", kwargs={"uv_id": self.uv_comment.uv.id}
)
return reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv_comment.uv_id})
class UVModerationFormView(FormView):
class UVModerationFormView(PermissionRequiredMixin, FormView):
"""Moderation interface (Privileged)."""
form_class = UVCommentModerationForm
template_name = "pedagogy/moderation.jinja"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_owner(UV()):
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
permission_required = "pedagogy.delete_uvcomment"
success_url = reverse_lazy("pedagogy:moderation")
def form_valid(self, form):
form_clean = form.clean()
@ -194,9 +193,6 @@ class UVModerationFormView(FormView):
UVCommentReport.objects.filter(id__in={d.id for d in denied}).delete()
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("pedagogy:moderation")
class UVCreateView(PermissionRequiredMixin, CreateView):
"""Add a new UV (Privileged)."""
@ -211,34 +207,28 @@ class UVCreateView(PermissionRequiredMixin, CreateView):
kwargs["author_id"] = self.request.user.id
return kwargs
def get_success_url(self):
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.id})
class UVDeleteView(CanEditPropMixin, DeleteView):
class UVDeleteView(PermissionRequiredMixin, DeleteView):
"""Allow to delete an UV (Privileged)."""
model = UV
pk_url_kwarg = "uv_id"
template_name = "core/delete_confirm.jinja"
def get_success_url(self):
return reverse_lazy("pedagogy:guide")
permission_required = "pedagogy.delete_uv"
success_url = reverse_lazy("pedagogy:guide")
class UVUpdateView(CanEditPropMixin, UpdateView):
class UVUpdateView(PermissionRequiredMixin, UpdateView):
"""Allow to edit an UV (Privilegied)."""
model = UV
form_class = UVForm
pk_url_kwarg = "uv_id"
template_name = "pedagogy/uv_edit.jinja"
permission_required = "pedagogy.change_uv"
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
obj = self.get_object()
kwargs["author_id"] = obj.author.id
kwargs["author_id"] = obj.author_id
return kwargs
def get_success_url(self):
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.id})