diff options
author | django-bot <ops@djangoproject.com> | 2022-02-03 20:24:19 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-07 20:37:05 +0100 |
commit | 9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch) | |
tree | f0506b668a013d0063e5fba3dbf4863b466713ba /tests/auth_tests/test_views.py | |
parent | f68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff) | |
download | django-9c19aff7c7561e3a82978a272ecdaad40dda5c00.tar.gz |
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'tests/auth_tests/test_views.py')
-rw-r--r-- | tests/auth_tests/test_views.py | 1168 |
1 files changed, 679 insertions, 489 deletions
diff --git a/tests/auth_tests/test_views.py b/tests/auth_tests/test_views.py index a572e2610f..5ba05e8a00 100644 --- a/tests/auth_tests/test_views.py +++ b/tests/auth_tests/test_views.py @@ -8,15 +8,17 @@ from urllib.parse import quote, urljoin from django.apps import apps from django.conf import settings from django.contrib.admin.models import LogEntry -from django.contrib.auth import ( - BACKEND_SESSION_KEY, 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, + AuthenticationForm, + PasswordChangeForm, + SetPasswordForm, ) from django.contrib.auth.models import Permission, User from django.contrib.auth.views import ( - INTERNAL_RESET_SESSION_TOKEN, LoginView, logout_then_login, + INTERNAL_RESET_SESSION_TOKEN, + LoginView, + logout_then_login, redirect_to_login, ) from django.contrib.contenttypes.models import ContentType @@ -38,10 +40,10 @@ from .settings import AUTH_TEMPLATES @override_settings( - LANGUAGES=[('en', 'English')], - LANGUAGE_CODE='en', + LANGUAGES=[("en", "English")], + LANGUAGE_CODE="en", TEMPLATES=AUTH_TEMPLATES, - ROOT_URLCONF='auth_tests.urls', + ROOT_URLCONF="auth_tests.urls", ) class AuthViewsTestCase(TestCase): """ @@ -50,71 +52,86 @@ class AuthViewsTestCase(TestCase): @classmethod def setUpTestData(cls): - cls.u1 = User.objects.create_user(username='testclient', password='password', email='testclient@example.com') - cls.u3 = User.objects.create_user(username='staff', password='password', email='staffmember@example.com') - - def login(self, username='testclient', password='password', url='/login/'): - response = self.client.post(url, { - 'username': username, - 'password': password, - }) + cls.u1 = User.objects.create_user( + username="testclient", password="password", email="testclient@example.com" + ) + cls.u3 = User.objects.create_user( + username="staff", password="password", email="staffmember@example.com" + ) + + def login(self, username="testclient", password="password", url="/login/"): + response = self.client.post( + url, + { + "username": username, + "password": password, + }, + ) self.assertIn(SESSION_KEY, self.client.session) return response def logout(self): - response = self.client.get('/admin/logout/') + response = self.client.get("/admin/logout/") self.assertEqual(response.status_code, 200) self.assertNotIn(SESSION_KEY, self.client.session) def assertFormError(self, response, error): """Assert that error is found in response.context['form'] errors""" - form_errors = list(itertools.chain(*response.context['form'].errors.values())) + form_errors = list(itertools.chain(*response.context["form"].errors.values())) self.assertIn(str(error), form_errors) -@override_settings(ROOT_URLCONF='django.contrib.auth.urls') +@override_settings(ROOT_URLCONF="django.contrib.auth.urls") class AuthViewNamedURLTests(AuthViewsTestCase): - def test_named_urls(self): "Named URLs should be reversible" expected_named_urls = [ - ('login', [], {}), - ('logout', [], {}), - ('password_change', [], {}), - ('password_change_done', [], {}), - ('password_reset', [], {}), - ('password_reset_done', [], {}), - ('password_reset_confirm', [], { - 'uidb64': 'aaaaaaa', - 'token': '1111-aaaaa', - }), - ('password_reset_complete', [], {}), + ("login", [], {}), + ("logout", [], {}), + ("password_change", [], {}), + ("password_change_done", [], {}), + ("password_reset", [], {}), + ("password_reset_done", [], {}), + ( + "password_reset_confirm", + [], + { + "uidb64": "aaaaaaa", + "token": "1111-aaaaa", + }, + ), + ("password_reset_complete", [], {}), ] for name, args, kwargs in expected_named_urls: with self.subTest(name=name): try: reverse(name, args=args, kwargs=kwargs) except NoReverseMatch: - self.fail("Reversal of url named '%s' failed with NoReverseMatch" % name) + self.fail( + "Reversal of url named '%s' failed with NoReverseMatch" % name + ) class PasswordResetTest(AuthViewsTestCase): - def setUp(self): self.client = PasswordResetConfirmClient() def test_email_not_found(self): """If the provided email is not registered, don't raise any error but also don't send any email.""" - response = self.client.get('/password_reset/') + response = self.client.get("/password_reset/") self.assertEqual(response.status_code, 200) - response = self.client.post('/password_reset/', {'email': 'not_a_real_email@email.com'}) + response = self.client.post( + "/password_reset/", {"email": "not_a_real_email@email.com"} + ) self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 0) def test_email_found(self): "Email is sent if a valid email address is provided for password reset" - response = self.client.post('/password_reset/', {'email': 'staffmember@example.com'}) + response = self.client.post( + "/password_reset/", {"email": "staffmember@example.com"} + ) self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) self.assertIn("http://", mail.outbox[0].body) @@ -128,33 +145,37 @@ class PasswordResetTest(AuthViewsTestCase): extra_email_context should be available in the email template context. """ response = self.client.post( - '/password_reset_extra_email_context/', - {'email': 'staffmember@example.com'}, + "/password_reset_extra_email_context/", + {"email": "staffmember@example.com"}, ) self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) self.assertIn('Email email context: "Hello!"', mail.outbox[0].body) - self.assertIn('http://custom.example.com/reset/', mail.outbox[0].body) + self.assertIn("http://custom.example.com/reset/", mail.outbox[0].body) def test_html_mail_template(self): """ A multipart email with text/plain and text/html is sent if the html_email_template parameter is passed to the view """ - response = self.client.post('/password_reset/html_email_template/', {'email': 'staffmember@example.com'}) + response = self.client.post( + "/password_reset/html_email_template/", {"email": "staffmember@example.com"} + ) self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) message = mail.outbox[0].message() self.assertEqual(len(message.get_payload()), 2) self.assertTrue(message.is_multipart()) - self.assertEqual(message.get_payload(0).get_content_type(), 'text/plain') - self.assertEqual(message.get_payload(1).get_content_type(), 'text/html') - self.assertNotIn('<html>', message.get_payload(0).get_payload()) - self.assertIn('<html>', message.get_payload(1).get_payload()) + self.assertEqual(message.get_payload(0).get_content_type(), "text/plain") + self.assertEqual(message.get_payload(1).get_content_type(), "text/html") + self.assertNotIn("<html>", message.get_payload(0).get_payload()) + self.assertIn("<html>", message.get_payload(1).get_payload()) def test_email_found_custom_from(self): "Email is sent if a valid email address is provided for password reset when a custom from_email is provided." - response = self.client.post('/password_reset_from_email/', {'email': 'staffmember@example.com'}) + response = self.client.post( + "/password_reset_from_email/", {"email": "staffmember@example.com"} + ) self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) self.assertEqual("staffmember@example.com", mail.outbox[0].from_email) @@ -170,11 +191,11 @@ class PasswordResetTest(AuthViewsTestCase): # produce a meaningful reset URL, we need to be certain that the # HTTP_HOST header isn't poisoned. This is done as a check when get_host() # is invoked, but we check here as a practical consequence. - with self.assertLogs('django.security.DisallowedHost', 'ERROR'): + with self.assertLogs("django.security.DisallowedHost", "ERROR"): response = self.client.post( - '/password_reset/', - {'email': 'staffmember@example.com'}, - HTTP_HOST='www.example:dr.frankenstein@evil.tld' + "/password_reset/", + {"email": "staffmember@example.com"}, + HTTP_HOST="www.example:dr.frankenstein@evil.tld", ) self.assertEqual(response.status_code, 400) self.assertEqual(len(mail.outbox), 0) @@ -183,18 +204,18 @@ class PasswordResetTest(AuthViewsTestCase): @override_settings(DEBUG_PROPAGATE_EXCEPTIONS=True) def test_poisoned_http_host_admin_site(self): "Poisoned HTTP_HOST headers can't be used for reset emails on admin views" - with self.assertLogs('django.security.DisallowedHost', 'ERROR'): + with self.assertLogs("django.security.DisallowedHost", "ERROR"): response = self.client.post( - '/admin_password_reset/', - {'email': 'staffmember@example.com'}, - HTTP_HOST='www.example:dr.frankenstein@evil.tld' + "/admin_password_reset/", + {"email": "staffmember@example.com"}, + HTTP_HOST="www.example:dr.frankenstein@evil.tld", ) self.assertEqual(response.status_code, 400) self.assertEqual(len(mail.outbox), 0) def _test_confirm_start(self): # Start by creating the email - self.client.post('/password_reset/', {'email': 'staffmember@example.com'}) + self.client.post("/password_reset/", {"email": "staffmember@example.com"}) self.assertEqual(len(mail.outbox), 1) return self._read_signup_email(mail.outbox[0]) @@ -220,12 +241,12 @@ class PasswordResetTest(AuthViewsTestCase): def test_confirm_invalid_user(self): # A nonexistent user returns a 200 response, not a 404. - response = self.client.get('/reset/123456/1-1/') + response = self.client.get("/reset/123456/1-1/") self.assertContains(response, "The password reset link was invalid") def test_confirm_overflow_user(self): # A base36 user id that overflows int returns a 200 response. - response = self.client.get('/reset/zzzzzzzzzzzzz/1-1/') + response = self.client.get("/reset/zzzzzzzzzzzzz/1-1/") self.assertContains(response, "The password reset link was invalid") def test_confirm_invalid_post(self): @@ -233,36 +254,44 @@ class PasswordResetTest(AuthViewsTestCase): url, path = self._test_confirm_start() path = path[:-5] + ("0" * 4) + path[-1] - self.client.post(path, { - 'new_password1': 'anewpassword', - 'new_password2': ' anewpassword', - }) + self.client.post( + path, + { + "new_password1": "anewpassword", + "new_password2": " anewpassword", + }, + ) # Check the password has not been changed - u = User.objects.get(email='staffmember@example.com') + u = User.objects.get(email="staffmember@example.com") self.assertTrue(not u.check_password("anewpassword")) def test_confirm_invalid_hash(self): """A POST with an invalid token is rejected.""" - u = User.objects.get(email='staffmember@example.com') + u = User.objects.get(email="staffmember@example.com") original_password = u.password url, path = self._test_confirm_start() - path_parts = path.split('-') - path_parts[-1] = ("0") * 20 + '/' - path = '-'.join(path_parts) - - response = self.client.post(path, { - 'new_password1': 'anewpassword', - 'new_password2': 'anewpassword', - }) - self.assertIs(response.context['validlink'], False) + path_parts = path.split("-") + path_parts[-1] = ("0") * 20 + "/" + path = "-".join(path_parts) + + response = self.client.post( + path, + { + "new_password1": "anewpassword", + "new_password2": "anewpassword", + }, + ) + self.assertIs(response.context["validlink"], False) u.refresh_from_db() self.assertEqual(original_password, u.password) # password hasn't changed def test_confirm_complete(self): url, path = self._test_confirm_start() - response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}) + response = self.client.post( + path, {"new_password1": "anewpassword", "new_password2": "anewpassword"} + ) # Check the password has been changed - u = User.objects.get(email='staffmember@example.com') + u = User.objects.get(email="staffmember@example.com") self.assertTrue(u.check_password("anewpassword")) # The reset token is deleted from the session. self.assertNotIn(INTERNAL_RESET_SESSION_TOKEN, self.client.session) @@ -273,77 +302,106 @@ class PasswordResetTest(AuthViewsTestCase): def test_confirm_different_passwords(self): url, path = self._test_confirm_start() - response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'x'}) - self.assertFormError(response, SetPasswordForm.error_messages['password_mismatch']) + response = self.client.post( + path, {"new_password1": "anewpassword", "new_password2": "x"} + ) + self.assertFormError( + response, SetPasswordForm.error_messages["password_mismatch"] + ) def test_reset_redirect_default(self): - response = self.client.post('/password_reset/', {'email': 'staffmember@example.com'}) - self.assertRedirects(response, '/password_reset/done/', fetch_redirect_response=False) + response = self.client.post( + "/password_reset/", {"email": "staffmember@example.com"} + ) + self.assertRedirects( + response, "/password_reset/done/", fetch_redirect_response=False + ) def test_reset_custom_redirect(self): - response = self.client.post('/password_reset/custom_redirect/', {'email': 'staffmember@example.com'}) - self.assertRedirects(response, '/custom/', fetch_redirect_response=False) + response = self.client.post( + "/password_reset/custom_redirect/", {"email": "staffmember@example.com"} + ) + self.assertRedirects(response, "/custom/", fetch_redirect_response=False) def test_reset_custom_redirect_named(self): - response = self.client.post('/password_reset/custom_redirect/named/', {'email': 'staffmember@example.com'}) - self.assertRedirects(response, '/password_reset/', fetch_redirect_response=False) + response = self.client.post( + "/password_reset/custom_redirect/named/", + {"email": "staffmember@example.com"}, + ) + self.assertRedirects( + response, "/password_reset/", fetch_redirect_response=False + ) def test_confirm_redirect_default(self): url, path = self._test_confirm_start() - response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}) - self.assertRedirects(response, '/reset/done/', fetch_redirect_response=False) + response = self.client.post( + path, {"new_password1": "anewpassword", "new_password2": "anewpassword"} + ) + self.assertRedirects(response, "/reset/done/", fetch_redirect_response=False) def test_confirm_redirect_custom(self): url, path = self._test_confirm_start() - path = path.replace('/reset/', '/reset/custom/') - response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}) - self.assertRedirects(response, '/custom/', fetch_redirect_response=False) + path = path.replace("/reset/", "/reset/custom/") + response = self.client.post( + path, {"new_password1": "anewpassword", "new_password2": "anewpassword"} + ) + self.assertRedirects(response, "/custom/", fetch_redirect_response=False) def test_confirm_redirect_custom_named(self): url, path = self._test_confirm_start() - path = path.replace('/reset/', '/reset/custom/named/') - response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}) - self.assertRedirects(response, '/password_reset/', fetch_redirect_response=False) + path = path.replace("/reset/", "/reset/custom/named/") + response = self.client.post( + path, {"new_password1": "anewpassword", "new_password2": "anewpassword"} + ) + self.assertRedirects( + response, "/password_reset/", fetch_redirect_response=False + ) def test_confirm_custom_reset_url_token(self): url, path = self._test_confirm_start() - path = path.replace('/reset/', '/reset/custom/token/') - self.client.reset_url_token = 'set-passwordcustom' + path = path.replace("/reset/", "/reset/custom/token/") + self.client.reset_url_token = "set-passwordcustom" response = self.client.post( path, - {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}, + {"new_password1": "anewpassword", "new_password2": "anewpassword"}, ) - self.assertRedirects(response, '/reset/done/', fetch_redirect_response=False) + self.assertRedirects(response, "/reset/done/", fetch_redirect_response=False) 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.assertRedirects(response, '/reset/done/', fetch_redirect_response=False) + path = path.replace("/reset/", "/reset/post_reset_login/") + 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) @override_settings( AUTHENTICATION_BACKENDS=[ - 'django.contrib.auth.backends.ModelBackend', - 'django.contrib.auth.backends.AllowAllUsersModelBackend', + "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 pattern. - backend = 'django.contrib.auth.backends.AllowAllUsersModelBackend' + 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) + 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/') + path = path.replace("/reset/", "/reset/post_reset_login/") self.login() - response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'}) - self.assertRedirects(response, '/reset/done/', fetch_redirect_response=False) + 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) def test_confirm_display_user_from_form(self): @@ -353,11 +411,11 @@ class PasswordResetTest(AuthViewsTestCase): # SetPasswordForm``, even on GET requests (#16919). For this test, # {{ form.user }}`` is rendered in the template # registration/password_reset_confirm.html. - username = User.objects.get(email='staffmember@example.com').username + username = User.objects.get(email="staffmember@example.com").username self.assertContains(response, "Hello, %s." % username) # However, the view should NOT pass any user object on a form if the # password reset link was invalid. - response = self.client.get('/reset/zzzzzzzzzzzzz/1-1/') + response = self.client.get("/reset/zzzzzzzzzzzzz/1-1/") self.assertContains(response, "Hello, .") def test_confirm_link_redirects_to_set_password_page(self): @@ -366,44 +424,46 @@ class PasswordResetTest(AuthViewsTestCase): # automatically fetches the redirect page. client = Client() response = client.get(path) - token = response.resolver_match.kwargs['token'] - uuidb64 = response.resolver_match.kwargs['uidb64'] - self.assertRedirects(response, '/reset/%s/set-password/' % uuidb64) - self.assertEqual(client.session['_password_reset_token'], token) + token = response.resolver_match.kwargs["token"] + uuidb64 = response.resolver_match.kwargs["uidb64"] + self.assertRedirects(response, "/reset/%s/set-password/" % uuidb64) + self.assertEqual(client.session["_password_reset_token"], token) def test_confirm_custom_reset_url_token_link_redirects_to_set_password_page(self): url, path = self._test_confirm_start() - path = path.replace('/reset/', '/reset/custom/token/') + path = path.replace("/reset/", "/reset/custom/token/") client = Client() response = client.get(path) - token = response.resolver_match.kwargs['token'] - uuidb64 = response.resolver_match.kwargs['uidb64'] - self.assertRedirects(response, '/reset/custom/token/%s/set-passwordcustom/' % uuidb64) - self.assertEqual(client.session['_password_reset_token'], token) + token = response.resolver_match.kwargs["token"] + uuidb64 = response.resolver_match.kwargs["uidb64"] + self.assertRedirects( + response, "/reset/custom/token/%s/set-passwordcustom/" % uuidb64 + ) + self.assertEqual(client.session["_password_reset_token"], token) def test_invalid_link_if_going_directly_to_the_final_reset_password_url(self): url, path = self._test_confirm_start() - _, uuidb64, _ = path.strip('/').split('/') - response = Client().get('/reset/%s/set-password/' % uuidb64) - self.assertContains(response, 'The password reset link was invalid') + _, uuidb64, _ = path.strip("/").split("/") + response = Client().get("/reset/%s/set-password/" % uuidb64) + self.assertContains(response, "The password reset link was invalid") def test_missing_kwargs(self): msg = "The URL path must contain 'uidb64' and 'token' parameters." with self.assertRaisesMessage(ImproperlyConfigured, msg): - self.client.get('/reset/missing_parameters/') + self.client.get("/reset/missing_parameters/") -@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser') +@override_settings(AUTH_USER_MODEL="auth_tests.CustomUser") class CustomUserPasswordResetTest(AuthViewsTestCase): - user_email = 'staffmember@example.com' + user_email = "staffmember@example.com" @classmethod def setUpTestData(cls): cls.u1 = CustomUser.custom_objects.create( - email='staffmember@example.com', + email="staffmember@example.com", date_of_birth=datetime.date(1976, 11, 8), ) - cls.u1.set_password('password') + cls.u1.set_password("password") cls.u1.save() def setUp(self): @@ -411,7 +471,7 @@ class CustomUserPasswordResetTest(AuthViewsTestCase): def _test_confirm_start(self): # Start by creating the email - response = self.client.post('/password_reset/', {'email': self.user_email}) + response = self.client.post("/password_reset/", {"email": self.user_email}) self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) return self._read_signup_email(mail.outbox[0]) @@ -427,116 +487,159 @@ class CustomUserPasswordResetTest(AuthViewsTestCase): # redirect to a 'complete' page: self.assertContains(response, "Please enter your new password") # then submit a new password - response = self.client.post(path, { - 'new_password1': 'anewpassword', - 'new_password2': 'anewpassword', - }) - self.assertRedirects(response, '/reset/done/') + response = self.client.post( + path, + { + "new_password1": "anewpassword", + "new_password2": "anewpassword", + }, + ) + self.assertRedirects(response, "/reset/done/") -@override_settings(AUTH_USER_MODEL='auth_tests.UUIDUser') +@override_settings(AUTH_USER_MODEL="auth_tests.UUIDUser") class UUIDUserPasswordResetTest(CustomUserPasswordResetTest): - def _test_confirm_start(self): # instead of fixture UUIDUser.objects.create_user( email=self.user_email, - username='foo', - password='foo', + username="foo", + password="foo", ) return super()._test_confirm_start() def test_confirm_invalid_uuid(self): """A uidb64 that decodes to a non-UUID doesn't crash.""" _, path = self._test_confirm_start() - invalid_uidb64 = urlsafe_base64_encode(b'INVALID_UUID') - first, _uuidb64_, second = path.strip('/').split('/') - response = self.client.get('/' + '/'.join((first, invalid_uidb64, second)) + '/') - self.assertContains(response, 'The password reset link was invalid') + invalid_uidb64 = urlsafe_base64_encode(b"INVALID_UUID") + first, _uuidb64_, second = path.strip("/").split("/") + response = self.client.get( + "/" + "/".join((first, invalid_uidb64, second)) + "/" + ) + self.assertContains(response, "The password reset link was invalid") class ChangePasswordTest(AuthViewsTestCase): - def fail_login(self): - response = self.client.post('/login/', { - 'username': 'testclient', - 'password': 'password', - }) - self.assertFormError(response, AuthenticationForm.error_messages['invalid_login'] % { - 'username': User._meta.get_field('username').verbose_name - }) + response = self.client.post( + "/login/", + { + "username": "testclient", + "password": "password", + }, + ) + self.assertFormError( + response, + AuthenticationForm.error_messages["invalid_login"] + % {"username": User._meta.get_field("username").verbose_name}, + ) def logout(self): - self.client.get('/logout/') + self.client.get("/logout/") def test_password_change_fails_with_invalid_old_password(self): self.login() - response = self.client.post('/password_change/', { - 'old_password': 'donuts', - 'new_password1': 'password1', - 'new_password2': 'password1', - }) - self.assertFormError(response, PasswordChangeForm.error_messages['password_incorrect']) + response = self.client.post( + "/password_change/", + { + "old_password": "donuts", + "new_password1": "password1", + "new_password2": "password1", + }, + ) + self.assertFormError( + response, PasswordChangeForm.error_messages["password_incorrect"] + ) def test_password_change_fails_with_mismatched_passwords(self): self.login() - response = self.client.post('/password_change/', { - 'old_password': 'password', - 'new_password1': 'password1', - 'new_password2': 'donuts', - }) - self.assertFormError(response, SetPasswordForm.error_messages['password_mismatch']) + response = self.client.post( + "/password_change/", + { + "old_password": "password", + "new_password1": "password1", + "new_password2": "donuts", + }, + ) + self.assertFormError( + response, SetPasswordForm.error_messages["password_mismatch"] + ) def test_password_change_succeeds(self): self.login() - self.client.post('/password_change/', { - 'old_password': 'password', - 'new_password1': 'password1', - 'new_password2': 'password1', - }) + self.client.post( + "/password_change/", + { + "old_password": "password", + "new_password1": "password1", + "new_password2": "password1", + }, + ) self.fail_login() - self.login(password='password1') + self.login(password="password1") def test_password_change_done_succeeds(self): self.login() - response = self.client.post('/password_change/', { - 'old_password': 'password', - 'new_password1': 'password1', - 'new_password2': 'password1', - }) - self.assertRedirects(response, '/password_change/done/', fetch_redirect_response=False) - - @override_settings(LOGIN_URL='/login/') + response = self.client.post( + "/password_change/", + { + "old_password": "password", + "new_password1": "password1", + "new_password2": "password1", + }, + ) + self.assertRedirects( + response, "/password_change/done/", fetch_redirect_response=False + ) + + @override_settings(LOGIN_URL="/login/") def test_password_change_done_fails(self): - response = self.client.get('/password_change/done/') - self.assertRedirects(response, '/login/?next=/password_change/done/', fetch_redirect_response=False) + response = self.client.get("/password_change/done/") + self.assertRedirects( + response, + "/login/?next=/password_change/done/", + fetch_redirect_response=False, + ) def test_password_change_redirect_default(self): self.login() - response = self.client.post('/password_change/', { - 'old_password': 'password', - 'new_password1': 'password1', - 'new_password2': 'password1', - }) - self.assertRedirects(response, '/password_change/done/', fetch_redirect_response=False) + response = self.client.post( + "/password_change/", + { + "old_password": "password", + "new_password1": "password1", + "new_password2": "password1", + }, + ) + self.assertRedirects( + response, "/password_change/done/", fetch_redirect_response=False + ) def test_password_change_redirect_custom(self): self.login() - response = self.client.post('/password_change/custom/', { - 'old_password': 'password', - 'new_password1': 'password1', - 'new_password2': 'password1', - }) - self.assertRedirects(response, '/custom/', fetch_redirect_response=False) + response = self.client.post( + "/password_change/custom/", + { + "old_password": "password", + "new_password1": "password1", + "new_password2": "password1", + }, + ) + self.assertRedirects(response, "/custom/", fetch_redirect_response=False) def test_password_change_redirect_custom_named(self): self.login() - response = self.client.post('/password_change/custom/named/', { - 'old_password': 'password', - 'new_password1': 'password1', - 'new_password2': 'password1', - }) - self.assertRedirects(response, '/password_reset/', fetch_redirect_response=False) + response = self.client.post( + "/password_change/custom/named/", + { + "old_password": "password", + "new_password1": "password1", + "new_password2": "password1", + }, + ) + self.assertRedirects( + response, "/password_reset/", fetch_redirect_response=False + ) class SessionAuthenticationTests(AuthViewsTestCase): @@ -547,94 +650,104 @@ class SessionAuthenticationTests(AuthViewsTestCase): """ self.login() original_session_key = self.client.session.session_key - response = self.client.post('/password_change/', { - 'old_password': 'password', - 'new_password1': 'password1', - 'new_password2': 'password1', - }) + response = self.client.post( + "/password_change/", + { + "old_password": "password", + "new_password1": "password1", + "new_password2": "password1", + }, + ) # if the hash isn't updated, retrieving the redirection page will fail. - self.assertRedirects(response, '/password_change/done/') + self.assertRedirects(response, "/password_change/done/") # The session key is rotated. self.assertNotEqual(original_session_key, self.client.session.session_key) class LoginTest(AuthViewsTestCase): - def test_current_site_in_context_after_login(self): - response = self.client.get(reverse('login')) + response = self.client.get(reverse("login")) self.assertEqual(response.status_code, 200) - if apps.is_installed('django.contrib.sites'): - Site = apps.get_model('sites.Site') + if apps.is_installed("django.contrib.sites"): + Site = apps.get_model("sites.Site") site = Site.objects.get_current() - self.assertEqual(response.context['site'], site) - self.assertEqual(response.context['site_name'], site.name) + self.assertEqual(response.context["site"], site) + self.assertEqual(response.context["site_name"], site.name) else: - self.assertIsInstance(response.context['site'], RequestSite) - self.assertIsInstance(response.context['form'], AuthenticationForm) + self.assertIsInstance(response.context["site"], RequestSite) + self.assertIsInstance(response.context["form"], AuthenticationForm) def test_security_check(self): - login_url = reverse('login') + login_url = reverse("login") # These URLs should not pass the security check. bad_urls = ( - 'http://example.com', - 'http:///example.com', - 'https://example.com', - 'ftp://example.com', - '///example.com', - '//example.com', + "http://example.com", + "http:///example.com", + "https://example.com", + "ftp://example.com", + "///example.com", + "//example.com", 'javascript:alert("XSS")', ) for bad_url in bad_urls: with self.subTest(bad_url=bad_url): - nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { - 'url': login_url, - 'next': REDIRECT_FIELD_NAME, - 'bad_url': quote(bad_url), + nasty_url = "%(url)s?%(next)s=%(bad_url)s" % { + "url": login_url, + "next": REDIRECT_FIELD_NAME, + "bad_url": quote(bad_url), } - response = self.client.post(nasty_url, { - 'username': 'testclient', - 'password': 'password', - }) + response = self.client.post( + nasty_url, + { + "username": "testclient", + "password": "password", + }, + ) self.assertEqual(response.status_code, 302) - self.assertNotIn(bad_url, response.url, '%s should be blocked' % bad_url) + self.assertNotIn( + bad_url, response.url, "%s should be blocked" % bad_url + ) # These URLs should pass the security check. good_urls = ( - '/view/?param=http://example.com', - '/view/?param=https://example.com', - '/view?param=ftp://example.com', - 'view/?param=//example.com', - 'https://testserver/', - 'HTTPS://testserver/', - '//testserver/', - '/url%20with%20spaces/', + "/view/?param=http://example.com", + "/view/?param=https://example.com", + "/view?param=ftp://example.com", + "view/?param=//example.com", + "https://testserver/", + "HTTPS://testserver/", + "//testserver/", + "/url%20with%20spaces/", ) for good_url in good_urls: with self.subTest(good_url=good_url): - safe_url = '%(url)s?%(next)s=%(good_url)s' % { - 'url': login_url, - 'next': REDIRECT_FIELD_NAME, - 'good_url': quote(good_url), + safe_url = "%(url)s?%(next)s=%(good_url)s" % { + "url": login_url, + "next": REDIRECT_FIELD_NAME, + "good_url": quote(good_url), } - response = self.client.post(safe_url, { - 'username': 'testclient', - 'password': 'password', - }) + response = self.client.post( + safe_url, + { + "username": "testclient", + "password": "password", + }, + ) self.assertEqual(response.status_code, 302) - self.assertIn(good_url, response.url, '%s should be allowed' % good_url) + self.assertIn(good_url, response.url, "%s should be allowed" % good_url) def test_security_check_https(self): - login_url = reverse('login') - non_https_next_url = 'http://testserver/path' - not_secured_url = '%(url)s?%(next)s=%(next_url)s' % { - 'url': login_url, - 'next': REDIRECT_FIELD_NAME, - 'next_url': quote(non_https_next_url), + login_url = reverse("login") + non_https_next_url = "http://testserver/path" + not_secured_url = "%(url)s?%(next)s=%(next_url)s" % { + "url": login_url, + "next": REDIRECT_FIELD_NAME, + "next_url": quote(non_https_next_url), } post_data = { - 'username': 'testclient', - 'password': 'password', + "username": "testclient", + "password": "password", } response = self.client.post(not_secured_url, post_data, secure=True) self.assertEqual(response.status_code, 302) @@ -644,17 +757,23 @@ class LoginTest(AuthViewsTestCase): def test_login_form_contains_request(self): # The custom authentication form for this login requires a request to # initialize it. - response = self.client.post('/custom_request_auth_login/', { - 'username': 'testclient', - 'password': 'password', - }) + response = self.client.post( + "/custom_request_auth_login/", + { + "username": "testclient", + "password": "password", + }, + ) # The login was successful. - self.assertRedirects(response, settings.LOGIN_REDIRECT_URL, fetch_redirect_response=False) + self.assertRedirects( + response, settings.LOGIN_REDIRECT_URL, fetch_redirect_response=False + ) def test_login_csrf_rotate(self): """ Makes sure that a login rotates the currently-used CSRF token. """ + def get_response(request): return HttpResponse() @@ -672,12 +791,18 @@ class LoginTest(AuthViewsTestCase): req = HttpRequest() req.COOKIES[settings.CSRF_COOKIE_NAME] = token1 req.method = "POST" - req.POST = {'username': 'testclient', 'password': 'password', 'csrfmiddlewaretoken': token1} + req.POST = { + "username": "testclient", + "password": "password", + "csrfmiddlewaretoken": token1, + } # Use POST request to log in SessionMiddleware(get_response).process_request(req) CsrfViewMiddleware(get_response).process_view(req, LoginView.as_view(), (), {}) - req.META["SERVER_NAME"] = "testserver" # Required to have redirect work in login view + req.META[ + "SERVER_NAME" + ] = "testserver" # Required to have redirect work in login view req.META["SERVER_PORT"] = 80 resp = CsrfViewMiddleware(LoginView.as_view())(req) csrf_cookie = resp.cookies.get(settings.CSRF_COOKIE_NAME, None) @@ -695,7 +820,7 @@ class LoginTest(AuthViewsTestCase): self.login() original_session_key = self.client.session.session_key - self.login(username='staff') + self.login(username="staff") self.assertNotEqual(original_session_key, self.client.session.session_key) def test_session_key_flushed_on_login_after_password_change(self): @@ -709,11 +834,11 @@ class LoginTest(AuthViewsTestCase): self.login() self.assertEqual(original_session_key, self.client.session.session_key) - user = User.objects.get(username='testclient') - user.set_password('foobar') + user = User.objects.get(username="testclient") + user.set_password("foobar") user.save() - self.login(password='foobar') + self.login(password="foobar") self.assertNotEqual(original_session_key, self.client.session.session_key) def test_login_session_without_hash_session_key(self): @@ -721,7 +846,7 @@ class LoginTest(AuthViewsTestCase): Session without django.contrib.auth.HASH_SESSION_KEY should login without an exception. """ - user = User.objects.get(username='testclient') + user = User.objects.get(username="testclient") engine = import_module(settings.SESSION_ENGINE) session = engine.SessionStore() session[SESSION_KEY] = user.id @@ -733,106 +858,111 @@ class LoginTest(AuthViewsTestCase): self.assertNotEqual(original_session_key, self.client.session.session_key) def test_login_get_default_redirect_url(self): - response = self.login(url='/login/get_default_redirect_url/') - self.assertRedirects(response, '/custom/', fetch_redirect_response=False) + response = self.login(url="/login/get_default_redirect_url/") + self.assertRedirects(response, "/custom/", fetch_redirect_response=False) def test_login_next_page(self): - response = self.login(url='/login/next_page/') - self.assertRedirects(response, '/somewhere/', fetch_redirect_response=False) + response = self.login(url="/login/next_page/") + self.assertRedirects(response, "/somewhere/", fetch_redirect_response=False) def test_login_named_next_page_named(self): - response = self.login(url='/login/next_page/named/') - self.assertRedirects(response, '/password_reset/', fetch_redirect_response=False) + response = self.login(url="/login/next_page/named/") + self.assertRedirects( + response, "/password_reset/", fetch_redirect_response=False + ) - @override_settings(LOGIN_REDIRECT_URL='/custom/') + @override_settings(LOGIN_REDIRECT_URL="/custom/") def test_login_next_page_overrides_login_redirect_url_setting(self): - response = self.login(url='/login/next_page/') - self.assertRedirects(response, '/somewhere/', fetch_redirect_response=False) + response = self.login(url="/login/next_page/") + self.assertRedirects(response, "/somewhere/", fetch_redirect_response=False) def test_login_redirect_url_overrides_next_page(self): - response = self.login(url='/login/next_page/?next=/test/') - self.assertRedirects(response, '/test/', fetch_redirect_response=False) + response = self.login(url="/login/next_page/?next=/test/") + self.assertRedirects(response, "/test/", fetch_redirect_response=False) def test_login_redirect_url_overrides_get_default_redirect_url(self): - response = self.login(url='/login/get_default_redirect_url/?next=/test/') - self.assertRedirects(response, '/test/', fetch_redirect_response=False) + response = self.login(url="/login/get_default_redirect_url/?next=/test/") + self.assertRedirects(response, "/test/", fetch_redirect_response=False) class LoginURLSettings(AuthViewsTestCase): """Tests for settings.LOGIN_URL.""" + def assertLoginURLEquals(self, url): - response = self.client.get('/login_required/') + response = self.client.get("/login_required/") self.assertRedirects(response, url, fetch_redirect_response=False) - @override_settings(LOGIN_URL='/login/') + @override_settings(LOGIN_URL="/login/") def test_standard_login_url(self): - self.assertLoginURLEquals('/login/?next=/login_required/') + self.assertLoginURLEquals("/login/?next=/login_required/") - @override_settings(LOGIN_URL='login') + @override_settings(LOGIN_URL="login") def test_named_login_url(self): - self.assertLoginURLEquals('/login/?next=/login_required/') + self.assertLoginURLEquals("/login/?next=/login_required/") - @override_settings(LOGIN_URL='http://remote.example.com/login') + @override_settings(LOGIN_URL="http://remote.example.com/login") def test_remote_login_url(self): - quoted_next = quote('http://testserver/login_required/') - expected = 'http://remote.example.com/login?next=%s' % quoted_next + quoted_next = quote("http://testserver/login_required/") + expected = "http://remote.example.com/login?next=%s" % quoted_next self.assertLoginURLEquals(expected) - @override_settings(LOGIN_URL='https:///login/') + @override_settings(LOGIN_URL="https:///login/") def test_https_login_url(self): - quoted_next = quote('http://testserver/login_required/') - expected = 'https:///login/?next=%s' % quoted_next + quoted_next = quote("http://testserver/login_required/") + expected = "https:///login/?next=%s" % quoted_next self.assertLoginURLEquals(expected) - @override_settings(LOGIN_URL='/login/?pretty=1') + @override_settings(LOGIN_URL="/login/?pretty=1") def test_login_url_with_querystring(self): - self.assertLoginURLEquals('/login/?pretty=1&next=/login_required/') + self.assertLoginURLEquals("/login/?pretty=1&next=/login_required/") - @override_settings(LOGIN_URL='http://remote.example.com/login/?next=/default/') + @override_settings(LOGIN_URL="http://remote.example.com/login/?next=/default/") def test_remote_login_url_with_next_querystring(self): - quoted_next = quote('http://testserver/login_required/') - expected = 'http://remote.example.com/login/?next=%s' % quoted_next + quoted_next = quote("http://testserver/login_required/") + expected = "http://remote.example.com/login/?next=%s" % quoted_next self.assertLoginURLEquals(expected) - @override_settings(LOGIN_URL=reverse_lazy('login')) + @override_settings(LOGIN_URL=reverse_lazy("login")) def test_lazy_login_url(self): - self.assertLoginURLEquals('/login/?next=/login_required/') + self.assertLoginURLEquals("/login/?next=/login_required/") class LoginRedirectUrlTest(AuthViewsTestCase): """Tests for settings.LOGIN_REDIRECT_URL.""" + def assertLoginRedirectURLEqual(self, url): response = self.login() self.assertRedirects(response, url, fetch_redirect_response=False) def test_default(self): - self.assertLoginRedirectURLEqual('/accounts/profile/') + self.assertLoginRedirectURLEqual("/accounts/profile/") - @override_settings(LOGIN_REDIRECT_URL='/custom/') + @override_settings(LOGIN_REDIRECT_URL="/custom/") def test_custom(self): - self.assertLoginRedirectURLEqual('/custom/') + self.assertLoginRedirectURLEqual("/custom/") - @override_settings(LOGIN_REDIRECT_URL='password_reset') + @override_settings(LOGIN_REDIRECT_URL="password_reset") def test_named(self): - self.assertLoginRedirectURLEqual('/password_reset/') + self.assertLoginRedirectURLEqual("/password_reset/") - @override_settings(LOGIN_REDIRECT_URL='http://remote.example.com/welcome/') + @override_settings(LOGIN_REDIRECT_URL="http://remote.example.com/welcome/") def test_remote(self): - self.assertLoginRedirectURLEqual('http://remote.example.com/welcome/') + self.assertLoginRedirectURLEqual("http://remote.example.com/welcome/") class RedirectToLoginTests(AuthViewsTestCase): """Tests for the redirect_to_login view""" - @override_settings(LOGIN_URL=reverse_lazy('login')) + + @override_settings(LOGIN_URL=reverse_lazy("login")) def test_redirect_to_login_with_lazy(self): - login_redirect_response = redirect_to_login(next='/else/where/') - expected = '/login/?next=/else/where/' + login_redirect_response = redirect_to_login(next="/else/where/") + expected = "/login/?next=/else/where/" self.assertEqual(expected, login_redirect_response.url) - @override_settings(LOGIN_URL=reverse_lazy('login')) + @override_settings(LOGIN_URL=reverse_lazy("login")) def test_redirect_to_login_with_lazy_and_unicode(self): - login_redirect_response = redirect_to_login(next='/else/where/झ/') - expected = '/login/?next=/else/where/%E0%A4%9D/' + login_redirect_response = redirect_to_login(next="/else/where/झ/") + expected = "/login/?next=/else/where/%E0%A4%9D/" self.assertEqual(expected, login_redirect_response.url) @@ -842,36 +972,36 @@ class LogoutThenLoginTests(AuthViewsTestCase): def confirm_logged_out(self): self.assertNotIn(SESSION_KEY, self.client.session) - @override_settings(LOGIN_URL='/login/') + @override_settings(LOGIN_URL="/login/") def test_default_logout_then_login(self): self.login() req = HttpRequest() - req.method = 'GET' + req.method = "GET" req.session = self.client.session response = logout_then_login(req) self.confirm_logged_out() - self.assertRedirects(response, '/login/', fetch_redirect_response=False) + self.assertRedirects(response, "/login/", fetch_redirect_response=False) def test_logout_then_login_with_custom_login(self): self.login() req = HttpRequest() - req.method = 'GET' + req.method = "GET" req.session = self.client.session - response = logout_then_login(req, login_url='/custom/') + response = logout_then_login(req, login_url="/custom/") self.confirm_logged_out() - self.assertRedirects(response, '/custom/', fetch_redirect_response=False) + self.assertRedirects(response, "/custom/", fetch_redirect_response=False) class LoginRedirectAuthenticatedUser(AuthViewsTestCase): - dont_redirect_url = '/login/redirect_authenticated_user_default/' - do_redirect_url = '/login/redirect_authenticated_user/' + dont_redirect_url = "/login/redirect_authenticated_user_default/" + do_redirect_url = "/login/redirect_authenticated_user/" def test_default(self): """Stay on the login page by default.""" self.login() response = self.client.get(self.dont_redirect_url) self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['next'], '') + self.assertEqual(response.context["next"], "") def test_guest(self): """If not logged in, stay on the same page.""" @@ -882,21 +1012,23 @@ class LoginRedirectAuthenticatedUser(AuthViewsTestCase): """If logged in, go to default redirected URL.""" self.login() response = self.client.get(self.do_redirect_url) - self.assertRedirects(response, '/accounts/profile/', fetch_redirect_response=False) + self.assertRedirects( + response, "/accounts/profile/", fetch_redirect_response=False + ) - @override_settings(LOGIN_REDIRECT_URL='/custom/') + @override_settings(LOGIN_REDIRECT_URL="/custom/") def test_redirect_url(self): """If logged in, go to custom redirected URL.""" self.login() response = self.client.get(self.do_redirect_url) - self.assertRedirects(response, '/custom/', fetch_redirect_response=False) + self.assertRedirects(response, "/custom/", fetch_redirect_response=False) def test_redirect_param(self): """If next is specified as a GET parameter, go there.""" self.login() - url = self.do_redirect_url + '?next=/custom_next/' + url = self.do_redirect_url + "?next=/custom_next/" response = self.client.get(url) - self.assertRedirects(response, '/custom_next/', fetch_redirect_response=False) + self.assertRedirects(response, "/custom_next/", fetch_redirect_response=False) def test_redirect_loop(self): """ @@ -912,7 +1044,7 @@ class LoginRedirectAuthenticatedUser(AuthViewsTestCase): with self.assertRaisesMessage(ValueError, msg): self.client.get(self.do_redirect_url) - url = self.do_redirect_url + '?bla=2' + url = self.do_redirect_url + "?bla=2" with self.assertRaisesMessage(ValueError, msg): self.client.get(url) @@ -920,13 +1052,15 @@ class LoginRedirectAuthenticatedUser(AuthViewsTestCase): # Not logged in ... with self.settings(LOGIN_URL=self.do_redirect_url): # redirected to login. - response = self.client.get('/permission_required_redirect/', follow=True) + response = self.client.get("/permission_required_redirect/", follow=True) self.assertEqual(response.status_code, 200) # exception raised. - response = self.client.get('/permission_required_exception/', follow=True) + response = self.client.get("/permission_required_exception/", follow=True) self.assertEqual(response.status_code, 403) # redirected to login. - response = self.client.get('/login_and_permission_required_exception/', follow=True) + response = self.client.get( + "/login_and_permission_required_exception/", follow=True + ) self.assertEqual(response.status_code, 200) def test_permission_required_logged_in(self): @@ -934,191 +1068,219 @@ class LoginRedirectAuthenticatedUser(AuthViewsTestCase): # Already logged in... with self.settings(LOGIN_URL=self.do_redirect_url): # redirect loop encountered. - with self.assertRaisesMessage(RedirectCycleError, 'Redirect loop detected.'): - self.client.get('/permission_required_redirect/', follow=True) + with self.assertRaisesMessage( + RedirectCycleError, "Redirect loop detected." + ): + self.client.get("/permission_required_redirect/", follow=True) # exception raised. - response = self.client.get('/permission_required_exception/', follow=True) + response = self.client.get("/permission_required_exception/", follow=True) self.assertEqual(response.status_code, 403) # exception raised. - response = self.client.get('/login_and_permission_required_exception/', follow=True) + response = self.client.get( + "/login_and_permission_required_exception/", follow=True + ) self.assertEqual(response.status_code, 403) class LoginSuccessURLAllowedHostsTest(AuthViewsTestCase): def test_success_url_allowed_hosts_same_host(self): - response = self.client.post('/login/allowed_hosts/', { - 'username': 'testclient', - 'password': 'password', - 'next': 'https://testserver/home', - }) + response = self.client.post( + "/login/allowed_hosts/", + { + "username": "testclient", + "password": "password", + "next": "https://testserver/home", + }, + ) self.assertIn(SESSION_KEY, self.client.session) - self.assertRedirects(response, 'https://testserver/home', fetch_redirect_response=False) + self.assertRedirects( + response, "https://testserver/home", fetch_redirect_response=False + ) def test_success_url_allowed_hosts_safe_host(self): - response = self.client.post('/login/allowed_hosts/', { - 'username': 'testclient', - 'password': 'password', - 'next': 'https://otherserver/home', - }) + response = self.client.post( + "/login/allowed_hosts/", + { + "username": "testclient", + "password": "password", + "next": "https://otherserver/home", + }, + ) self.assertIn(SESSION_KEY, self.client.session) - self.assertRedirects(response, 'https://otherserver/home', fetch_redirect_response=False) + self.assertRedirects( + response, "https://otherserver/home", fetch_redirect_response=False + ) def test_success_url_allowed_hosts_unsafe_host(self): - response = self.client.post('/login/allowed_hosts/', { - 'username': 'testclient', - 'password': 'password', - 'next': 'https://evil/home', - }) + response = self.client.post( + "/login/allowed_hosts/", + { + "username": "testclient", + "password": "password", + "next": "https://evil/home", + }, + ) self.assertIn(SESSION_KEY, self.client.session) - self.assertRedirects(response, '/accounts/profile/', fetch_redirect_response=False) + self.assertRedirects( + response, "/accounts/profile/", fetch_redirect_response=False + ) class LogoutTest(AuthViewsTestCase): - def confirm_logged_out(self): self.assertNotIn(SESSION_KEY, self.client.session) def test_logout_default(self): "Logout without next_page option renders the default template" self.login() - response = self.client.get('/logout/') - self.assertContains(response, 'Logged out') + response = self.client.get("/logout/") + self.assertContains(response, "Logged out") self.confirm_logged_out() def test_logout_with_post(self): self.login() - response = self.client.post('/logout/') - self.assertContains(response, 'Logged out') + response = self.client.post("/logout/") + self.assertContains(response, "Logged out") self.confirm_logged_out() def test_14377(self): # Bug 14377 self.login() - response = self.client.get('/logout/') - self.assertIn('site', response.context) + response = self.client.get("/logout/") + self.assertIn("site", response.context) def test_logout_doesnt_cache(self): """ The logout() view should send "no-cache" headers for reasons described in #25490. """ - response = self.client.get('/logout/') - self.assertIn('no-store', response.headers['Cache-Control']) + response = self.client.get("/logout/") + self.assertIn("no-store", response.headers["Cache-Control"]) def test_logout_with_overridden_redirect_url(self): # Bug 11223 self.login() - response = self.client.get('/logout/next_page/') - self.assertRedirects(response, '/somewhere/', fetch_redirect_response=False) + response = self.client.get("/logout/next_page/") + self.assertRedirects(response, "/somewhere/", fetch_redirect_response=False) - response = self.client.get('/logout/next_page/?next=/login/') - self.assertRedirects(response, '/login/', fetch_redirect_response=False) + response = self.client.get("/logout/next_page/?next=/login/") + self.assertRedirects(response, "/login/", fetch_redirect_response=False) self.confirm_logged_out() def test_logout_with_next_page_specified(self): "Logout with next_page option given redirects to specified resource" self.login() - response = self.client.get('/logout/next_page/') - self.assertRedirects(response, '/somewhere/', fetch_redirect_response=False) + response = self.client.get("/logout/next_page/") + self.assertRedirects(response, "/somewhere/", fetch_redirect_response=False) self.confirm_logged_out() def test_logout_with_redirect_argument(self): "Logout with query string redirects to specified resource" self.login() - response = self.client.get('/logout/?next=/login/') - self.assertRedirects(response, '/login/', fetch_redirect_response=False) + response = self.client.get("/logout/?next=/login/") + self.assertRedirects(response, "/login/", fetch_redirect_response=False) self.confirm_logged_out() def test_logout_with_custom_redirect_argument(self): "Logout with custom query string redirects to specified resource" self.login() - response = self.client.get('/logout/custom_query/?follow=/somewhere/') - self.assertRedirects(response, '/somewhere/', fetch_redirect_response=False) + response = self.client.get("/logout/custom_query/?follow=/somewhere/") + self.assertRedirects(response, "/somewhere/", fetch_redirect_response=False) self.confirm_logged_out() def test_logout_with_named_redirect(self): "Logout resolves names or URLs passed as next_page." self.login() - response = self.client.get('/logout/next_page/named/') - self.assertRedirects(response, '/password_reset/', fetch_redirect_response=False) + response = self.client.get("/logout/next_page/named/") + self.assertRedirects( + response, "/password_reset/", fetch_redirect_response=False + ) self.confirm_logged_out() def test_success_url_allowed_hosts_same_host(self): self.login() - response = self.client.get('/logout/allowed_hosts/?next=https://testserver/') - self.assertRedirects(response, 'https://testserver/', fetch_redirect_response=False) + response = self.client.get("/logout/allowed_hosts/?next=https://testserver/") + self.assertRedirects( + response, "https://testserver/", fetch_redirect_response=False + ) self.confirm_logged_out() def test_success_url_allowed_hosts_safe_host(self): self.login() - response = self.client.get('/logout/allowed_hosts/?next=https://otherserver/') - self.assertRedirects(response, 'https://otherserver/', fetch_redirect_response=False) + response = self.client.get("/logout/allowed_hosts/?next=https://otherserver/") + self.assertRedirects( + response, "https://otherserver/", fetch_redirect_response=False + ) self.confirm_logged_out() def test_success_url_allowed_hosts_unsafe_host(self): self.login() - response = self.client.get('/logout/allowed_hosts/?next=https://evil/') - self.assertRedirects(response, '/logout/allowed_hosts/', fetch_redirect_response=False) + response = self.client.get("/logout/allowed_hosts/?next=https://evil/") + self.assertRedirects( + response, "/logout/allowed_hosts/", fetch_redirect_response=False + ) self.confirm_logged_out() def test_security_check(self): - logout_url = reverse('logout') + logout_url = reverse("logout") # These URLs should not pass the security check. bad_urls = ( - 'http://example.com', - 'http:///example.com', - 'https://example.com', - 'ftp://example.com', - '///example.com', - '//example.com', + "http://example.com", + "http:///example.com", + "https://example.com", + "ftp://example.com", + "///example.com", + "//example.com", 'javascript:alert("XSS")', ) for bad_url in bad_urls: with self.subTest(bad_url=bad_url): - nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { - 'url': logout_url, - 'next': REDIRECT_FIELD_NAME, - 'bad_url': quote(bad_url), + nasty_url = "%(url)s?%(next)s=%(bad_url)s" % { + "url": logout_url, + "next": REDIRECT_FIELD_NAME, + "bad_url": quote(bad_url), } self.login() response = self.client.get(nasty_url) self.assertEqual(response.status_code, 302) - self.assertNotIn(bad_url, response.url, '%s should be blocked' % bad_url) + self.assertNotIn( + bad_url, response.url, "%s should be blocked" % bad_url + ) self.confirm_logged_out() # These URLs should pass the security check. good_urls = ( - '/view/?param=http://example.com', - '/view/?param=https://example.com', - '/view?param=ftp://example.com', - 'view/?param=//example.com', - 'https://testserver/', - 'HTTPS://testserver/', - '//testserver/', - '/url%20with%20spaces/', + "/view/?param=http://example.com", + "/view/?param=https://example.com", + "/view?param=ftp://example.com", + "view/?param=//example.com", + "https://testserver/", + "HTTPS://testserver/", + "//testserver/", + "/url%20with%20spaces/", ) for good_url in good_urls: with self.subTest(good_url=good_url): - safe_url = '%(url)s?%(next)s=%(good_url)s' % { - 'url': logout_url, - 'next': REDIRECT_FIELD_NAME, - 'good_url': quote(good_url), + safe_url = "%(url)s?%(next)s=%(good_url)s" % { + "url": logout_url, + "next": REDIRECT_FIELD_NAME, + "good_url": quote(good_url), } self.login() response = self.client.get(safe_url) self.assertEqual(response.status_code, 302) - self.assertIn(good_url, response.url, '%s should be allowed' % good_url) + self.assertIn(good_url, response.url, "%s should be allowed" % good_url) self.confirm_logged_out() def test_security_check_https(self): - logout_url = reverse('logout') - non_https_next_url = 'http://testserver/' - url = '%(url)s?%(next)s=%(next_url)s' % { - 'url': logout_url, - 'next': REDIRECT_FIELD_NAME, - 'next_url': quote(non_https_next_url), + logout_url = reverse("logout") + non_https_next_url = "http://testserver/" + url = "%(url)s?%(next)s=%(next_url)s" % { + "url": logout_url, + "next": REDIRECT_FIELD_NAME, + "next_url": quote(non_https_next_url), } self.login() response = self.client.get(url, secure=True) @@ -1128,22 +1290,22 @@ class LogoutTest(AuthViewsTestCase): def test_logout_preserve_language(self): """Language is preserved after logout.""" self.login() - self.client.post('/setlang/', {'language': 'pl'}) - self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, 'pl') - self.client.get('/logout/') - self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, 'pl') + self.client.post("/setlang/", {"language": "pl"}) + self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, "pl") + self.client.get("/logout/") + self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value, "pl") - @override_settings(LOGOUT_REDIRECT_URL='/custom/') + @override_settings(LOGOUT_REDIRECT_URL="/custom/") def test_logout_redirect_url_setting(self): self.login() - response = self.client.get('/logout/') - self.assertRedirects(response, '/custom/', fetch_redirect_response=False) + response = self.client.get("/logout/") + self.assertRedirects(response, "/custom/", fetch_redirect_response=False) - @override_settings(LOGOUT_REDIRECT_URL='logout') + @override_settings(LOGOUT_REDIRECT_URL="logout") def test_logout_redirect_url_named_setting(self): self.login() - response = self.client.get('/logout/') - self.assertRedirects(response, '/logout/', fetch_redirect_response=False) + response = self.client.get("/logout/") + self.assertRedirects(response, "/logout/", fetch_redirect_response=False) def get_perm(Model, perm): @@ -1153,14 +1315,15 @@ def get_perm(Model, perm): # Redirect in test_user_change_password will fail if session auth hash # isn't updated after password change (#21649) -@override_settings(ROOT_URLCONF='auth_tests.urls_admin') +@override_settings(ROOT_URLCONF="auth_tests.urls_admin") class ChangelistTests(AuthViewsTestCase): - @classmethod def setUpTestData(cls): super().setUpTestData() # Make me a superuser before logging in. - User.objects.filter(username='testclient').update(is_staff=True, is_superuser=True) + User.objects.filter(username="testclient").update( + is_staff=True, is_superuser=True + ) def setUp(self): self.login() @@ -1169,126 +1332,145 @@ class ChangelistTests(AuthViewsTestCase): def get_user_data(self, user): return { - 'username': user.username, - 'password': user.password, - 'email': user.email, - 'is_active': user.is_active, - 'is_staff': user.is_staff, - 'is_superuser': user.is_superuser, - 'last_login_0': user.last_login.strftime('%Y-%m-%d'), - 'last_login_1': user.last_login.strftime('%H:%M:%S'), - 'initial-last_login_0': user.last_login.strftime('%Y-%m-%d'), - 'initial-last_login_1': user.last_login.strftime('%H:%M:%S'), - 'date_joined_0': user.date_joined.strftime('%Y-%m-%d'), - 'date_joined_1': user.date_joined.strftime('%H:%M:%S'), - 'initial-date_joined_0': user.date_joined.strftime('%Y-%m-%d'), - 'initial-date_joined_1': user.date_joined.strftime('%H:%M:%S'), - 'first_name': user.first_name, - 'last_name': user.last_name, + "username": user.username, + "password": user.password, + "email": user.email, + "is_active": user.is_active, + "is_staff": user.is_staff, + "is_superuser": user.is_superuser, + "last_login_0": user.last_login.strftime("%Y-%m-%d"), + "last_login_1": user.last_login.strftime("%H:%M:%S"), + "initial-last_login_0": user.last_login.strftime("%Y-%m-%d"), + "initial-last_login_1": user.last_login.strftime("%H:%M:%S"), + "date_joined_0": user.date_joined.strftime("%Y-%m-%d"), + "date_joined_1": user.date_joined.strftime("%H:%M:%S"), + "initial-date_joined_0": user.date_joined.strftime("%Y-%m-%d"), + "initial-date_joined_1": user.date_joined.strftime("%H:%M:%S"), + "first_name": user.first_name, + "last_name": user.last_name, } # #20078 - users shouldn't be allowed to guess password hashes via # repeated password__startswith queries. def test_changelist_disallows_password_lookups(self): # A lookup that tries to filter on password isn't OK - with self.assertLogs('django.security.DisallowedModelAdminLookup', 'ERROR'): - response = self.client.get(reverse('auth_test_admin:auth_user_changelist') + '?password__startswith=sha1$') + with self.assertLogs("django.security.DisallowedModelAdminLookup", "ERROR"): + response = self.client.get( + reverse("auth_test_admin:auth_user_changelist") + + "?password__startswith=sha1$" + ) self.assertEqual(response.status_code, 400) def test_user_change_email(self): data = self.get_user_data(self.admin) - data['email'] = 'new_' + data['email'] + data["email"] = "new_" + data["email"] response = self.client.post( - reverse('auth_test_admin:auth_user_change', args=(self.admin.pk,)), - data + reverse("auth_test_admin:auth_user_change", args=(self.admin.pk,)), data ) - self.assertRedirects(response, reverse('auth_test_admin:auth_user_changelist')) - row = LogEntry.objects.latest('id') - self.assertEqual(row.get_change_message(), 'Changed Email address.') + self.assertRedirects(response, reverse("auth_test_admin:auth_user_changelist")) + row = LogEntry.objects.latest("id") + self.assertEqual(row.get_change_message(), "Changed Email address.") def test_user_not_change(self): response = self.client.post( - reverse('auth_test_admin:auth_user_change', args=(self.admin.pk,)), - self.get_user_data(self.admin) + reverse("auth_test_admin:auth_user_change", args=(self.admin.pk,)), + self.get_user_data(self.admin), ) - self.assertRedirects(response, reverse('auth_test_admin:auth_user_changelist')) - row = LogEntry.objects.latest('id') - self.assertEqual(row.get_change_message(), 'No fields changed.') + self.assertRedirects(response, reverse("auth_test_admin:auth_user_changelist")) + row = LogEntry.objects.latest("id") + self.assertEqual(row.get_change_message(), "No fields changed.") def test_user_change_password(self): - user_change_url = reverse('auth_test_admin:auth_user_change', args=(self.admin.pk,)) - password_change_url = reverse('auth_test_admin:auth_user_password_change', args=(self.admin.pk,)) + user_change_url = reverse( + "auth_test_admin:auth_user_change", args=(self.admin.pk,) + ) + password_change_url = reverse( + "auth_test_admin:auth_user_password_change", args=(self.admin.pk,) + ) response = self.client.get(user_change_url) # Test the link inside password field help_text. rel_link = re.search( r'you can change the password using <a href="([^"]*)">this form</a>', - response.content.decode() + response.content.decode(), )[1] self.assertEqual(urljoin(user_change_url, rel_link), password_change_url) response = self.client.post( password_change_url, { - 'password1': 'password1', - 'password2': 'password1', - } + "password1": "password1", + "password2": "password1", + }, ) self.assertRedirects(response, user_change_url) - row = LogEntry.objects.latest('id') - self.assertEqual(row.get_change_message(), 'Changed password.') + row = LogEntry.objects.latest("id") + self.assertEqual(row.get_change_message(), "Changed password.") self.logout() - self.login(password='password1') + self.login(password="password1") def test_user_change_different_user_password(self): - u = User.objects.get(email='staffmember@example.com') + u = User.objects.get(email="staffmember@example.com") response = self.client.post( - reverse('auth_test_admin:auth_user_password_change', args=(u.pk,)), + reverse("auth_test_admin:auth_user_password_change", args=(u.pk,)), { - 'password1': 'password1', - 'password2': 'password1', - } + "password1": "password1", + "password2": "password1", + }, + ) + self.assertRedirects( + response, reverse("auth_test_admin:auth_user_change", args=(u.pk,)) ) - self.assertRedirects(response, reverse('auth_test_admin:auth_user_change', args=(u.pk,))) - row = LogEntry.objects.latest('id') + row = LogEntry.objects.latest("id") self.assertEqual(row.user_id, self.admin.pk) self.assertEqual(row.object_id, str(u.pk)) - self.assertEqual(row.get_change_message(), 'Changed password.') + self.assertEqual(row.get_change_message(), "Changed password.") def test_password_change_bad_url(self): - response = self.client.get(reverse('auth_test_admin:auth_user_password_change', args=('foobar',))) + response = self.client.get( + reverse("auth_test_admin:auth_user_password_change", args=("foobar",)) + ) self.assertEqual(response.status_code, 404) - @mock.patch('django.contrib.auth.admin.UserAdmin.has_change_permission') - def test_user_change_password_passes_user_to_has_change_permission(self, has_change_permission): - url = reverse('auth_test_admin:auth_user_password_change', args=(self.admin.pk,)) - self.client.post(url, {'password1': 'password1', 'password2': 'password1'}) + @mock.patch("django.contrib.auth.admin.UserAdmin.has_change_permission") + def test_user_change_password_passes_user_to_has_change_permission( + self, has_change_permission + ): + url = reverse( + "auth_test_admin:auth_user_password_change", args=(self.admin.pk,) + ) + self.client.post(url, {"password1": "password1", "password2": "password1"}) (_request, user), _kwargs = has_change_permission.call_args self.assertEqual(user.pk, self.admin.pk) def test_view_user_password_is_readonly(self): - u = User.objects.get(username='testclient') + u = User.objects.get(username="testclient") u.is_superuser = False u.save() original_password = u.password - u.user_permissions.add(get_perm(User, 'view_user')) - response = self.client.get(reverse('auth_test_admin:auth_user_change', args=(u.pk,)),) - algo, salt, hash_string = (u.password.split('$')) + u.user_permissions.add(get_perm(User, "view_user")) + response = self.client.get( + reverse("auth_test_admin:auth_user_change", args=(u.pk,)), + ) + algo, salt, hash_string = u.password.split("$") self.assertContains(response, '<div class="readonly">testclient</div>') # ReadOnlyPasswordHashWidget is used to render the field. self.assertContains( response, - '<strong>algorithm</strong>: %s\n\n' - '<strong>salt</strong>: %s********************\n\n' - '<strong>hash</strong>: %s**************************\n\n' % ( - algo, salt[:2], hash_string[:6], + "<strong>algorithm</strong>: %s\n\n" + "<strong>salt</strong>: %s********************\n\n" + "<strong>hash</strong>: %s**************************\n\n" + % ( + algo, + salt[:2], + hash_string[:6], ), html=True, ) # Value in POST data is ignored. data = self.get_user_data(u) - data['password'] = 'shouldnotchange' - change_url = reverse('auth_test_admin:auth_user_change', args=(u.pk,)) + data["password"] = "shouldnotchange" + change_url = reverse("auth_test_admin:auth_user_change", args=(u.pk,)) response = self.client.post(change_url, data) self.assertEqual(response.status_code, 403) u.refresh_from_db() @@ -1296,35 +1478,43 @@ class ChangelistTests(AuthViewsTestCase): @override_settings( - AUTH_USER_MODEL='auth_tests.UUIDUser', - ROOT_URLCONF='auth_tests.urls_custom_user_admin', + AUTH_USER_MODEL="auth_tests.UUIDUser", + ROOT_URLCONF="auth_tests.urls_custom_user_admin", ) class UUIDUserTests(TestCase): - def test_admin_password_change(self): - u = UUIDUser.objects.create_superuser(username='uuid', email='foo@bar.com', password='test') - self.assertTrue(self.client.login(username='uuid', password='test')) + u = UUIDUser.objects.create_superuser( + username="uuid", email="foo@bar.com", password="test" + ) + self.assertTrue(self.client.login(username="uuid", password="test")) - user_change_url = reverse('custom_user_admin:auth_tests_uuiduser_change', args=(u.pk,)) + user_change_url = reverse( + "custom_user_admin:auth_tests_uuiduser_change", args=(u.pk,) + ) response = self.client.get(user_change_url) self.assertEqual(response.status_code, 200) - password_change_url = reverse('custom_user_admin:auth_user_password_change', args=(u.pk,)) + password_change_url = reverse( + "custom_user_admin:auth_user_password_change", args=(u.pk,) + ) response = self.client.get(password_change_url) # The action attribute is omitted. self.assertContains(response, '<form method="post" id="uuiduser_form">') # A LogEntry is created with pk=1 which breaks a FK constraint on MySQL with connection.constraint_checks_disabled(): - response = self.client.post(password_change_url, { - 'password1': 'password1', - 'password2': 'password1', - }) + response = self.client.post( + password_change_url, + { + "password1": "password1", + "password2": "password1", + }, + ) self.assertRedirects(response, user_change_url) - row = LogEntry.objects.latest('id') + row = LogEntry.objects.latest("id") self.assertEqual(row.user_id, 1) # hardcoded in CustomUserAdmin.log_change() self.assertEqual(row.object_id, str(u.pk)) - self.assertEqual(row.get_change_message(), 'Changed password.') + self.assertEqual(row.get_change_message(), "Changed password.") # The LogEntry.user column isn't altered to a UUID type so it's set to # an integer manually in CustomUserAdmin to avoid an error. To avoid a |