Code

Ticket #2550: ticket2550c.diff

File ticket2550c.diff, 4.3 KB (added by danielr, 2 years ago)

Update patch to apply against 1.4

Line 
1Index: docs/topics/auth.txt
2===================================================================
3--- docs/topics/auth.txt        (revision 17683)
4+++ docs/topics/auth.txt        (working copy)
5@@ -1786,6 +1786,12 @@
6     you need to force users to re-authenticate using different methods. A simple
7     way to do that is simply to execute ``Session.objects.all().delete()``.
8 
9+.. versionadded:: 1.4
10+
11+If a backend raises a :class:`~django.core.exceptions.PermissionDenied`
12+exception, authentication will immediately fail. Django won't check the backends that follow.
13+
14+
15 Writing an authentication backend
16 ---------------------------------
17 
18Index: django/contrib/auth/__init__.py
19===================================================================
20--- django/contrib/auth/__init__.py     (revision 17683)
21+++ django/contrib/auth/__init__.py     (working copy)
22@@ -1,5 +1,5 @@
23 from warnings import warn
24-from django.core.exceptions import ImproperlyConfigured
25+from django.core.exceptions import ImproperlyConfigured, PermissionDenied
26 from django.utils.importlib import import_module
27 from django.contrib.auth.signals import user_logged_in, user_logged_out
28 
29@@ -46,6 +46,9 @@
30         except TypeError:
31             # This backend doesn't accept these credentials as arguments. Try the next one.
32             continue
33+        except PermissionDenied:
34+            # This backend says to stop in our tracks - this user should not be allowed in at all.
35+            return None
36         if user is None:
37             continue
38         # Annotate the user object with the path of the backend.
39Index: django/contrib/auth/tests/auth_backends.py
40===================================================================
41--- django/contrib/auth/tests/auth_backends.py  (revision 17683)
42+++ django/contrib/auth/tests/auth_backends.py  (working copy)
43@@ -1,7 +1,8 @@
44 from django.conf import settings
45 from django.contrib.auth.models import User, Group, Permission, AnonymousUser
46 from django.contrib.contenttypes.models import ContentType
47-from django.core.exceptions import ImproperlyConfigured
48+from django.core.exceptions import ImproperlyConfigured, PermissionDenied
49+from django.contrib.auth import authenticate
50 from django.test import TestCase
51 
52 
53@@ -306,3 +307,37 @@
54         self.assertEqual(self.user1.has_module_perms("app1"), False)
55         self.assertEqual(self.user1.has_module_perms("app2"), False)
56 
57+class PermissionDeniedBackend(object):
58+    """
59+    Always raises PermissionDenied.
60+    """
61+    supports_object_permissions = True
62+    supports_anonymous_user = True
63+    supports_inactive_user = True
64+
65+    def authenticate(self, username=None, password=None):
66+        raise PermissionDenied
67+
68+
69+class PermissionDeniedBackendTest(TestCase):
70+    """
71+    Tests that other backends are not checked once a backend raises PermissionDenied
72+    """
73+    backend = 'django.contrib.auth.tests.auth_backends.PermissionDeniedBackend'
74+
75+    def setUp(self):
76+        self.curr_auth = settings.AUTHENTICATION_BACKENDS
77+        self.user1 = User.objects.create_user('test', 'test@example.com', 'test')
78+        self.user1.save()
79+
80+    def tearDown(self):
81+        settings.AUTHENTICATION_BACKENDS = self.curr_auth
82+
83+    def test_permission_denied(self):
84+        "user is not authenticated after a backend raises permission denied #2550"
85+        settings.AUTHENTICATION_BACKENDS = (self.backend,) + tuple(self.curr_auth)
86+        self.assertEqual(authenticate(username='test', password='test'), None)
87+
88+    def test_authenticates(self):
89+        settings.AUTHENTICATION_BACKENDS = tuple(self.curr_auth) + (self.backend,)
90+        self.assertEqual(authenticate(username='test', password='test'), self.user1)
91Index: django/contrib/auth/tests/__init__.py
92===================================================================
93--- django/contrib/auth/tests/__init__.py       (revision 17683)
94+++ django/contrib/auth/tests/__init__.py       (working copy)
95@@ -1,6 +1,6 @@
96 from django.contrib.auth.tests.auth_backends import (BackendTest,
97     RowlevelBackendTest, AnonymousUserBackendTest, NoBackendsTest,
98-    InActiveUserBackendTest, NoInActiveUserBackendTest)
99+    InActiveUserBackendTest, NoInActiveUserBackendTest, PermissionDeniedBackendTest)
100 from django.contrib.auth.tests.basic import BasicTestCase
101 from django.contrib.auth.tests.context_processors import AuthContextProcessorTests
102 from django.contrib.auth.tests.decorators import LoginRequiredTestCase