From f44b3cc4b21b747ba5517c6b0f9a41335fca660d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 10 Jul 2022 20:05:54 -0700 Subject: [PATCH] Improves change password flow There are two changes: one is to require the current password to change your password (which is a security improvement), and the other is error reporting when you either get your current password wrong or your new password doesn't match it's second entry. --- .../preferences/change_password.html | 33 ++++++++++++++++++- bookwyrm/views/preferences/change_password.py | 24 ++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templates/preferences/change_password.html b/bookwyrm/templates/preferences/change_password.html index 563bdee4d..ad34aca1a 100644 --- a/bookwyrm/templates/preferences/change_password.html +++ b/bookwyrm/templates/preferences/change_password.html @@ -8,15 +8,46 @@ {% endblock %} {% block panel %} +{% if success %} +
+ + + {% trans "Successfully changed password" %} + +
+{% endif %}
{% csrf_token %} +
+ + + {% include 'snippets/form_errors.html' with errors_list=errors.current_password id="desc_current_password" %} +
+
- + + {% include 'snippets/form_errors.html' with errors_list=errors.confirm_password id="desc_confirm_password" %}
diff --git a/bookwyrm/views/preferences/change_password.py b/bookwyrm/views/preferences/change_password.py index cdfc9d333..eaca2d8fa 100644 --- a/bookwyrm/views/preferences/change_password.py +++ b/bookwyrm/views/preferences/change_password.py @@ -1,10 +1,13 @@ """ class views for password management """ from django.contrib.auth import login from django.contrib.auth.decorators import login_required -from django.shortcuts import redirect from django.template.response import TemplateResponse from django.utils.decorators import method_decorator +from django.utils.translation import gettext_lazy as _ from django.views import View +from django.views.decorators.debug import sensitive_variables, sensitive_post_parameters + +from bookwyrm import models # pylint: disable= no-self-use @@ -17,15 +20,30 @@ class ChangePassword(View): data = {"user": request.user} return TemplateResponse(request, "preferences/change_password.html", data) + @sensitive_variables("new_password") + @sensitive_variables("confirm_password") + @method_decorator(sensitive_post_parameters("current_password")) + @method_decorator(sensitive_post_parameters("password")) + @method_decorator(sensitive_post_parameters("confirm__password")) def post(self, request): """allow a user to change their password""" + data = {"user": request.user} + + # check current password + user = models.User.objects.get(id=request.user.id) + if not user.check_password(request.POST.get("current_password")): + data["errors"] = {"current_password": [_("Incorrect password")]} + return TemplateResponse(request, "preferences/change_password.html", data) + new_password = request.POST.get("password") confirm_password = request.POST.get("confirm-password") if new_password != confirm_password: - return redirect("prefs-password") + data["errors"] = {"confirm_password": [_("Password does not match")]} + return TemplateResponse(request, "preferences/change_password.html", data) request.user.set_password(new_password) request.user.save(broadcast=False, update_fields=["password"]) login(request, request.user) - return redirect("user-feed", request.user.localname) + data["success"] = True + return TemplateResponse(request, "preferences/change_password.html", data)