test_middleware.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. from django.conf import settings
  2. from django.contrib.auth import REDIRECT_FIELD_NAME
  3. from django.contrib.auth.middleware import (
  4. AuthenticationMiddleware,
  5. LoginRequiredMiddleware,
  6. )
  7. from django.contrib.auth.models import User
  8. from django.core.exceptions import ImproperlyConfigured
  9. from django.http import HttpRequest, HttpResponse
  10. from django.test import TestCase, modify_settings, override_settings
  11. from django.urls import reverse
  12. class TestAuthenticationMiddleware(TestCase):
  13. @classmethod
  14. def setUpTestData(cls):
  15. cls.user = User.objects.create_user(
  16. "test_user", "test@example.com", "test_password"
  17. )
  18. def setUp(self):
  19. self.middleware = AuthenticationMiddleware(lambda req: HttpResponse())
  20. self.client.force_login(self.user)
  21. self.request = HttpRequest()
  22. self.request.session = self.client.session
  23. def test_no_password_change_doesnt_invalidate_session(self):
  24. self.request.session = self.client.session
  25. self.middleware(self.request)
  26. self.assertIsNotNone(self.request.user)
  27. self.assertFalse(self.request.user.is_anonymous)
  28. def test_changed_password_invalidates_session(self):
  29. # After password change, user should be anonymous
  30. self.user.set_password("new_password")
  31. self.user.save()
  32. self.middleware(self.request)
  33. self.assertIsNotNone(self.request.user)
  34. self.assertTrue(self.request.user.is_anonymous)
  35. # session should be flushed
  36. self.assertIsNone(self.request.session.session_key)
  37. def test_no_session(self):
  38. msg = (
  39. "The Django authentication middleware requires session middleware "
  40. "to be installed. Edit your MIDDLEWARE setting to insert "
  41. "'django.contrib.sessions.middleware.SessionMiddleware' before "
  42. "'django.contrib.auth.middleware.AuthenticationMiddleware'."
  43. )
  44. with self.assertRaisesMessage(ImproperlyConfigured, msg):
  45. self.middleware(HttpRequest())
  46. async def test_auser(self):
  47. self.middleware(self.request)
  48. auser = await self.request.auser()
  49. self.assertEqual(auser, self.user)
  50. auser_second = await self.request.auser()
  51. self.assertIs(auser, auser_second)
  52. @override_settings(ROOT_URLCONF="auth_tests.urls")
  53. @modify_settings(
  54. MIDDLEWARE={"append": "django.contrib.auth.middleware.LoginRequiredMiddleware"}
  55. )
  56. class TestLoginRequiredMiddleware(TestCase):
  57. @classmethod
  58. def setUpTestData(cls):
  59. cls.user = User.objects.create_user(
  60. "test_user", "test@example.com", "test_password"
  61. )
  62. def setUp(self):
  63. self.middleware = LoginRequiredMiddleware(lambda req: HttpResponse())
  64. self.request = HttpRequest()
  65. def test_public_paths(self):
  66. paths = ["public_view", "public_function_view"]
  67. for path in paths:
  68. response = self.client.get(f"/{path}/")
  69. self.assertEqual(response.status_code, 200)
  70. def test_protected_paths(self):
  71. paths = ["protected_view", "protected_function_view"]
  72. for path in paths:
  73. response = self.client.get(f"/{path}/")
  74. self.assertRedirects(
  75. response,
  76. settings.LOGIN_URL + f"?next=/{path}/",
  77. fetch_redirect_response=False,
  78. )
  79. def test_login_required_paths(self):
  80. paths = ["login_required_cbv_view", "login_required_decorator_view"]
  81. for path in paths:
  82. response = self.client.get(f"/{path}/")
  83. self.assertRedirects(
  84. response,
  85. "/custom_login/" + f"?step=/{path}/",
  86. fetch_redirect_response=False,
  87. )
  88. def test_admin_path(self):
  89. admin_url = reverse("admin:index")
  90. response = self.client.get(admin_url)
  91. self.assertRedirects(
  92. response,
  93. reverse("admin:login") + f"?next={admin_url}",
  94. target_status_code=200,
  95. )
  96. def test_non_existent_path(self):
  97. response = self.client.get("/non_existent/")
  98. self.assertEqual(response.status_code, 404)
  99. def test_paths_with_logged_in_user(self):
  100. paths = [
  101. "public_view",
  102. "public_function_view",
  103. "protected_view",
  104. "protected_function_view",
  105. "login_required_cbv_view",
  106. "login_required_decorator_view",
  107. ]
  108. self.client.login(username="test_user", password="test_password")
  109. for path in paths:
  110. response = self.client.get(f"/{path}/")
  111. self.assertEqual(response.status_code, 200)
  112. def test_get_login_url_from_view_func(self):
  113. def view_func(request):
  114. return HttpResponse()
  115. view_func.login_url = "/custom_login/"
  116. login_url = self.middleware.get_login_url(view_func)
  117. self.assertEqual(login_url, "/custom_login/")
  118. @override_settings(LOGIN_URL="/settings_login/")
  119. def test_get_login_url_from_settings(self):
  120. login_url = self.middleware.get_login_url(lambda: None)
  121. self.assertEqual(login_url, "/settings_login/")
  122. @override_settings(LOGIN_URL=None)
  123. def test_get_login_url_no_login_url(self):
  124. with self.assertRaises(ImproperlyConfigured) as e:
  125. self.middleware.get_login_url(lambda: None)
  126. self.assertEqual(
  127. str(e.exception),
  128. "No login URL to redirect to. Define settings.LOGIN_URL or provide "
  129. "a login_url via the 'django.contrib.auth.decorators.login_required' "
  130. "decorator.",
  131. )
  132. def test_get_redirect_field_name_from_view_func(self):
  133. def view_func(request):
  134. return HttpResponse()
  135. view_func.redirect_field_name = "next_page"
  136. redirect_field_name = self.middleware.get_redirect_field_name(view_func)
  137. self.assertEqual(redirect_field_name, "next_page")
  138. @override_settings(
  139. MIDDLEWARE=[
  140. "django.contrib.sessions.middleware.SessionMiddleware",
  141. "django.contrib.auth.middleware.AuthenticationMiddleware",
  142. "auth_tests.test_checks.LoginRequiredMiddlewareSubclass",
  143. ],
  144. LOGIN_URL="/settings_login/",
  145. )
  146. def test_login_url_resolve_logic(self):
  147. paths = ["login_required_cbv_view", "login_required_decorator_view"]
  148. for path in paths:
  149. response = self.client.get(f"/{path}/")
  150. self.assertRedirects(
  151. response,
  152. "/custom_login/" + f"?step=/{path}/",
  153. fetch_redirect_response=False,
  154. )
  155. paths = ["protected_view", "protected_function_view"]
  156. for path in paths:
  157. response = self.client.get(f"/{path}/")
  158. self.assertRedirects(
  159. response,
  160. f"/settings_login/?redirect_to=/{path}/",
  161. fetch_redirect_response=False,
  162. )
  163. def test_get_redirect_field_name_default(self):
  164. redirect_field_name = self.middleware.get_redirect_field_name(lambda: None)
  165. self.assertEqual(redirect_field_name, REDIRECT_FIELD_NAME)