diff options
Diffstat (limited to 'tests/auth_tests/test_models.py')
| -rw-r--r-- | tests/auth_tests/test_models.py | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/tests/auth_tests/test_models.py b/tests/auth_tests/test_models.py index a3502a224f..c60b66c993 100644 --- a/tests/auth_tests/test_models.py +++ b/tests/auth_tests/test_models.py @@ -2,6 +2,7 @@ from unittest import mock from django.conf.global_settings import PASSWORD_HASHERS from django.contrib.auth import get_user_model +from django.contrib.auth.backends import ModelBackend from django.contrib.auth.base_user import AbstractBaseUser from django.contrib.auth.hashers import get_hasher from django.contrib.auth.models import ( @@ -261,6 +262,142 @@ class AbstractUserTestCase(TestCase): hasher.iterations = old_iterations +class CustomModelBackend(ModelBackend): + def with_perm(self, perm, is_active=True, include_superusers=True, backend=None, obj=None): + if obj is not None and obj.username == 'charliebrown': + return User.objects.filter(pk=obj.pk) + return User.objects.filter(username__startswith='charlie') + + +class UserWithPermTestCase(TestCase): + + @classmethod + def setUpTestData(cls): + content_type = ContentType.objects.get_for_model(Group) + cls.permission = Permission.objects.create( + name='test', content_type=content_type, codename='test', + ) + # User with permission. + cls.user1 = User.objects.create_user('user 1', 'foo@example.com') + cls.user1.user_permissions.add(cls.permission) + # User with group permission. + group1 = Group.objects.create(name='group 1') + group1.permissions.add(cls.permission) + group2 = Group.objects.create(name='group 2') + group2.permissions.add(cls.permission) + cls.user2 = User.objects.create_user('user 2', 'bar@example.com') + cls.user2.groups.add(group1, group2) + # Users without permissions. + cls.user_charlie = User.objects.create_user('charlie', 'charlie@example.com') + cls.user_charlie_b = User.objects.create_user('charliebrown', 'charlie@brown.com') + # Superuser. + cls.superuser = User.objects.create_superuser( + 'superuser', 'superuser@example.com', 'superpassword', + ) + # Inactive user with permission. + cls.inactive_user = User.objects.create_user( + 'inactive_user', 'baz@example.com', is_active=False, + ) + cls.inactive_user.user_permissions.add(cls.permission) + + def test_invalid_permission_name(self): + msg = 'Permission name should be in the form app_label.permission_codename.' + for perm in ('nodots', 'too.many.dots', '...', ''): + with self.subTest(perm), self.assertRaisesMessage(ValueError, msg): + User.objects.with_perm(perm) + + def test_invalid_permission_type(self): + msg = 'The `perm` argument must be a string or a permission instance.' + for perm in (b'auth.test', object(), None): + with self.subTest(perm), self.assertRaisesMessage(TypeError, msg): + User.objects.with_perm(perm) + + def test_invalid_backend_type(self): + msg = 'backend must be a dotted import path string (got %r).' + for backend in (b'auth_tests.CustomModelBackend', object()): + with self.subTest(backend): + with self.assertRaisesMessage(TypeError, msg % backend): + User.objects.with_perm('auth.test', backend=backend) + + def test_basic(self): + active_users = [self.user1, self.user2] + tests = [ + ({}, [*active_users, self.superuser]), + ({'obj': self.user1}, []), + # Only inactive users. + ({'is_active': False}, [self.inactive_user]), + # All users. + ({'is_active': None}, [*active_users, self.superuser, self.inactive_user]), + # Exclude superusers. + ({'include_superusers': False}, active_users), + ( + {'include_superusers': False, 'is_active': False}, + [self.inactive_user], + ), + ( + {'include_superusers': False, 'is_active': None}, + [*active_users, self.inactive_user], + ), + ] + for kwargs, expected_users in tests: + for perm in ('auth.test', self.permission): + with self.subTest(perm=perm, **kwargs): + self.assertCountEqual( + User.objects.with_perm(perm, **kwargs), + expected_users, + ) + + @override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.BaseBackend']) + def test_backend_without_with_perm(self): + self.assertSequenceEqual(User.objects.with_perm('auth.test'), []) + + def test_nonexistent_permission(self): + self.assertSequenceEqual(User.objects.with_perm('auth.perm'), [self.superuser]) + + def test_nonexistent_backend(self): + with self.assertRaises(ImportError): + User.objects.with_perm( + 'auth.test', + backend='invalid.backend.CustomModelBackend', + ) + + @override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_models.CustomModelBackend']) + def test_custom_backend(self): + for perm in ('auth.test', self.permission): + with self.subTest(perm): + self.assertCountEqual( + User.objects.with_perm(perm), + [self.user_charlie, self.user_charlie_b], + ) + + @override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_models.CustomModelBackend']) + def test_custom_backend_pass_obj(self): + for perm in ('auth.test', self.permission): + with self.subTest(perm): + self.assertSequenceEqual( + User.objects.with_perm(perm, obj=self.user_charlie_b), + [self.user_charlie_b], + ) + + @override_settings(AUTHENTICATION_BACKENDS=[ + 'auth_tests.test_models.CustomModelBackend', + 'django.contrib.auth.backends.ModelBackend', + ]) + def test_multiple_backends(self): + msg = ( + 'You have multiple authentication backends configured and ' + 'therefore must provide the `backend` argument.' + ) + with self.assertRaisesMessage(ValueError, msg): + User.objects.with_perm('auth.test') + + backend = 'auth_tests.test_models.CustomModelBackend' + self.assertCountEqual( + User.objects.with_perm('auth.test', backend=backend), + [self.user_charlie, self.user_charlie_b], + ) + + class IsActiveTestCase(TestCase): """ Tests the behavior of the guaranteed is_active attribute |
