refactor: PasswordRootChangeView

This commit is contained in:
imperosol
2025-11-25 20:40:55 +01:00
rodzic e9fbac8264
commit 55d6e2bbec
4 zmienionych plików z 38 dodań i 20 usunięć

Wyświetl plik

@@ -3,7 +3,7 @@
{% block content %}
{% if target %}
<p>{% trans user=target.get_display_name() %}Change password for {{ user }}{% endtrans %}</p>
<p>{% trans user=form.user.get_display_name() %}Change password for {{ user }}{% endtrans %}</p>
{% endif %}
<form method="post" action="">
{% csrf_token %}

Wyświetl plik

@@ -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

Wyświetl plik

@@ -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/<int:user_id>/",
password_root_change,
PasswordRootChangeView.as_view(),
name="password_root_change",
),
path(

Wyświetl plik

@@ -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")