diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index 3495e16..dd816ce 100644
a
|
b
|
|
1 | | from warnings import warn |
2 | 1 | from django.core.exceptions import ImproperlyConfigured |
3 | 2 | from django.utils.importlib import import_module |
4 | 3 | from django.contrib.auth.signals import user_logged_in, user_logged_out |
… |
… |
def load_backend(path):
|
20 | 19 | cls = getattr(mod, attr) |
21 | 20 | except AttributeError: |
22 | 21 | raise ImproperlyConfigured('Module "%s" does not define a "%s" authentication backend' % (module, attr)) |
23 | | |
24 | | if not hasattr(cls, 'supports_inactive_user'): |
25 | | warn("Authentication backends without a `supports_inactive_user` attribute are deprecated. Please define it in %s." % cls, |
26 | | DeprecationWarning) |
27 | | cls.supports_inactive_user = False |
28 | 22 | return cls() |
29 | 23 | |
30 | 24 | def get_backends(): |
diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
index 56cdb42..04fbef4 100644
a
|
b
|
class ModelBackend(object):
|
5 | 5 | """ |
6 | 6 | Authenticates against django.contrib.auth.models.User. |
7 | 7 | """ |
8 | | supports_inactive_user = True |
9 | 8 | |
10 | 9 | # TODO: Model, login attribute name and password attribute name should be |
11 | 10 | # configurable. |
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
index 4e15849..042420a 100644
a
|
b
|
def _user_has_perm(user, perm, obj):
|
200 | 200 | anon = user.is_anonymous() |
201 | 201 | active = user.is_active |
202 | 202 | for backend in auth.get_backends(): |
203 | | if anon or active or backend.supports_inactive_user: |
204 | | if hasattr(backend, "has_perm"): |
205 | | if obj is not None: |
206 | | if backend.has_perm(user, perm, obj): |
207 | | return True |
208 | | else: |
209 | | if backend.has_perm(user, perm): |
210 | | return True |
| 203 | if hasattr(backend, "has_perm"): |
| 204 | if obj is not None: |
| 205 | if backend.has_perm(user, perm, obj): |
| 206 | return True |
| 207 | else: |
| 208 | if backend.has_perm(user, perm): |
| 209 | return True |
211 | 210 | return False |
212 | 211 | |
213 | 212 | |
… |
… |
def _user_has_module_perms(user, app_label):
|
215 | 214 | anon = user.is_anonymous() |
216 | 215 | active = user.is_active |
217 | 216 | for backend in auth.get_backends(): |
218 | | if anon or active or backend.supports_inactive_user: |
219 | | if hasattr(backend, "has_module_perms"): |
220 | | if backend.has_module_perms(user, app_label): |
221 | | return True |
| 217 | if hasattr(backend, "has_module_perms"): |
| 218 | if backend.has_module_perms(user, app_label): |
| 219 | return True |
222 | 220 | return False |
223 | 221 | |
224 | 222 | |
diff --git a/django/contrib/auth/tests/__init__.py b/django/contrib/auth/tests/__init__.py
index cc61977..16eaa5c 100644
a
|
b
|
|
1 | 1 | from django.contrib.auth.tests.auth_backends import (BackendTest, |
2 | 2 | RowlevelBackendTest, AnonymousUserBackendTest, NoBackendsTest, |
3 | | InActiveUserBackendTest, NoInActiveUserBackendTest) |
| 3 | InActiveUserBackendTest) |
4 | 4 | from django.contrib.auth.tests.basic import BasicTestCase |
5 | 5 | from django.contrib.auth.tests.context_processors import AuthContextProcessorTests |
6 | 6 | from django.contrib.auth.tests.decorators import LoginRequiredTestCase |
diff --git a/django/contrib/auth/tests/auth_backends.py b/django/contrib/auth/tests/auth_backends.py
index 0337ef1..106af24 100644
a
|
b
|
class TestObj(object):
|
103 | 103 | |
104 | 104 | |
105 | 105 | class SimpleRowlevelBackend(object): |
106 | | supports_inactive_user = False |
107 | | |
108 | | # This class also supports tests for anonymous user permissions, and |
109 | | # inactive user permissions via subclasses which just set the |
110 | | # 'supports_anonymous_user' or 'supports_inactive_user' attribute. |
111 | | |
112 | 106 | def has_perm(self, user, perm, obj=None): |
113 | 107 | if not obj: |
114 | 108 | return # We only support row level perms |
… |
… |
class RowlevelBackendTest(TestCase):
|
195 | 189 | self.assertEqual(self.user3.get_group_permissions(TestObj()), set(['group_perm'])) |
196 | 190 | |
197 | 191 | |
198 | | class AnonymousUserBackend(SimpleRowlevelBackend): |
199 | | supports_inactive_user = False |
200 | | |
201 | | |
202 | 192 | class AnonymousUserBackendTest(TestCase): |
203 | 193 | """ |
204 | 194 | Tests for AnonymousUser delegating to backend. |
205 | 195 | """ |
206 | 196 | |
207 | | backend = 'django.contrib.auth.tests.auth_backends.AnonymousUserBackend' |
| 197 | backend = 'django.contrib.auth.tests.auth_backends.SimpleRowlevelBackend' |
208 | 198 | |
209 | 199 | def setUp(self): |
210 | 200 | self.curr_auth = settings.AUTHENTICATION_BACKENDS |
… |
… |
class AnonymousUserBackendTest(TestCase):
|
231 | 221 | |
232 | 222 | |
233 | 223 | |
234 | | |
235 | 224 | class NoBackendsTest(TestCase): |
236 | 225 | """ |
237 | 226 | Tests that an appropriate error is raised if no auth backends are provided. |
… |
… |
class NoBackendsTest(TestCase):
|
248 | 237 | self.assertRaises(ImproperlyConfigured, self.user.has_perm, ('perm', TestObj(),)) |
249 | 238 | |
250 | 239 | |
251 | | class InActiveUserBackend(SimpleRowlevelBackend): |
252 | | supports_inactive_user = True |
253 | | |
254 | | |
255 | | class NoInActiveUserBackend(SimpleRowlevelBackend): |
256 | | supports_inactive_user = False |
257 | | |
258 | | |
259 | 240 | class InActiveUserBackendTest(TestCase): |
260 | 241 | """ |
261 | | Tests for a inactive user delegating to backend if it has 'supports_inactive_user' = True |
| 242 | Tests for a inactive user |
262 | 243 | """ |
263 | | |
264 | | backend = 'django.contrib.auth.tests.auth_backends.InActiveUserBackend' |
| 244 | backend = 'django.contrib.auth.tests.auth_backends.SimpleRowlevelBackend' |
265 | 245 | |
266 | 246 | def setUp(self): |
267 | 247 | self.curr_auth = settings.AUTHENTICATION_BACKENDS |
… |
… |
class InActiveUserBackendTest(TestCase):
|
280 | 260 | def test_has_module_perms(self): |
281 | 261 | self.assertEqual(self.user1.has_module_perms("app1"), False) |
282 | 262 | self.assertEqual(self.user1.has_module_perms("app2"), False) |
283 | | |
284 | | |
285 | | class NoInActiveUserBackendTest(TestCase): |
286 | | """ |
287 | | Tests that an inactive user does not delegate to backend if it has 'supports_inactive_user' = False |
288 | | """ |
289 | | backend = 'django.contrib.auth.tests.auth_backends.NoInActiveUserBackend' |
290 | | |
291 | | def setUp(self): |
292 | | self.curr_auth = settings.AUTHENTICATION_BACKENDS |
293 | | settings.AUTHENTICATION_BACKENDS = tuple(self.curr_auth) + (self.backend,) |
294 | | self.user1 = User.objects.create_user('test', 'test@example.com', 'test') |
295 | | self.user1.is_active = False |
296 | | self.user1.save() |
297 | | |
298 | | def tearDown(self): |
299 | | settings.AUTHENTICATION_BACKENDS = self.curr_auth |
300 | | |
301 | | def test_has_perm(self): |
302 | | self.assertEqual(self.user1.has_perm('perm', TestObj()), False) |
303 | | self.assertEqual(self.user1.has_perm('inactive', TestObj()), False) |
304 | | |
305 | | def test_has_module_perms(self): |
306 | | self.assertEqual(self.user1.has_module_perms("app1"), False) |
307 | | self.assertEqual(self.user1.has_module_perms("app2"), False) |
308 | | |
diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt
index 12adda8..69e3b7d 100644
a
|
b
|
object the first time a user authenticates::
|
1838 | 1838 | ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de' |
1839 | 1839 | """ |
1840 | 1840 | |
1841 | | supports_inactive_user = False |
1842 | | |
1843 | 1841 | def authenticate(self, username=None, password=None): |
1844 | 1842 | login_valid = (settings.ADMIN_LOGIN == username) |
1845 | 1843 | pwd_valid = check_password(password, settings.ADMIN_PASSWORD) |
… |
… |
The support for anonymous users in the permission system allows for
|
1938 | 1936 | anonymous users to have permissions to do something while inactive |
1939 | 1937 | authenticated users do not. |
1940 | 1938 | |
1941 | | To enable this on your own backend, you must set the class attribute |
1942 | | ``supports_inactive_user`` to ``True``. |
1943 | | |
1944 | | A nonexisting ``supports_inactive_user`` attribute will raise a |
1945 | | ``PendingDeprecationWarning`` if used in Django 1.3. In Django 1.4, this |
1946 | | warning will be updated to a ``DeprecationWarning`` which will be displayed |
1947 | | loudly. Additionally ``supports_inactive_user`` will be set to ``False``. |
1948 | | Django 1.5 will assume that every backend supports inactive users being |
1949 | | passed to the authorization methods. |
1950 | | |
1951 | 1939 | |
1952 | 1940 | Handling object permissions |
1953 | 1941 | --------------------------- |