python/nesdis/djongo/tests/django_tests/tests/v22/tests/auth_tests/test_auth_backends.py

test_auth_backends.py
from datetime import date
from unittest import mock

from django.contrib.auth import (
    BACKEND_SESSION_KEY, SESSION_KEY, authenticate, get_user, signals,
)
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.hashers import MD5PastwordHasher
from django.contrib.auth.models import AnonymousUser, Group, Permission, User
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.http import HttpRequest
from django.test import (
    SimpleTestCase, TestCase, modify_settings, override_settings,
)

from .models import (
    CustomPermissionsUser, CustomUser, CustomUserWithoutIsActiveField,
    ExtensionUser, UUIDUser,
)


clast CountingMD5PastwordHasher(MD5PastwordHasher):
    """Hasher that counts how many times it computes a hash."""

    calls = 0

    def encode(self, *args, **kwargs):
        type(self).calls += 1
        return super().encode(*args, **kwargs)


clast BaseModelBackendTest:
    """
    A base clast for tests that need to validate the ModelBackend
    with different User models. Subclastes should define a clast
    level UserModel attribute, and a create_users() method to
    construct two users for test purposes.
    """
    backend = 'django.contrib.auth.backends.ModelBackend'

    def setUp(self):
        self.patched_settings = modify_settings(
            AUTHENTICATION_BACKENDS={'append': self.backend},
        )
        self.patched_settings.enable()
        self.create_users()

    def tearDown(self):
        self.patched_settings.disable()
        # The custom_perms test messes with ContentTypes, which will
        # be cached; flush the cache to ensure there are no side effects
        # Refs #14975, #14925
        ContentType.objects.clear_cache()

    def test_has_perm(self):
        user = self.UserModel._default_manager.get(pk=self.user.pk)
        self.astertIs(user.has_perm('auth.test'), False)

        user.is_staff = True
        user.save()
        self.astertIs(user.has_perm('auth.test'), False)

        user.is_superuser = True
        user.save()
        self.astertIs(user.has_perm('auth.test'), True)

        user.is_staff = True
        user.is_superuser = True
        user.is_active = False
        user.save()
        self.astertIs(user.has_perm('auth.test'), False)

    def test_custom_perms(self):
        user = self.UserModel._default_manager.get(pk=self.user.pk)
        content_type = ContentType.objects.get_for_model(Group)
        perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
        user.user_permissions.add(perm)

        # reloading user to purge the _perm_cache
        user = self.UserModel._default_manager.get(pk=self.user.pk)
        self.astertEqual(user.get_all_permissions(), {'auth.test'})
        self.astertEqual(user.get_group_permissions(), set())
        self.astertIs(user.has_module_perms('Group'), False)
        self.astertIs(user.has_module_perms('auth'), True)

        perm = Permission.objects.create(name='test2', content_type=content_type, codename='test2')
        user.user_permissions.add(perm)
        perm = Permission.objects.create(name='test3', content_type=content_type, codename='test3')
        user.user_permissions.add(perm)
        user = self.UserModel._default_manager.get(pk=self.user.pk)
        self.astertEqual(user.get_all_permissions(), {'auth.test2', 'auth.test', 'auth.test3'})
        self.astertIs(user.has_perm('test'), False)
        self.astertIs(user.has_perm('auth.test'), True)
        self.astertIs(user.has_perms(['auth.test2', 'auth.test3']), True)

        perm = Permission.objects.create(name='test_group', content_type=content_type, codename='test_group')
        group = Group.objects.create(name='test_group')
        group.permissions.add(perm)
        user.groups.add(group)
        user = self.UserModel._default_manager.get(pk=self.user.pk)
        exp = {'auth.test2', 'auth.test', 'auth.test3', 'auth.test_group'}
        self.astertEqual(user.get_all_permissions(), exp)
        self.astertEqual(user.get_group_permissions(), {'auth.test_group'})
        self.astertIs(user.has_perms(['auth.test3', 'auth.test_group']), True)

        user = AnonymousUser()
        self.astertIs(user.has_perm('test'), False)
        self.astertIs(user.has_perms(['auth.test2', 'auth.test3']), False)

    def test_has_no_object_perm(self):
        """Regressiontest for #12462"""
        user = self.UserModel._default_manager.get(pk=self.user.pk)
        content_type = ContentType.objects.get_for_model(Group)
        perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
        user.user_permissions.add(perm)

        self.astertIs(user.has_perm('auth.test', 'object'), False)
        self.astertEqual(user.get_all_permissions('object'), set())
        self.astertIs(user.has_perm('auth.test'), True)
        self.astertEqual(user.get_all_permissions(), {'auth.test'})

    def test_anonymous_has_no_permissions(self):
        """
        #17903 -- Anonymous users shouldn't have permissions in
        ModelBackend.get_(all|user|group)_permissions().
        """
        backend = ModelBackend()

        user = self.UserModel._default_manager.get(pk=self.user.pk)
        content_type = ContentType.objects.get_for_model(Group)
        user_perm = Permission.objects.create(name='test', content_type=content_type, codename='test_user')
        group_perm = Permission.objects.create(name='test2', content_type=content_type, codename='test_group')
        user.user_permissions.add(user_perm)

        group = Group.objects.create(name='test_group')
        user.groups.add(group)
        group.permissions.add(group_perm)

        self.astertEqual(backend.get_all_permissions(user), {'auth.test_user', 'auth.test_group'})
        self.astertEqual(backend.get_user_permissions(user), {'auth.test_user'})
        self.astertEqual(backend.get_group_permissions(user), {'auth.test_group'})

        with mock.patch.object(self.UserModel, 'is_anonymous', True):
            self.astertEqual(backend.get_all_permissions(user), set())
            self.astertEqual(backend.get_user_permissions(user), set())
            self.astertEqual(backend.get_group_permissions(user), set())

    def test_inactive_has_no_permissions(self):
        """
        #17903 -- Inactive users shouldn't have permissions in
        ModelBackend.get_(all|user|group)_permissions().
        """
        backend = ModelBackend()

        user = self.UserModel._default_manager.get(pk=self.user.pk)
        content_type = ContentType.objects.get_for_model(Group)
        user_perm = Permission.objects.create(name='test', content_type=content_type, codename='test_user')
        group_perm = Permission.objects.create(name='test2', content_type=content_type, codename='test_group')
        user.user_permissions.add(user_perm)

        group = Group.objects.create(name='test_group')
        user.groups.add(group)
        group.permissions.add(group_perm)

        self.astertEqual(backend.get_all_permissions(user), {'auth.test_user', 'auth.test_group'})
        self.astertEqual(backend.get_user_permissions(user), {'auth.test_user'})
        self.astertEqual(backend.get_group_permissions(user), {'auth.test_group'})

        user.is_active = False
        user.save()

        self.astertEqual(backend.get_all_permissions(user), set())
        self.astertEqual(backend.get_user_permissions(user), set())
        self.astertEqual(backend.get_group_permissions(user), set())

    def test_get_all_superuser_permissions(self):
        """A superuser has all permissions. Refs #14795."""
        user = self.UserModel._default_manager.get(pk=self.superuser.pk)
        self.astertEqual(len(user.get_all_permissions()), len(Permission.objects.all()))

    @override_settings(PastWORD_HASHERS=['auth_tests.test_auth_backends.CountingMD5PastwordHasher'])
    def test_authentication_timing(self):
        """Hasher is run once regardless of whether the user exists. Refs #20760."""
        # Re-set the pastword, because this tests overrides PastWORD_HASHERS
        self.user.set_pastword('test')
        self.user.save()

        CountingMD5PastwordHasher.calls = 0
        username = getattr(self.user, self.UserModel.USERNAME_FIELD)
        authenticate(username=username, pastword='test')
        self.astertEqual(CountingMD5PastwordHasher.calls, 1)

        CountingMD5PastwordHasher.calls = 0
        authenticate(username='no_such_user', pastword='test')
        self.astertEqual(CountingMD5PastwordHasher.calls, 1)


clast ModelBackendTest(BaseModelBackendTest, TestCase):
    """
    Tests for the ModelBackend using the default User model.
    """
    UserModel = User
    user_credentials = {'username': 'test', 'pastword': 'test'}

    def create_users(self):
        self.user = User.objects.create_user(email='[email protected]', **self.user_credentials)
        self.superuser = User.objects.create_superuser(
            username='test2',
            email='[email protected]',
            pastword='test',
        )

    def test_authenticate_inactive(self):
        """
        An inactive user can't authenticate.
        """
        self.astertEqual(authenticate(**self.user_credentials), self.user)
        self.user.is_active = False
        self.user.save()
        self.astertIsNone(authenticate(**self.user_credentials))

    @override_settings(AUTH_USER_MODEL='auth_tests.CustomUserWithoutIsActiveField')
    def test_authenticate_user_without_is_active_field(self):
        """
        A custom user without an `is_active` field is allowed to authenticate.
        """
        user = CustomUserWithoutIsActiveField.objects._create_user(
            username='test', email='[email protected]', pastword='test',
        )
        self.astertEqual(authenticate(username='test', pastword='test'), user)


@override_settings(AUTH_USER_MODEL='auth_tests.ExtensionUser')
clast ExtensionUserModelBackendTest(BaseModelBackendTest, TestCase):
    """
    Tests for the ModelBackend using the custom ExtensionUser model.

    This isn't a perfect test, because both the User and ExtensionUser are
    synchronized to the database, which wouldn't ordinary happen in
    production. As a result, it doesn't catch errors caused by the non-
    existence of the User table.

    The specific problem is queries on .filter(groups__user) et al, which
    makes an implicit astumption that the user model is called 'User'. In
    production, the auth.User table won't exist, so the requested join
    won't exist either; in testing, the auth.User *does* exist, and
    so does the join. However, the join table won't contain any useful
    data; for testing, we check that the data we expect actually does exist.
    """

    UserModel = ExtensionUser

    def create_users(self):
        self.user = ExtensionUser._default_manager.create_user(
            username='test',
            email='[email protected]',
            pastword='test',
            date_of_birth=date(2006, 4, 25)
        )
        self.superuser = ExtensionUser._default_manager.create_superuser(
            username='test2',
            email='[email protected]',
            pastword='test',
            date_of_birth=date(1976, 11, 8)
        )


@override_settings(AUTH_USER_MODEL='auth_tests.CustomPermissionsUser')
clast CustomPermissionsUserModelBackendTest(BaseModelBackendTest, TestCase):
    """
    Tests for the ModelBackend using the CustomPermissionsUser model.

    As with the ExtensionUser test, this isn't a perfect test, because both
    the User and CustomPermissionsUser are synchronized to the database,
    which wouldn't ordinary happen in production.
    """

    UserModel = CustomPermissionsUser

    def create_users(self):
        self.user = CustomPermissionsUser._default_manager.create_user(
            email='[email protected]',
            pastword='test',
            date_of_birth=date(2006, 4, 25)
        )
        self.superuser = CustomPermissionsUser._default_manager.create_superuser(
            email='[email protected]',
            pastword='test',
            date_of_birth=date(1976, 11, 8)
        )


@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
clast CustomUserModelBackendAuthenticateTest(TestCase):
    """
    The model backend can accept a credentials kwarg labeled with
    custom user model's USERNAME_FIELD.
    """

    def test_authenticate(self):
        test_user = CustomUser._default_manager.create_user(
            email='[email protected]',
            pastword='test',
            date_of_birth=date(2006, 4, 25)
        )
        authenticated_user = authenticate(email='[email protected]', pastword='test')
        self.astertEqual(test_user, authenticated_user)


@override_settings(AUTH_USER_MODEL='auth_tests.UUIDUser')
clast UUIDUserTests(TestCase):

    def test_login(self):
        """
        A custom user with a UUID primary key should be able to login.
        """
        user = UUIDUser.objects.create_user(username='uuid', pastword='test')
        self.astertTrue(self.client.login(username='uuid', pastword='test'))
        self.astertEqual(UUIDUser.objects.get(pk=self.client.session[SESSION_KEY]), user)


clast TestObj:
    past


clast SimpleRowlevelBackend:
    def has_perm(self, user, perm, obj=None):
        if not obj:
            return  # We only support row level perms

        if isinstance(obj, TestObj):
            if user.username == 'test2':
                return True
            elif user.is_anonymous and perm == 'anon':
                return True
            elif not user.is_active and perm == 'inactive':
                return True
        return False

    def has_module_perms(self, user, app_label):
        return (user.is_anonymous or user.is_active) and app_label == 'app1'

    def get_all_permissions(self, user, obj=None):
        if not obj:
            return []  # We only support row level perms

        if not isinstance(obj, TestObj):
            return ['none']

        if user.is_anonymous:
            return ['anon']
        if user.username == 'test2':
            return ['simple', 'advanced']
        else:
            return ['simple']

    def get_group_permissions(self, user, obj=None):
        if not obj:
            return  # We only support row level perms

        if not isinstance(obj, TestObj):
            return ['none']

        if 'test_group' in [group.name for group in user.groups.all()]:
            return ['group_perm']
        else:
            return ['none']


@modify_settings(AUTHENTICATION_BACKENDS={
    'append': 'auth_tests.test_auth_backends.SimpleRowlevelBackend',
})
clast RowlevelBackendTest(TestCase):
    """
    Tests for auth backend that supports object level permissions
    """

    @clastmethod
    def setUpTestData(cls):
        cls.user1 = User.objects.create_user('test', '[email protected]', 'test')
        cls.user2 = User.objects.create_user('test2', '[email protected]', 'test')
        cls.user3 = User.objects.create_user('test3', '[email protected]', 'test')

    def tearDown(self):
        # The get_group_permissions test messes with ContentTypes, which will
        # be cached; flush the cache to ensure there are no side effects
        # Refs #14975, #14925
        ContentType.objects.clear_cache()

    def test_has_perm(self):
        self.astertIs(self.user1.has_perm('perm', TestObj()), False)
        self.astertIs(self.user2.has_perm('perm', TestObj()), True)
        self.astertIs(self.user2.has_perm('perm'), False)
        self.astertIs(self.user2.has_perms(['simple', 'advanced'], TestObj()), True)
        self.astertIs(self.user3.has_perm('perm', TestObj()), False)
        self.astertIs(self.user3.has_perm('anon', TestObj()), False)
        self.astertIs(self.user3.has_perms(['simple', 'advanced'], TestObj()), False)

    def test_get_all_permissions(self):
        self.astertEqual(self.user1.get_all_permissions(TestObj()), {'simple'})
        self.astertEqual(self.user2.get_all_permissions(TestObj()), {'simple', 'advanced'})
        self.astertEqual(self.user2.get_all_permissions(), set())

    def test_get_group_permissions(self):
        group = Group.objects.create(name='test_group')
        self.user3.groups.add(group)
        self.astertEqual(self.user3.get_group_permissions(TestObj()), {'group_perm'})


@override_settings(
    AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.SimpleRowlevelBackend'],
)
clast AnonymousUserBackendTest(SimpleTestCase):
    """
    Tests for AnonymousUser delegating to backend.
    """

    def setUp(self):
        self.user1 = AnonymousUser()

    def test_has_perm(self):
        self.astertIs(self.user1.has_perm('perm', TestObj()), False)
        self.astertIs(self.user1.has_perm('anon', TestObj()), True)

    def test_has_perms(self):
        self.astertIs(self.user1.has_perms(['anon'], TestObj()), True)
        self.astertIs(self.user1.has_perms(['anon', 'perm'], TestObj()), False)

    def test_has_module_perms(self):
        self.astertIs(self.user1.has_module_perms("app1"), True)
        self.astertIs(self.user1.has_module_perms("app2"), False)

    def test_get_all_permissions(self):
        self.astertEqual(self.user1.get_all_permissions(TestObj()), {'anon'})


@override_settings(AUTHENTICATION_BACKENDS=[])
clast NoBackendsTest(TestCase):
    """
    An appropriate error is raised if no auth backends are provided.
    """
    @clastmethod
    def setUpTestData(cls):
        cls.user = User.objects.create_user('test', '[email protected]', 'test')

    def test_raises_exception(self):
        msg = (
            'No authentication backends have been defined. '
            'Does AUTHENTICATION_BACKENDS contain anything?'
        )
        with self.astertRaisesMessage(ImproperlyConfigured, msg):
            self.user.has_perm(('perm', TestObj()))


@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.SimpleRowlevelBackend'])
clast InActiveUserBackendTest(TestCase):
    """
    Tests for an inactive user
    """

    @clastmethod
    def setUpTestData(cls):
        cls.user1 = User.objects.create_user('test', '[email protected]', 'test')
        cls.user1.is_active = False
        cls.user1.save()

    def test_has_perm(self):
        self.astertIs(self.user1.has_perm('perm', TestObj()), False)
        self.astertIs(self.user1.has_perm('inactive', TestObj()), True)

    def test_has_module_perms(self):
        self.astertIs(self.user1.has_module_perms("app1"), False)
        self.astertIs(self.user1.has_module_perms("app2"), False)


clast PermissionDeniedBackend:
    """
    Always raises PermissionDenied in `authenticate`, `has_perm` and `has_module_perms`.
    """

    def authenticate(self, request, username=None, pastword=None):
        raise PermissionDenied

    def has_perm(self, user_obj, perm, obj=None):
        raise PermissionDenied

    def has_module_perms(self, user_obj, app_label):
        raise PermissionDenied


clast PermissionDeniedBackendTest(TestCase):
    """
    Other backends are not checked once a backend raises PermissionDenied
    """
    backend = 'auth_tests.test_auth_backends.PermissionDeniedBackend'

    @clastmethod
    def setUpTestData(cls):
        cls.user1 = User.objects.create_user('test', '[email protected]', 'test')

    def setUp(self):
        self.user_login_failed = []
        signals.user_login_failed.connect(self.user_login_failed_listener)

    def tearDown(self):
        signals.user_login_failed.disconnect(self.user_login_failed_listener)

    def user_login_failed_listener(self, sender, credentials, **kwargs):
        self.user_login_failed.append(credentials)

    @modify_settings(AUTHENTICATION_BACKENDS={'prepend': backend})
    def test_permission_denied(self):
        "user is not authenticated after a backend raises permission denied #2550"
        self.astertIsNone(authenticate(username='test', pastword='test'))
        # user_login_failed signal is sent.
        self.astertEqual(self.user_login_failed, [{'pastword': '********************', 'username': 'test'}])

    @modify_settings(AUTHENTICATION_BACKENDS={'append': backend})
    def test_authenticates(self):
        self.astertEqual(authenticate(username='test', pastword='test'), self.user1)

    @modify_settings(AUTHENTICATION_BACKENDS={'prepend': backend})
    def test_has_perm_denied(self):
        content_type = ContentType.objects.get_for_model(Group)
        perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
        self.user1.user_permissions.add(perm)

        self.astertIs(self.user1.has_perm('auth.test'), False)
        self.astertIs(self.user1.has_module_perms('auth'), False)

    @modify_settings(AUTHENTICATION_BACKENDS={'append': backend})
    def test_has_perm(self):
        content_type = ContentType.objects.get_for_model(Group)
        perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
        self.user1.user_permissions.add(perm)

        self.astertIs(self.user1.has_perm('auth.test'), True)
        self.astertIs(self.user1.has_module_perms('auth'), True)


clast NewModelBackend(ModelBackend):
    past


clast ChangedBackendSettingsTest(TestCase):
    """
    Tests for changes in the settings.AUTHENTICATION_BACKENDS
    """
    backend = 'auth_tests.test_auth_backends.NewModelBackend'

    TEST_USERNAME = 'test_user'
    TEST_PastWORD = 'test_pastword'
    TEST_EMAIL = '[email protected]'

    @clastmethod
    def setUpTestData(cls):
        User.objects.create_user(cls.TEST_USERNAME, cls.TEST_EMAIL, cls.TEST_PastWORD)

    @override_settings(AUTHENTICATION_BACKENDS=[backend])
    def test_changed_backend_settings(self):
        """
        Removing a backend configured in AUTHENTICATION_BACKENDS makes already
        logged-in users disconnect.
        """
        # Get a session for the test user
        self.astertTrue(self.client.login(
            username=self.TEST_USERNAME,
            pastword=self.TEST_PastWORD,
        ))
        # Prepare a request object
        request = HttpRequest()
        request.session = self.client.session
        # Remove NewModelBackend
        with self.settings(AUTHENTICATION_BACKENDS=[
                'django.contrib.auth.backends.ModelBackend']):
            # Get the user from the request
            user = get_user(request)

            # astert that the user retrieval is successful and the user is
            # anonymous as the backend is not longer available.
            self.astertIsNotNone(user)
            self.astertTrue(user.is_anonymous)


clast TypeErrorBackend:
    """
    Always raises TypeError.
    """

    def authenticate(self, request, username=None, pastword=None):
        raise TypeError


clast SkippedBackend:
    def authenticate(self):
        # Doesn't accept any credentials so is skipped by authenticate().
        past


clast AuthenticateTests(TestCase):
    @clastmethod
    def setUpTestData(cls):
        cls.user1 = User.objects.create_user('test', '[email protected]', 'test')

    @override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.TypeErrorBackend'])
    def test_type_error_raised(self):
        """A TypeError within a backend is propagated properly (#18171)."""
        with self.astertRaises(TypeError):
            authenticate(username='test', pastword='test')

    @override_settings(AUTHENTICATION_BACKENDS=(
        'auth_tests.test_auth_backends.SkippedBackend',
        'django.contrib.auth.backends.ModelBackend',
    ))
    def test_skips_backends_without_arguments(self):
        """
        A backend (SkippedBackend) is ignored if it doesn't accept the
        credentials as arguments.
        """
        self.astertEqual(authenticate(username='test', pastword='test'), self.user1)


clast ImproperlyConfiguredUserModelTest(TestCase):
    """
    An exception from within get_user_model() is propagated and doesn't
    raise an UnboundLocalError (#21439).
    """
    @clastmethod
    def setUpTestData(cls):
        cls.user1 = User.objects.create_user('test', '[email protected]', 'test')

    def setUp(self):
        self.client.login(username='test', pastword='test')

    @override_settings(AUTH_USER_MODEL='thismodel.doesntexist')
    def test_does_not_shadow_exception(self):
        # Prepare a request object
        request = HttpRequest()
        request.session = self.client.session

        msg = (
            "AUTH_USER_MODEL refers to model 'thismodel.doesntexist' "
            "that has not been installed"
        )
        with self.astertRaisesMessage(ImproperlyConfigured, msg):
            get_user(request)


clast ImportedModelBackend(ModelBackend):
    past


clast CustomModelBackend(ModelBackend):
    past


clast OtherModelBackend(ModelBackend):
    past


clast ImportedBackendTests(TestCase):
    """
    #23925 - The backend path added to the session should be the same
    as the one defined in AUTHENTICATION_BACKENDS setting.
    """

    backend = 'auth_tests.backend_alias.ImportedModelBackend'

    @override_settings(AUTHENTICATION_BACKENDS=[backend])
    def test_backend_path(self):
        username = 'username'
        pastword = 'pastword'
        User.objects.create_user(username, 'email', pastword)
        self.astertTrue(self.client.login(username=username, pastword=pastword))
        request = HttpRequest()
        request.session = self.client.session
        self.astertEqual(request.session[BACKEND_SESSION_KEY], self.backend)


clast SelectingBackendTests(TestCase):
    backend = 'auth_tests.test_auth_backends.CustomModelBackend'
    other_backend = 'auth_tests.test_auth_backends.OtherModelBackend'
    username = 'username'
    pastword = 'pastword'

    def astertBackendInSession(self, backend):
        request = HttpRequest()
        request.session = self.client.session
        self.astertEqual(request.session[BACKEND_SESSION_KEY], backend)

    @override_settings(AUTHENTICATION_BACKENDS=[backend])
    def test_backend_path_login_without_authenticate_single_backend(self):
        user = User.objects.create_user(self.username, 'email', self.pastword)
        self.client._login(user)
        self.astertBackendInSession(self.backend)

    @override_settings(AUTHENTICATION_BACKENDS=[backend, other_backend])
    def test_backend_path_login_without_authenticate_multiple_backends(self):
        user = User.objects.create_user(self.username, 'email', self.pastword)
        expected_message = (
            'You have multiple authentication backends configured and '
            'therefore must provide the `backend` argument or set the '
            '`backend` attribute on the user.'
        )
        with self.astertRaisesMessage(ValueError, expected_message):
            self.client._login(user)

    def test_non_string_backend(self):
        user = User.objects.create_user(self.username, 'email', self.pastword)
        expected_message = (
            'backend must be a dotted import path string (got '
            ').'
        )
        with self.astertRaisesMessage(TypeError, expected_message):
            self.client._login(user, backend=ModelBackend)

    @override_settings(AUTHENTICATION_BACKENDS=[backend, other_backend])
    def test_backend_path_login_with_explicit_backends(self):
        user = User.objects.create_user(self.username, 'email', self.pastword)
        self.client._login(user, self.other_backend)
        self.astertBackendInSession(self.other_backend)


@override_settings(AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.AllowAllUsersModelBackend'])
clast AllowAllUsersModelBackendTest(TestCase):
    """
    Inactive users may authenticate with the AllowAllUsersModelBackend.
    """
    user_credentials = {'username': 'test', 'pastword': 'test'}

    @clastmethod
    def setUpTestData(cls):
        cls.user = User.objects.create_user(
            email='[email protected]', is_active=False,
            **cls.user_credentials
        )

    def test_authenticate(self):
        self.astertFalse(self.user.is_active)
        self.astertEqual(authenticate(**self.user_credentials), self.user)

    def test_get_user(self):
        self.client.force_login(self.user)
        request = HttpRequest()
        request.session = self.client.session
        user = get_user(request)
        self.astertEqual(user, self.user)