summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Verheul <dylan@zostera.nl>2017-07-12 12:07:06 +0200
committerTim Graham <timograham@gmail.com>2018-02-16 13:58:55 -0500
commit9b1125bfc7e2dc747128e6e7e8a2259ff1a7d39f (patch)
tree4044872d7364729559a87fb1e3f508fc02586d07
parente307ff29d28737d5a764ce2fa7db010231d6fc8e (diff)
Fixed #28379 -- Made AccessMixin raise Permissiondenied for authenticated users.
-rw-r--r--django/contrib/auth/mixins.py2
-rw-r--r--docs/topics/auth/default.txt18
-rw-r--r--tests/auth_tests/test_mixins.py19
3 files changed, 34 insertions, 5 deletions
diff --git a/django/contrib/auth/mixins.py b/django/contrib/auth/mixins.py
index a06e04dadd..362a734f96 100644
--- a/django/contrib/auth/mixins.py
+++ b/django/contrib/auth/mixins.py
@@ -39,7 +39,7 @@ class AccessMixin:
return self.redirect_field_name
def handle_no_permission(self):
- if self.raise_exception:
+ if self.raise_exception or self.request.user.is_authenticated:
raise PermissionDenied(self.get_permission_denied_message())
return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt
index a118e56543..3d9317f8f6 100644
--- a/docs/topics/auth/default.txt
+++ b/docs/topics/auth/default.txt
@@ -757,8 +757,17 @@ Redirecting unauthorized requests in class-based views
------------------------------------------------------
To ease the handling of access restrictions in :doc:`class-based views
-</ref/class-based-views/index>`, the ``AccessMixin`` can be used to redirect a
-user to the login page or issue an HTTP 403 Forbidden response.
+</ref/class-based-views/index>`, the ``AccessMixin`` can be used to configure
+the behavior of a view when access is denied. Authenticated users are denied
+access with an HTTP 403 Forbidden response. Anonymous users are redirected to
+the login page or shown an HTTP 403 Forbidden response, depending on the
+:attr:`~django.contrib.auth.mixins.AccessMixin.raise_exception` attribute.
+
+.. versionchanged:: 2.1
+
+ In older versions, authenticated users who lacked permissions were
+ redirected to the login page (which resulted in a loop) instead of
+ receiving an HTTP 403 Forbidden response.
.. class:: AccessMixin
@@ -781,8 +790,9 @@ user to the login page or issue an HTTP 403 Forbidden response.
.. attribute:: raise_exception
If this attribute is set to ``True``, a
- :class:`~django.core.exceptions.PermissionDenied` exception will be
- raised instead of the redirect. Defaults to ``False``.
+ :class:`~django.core.exceptions.PermissionDenied` exception is raised
+ when the conditions are not met. When ``False`` (the default),
+ anonymous users are redirected to the login page.
.. method:: get_login_url()
diff --git a/tests/auth_tests/test_mixins.py b/tests/auth_tests/test_mixins.py
index 70e8f27675..04cedcd9cf 100644
--- a/tests/auth_tests/test_mixins.py
+++ b/tests/auth_tests/test_mixins.py
@@ -80,6 +80,20 @@ class AccessMixinTests(TestCase):
with self.assertRaises(PermissionDenied):
view(request)
+ def test_access_mixin_permission_denied_response(self):
+ user = models.User.objects.create(username='joe', password='qwerty')
+ # Authenticated users receive PermissionDenied.
+ request = self.factory.get('/rand')
+ request.user = user
+ view = AlwaysFalseView.as_view()
+ with self.assertRaises(PermissionDenied):
+ view(request)
+ # Anonymous users are redirected to the login page.
+ request.user = AnonymousUser()
+ response = view(request)
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(response.url, '/accounts/login/?next=/rand')
+
@mock.patch.object(models.User, 'is_authenticated', False)
def test_stacked_mixins_not_logged_in(self):
user = models.User.objects.create(username='joe', password='qwerty')
@@ -241,8 +255,13 @@ class PermissionsRequiredMixinTests(TestCase):
'auth_tests.add_customuser', 'auth_tests.change_customuser', 'nonexistent-permission',
]
+ # Authenticated users receive PermissionDenied.
request = self.factory.get('/rand')
request.user = self.user
+ with self.assertRaises(PermissionDenied):
+ AView.as_view()(request)
+ # Anonymous users are redirected to the login page.
+ request.user = AnonymousUser()
resp = AView.as_view()(request)
self.assertEqual(resp.status_code, 302)