1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
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)
|