diff --git a/tests/auth_tests/test_views.py b/tests/auth_tests/test_views.py
index 9d669c5d85..861e5a9299 100644
a
|
b
|
class PasswordResetTest(AuthViewsTestCase):
|
321 | 321 | self.assertRedirects(response, '/reset/done/', fetch_redirect_response=False) |
322 | 322 | self.assertIn(SESSION_KEY, self.client.session) |
323 | 323 | |
| 324 | def test_key_error_accessing_user_from_request_after_form_save(self): |
| 325 | self.login(username=self.u3.username, password='password') |
| 326 | url, path = self._test_confirm_start() |
| 327 | path = path.replace('/reset/', '/reset/key_error_reset_confirm/') |
| 328 | response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}) |
| 329 | # We don't get here KeyError: '_password_reset_token' |
| 330 | # Check the password has been changed |
| 331 | u = User.objects.get(email='staffmember@example.com') |
| 332 | self.assertTrue(u.check_password("anewpassword")) |
| 333 | self.assertRedirects(response, '/reset/done/', fetch_redirect_response=False) |
| 334 | |
324 | 335 | @override_settings( |
325 | 336 | AUTHENTICATION_BACKENDS=[ |
326 | 337 | 'django.contrib.auth.backends.ModelBackend', |
diff --git a/tests/auth_tests/urls.py b/tests/auth_tests/urls.py
index e225ab9362..ed9b2f7978 100644
a
|
b
|
|
1 | 1 | from django.contrib import admin |
2 | 2 | from django.contrib.auth import views |
3 | 3 | from django.contrib.auth.decorators import login_required, permission_required |
4 | | from django.contrib.auth.forms import AuthenticationForm |
| 4 | from django.contrib.auth.forms import AuthenticationForm, SetPasswordForm |
5 | 5 | from django.contrib.auth.urls import urlpatterns as auth_urlpatterns |
6 | 6 | from django.contrib.messages.api import info |
7 | 7 | from django.http import HttpRequest, HttpResponse |
… |
… |
def login_and_permission_required_exception(request):
|
78 | 78 | pass |
79 | 79 | |
80 | 80 | |
| 81 | class KeyErrorSetPasswordForm(SetPasswordForm): |
| 82 | def __init__(self, *args, request=None, **kwargs): |
| 83 | super().__init__(*args, **kwargs) |
| 84 | self.request = request |
| 85 | |
| 86 | def save(self, commit=True): |
| 87 | user = super().save(commit) |
| 88 | # Access attribute on user via request, triggering flush of session that |
| 89 | # later leads to key error. |
| 90 | self.request.user.is_anonymous |
| 91 | return user |
| 92 | |
| 93 | |
| 94 | class KeyErrorPasswordResetConfirmView(views.PasswordResetConfirmView): |
| 95 | form_class = KeyErrorSetPasswordForm |
| 96 | |
| 97 | def get_form_kwargs(self): |
| 98 | kwargs = super().get_form_kwargs() |
| 99 | kwargs["request"] = self.request |
| 100 | return kwargs |
| 101 | |
| 102 | |
81 | 103 | # special urls for auth test cases |
82 | 104 | urlpatterns = auth_urlpatterns + [ |
83 | 105 | path('logout/custom_query/', views.LogoutView.as_view(redirect_field_name='follow')), |
… |
… |
urlpatterns = auth_urlpatterns + [
|
127 | 149 | post_reset_login_backend='django.contrib.auth.backends.AllowAllUsersModelBackend', |
128 | 150 | ), |
129 | 151 | ), |
| 152 | path( |
| 153 | 'reset/key_error_reset_confirm/<uidb64>/<token>/', |
| 154 | KeyErrorPasswordResetConfirmView.as_view(), |
| 155 | ), |
130 | 156 | path('password_change/custom/', |
131 | 157 | views.PasswordChangeView.as_view(success_url='/custom/')), |
132 | 158 | path('password_change/custom/named/', |