123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- from django.conf import settings
- from django.contrib.auth import REDIRECT_FIELD_NAME
- from django.contrib.auth.middleware import (
- AuthenticationMiddleware,
- LoginRequiredMiddleware,
- )
- from django.contrib.auth.models import User
- from django.core.exceptions import ImproperlyConfigured
- from django.http import HttpRequest, HttpResponse
- from django.test import TestCase, modify_settings, override_settings
- from django.urls import reverse
- class TestAuthenticationMiddleware(TestCase):
- @classmethod
- def setUpTestData(cls):
- cls.user = User.objects.create_user(
- "test_user", "test@example.com", "test_password"
- )
- def setUp(self):
- self.middleware = AuthenticationMiddleware(lambda req: HttpResponse())
- self.client.force_login(self.user)
- self.request = HttpRequest()
- self.request.session = self.client.session
- def test_no_password_change_doesnt_invalidate_session(self):
- self.request.session = self.client.session
- self.middleware(self.request)
- self.assertIsNotNone(self.request.user)
- self.assertFalse(self.request.user.is_anonymous)
- def test_changed_password_invalidates_session(self):
- # After password change, user should be anonymous
- self.user.set_password("new_password")
- self.user.save()
- self.middleware(self.request)
- self.assertIsNotNone(self.request.user)
- self.assertTrue(self.request.user.is_anonymous)
- # session should be flushed
- self.assertIsNone(self.request.session.session_key)
- def test_no_session(self):
- msg = (
- "The Django authentication middleware requires session middleware "
- "to be installed. Edit your MIDDLEWARE setting to insert "
- "'django.contrib.sessions.middleware.SessionMiddleware' before "
- "'django.contrib.auth.middleware.AuthenticationMiddleware'."
- )
- with self.assertRaisesMessage(ImproperlyConfigured, msg):
- self.middleware(HttpRequest())
- async def test_auser(self):
- self.middleware(self.request)
- auser = await self.request.auser()
- self.assertEqual(auser, self.user)
- auser_second = await self.request.auser()
- self.assertIs(auser, auser_second)
- @override_settings(ROOT_URLCONF="auth_tests.urls")
- @modify_settings(
- MIDDLEWARE={"append": "django.contrib.auth.middleware.LoginRequiredMiddleware"}
- )
- class TestLoginRequiredMiddleware(TestCase):
- @classmethod
- def setUpTestData(cls):
- cls.user = User.objects.create_user(
- "test_user", "test@example.com", "test_password"
- )
- def setUp(self):
- self.middleware = LoginRequiredMiddleware(lambda req: HttpResponse())
- self.request = HttpRequest()
- def test_public_paths(self):
- paths = ["public_view", "public_function_view"]
- for path in paths:
- response = self.client.get(f"/{path}/")
- self.assertEqual(response.status_code, 200)
- def test_protected_paths(self):
- paths = ["protected_view", "protected_function_view"]
- for path in paths:
- response = self.client.get(f"/{path}/")
- self.assertRedirects(
- response,
- settings.LOGIN_URL + f"?next=/{path}/",
- fetch_redirect_response=False,
- )
- def test_login_required_paths(self):
- paths = ["login_required_cbv_view", "login_required_decorator_view"]
- for path in paths:
- response = self.client.get(f"/{path}/")
- self.assertRedirects(
- response,
- "/custom_login/" + f"?step=/{path}/",
- fetch_redirect_response=False,
- )
- def test_admin_path(self):
- admin_url = reverse("admin:index")
- response = self.client.get(admin_url)
- self.assertRedirects(
- response,
- reverse("admin:login") + f"?next={admin_url}",
- target_status_code=200,
- )
- def test_non_existent_path(self):
- response = self.client.get("/non_existent/")
- self.assertEqual(response.status_code, 404)
- def test_paths_with_logged_in_user(self):
- paths = [
- "public_view",
- "public_function_view",
- "protected_view",
- "protected_function_view",
- "login_required_cbv_view",
- "login_required_decorator_view",
- ]
- self.client.login(username="test_user", password="test_password")
- for path in paths:
- response = self.client.get(f"/{path}/")
- self.assertEqual(response.status_code, 200)
- def test_get_login_url_from_view_func(self):
- def view_func(request):
- return HttpResponse()
- view_func.login_url = "/custom_login/"
- login_url = self.middleware.get_login_url(view_func)
- self.assertEqual(login_url, "/custom_login/")
- @override_settings(LOGIN_URL="/settings_login/")
- def test_get_login_url_from_settings(self):
- login_url = self.middleware.get_login_url(lambda: None)
- self.assertEqual(login_url, "/settings_login/")
- @override_settings(LOGIN_URL=None)
- def test_get_login_url_no_login_url(self):
- with self.assertRaises(ImproperlyConfigured) as e:
- self.middleware.get_login_url(lambda: None)
- self.assertEqual(
- str(e.exception),
- "No login URL to redirect to. Define settings.LOGIN_URL or provide "
- "a login_url via the 'django.contrib.auth.decorators.login_required' "
- "decorator.",
- )
- def test_get_redirect_field_name_from_view_func(self):
- def view_func(request):
- return HttpResponse()
- view_func.redirect_field_name = "next_page"
- redirect_field_name = self.middleware.get_redirect_field_name(view_func)
- self.assertEqual(redirect_field_name, "next_page")
- @override_settings(
- MIDDLEWARE=[
- "django.contrib.sessions.middleware.SessionMiddleware",
- "django.contrib.auth.middleware.AuthenticationMiddleware",
- "auth_tests.test_checks.LoginRequiredMiddlewareSubclass",
- ],
- LOGIN_URL="/settings_login/",
- )
- def test_login_url_resolve_logic(self):
- paths = ["login_required_cbv_view", "login_required_decorator_view"]
- for path in paths:
- response = self.client.get(f"/{path}/")
- self.assertRedirects(
- response,
- "/custom_login/" + f"?step=/{path}/",
- fetch_redirect_response=False,
- )
- paths = ["protected_view", "protected_function_view"]
- for path in paths:
- response = self.client.get(f"/{path}/")
- self.assertRedirects(
- response,
- f"/settings_login/?redirect_to=/{path}/",
- fetch_redirect_response=False,
- )
- def test_get_redirect_field_name_default(self):
- redirect_field_name = self.middleware.get_redirect_field_name(lambda: None)
- self.assertEqual(redirect_field_name, REDIRECT_FIELD_NAME)
|