Răsfoiți Sursa

Fixed #27891 -- Added PasswordResetConfirmView.post_reset_login_backend.

Camilo Nova 8 ani în urmă
părinte
comite
5db465d5a6

+ 2 - 1
django/contrib/auth/views.py

@@ -409,6 +409,7 @@ class PasswordResetDoneView(PasswordContextMixin, TemplateView):
 class PasswordResetConfirmView(PasswordContextMixin, FormView):
     form_class = SetPasswordForm
     post_reset_login = False
+    post_reset_login_backend = None
     success_url = reverse_lazy('password_reset_complete')
     template_name = 'registration/password_reset_confirm.html'
     title = _('Enter new password')
@@ -461,7 +462,7 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
         user = form.save()
         del self.request.session[INTERNAL_RESET_SESSION_TOKEN]
         if self.post_reset_login:
-            auth_login(self.request, user)
+            auth_login(self.request, user, self.post_reset_login_backend)
         return super().form_valid(form)
 
     def get_context_data(self, **kwargs):

+ 2 - 0
docs/releases/1.11.txt

@@ -118,6 +118,8 @@ Minor features
 * The new ``post_reset_login`` attribute for
   :class:`~django.contrib.auth.views.PasswordResetConfirmView` allows
   automatically logging in a user after a successful password reset.
+  If you have multiple ``AUTHENTICATION_BACKENDS`` configured, use the
+  ``post_reset_login_backend`` attribute to choose which one to use.
 
 * To avoid the possibility of leaking a password reset token via the HTTP
   Referer header (for example, if the reset page includes a reference to CSS or

+ 5 - 0
docs/topics/auth/default.txt

@@ -1413,6 +1413,11 @@ implementation details see :ref:`using-the-views`.
       automatically authenticated after a successful password reset. Defaults
       to ``False``.
 
+    * ``post_reset_login_backend``: A dotted path to the authentication
+      backend to use when authenticating a user if ``post_reset_login`` is
+      ``True``. Required only if you have multiple
+      :setting:`AUTHENTICATION_BACKENDS` configured. Defaults to ``None``.
+
     * ``form_class``: Form that will be used to set the password. Defaults to
       :class:`~django.contrib.auth.forms.SetPasswordForm`.
 

+ 19 - 1
tests/auth_tests/test_views.py

@@ -8,7 +8,9 @@ from urllib.parse import ParseResult, quote, urlparse
 from django.apps import apps
 from django.conf import settings
 from django.contrib.admin.models import LogEntry
-from django.contrib.auth import REDIRECT_FIELD_NAME, SESSION_KEY
+from django.contrib.auth import (
+    BACKEND_SESSION_KEY, REDIRECT_FIELD_NAME, SESSION_KEY,
+)
 from django.contrib.auth.forms import (
     AuthenticationForm, PasswordChangeForm, SetPasswordForm,
 )
@@ -327,6 +329,22 @@ class PasswordResetTest(AuthViewsTestCase):
         self.assertRedirects(response, '/reset/done/', fetch_redirect_response=False)
         self.assertIn(SESSION_KEY, self.client.session)
 
+    @override_settings(
+        AUTHENTICATION_BACKENDS=[
+            'django.contrib.auth.backends.ModelBackend',
+            'django.contrib.auth.backends.AllowAllUsersModelBackend',
+        ]
+    )
+    def test_confirm_login_post_reset_custom_backend(self):
+        # This backend is specified in the url().
+        backend = 'django.contrib.auth.backends.AllowAllUsersModelBackend'
+        url, path = self._test_confirm_start()
+        path = path.replace('/reset/', '/reset/post_reset_login_custom_backend/')
+        response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'})
+        self.assertRedirects(response, '/reset/done/', fetch_redirect_response=False)
+        self.assertIn(SESSION_KEY, self.client.session)
+        self.assertEqual(self.client.session[BACKEND_SESSION_KEY], backend)
+
     def test_confirm_login_post_reset_already_logged_in(self):
         url, path = self._test_confirm_start()
         path = path.replace('/reset/', '/reset/post_reset_login/')

+ 7 - 0
tests/auth_tests/urls.py

@@ -90,6 +90,13 @@ urlpatterns = auth_urlpatterns + [
         views.PasswordResetConfirmView.as_view(success_url=reverse_lazy('password_reset'))),
     url(r'^reset/post_reset_login/{}/$'.format(uid_token),
         views.PasswordResetConfirmView.as_view(post_reset_login=True)),
+    url(
+        r'^reset/post_reset_login_custom_backend/{}/$'.format(uid_token),
+        views.PasswordResetConfirmView.as_view(
+            post_reset_login=True,
+            post_reset_login_backend='django.contrib.auth.backends.AllowAllUsersModelBackend',
+        ),
+    ),
     url(r'^password_change/custom/$',
         views.PasswordChangeView.as_view(success_url='/custom/')),
     url(r'^password_change/custom/named/$',