diff --git a/core/templates/core/password_change.jinja b/core/templates/core/password_change.jinja index 7cd27b1e..a90fd39b 100644 --- a/core/templates/core/password_change.jinja +++ b/core/templates/core/password_change.jinja @@ -3,7 +3,7 @@ {% block content %} {% if target %} -

{% trans user=target.get_display_name() %}Change password for {{ user }}{% endtrans %}

+

{% trans user=form.user.get_display_name() %}Change password for {{ user }}{% endtrans %}

{% endif %}
{% csrf_token %} diff --git a/core/tests/test_user.py b/core/tests/test_user.py index 2492aa4b..4c6d4036 100644 --- a/core/tests/test_user.py +++ b/core/tests/test_user.py @@ -463,3 +463,20 @@ def test_user_stats(client: Client): client.force_login(user) response = client.get(reverse("core:user_stats", kwargs={"user_id": user.id})) assert response.status_code == 200 + + +@pytest.mark.django_db +class TestChangeUserPassword: + def test_as_root(self, client: Client, admin_user: User): + client.force_login(admin_user) + user = subscriber_user.make() + url = reverse("core:password_root_change", kwargs={"user_id": user.id}) + response = client.get(url) + assert response.status_code == 200 + response = client.post( + url, {"new_password1": "poutou", "new_password2": "poutou"} + ) + print(response.text) + assertRedirects(response, reverse("core:password_change_done")) + user.refresh_from_db() + assert user.check_password("poutou") is True diff --git a/core/urls.py b/core/urls.py index 0695e009..71f76261 100644 --- a/core/urls.py +++ b/core/urls.py @@ -54,6 +54,7 @@ from core.views import ( PagePropView, PageRevView, PageView, + PasswordRootChangeView, SearchView, SithLoginView, SithPasswordChangeDoneView, @@ -80,7 +81,6 @@ from core.views import ( delete_user_godfather, logout, notification, - password_root_change, send_file, ) @@ -100,7 +100,7 @@ urlpatterns = [ path("password_change/", SithPasswordChangeView.as_view(), name="password_change"), path( "password_change//", - password_root_change, + PasswordRootChangeView.as_view(), name="password_root_change", ), path( diff --git a/core/views/user.py b/core/views/user.py index f4fd865e..4c9bb1cd 100644 --- a/core/views/user.py +++ b/core/views/user.py @@ -29,8 +29,8 @@ from operator import itemgetter from smtplib import SMTPException from django.contrib.auth import login, views -from django.contrib.auth.forms import PasswordChangeForm -from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.forms import PasswordChangeForm, SetPasswordForm +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.core.exceptions import PermissionDenied from django.db.models import DateField, F, QuerySet, Sum from django.db.models.functions import Trunc @@ -38,7 +38,6 @@ from django.forms.models import modelform_factory from django.http import Http404 from django.shortcuts import get_object_or_404, redirect from django.template.loader import render_to_string -from django.template.response import TemplateResponse from django.urls import reverse, reverse_lazy from django.utils.decorators import method_decorator from django.utils.safestring import SafeString @@ -98,21 +97,23 @@ def logout(request): return views.logout_then_login(request) -def password_root_change(request, user_id): +class PasswordRootChangeView(UserPassesTestMixin, FormView): """Allows a root user to change someone's password.""" - if not request.user.is_root: - raise PermissionDenied - user = get_object_or_404(User, id=user_id) - if request.method == "POST": - form = views.SetPasswordForm(user=user, data=request.POST) - if form.is_valid(): - form.save() - return redirect("core:password_change_done") - else: - form = views.SetPasswordForm(user=user) - return TemplateResponse( - request, "core/password_change.jinja", {"form": form, "target": user} - ) + + template_name = "core/password_change.jinja" + form_class = SetPasswordForm + success_url = reverse_lazy("core:password_change_done") + + def test_func(self): + return self.request.user.is_root + + def get_form_kwargs(self): + user = get_object_or_404(User, id=self.kwargs["user_id"]) + return super().get_form_kwargs() | {"user": user} + + def form_valid(self, form: SetPasswordForm): + form.save() + return super().form_valid(form) @method_decorator(check_honeypot, name="post")