From 0814566bf1212c9d63982a7107693108b73394df Mon Sep 17 00:00:00 2001 From: jordij Date: Thu, 28 Jul 2016 10:33:07 +1200 Subject: [PATCH] Fixed #26960 -- Added PasswordResetConfirmView option to automatically log in after a reset. --- AUTHORS | 1 + django/contrib/auth/views.py | 5 ++++- docs/releases/1.11.txt | 4 ++++ docs/topics/auth/default.txt | 4 ++++ tests/auth_tests/test_views.py | 8 ++++++++ tests/auth_tests/urls.py | 2 ++ 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index d399a54158..d0c9deffeb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -381,6 +381,7 @@ answer newbie questions, and generally made Django that much better: Jonathan Feignberg Jonathan Slenders Jordan Dimov + Jordi J. Tablada Jorge Bastida Jorge Gajon José Tomás Tocino García diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py index 60e150a0bf..fd5508f3bf 100644 --- a/django/contrib/auth/views.py +++ b/django/contrib/auth/views.py @@ -411,6 +411,7 @@ class PasswordResetDoneView(PasswordContextMixin, TemplateView): class PasswordResetConfirmView(PasswordContextMixin, FormView): form_class = SetPasswordForm + post_reset_login = False success_url = reverse_lazy('password_reset_complete') template_name = 'registration/password_reset_confirm.html' title = _('Enter new password') @@ -438,7 +439,9 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView): return kwargs def form_valid(self, form): - form.save() + user = form.save() + if self.post_reset_login: + auth_login(self.request, user) return super(PasswordResetConfirmView, self).form_valid(form) def get_context_data(self, **kwargs): diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt index 4d29ad3640..d8534c0d11 100644 --- a/docs/releases/1.11.txt +++ b/docs/releases/1.11.txt @@ -80,6 +80,10 @@ Minor features ``password_reset_confirm()``, and ``password_reset_complete()`` function-based views. +* The new ``post_reset_login`` attribute for + :class:`~django.contrib.auth.views.PasswordResetConfirmView` allows + automatically logging in a user after a successful password reset. + :mod:`django.contrib.contenttypes` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt index 60178348e9..4302534401 100644 --- a/docs/topics/auth/default.txt +++ b/docs/topics/auth/default.txt @@ -1480,6 +1480,10 @@ implementation details see :ref:`using-the-views`. will default to ``default_token_generator``, it's an instance of ``django.contrib.auth.tokens.PasswordResetTokenGenerator``. + * ``post_reset_login``: A boolean indicating if the user should be + automatically authenticated after a successful password reset. Defaults + to ``False``. + * ``form_class``: Form that will be used to set the password. Defaults to :class:`~django.contrib.auth.forms.SetPasswordForm`. diff --git a/tests/auth_tests/test_views.py b/tests/auth_tests/test_views.py index f44c21ac2a..3ae0bf4b89 100644 --- a/tests/auth_tests/test_views.py +++ b/tests/auth_tests/test_views.py @@ -307,6 +307,14 @@ class PasswordResetTest(AuthViewsTestCase): self.assertEqual(response.status_code, 302) self.assertURLEqual(response.url, '/password_reset/') + def test_confirm_login_post_reset(self): + url, path = self._test_confirm_start() + path = path.replace('/reset/', '/reset/post_reset_login/') + response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}) + self.assertEqual(response.status_code, 302) + self.assertURLEqual(response.url, '/reset/done/') + self.assertIn(SESSION_KEY, self.client.session) + def test_confirm_display_user_from_form(self): url, path = self._test_confirm_start() response = self.client.get(path) diff --git a/tests/auth_tests/urls.py b/tests/auth_tests/urls.py index 6a7574b8cd..e8174fb536 100644 --- a/tests/auth_tests/urls.py +++ b/tests/auth_tests/urls.py @@ -85,6 +85,8 @@ urlpatterns = auth_urlpatterns + [ views.PasswordResetConfirmView.as_view(success_url='/custom/')), url(r'^reset/custom/named/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', views.PasswordResetConfirmView.as_view(success_url=reverse_lazy('password_reset'))), + url(r'^reset/post_reset_login/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', + views.PasswordResetConfirmView.as_view(post_reset_login=True)), url(r'^password_change/custom/$', views.PasswordChangeView.as_view(success_url='/custom/')), url(r'^password_change/custom/named/$',