Loading django/contrib/auth/__init__.py +6 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,12 @@ def load_backend(path): warn("Authentication backends without a `supports_object_permissions` attribute are deprecated. Please define it in %s." % cls, PendingDeprecationWarning) cls.supports_object_permissions = False try: getattr(cls, 'supports_anonymous_user') except AttributeError: warn("Authentication backends without a `supports_anonymous_user` attribute are deprecated. Please define it in %s." % cls, PendingDeprecationWarning) cls.supports_anonymous_user = False return cls() def get_backends(): Loading django/contrib/auth/backends.py +3 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ class ModelBackend(object): Authenticates against django.contrib.auth.models.User. """ supports_object_permissions = False supports_anonymous_user = True # TODO: Model, login attribute name and password attribute name should be # configurable. Loading Loading @@ -58,6 +59,8 @@ class ModelBackend(object): return user_obj._group_perm_cache def get_all_permissions(self, user_obj): if user_obj.is_anonymous(): return set() if not hasattr(user_obj, '_perm_cache'): user_obj._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()]) user_obj._perm_cache.update(self.get_group_permissions(user_obj)) Loading django/contrib/auth/models.py +58 −29 Original line number Diff line number Diff line Loading @@ -128,6 +128,49 @@ class UserManager(models.Manager): from random import choice return ''.join([choice(allowed_chars) for i in range(length)]) # A few helper functions for common logic between User and AnonymousUser. def _user_get_all_permissions(user, obj): permissions = set() anon = user.is_anonymous() for backend in auth.get_backends(): if not anon or backend.supports_anonymous_user: if hasattr(backend, "get_all_permissions"): if obj is not None: if backend.supports_object_permissions: permissions.update( backend.get_all_permissions(user, obj) ) else: permissions.update(backend.get_all_permissions(user)) return permissions def _user_has_perm(user, perm, obj): anon = user.is_anonymous() for backend in auth.get_backends(): if not anon or backend.supports_anonymous_user: if hasattr(backend, "has_perm"): if obj is not None: if (backend.supports_object_permissions and backend.has_perm(user, perm, obj)): return True else: if backend.has_perm(user, perm): return True return False def _user_has_module_perms(user, app_label): anon = user.is_anonymous() for backend in auth.get_backends(): if not anon or backend.supports_anonymous_user: if hasattr(backend, "has_module_perms"): if backend.has_module_perms(user, app_label): return True return False class User(models.Model): """ Users within the Django authentication system are represented by this model. Loading Loading @@ -228,17 +271,7 @@ class User(models.Model): return permissions def get_all_permissions(self, obj=None): permissions = set() for backend in auth.get_backends(): if hasattr(backend, "get_all_permissions"): if obj is not None: if backend.supports_object_permissions: permissions.update( backend.get_all_permissions(self, obj) ) else: permissions.update(backend.get_all_permissions(self)) return permissions return _user_get_all_permissions(self, obj) def has_perm(self, perm, obj=None): """ Loading @@ -257,16 +290,7 @@ class User(models.Model): return True # Otherwise we need to check the backends. for backend in auth.get_backends(): if hasattr(backend, "has_perm"): if obj is not None: if (backend.supports_object_permissions and backend.has_perm(self, perm, obj)): return True else: if backend.has_perm(self, perm): return True return False return _user_has_perm(self, perm, obj) def has_perms(self, perm_list, obj=None): """ Loading @@ -290,11 +314,7 @@ class User(models.Model): if self.is_superuser: return True for backend in auth.get_backends(): if hasattr(backend, "has_module_perms"): if backend.has_module_perms(self, app_label): return True return False return _user_has_module_perms(self, app_label) def get_and_delete_messages(self): messages = [] Loading Loading @@ -396,14 +416,23 @@ class AnonymousUser(object): return self._user_permissions user_permissions = property(_get_user_permissions) def get_group_permissions(self, obj=None): return set() def get_all_permissions(self, obj=None): return _user_get_all_permissions(self, obj=obj) def has_perm(self, perm, obj=None): return False return _user_has_perm(self, perm, obj=obj) def has_perms(self, perm_list, obj=None): for perm in perm_list: if not self.has_perm(perm, obj): return False return True def has_module_perms(self, module): return False return _user_has_module_perms(self, module) def get_and_delete_messages(self): return [] Loading django/contrib/auth/tests/__init__.py +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ from django.contrib.auth.tests.views \ from django.contrib.auth.tests.forms import FORM_TESTS from django.contrib.auth.tests.remote_user \ import RemoteUserTest, RemoteUserNoCreateTest, RemoteUserCustomTest from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest, AnonymousUserBackendTest, NoAnonymousUserBackendTest from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS # The password for the fixture data users is 'password' Loading django/contrib/auth/tests/auth_backends.py +86 −8 Original line number Diff line number Diff line Loading @@ -88,8 +88,6 @@ class BackendTest(TestCase): self.assertEqual(user.get_all_permissions(), set(['auth.test'])) class TestObj(object): pass Loading @@ -97,6 +95,9 @@ class TestObj(object): class SimpleRowlevelBackend(object): supports_object_permissions = True # This class also supports tests for anonymous user permissions, # via subclasses which just set the 'supports_anonymous_user' attribute. def has_perm(self, user, perm, obj=None): if not obj: return # We only support row level perms Loading @@ -104,10 +105,14 @@ class SimpleRowlevelBackend(object): if isinstance(obj, TestObj): if user.username == 'test2': return True elif isinstance(user, AnonymousUser) and perm == 'anon': elif user.is_anonymous() and perm == 'anon': # not reached due to supports_anonymous_user = False return True return False def has_module_perms(self, user, app_label): return app_label == "app1" def get_all_permissions(self, user, obj=None): if not obj: return [] # We only support row level perms Loading @@ -115,6 +120,8 @@ class SimpleRowlevelBackend(object): if not isinstance(obj, TestObj): return ['none'] if user.is_anonymous(): return ['anon'] if user.username == 'test2': return ['simple', 'advanced'] else: Loading @@ -134,7 +141,9 @@ class SimpleRowlevelBackend(object): class RowlevelBackendTest(TestCase): """ Tests for auth backend that supports object level permissions """ backend = 'django.contrib.auth.tests.auth_backends.SimpleRowlevelBackend' def setUp(self): Loading @@ -142,8 +151,7 @@ class RowlevelBackendTest(TestCase): settings.AUTHENTICATION_BACKENDS = self.curr_auth + (self.backend,) self.user1 = User.objects.create_user('test', 'test@example.com', 'test') self.user2 = User.objects.create_user('test2', 'test2@example.com', 'test') self.user3 = AnonymousUser() self.user4 = User.objects.create_user('test4', 'test4@example.com', 'test') self.user3 = User.objects.create_user('test3', 'test3@example.com', 'test') def tearDown(self): settings.AUTHENTICATION_BACKENDS = self.curr_auth Loading @@ -165,5 +173,75 @@ class RowlevelBackendTest(TestCase): def test_get_group_permissions(self): content_type=ContentType.objects.get_for_model(Group) group = Group.objects.create(name='test_group') self.user4.groups.add(group) self.assertEqual(self.user4.get_group_permissions(TestObj()), set(['group_perm'])) self.user3.groups.add(group) self.assertEqual(self.user3.get_group_permissions(TestObj()), set(['group_perm'])) class AnonymousUserBackend(SimpleRowlevelBackend): supports_anonymous_user = True class NoAnonymousUserBackend(SimpleRowlevelBackend): supports_anonymous_user = False class AnonymousUserBackendTest(TestCase): """ Tests for AnonymousUser delegating to backend if it has 'supports_anonymous_user' = True """ backend = 'django.contrib.auth.tests.auth_backends.AnonymousUserBackend' def setUp(self): self.curr_auth = settings.AUTHENTICATION_BACKENDS settings.AUTHENTICATION_BACKENDS = (self.backend,) self.user1 = AnonymousUser() def tearDown(self): settings.AUTHENTICATION_BACKENDS = self.curr_auth def test_has_perm(self): self.assertEqual(self.user1.has_perm('perm', TestObj()), False) self.assertEqual(self.user1.has_perm('anon', TestObj()), True) def test_has_perms(self): self.assertEqual(self.user1.has_perms(['anon'], TestObj()), True) self.assertEqual(self.user1.has_perms(['anon', 'perm'], TestObj()), False) def test_has_module_perms(self): self.assertEqual(self.user1.has_module_perms("app1"), True) self.assertEqual(self.user1.has_module_perms("app2"), False) def test_get_all_permissions(self): self.assertEqual(self.user1.get_all_permissions(TestObj()), set(['anon'])) class NoAnonymousUserBackendTest(TestCase): """ Tests that AnonymousUser does not delegate to backend if it has 'supports_anonymous_user' = False """ backend = 'django.contrib.auth.tests.auth_backends.NoAnonymousUserBackend' def setUp(self): self.curr_auth = settings.AUTHENTICATION_BACKENDS settings.AUTHENTICATION_BACKENDS = self.curr_auth + (self.backend,) self.user1 = AnonymousUser() def tearDown(self): settings.AUTHENTICATION_BACKENDS = self.curr_auth def test_has_perm(self): self.assertEqual(self.user1.has_perm('perm', TestObj()), False) self.assertEqual(self.user1.has_perm('anon', TestObj()), False) def test_has_perms(self): self.assertEqual(self.user1.has_perms(['anon'], TestObj()), False) def test_has_module_perms(self): self.assertEqual(self.user1.has_module_perms("app1"), False) self.assertEqual(self.user1.has_module_perms("app2"), False) def test_get_all_permissions(self): self.assertEqual(self.user1.get_all_permissions(TestObj()), set()) Loading
django/contrib/auth/__init__.py +6 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,12 @@ def load_backend(path): warn("Authentication backends without a `supports_object_permissions` attribute are deprecated. Please define it in %s." % cls, PendingDeprecationWarning) cls.supports_object_permissions = False try: getattr(cls, 'supports_anonymous_user') except AttributeError: warn("Authentication backends without a `supports_anonymous_user` attribute are deprecated. Please define it in %s." % cls, PendingDeprecationWarning) cls.supports_anonymous_user = False return cls() def get_backends(): Loading
django/contrib/auth/backends.py +3 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ class ModelBackend(object): Authenticates against django.contrib.auth.models.User. """ supports_object_permissions = False supports_anonymous_user = True # TODO: Model, login attribute name and password attribute name should be # configurable. Loading Loading @@ -58,6 +59,8 @@ class ModelBackend(object): return user_obj._group_perm_cache def get_all_permissions(self, user_obj): if user_obj.is_anonymous(): return set() if not hasattr(user_obj, '_perm_cache'): user_obj._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()]) user_obj._perm_cache.update(self.get_group_permissions(user_obj)) Loading
django/contrib/auth/models.py +58 −29 Original line number Diff line number Diff line Loading @@ -128,6 +128,49 @@ class UserManager(models.Manager): from random import choice return ''.join([choice(allowed_chars) for i in range(length)]) # A few helper functions for common logic between User and AnonymousUser. def _user_get_all_permissions(user, obj): permissions = set() anon = user.is_anonymous() for backend in auth.get_backends(): if not anon or backend.supports_anonymous_user: if hasattr(backend, "get_all_permissions"): if obj is not None: if backend.supports_object_permissions: permissions.update( backend.get_all_permissions(user, obj) ) else: permissions.update(backend.get_all_permissions(user)) return permissions def _user_has_perm(user, perm, obj): anon = user.is_anonymous() for backend in auth.get_backends(): if not anon or backend.supports_anonymous_user: if hasattr(backend, "has_perm"): if obj is not None: if (backend.supports_object_permissions and backend.has_perm(user, perm, obj)): return True else: if backend.has_perm(user, perm): return True return False def _user_has_module_perms(user, app_label): anon = user.is_anonymous() for backend in auth.get_backends(): if not anon or backend.supports_anonymous_user: if hasattr(backend, "has_module_perms"): if backend.has_module_perms(user, app_label): return True return False class User(models.Model): """ Users within the Django authentication system are represented by this model. Loading Loading @@ -228,17 +271,7 @@ class User(models.Model): return permissions def get_all_permissions(self, obj=None): permissions = set() for backend in auth.get_backends(): if hasattr(backend, "get_all_permissions"): if obj is not None: if backend.supports_object_permissions: permissions.update( backend.get_all_permissions(self, obj) ) else: permissions.update(backend.get_all_permissions(self)) return permissions return _user_get_all_permissions(self, obj) def has_perm(self, perm, obj=None): """ Loading @@ -257,16 +290,7 @@ class User(models.Model): return True # Otherwise we need to check the backends. for backend in auth.get_backends(): if hasattr(backend, "has_perm"): if obj is not None: if (backend.supports_object_permissions and backend.has_perm(self, perm, obj)): return True else: if backend.has_perm(self, perm): return True return False return _user_has_perm(self, perm, obj) def has_perms(self, perm_list, obj=None): """ Loading @@ -290,11 +314,7 @@ class User(models.Model): if self.is_superuser: return True for backend in auth.get_backends(): if hasattr(backend, "has_module_perms"): if backend.has_module_perms(self, app_label): return True return False return _user_has_module_perms(self, app_label) def get_and_delete_messages(self): messages = [] Loading Loading @@ -396,14 +416,23 @@ class AnonymousUser(object): return self._user_permissions user_permissions = property(_get_user_permissions) def get_group_permissions(self, obj=None): return set() def get_all_permissions(self, obj=None): return _user_get_all_permissions(self, obj=obj) def has_perm(self, perm, obj=None): return False return _user_has_perm(self, perm, obj=obj) def has_perms(self, perm_list, obj=None): for perm in perm_list: if not self.has_perm(perm, obj): return False return True def has_module_perms(self, module): return False return _user_has_module_perms(self, module) def get_and_delete_messages(self): return [] Loading
django/contrib/auth/tests/__init__.py +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ from django.contrib.auth.tests.views \ from django.contrib.auth.tests.forms import FORM_TESTS from django.contrib.auth.tests.remote_user \ import RemoteUserTest, RemoteUserNoCreateTest, RemoteUserCustomTest from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest, AnonymousUserBackendTest, NoAnonymousUserBackendTest from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS # The password for the fixture data users is 'password' Loading
django/contrib/auth/tests/auth_backends.py +86 −8 Original line number Diff line number Diff line Loading @@ -88,8 +88,6 @@ class BackendTest(TestCase): self.assertEqual(user.get_all_permissions(), set(['auth.test'])) class TestObj(object): pass Loading @@ -97,6 +95,9 @@ class TestObj(object): class SimpleRowlevelBackend(object): supports_object_permissions = True # This class also supports tests for anonymous user permissions, # via subclasses which just set the 'supports_anonymous_user' attribute. def has_perm(self, user, perm, obj=None): if not obj: return # We only support row level perms Loading @@ -104,10 +105,14 @@ class SimpleRowlevelBackend(object): if isinstance(obj, TestObj): if user.username == 'test2': return True elif isinstance(user, AnonymousUser) and perm == 'anon': elif user.is_anonymous() and perm == 'anon': # not reached due to supports_anonymous_user = False return True return False def has_module_perms(self, user, app_label): return app_label == "app1" def get_all_permissions(self, user, obj=None): if not obj: return [] # We only support row level perms Loading @@ -115,6 +120,8 @@ class SimpleRowlevelBackend(object): if not isinstance(obj, TestObj): return ['none'] if user.is_anonymous(): return ['anon'] if user.username == 'test2': return ['simple', 'advanced'] else: Loading @@ -134,7 +141,9 @@ class SimpleRowlevelBackend(object): class RowlevelBackendTest(TestCase): """ Tests for auth backend that supports object level permissions """ backend = 'django.contrib.auth.tests.auth_backends.SimpleRowlevelBackend' def setUp(self): Loading @@ -142,8 +151,7 @@ class RowlevelBackendTest(TestCase): settings.AUTHENTICATION_BACKENDS = self.curr_auth + (self.backend,) self.user1 = User.objects.create_user('test', 'test@example.com', 'test') self.user2 = User.objects.create_user('test2', 'test2@example.com', 'test') self.user3 = AnonymousUser() self.user4 = User.objects.create_user('test4', 'test4@example.com', 'test') self.user3 = User.objects.create_user('test3', 'test3@example.com', 'test') def tearDown(self): settings.AUTHENTICATION_BACKENDS = self.curr_auth Loading @@ -165,5 +173,75 @@ class RowlevelBackendTest(TestCase): def test_get_group_permissions(self): content_type=ContentType.objects.get_for_model(Group) group = Group.objects.create(name='test_group') self.user4.groups.add(group) self.assertEqual(self.user4.get_group_permissions(TestObj()), set(['group_perm'])) self.user3.groups.add(group) self.assertEqual(self.user3.get_group_permissions(TestObj()), set(['group_perm'])) class AnonymousUserBackend(SimpleRowlevelBackend): supports_anonymous_user = True class NoAnonymousUserBackend(SimpleRowlevelBackend): supports_anonymous_user = False class AnonymousUserBackendTest(TestCase): """ Tests for AnonymousUser delegating to backend if it has 'supports_anonymous_user' = True """ backend = 'django.contrib.auth.tests.auth_backends.AnonymousUserBackend' def setUp(self): self.curr_auth = settings.AUTHENTICATION_BACKENDS settings.AUTHENTICATION_BACKENDS = (self.backend,) self.user1 = AnonymousUser() def tearDown(self): settings.AUTHENTICATION_BACKENDS = self.curr_auth def test_has_perm(self): self.assertEqual(self.user1.has_perm('perm', TestObj()), False) self.assertEqual(self.user1.has_perm('anon', TestObj()), True) def test_has_perms(self): self.assertEqual(self.user1.has_perms(['anon'], TestObj()), True) self.assertEqual(self.user1.has_perms(['anon', 'perm'], TestObj()), False) def test_has_module_perms(self): self.assertEqual(self.user1.has_module_perms("app1"), True) self.assertEqual(self.user1.has_module_perms("app2"), False) def test_get_all_permissions(self): self.assertEqual(self.user1.get_all_permissions(TestObj()), set(['anon'])) class NoAnonymousUserBackendTest(TestCase): """ Tests that AnonymousUser does not delegate to backend if it has 'supports_anonymous_user' = False """ backend = 'django.contrib.auth.tests.auth_backends.NoAnonymousUserBackend' def setUp(self): self.curr_auth = settings.AUTHENTICATION_BACKENDS settings.AUTHENTICATION_BACKENDS = self.curr_auth + (self.backend,) self.user1 = AnonymousUser() def tearDown(self): settings.AUTHENTICATION_BACKENDS = self.curr_auth def test_has_perm(self): self.assertEqual(self.user1.has_perm('perm', TestObj()), False) self.assertEqual(self.user1.has_perm('anon', TestObj()), False) def test_has_perms(self): self.assertEqual(self.user1.has_perms(['anon'], TestObj()), False) def test_has_module_perms(self): self.assertEqual(self.user1.has_module_perms("app1"), False) self.assertEqual(self.user1.has_module_perms("app2"), False) def test_get_all_permissions(self): self.assertEqual(self.user1.get_all_permissions(TestObj()), set())