1. import sys
    
  2. from datetime import date
    
  3. from unittest import mock
    
  4. 
    
  5. from django.contrib.auth import (
    
  6.     BACKEND_SESSION_KEY,
    
  7.     SESSION_KEY,
    
  8.     _clean_credentials,
    
  9.     authenticate,
    
  10.     get_user,
    
  11.     signals,
    
  12. )
    
  13. from django.contrib.auth.backends import BaseBackend, ModelBackend
    
  14. from django.contrib.auth.hashers import MD5PasswordHasher
    
  15. from django.contrib.auth.models import AnonymousUser, Group, Permission, User
    
  16. from django.contrib.contenttypes.models import ContentType
    
  17. from django.core.exceptions import ImproperlyConfigured, PermissionDenied
    
  18. from django.http import HttpRequest
    
  19. from django.test import (
    
  20.     RequestFactory,
    
  21.     SimpleTestCase,
    
  22.     TestCase,
    
  23.     modify_settings,
    
  24.     override_settings,
    
  25. )
    
  26. from django.views.debug import technical_500_response
    
  27. from django.views.decorators.debug import sensitive_variables
    
  28. 
    
  29. from .models import (
    
  30.     CustomPermissionsUser,
    
  31.     CustomUser,
    
  32.     CustomUserWithoutIsActiveField,
    
  33.     ExtensionUser,
    
  34.     UUIDUser,
    
  35. )
    
  36. 
    
  37. 
    
  38. class SimpleBackend(BaseBackend):
    
  39.     def get_user_permissions(self, user_obj, obj=None):
    
  40.         return ["user_perm"]
    
  41. 
    
  42.     def get_group_permissions(self, user_obj, obj=None):
    
  43.         return ["group_perm"]
    
  44. 
    
  45. 
    
  46. @override_settings(
    
  47.     AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.SimpleBackend"]
    
  48. )
    
  49. class BaseBackendTest(TestCase):
    
  50.     @classmethod
    
  51.     def setUpTestData(cls):
    
  52.         cls.user = User.objects.create_user("test", "[email protected]", "test")
    
  53. 
    
  54.     def test_get_user_permissions(self):
    
  55.         self.assertEqual(self.user.get_user_permissions(), {"user_perm"})
    
  56. 
    
  57.     def test_get_group_permissions(self):
    
  58.         self.assertEqual(self.user.get_group_permissions(), {"group_perm"})
    
  59. 
    
  60.     def test_get_all_permissions(self):
    
  61.         self.assertEqual(self.user.get_all_permissions(), {"user_perm", "group_perm"})
    
  62. 
    
  63.     def test_has_perm(self):
    
  64.         self.assertIs(self.user.has_perm("user_perm"), True)
    
  65.         self.assertIs(self.user.has_perm("group_perm"), True)
    
  66.         self.assertIs(self.user.has_perm("other_perm", TestObj()), False)
    
  67. 
    
  68.     def test_has_perms_perm_list_invalid(self):
    
  69.         msg = "perm_list must be an iterable of permissions."
    
  70.         with self.assertRaisesMessage(ValueError, msg):
    
  71.             self.user.has_perms("user_perm")
    
  72.         with self.assertRaisesMessage(ValueError, msg):
    
  73.             self.user.has_perms(object())
    
  74. 
    
  75. 
    
  76. class CountingMD5PasswordHasher(MD5PasswordHasher):
    
  77.     """Hasher that counts how many times it computes a hash."""
    
  78. 
    
  79.     calls = 0
    
  80. 
    
  81.     def encode(self, *args, **kwargs):
    
  82.         type(self).calls += 1
    
  83.         return super().encode(*args, **kwargs)
    
  84. 
    
  85. 
    
  86. class BaseModelBackendTest:
    
  87.     """
    
  88.     A base class for tests that need to validate the ModelBackend
    
  89.     with different User models. Subclasses should define a class
    
  90.     level UserModel attribute, and a create_users() method to
    
  91.     construct two users for test purposes.
    
  92.     """
    
  93. 
    
  94.     backend = "django.contrib.auth.backends.ModelBackend"
    
  95. 
    
  96.     def setUp(self):
    
  97.         self.patched_settings = modify_settings(
    
  98.             AUTHENTICATION_BACKENDS={"append": self.backend},
    
  99.         )
    
  100.         self.patched_settings.enable()
    
  101.         self.create_users()
    
  102. 
    
  103.     def tearDown(self):
    
  104.         self.patched_settings.disable()
    
  105.         # The custom_perms test messes with ContentTypes, which will
    
  106.         # be cached; flush the cache to ensure there are no side effects
    
  107.         # Refs #14975, #14925
    
  108.         ContentType.objects.clear_cache()
    
  109. 
    
  110.     def test_has_perm(self):
    
  111.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  112.         self.assertIs(user.has_perm("auth.test"), False)
    
  113. 
    
  114.         user.is_staff = True
    
  115.         user.save()
    
  116.         self.assertIs(user.has_perm("auth.test"), False)
    
  117. 
    
  118.         user.is_superuser = True
    
  119.         user.save()
    
  120.         self.assertIs(user.has_perm("auth.test"), True)
    
  121. 
    
  122.         user.is_staff = True
    
  123.         user.is_superuser = True
    
  124.         user.is_active = False
    
  125.         user.save()
    
  126.         self.assertIs(user.has_perm("auth.test"), False)
    
  127. 
    
  128.     def test_custom_perms(self):
    
  129.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  130.         content_type = ContentType.objects.get_for_model(Group)
    
  131.         perm = Permission.objects.create(
    
  132.             name="test", content_type=content_type, codename="test"
    
  133.         )
    
  134.         user.user_permissions.add(perm)
    
  135. 
    
  136.         # reloading user to purge the _perm_cache
    
  137.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  138.         self.assertEqual(user.get_all_permissions(), {"auth.test"})
    
  139.         self.assertEqual(user.get_user_permissions(), {"auth.test"})
    
  140.         self.assertEqual(user.get_group_permissions(), set())
    
  141.         self.assertIs(user.has_module_perms("Group"), False)
    
  142.         self.assertIs(user.has_module_perms("auth"), True)
    
  143. 
    
  144.         perm = Permission.objects.create(
    
  145.             name="test2", content_type=content_type, codename="test2"
    
  146.         )
    
  147.         user.user_permissions.add(perm)
    
  148.         perm = Permission.objects.create(
    
  149.             name="test3", content_type=content_type, codename="test3"
    
  150.         )
    
  151.         user.user_permissions.add(perm)
    
  152.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  153.         expected_user_perms = {"auth.test2", "auth.test", "auth.test3"}
    
  154.         self.assertEqual(user.get_all_permissions(), expected_user_perms)
    
  155.         self.assertIs(user.has_perm("test"), False)
    
  156.         self.assertIs(user.has_perm("auth.test"), True)
    
  157.         self.assertIs(user.has_perms(["auth.test2", "auth.test3"]), True)
    
  158. 
    
  159.         perm = Permission.objects.create(
    
  160.             name="test_group", content_type=content_type, codename="test_group"
    
  161.         )
    
  162.         group = Group.objects.create(name="test_group")
    
  163.         group.permissions.add(perm)
    
  164.         user.groups.add(group)
    
  165.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  166.         self.assertEqual(
    
  167.             user.get_all_permissions(), {*expected_user_perms, "auth.test_group"}
    
  168.         )
    
  169.         self.assertEqual(user.get_user_permissions(), expected_user_perms)
    
  170.         self.assertEqual(user.get_group_permissions(), {"auth.test_group"})
    
  171.         self.assertIs(user.has_perms(["auth.test3", "auth.test_group"]), True)
    
  172. 
    
  173.         user = AnonymousUser()
    
  174.         self.assertIs(user.has_perm("test"), False)
    
  175.         self.assertIs(user.has_perms(["auth.test2", "auth.test3"]), False)
    
  176. 
    
  177.     def test_has_no_object_perm(self):
    
  178.         """Regressiontest for #12462"""
    
  179.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  180.         content_type = ContentType.objects.get_for_model(Group)
    
  181.         perm = Permission.objects.create(
    
  182.             name="test", content_type=content_type, codename="test"
    
  183.         )
    
  184.         user.user_permissions.add(perm)
    
  185. 
    
  186.         self.assertIs(user.has_perm("auth.test", "object"), False)
    
  187.         self.assertEqual(user.get_all_permissions("object"), set())
    
  188.         self.assertIs(user.has_perm("auth.test"), True)
    
  189.         self.assertEqual(user.get_all_permissions(), {"auth.test"})
    
  190. 
    
  191.     def test_anonymous_has_no_permissions(self):
    
  192.         """
    
  193.         #17903 -- Anonymous users shouldn't have permissions in
    
  194.         ModelBackend.get_(all|user|group)_permissions().
    
  195.         """
    
  196.         backend = ModelBackend()
    
  197. 
    
  198.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  199.         content_type = ContentType.objects.get_for_model(Group)
    
  200.         user_perm = Permission.objects.create(
    
  201.             name="test", content_type=content_type, codename="test_user"
    
  202.         )
    
  203.         group_perm = Permission.objects.create(
    
  204.             name="test2", content_type=content_type, codename="test_group"
    
  205.         )
    
  206.         user.user_permissions.add(user_perm)
    
  207. 
    
  208.         group = Group.objects.create(name="test_group")
    
  209.         user.groups.add(group)
    
  210.         group.permissions.add(group_perm)
    
  211. 
    
  212.         self.assertEqual(
    
  213.             backend.get_all_permissions(user), {"auth.test_user", "auth.test_group"}
    
  214.         )
    
  215.         self.assertEqual(backend.get_user_permissions(user), {"auth.test_user"})
    
  216.         self.assertEqual(backend.get_group_permissions(user), {"auth.test_group"})
    
  217. 
    
  218.         with mock.patch.object(self.UserModel, "is_anonymous", True):
    
  219.             self.assertEqual(backend.get_all_permissions(user), set())
    
  220.             self.assertEqual(backend.get_user_permissions(user), set())
    
  221.             self.assertEqual(backend.get_group_permissions(user), set())
    
  222. 
    
  223.     def test_inactive_has_no_permissions(self):
    
  224.         """
    
  225.         #17903 -- Inactive users shouldn't have permissions in
    
  226.         ModelBackend.get_(all|user|group)_permissions().
    
  227.         """
    
  228.         backend = ModelBackend()
    
  229. 
    
  230.         user = self.UserModel._default_manager.get(pk=self.user.pk)
    
  231.         content_type = ContentType.objects.get_for_model(Group)
    
  232.         user_perm = Permission.objects.create(
    
  233.             name="test", content_type=content_type, codename="test_user"
    
  234.         )
    
  235.         group_perm = Permission.objects.create(
    
  236.             name="test2", content_type=content_type, codename="test_group"
    
  237.         )
    
  238.         user.user_permissions.add(user_perm)
    
  239. 
    
  240.         group = Group.objects.create(name="test_group")
    
  241.         user.groups.add(group)
    
  242.         group.permissions.add(group_perm)
    
  243. 
    
  244.         self.assertEqual(
    
  245.             backend.get_all_permissions(user), {"auth.test_user", "auth.test_group"}
    
  246.         )
    
  247.         self.assertEqual(backend.get_user_permissions(user), {"auth.test_user"})
    
  248.         self.assertEqual(backend.get_group_permissions(user), {"auth.test_group"})
    
  249. 
    
  250.         user.is_active = False
    
  251.         user.save()
    
  252. 
    
  253.         self.assertEqual(backend.get_all_permissions(user), set())
    
  254.         self.assertEqual(backend.get_user_permissions(user), set())
    
  255.         self.assertEqual(backend.get_group_permissions(user), set())
    
  256. 
    
  257.     def test_get_all_superuser_permissions(self):
    
  258.         """A superuser has all permissions. Refs #14795."""
    
  259.         user = self.UserModel._default_manager.get(pk=self.superuser.pk)
    
  260.         self.assertEqual(len(user.get_all_permissions()), len(Permission.objects.all()))
    
  261. 
    
  262.     @override_settings(
    
  263.         PASSWORD_HASHERS=["auth_tests.test_auth_backends.CountingMD5PasswordHasher"]
    
  264.     )
    
  265.     def test_authentication_timing(self):
    
  266.         """Hasher is run once regardless of whether the user exists. Refs #20760."""
    
  267.         # Re-set the password, because this tests overrides PASSWORD_HASHERS
    
  268.         self.user.set_password("test")
    
  269.         self.user.save()
    
  270. 
    
  271.         CountingMD5PasswordHasher.calls = 0
    
  272.         username = getattr(self.user, self.UserModel.USERNAME_FIELD)
    
  273.         authenticate(username=username, password="test")
    
  274.         self.assertEqual(CountingMD5PasswordHasher.calls, 1)
    
  275. 
    
  276.         CountingMD5PasswordHasher.calls = 0
    
  277.         authenticate(username="no_such_user", password="test")
    
  278.         self.assertEqual(CountingMD5PasswordHasher.calls, 1)
    
  279. 
    
  280.     @override_settings(
    
  281.         PASSWORD_HASHERS=["auth_tests.test_auth_backends.CountingMD5PasswordHasher"]
    
  282.     )
    
  283.     def test_authentication_without_credentials(self):
    
  284.         CountingMD5PasswordHasher.calls = 0
    
  285.         for credentials in (
    
  286.             {},
    
  287.             {"username": getattr(self.user, self.UserModel.USERNAME_FIELD)},
    
  288.             {"password": "test"},
    
  289.         ):
    
  290.             with self.subTest(credentials=credentials):
    
  291.                 with self.assertNumQueries(0):
    
  292.                     authenticate(**credentials)
    
  293.                 self.assertEqual(CountingMD5PasswordHasher.calls, 0)
    
  294. 
    
  295. 
    
  296. class ModelBackendTest(BaseModelBackendTest, TestCase):
    
  297.     """
    
  298.     Tests for the ModelBackend using the default User model.
    
  299.     """
    
  300. 
    
  301.     UserModel = User
    
  302.     user_credentials = {"username": "test", "password": "test"}
    
  303. 
    
  304.     def create_users(self):
    
  305.         self.user = User.objects.create_user(
    
  306.             email="[email protected]", **self.user_credentials
    
  307.         )
    
  308.         self.superuser = User.objects.create_superuser(
    
  309.             username="test2",
    
  310.             email="[email protected]",
    
  311.             password="test",
    
  312.         )
    
  313. 
    
  314.     def test_authenticate_inactive(self):
    
  315.         """
    
  316.         An inactive user can't authenticate.
    
  317.         """
    
  318.         self.assertEqual(authenticate(**self.user_credentials), self.user)
    
  319.         self.user.is_active = False
    
  320.         self.user.save()
    
  321.         self.assertIsNone(authenticate(**self.user_credentials))
    
  322. 
    
  323.     @override_settings(AUTH_USER_MODEL="auth_tests.CustomUserWithoutIsActiveField")
    
  324.     def test_authenticate_user_without_is_active_field(self):
    
  325.         """
    
  326.         A custom user without an `is_active` field is allowed to authenticate.
    
  327.         """
    
  328.         user = CustomUserWithoutIsActiveField.objects._create_user(
    
  329.             username="test",
    
  330.             email="[email protected]",
    
  331.             password="test",
    
  332.         )
    
  333.         self.assertEqual(authenticate(username="test", password="test"), user)
    
  334. 
    
  335. 
    
  336. @override_settings(AUTH_USER_MODEL="auth_tests.ExtensionUser")
    
  337. class ExtensionUserModelBackendTest(BaseModelBackendTest, TestCase):
    
  338.     """
    
  339.     Tests for the ModelBackend using the custom ExtensionUser model.
    
  340. 
    
  341.     This isn't a perfect test, because both the User and ExtensionUser are
    
  342.     synchronized to the database, which wouldn't ordinary happen in
    
  343.     production. As a result, it doesn't catch errors caused by the non-
    
  344.     existence of the User table.
    
  345. 
    
  346.     The specific problem is queries on .filter(groups__user) et al, which
    
  347.     makes an implicit assumption that the user model is called 'User'. In
    
  348.     production, the auth.User table won't exist, so the requested join
    
  349.     won't exist either; in testing, the auth.User *does* exist, and
    
  350.     so does the join. However, the join table won't contain any useful
    
  351.     data; for testing, we check that the data we expect actually does exist.
    
  352.     """
    
  353. 
    
  354.     UserModel = ExtensionUser
    
  355. 
    
  356.     def create_users(self):
    
  357.         self.user = ExtensionUser._default_manager.create_user(
    
  358.             username="test",
    
  359.             email="[email protected]",
    
  360.             password="test",
    
  361.             date_of_birth=date(2006, 4, 25),
    
  362.         )
    
  363.         self.superuser = ExtensionUser._default_manager.create_superuser(
    
  364.             username="test2",
    
  365.             email="[email protected]",
    
  366.             password="test",
    
  367.             date_of_birth=date(1976, 11, 8),
    
  368.         )
    
  369. 
    
  370. 
    
  371. @override_settings(AUTH_USER_MODEL="auth_tests.CustomPermissionsUser")
    
  372. class CustomPermissionsUserModelBackendTest(BaseModelBackendTest, TestCase):
    
  373.     """
    
  374.     Tests for the ModelBackend using the CustomPermissionsUser model.
    
  375. 
    
  376.     As with the ExtensionUser test, this isn't a perfect test, because both
    
  377.     the User and CustomPermissionsUser are synchronized to the database,
    
  378.     which wouldn't ordinary happen in production.
    
  379.     """
    
  380. 
    
  381.     UserModel = CustomPermissionsUser
    
  382. 
    
  383.     def create_users(self):
    
  384.         self.user = CustomPermissionsUser._default_manager.create_user(
    
  385.             email="[email protected]", password="test", date_of_birth=date(2006, 4, 25)
    
  386.         )
    
  387.         self.superuser = CustomPermissionsUser._default_manager.create_superuser(
    
  388.             email="[email protected]", password="test", date_of_birth=date(1976, 11, 8)
    
  389.         )
    
  390. 
    
  391. 
    
  392. @override_settings(AUTH_USER_MODEL="auth_tests.CustomUser")
    
  393. class CustomUserModelBackendAuthenticateTest(TestCase):
    
  394.     """
    
  395.     The model backend can accept a credentials kwarg labeled with
    
  396.     custom user model's USERNAME_FIELD.
    
  397.     """
    
  398. 
    
  399.     def test_authenticate(self):
    
  400.         test_user = CustomUser._default_manager.create_user(
    
  401.             email="[email protected]", password="test", date_of_birth=date(2006, 4, 25)
    
  402.         )
    
  403.         authenticated_user = authenticate(email="[email protected]", password="test")
    
  404.         self.assertEqual(test_user, authenticated_user)
    
  405. 
    
  406. 
    
  407. @override_settings(AUTH_USER_MODEL="auth_tests.UUIDUser")
    
  408. class UUIDUserTests(TestCase):
    
  409.     def test_login(self):
    
  410.         """
    
  411.         A custom user with a UUID primary key should be able to login.
    
  412.         """
    
  413.         user = UUIDUser.objects.create_user(username="uuid", password="test")
    
  414.         self.assertTrue(self.client.login(username="uuid", password="test"))
    
  415.         self.assertEqual(
    
  416.             UUIDUser.objects.get(pk=self.client.session[SESSION_KEY]), user
    
  417.         )
    
  418. 
    
  419. 
    
  420. class TestObj:
    
  421.     pass
    
  422. 
    
  423. 
    
  424. class SimpleRowlevelBackend:
    
  425.     def has_perm(self, user, perm, obj=None):
    
  426.         if not obj:
    
  427.             return  # We only support row level perms
    
  428. 
    
  429.         if isinstance(obj, TestObj):
    
  430.             if user.username == "test2":
    
  431.                 return True
    
  432.             elif user.is_anonymous and perm == "anon":
    
  433.                 return True
    
  434.             elif not user.is_active and perm == "inactive":
    
  435.                 return True
    
  436.         return False
    
  437. 
    
  438.     def has_module_perms(self, user, app_label):
    
  439.         return (user.is_anonymous or user.is_active) and app_label == "app1"
    
  440. 
    
  441.     def get_all_permissions(self, user, obj=None):
    
  442.         if not obj:
    
  443.             return []  # We only support row level perms
    
  444. 
    
  445.         if not isinstance(obj, TestObj):
    
  446.             return ["none"]
    
  447. 
    
  448.         if user.is_anonymous:
    
  449.             return ["anon"]
    
  450.         if user.username == "test2":
    
  451.             return ["simple", "advanced"]
    
  452.         else:
    
  453.             return ["simple"]
    
  454. 
    
  455.     def get_group_permissions(self, user, obj=None):
    
  456.         if not obj:
    
  457.             return  # We only support row level perms
    
  458. 
    
  459.         if not isinstance(obj, TestObj):
    
  460.             return ["none"]
    
  461. 
    
  462.         if "test_group" in [group.name for group in user.groups.all()]:
    
  463.             return ["group_perm"]
    
  464.         else:
    
  465.             return ["none"]
    
  466. 
    
  467. 
    
  468. @modify_settings(
    
  469.     AUTHENTICATION_BACKENDS={
    
  470.         "append": "auth_tests.test_auth_backends.SimpleRowlevelBackend",
    
  471.     }
    
  472. )
    
  473. class RowlevelBackendTest(TestCase):
    
  474.     """
    
  475.     Tests for auth backend that supports object level permissions
    
  476.     """
    
  477. 
    
  478.     @classmethod
    
  479.     def setUpTestData(cls):
    
  480.         cls.user1 = User.objects.create_user("test", "[email protected]", "test")
    
  481.         cls.user2 = User.objects.create_user("test2", "[email protected]", "test")
    
  482.         cls.user3 = User.objects.create_user("test3", "[email protected]", "test")
    
  483. 
    
  484.     def tearDown(self):
    
  485.         # The get_group_permissions test messes with ContentTypes, which will
    
  486.         # be cached; flush the cache to ensure there are no side effects
    
  487.         # Refs #14975, #14925
    
  488.         ContentType.objects.clear_cache()
    
  489. 
    
  490.     def test_has_perm(self):
    
  491.         self.assertIs(self.user1.has_perm("perm", TestObj()), False)
    
  492.         self.assertIs(self.user2.has_perm("perm", TestObj()), True)
    
  493.         self.assertIs(self.user2.has_perm("perm"), False)
    
  494.         self.assertIs(self.user2.has_perms(["simple", "advanced"], TestObj()), True)
    
  495.         self.assertIs(self.user3.has_perm("perm", TestObj()), False)
    
  496.         self.assertIs(self.user3.has_perm("anon", TestObj()), False)
    
  497.         self.assertIs(self.user3.has_perms(["simple", "advanced"], TestObj()), False)
    
  498. 
    
  499.     def test_get_all_permissions(self):
    
  500.         self.assertEqual(self.user1.get_all_permissions(TestObj()), {"simple"})
    
  501.         self.assertEqual(
    
  502.             self.user2.get_all_permissions(TestObj()), {"simple", "advanced"}
    
  503.         )
    
  504.         self.assertEqual(self.user2.get_all_permissions(), set())
    
  505. 
    
  506.     def test_get_group_permissions(self):
    
  507.         group = Group.objects.create(name="test_group")
    
  508.         self.user3.groups.add(group)
    
  509.         self.assertEqual(self.user3.get_group_permissions(TestObj()), {"group_perm"})
    
  510. 
    
  511. 
    
  512. @override_settings(
    
  513.     AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.SimpleRowlevelBackend"],
    
  514. )
    
  515. class AnonymousUserBackendTest(SimpleTestCase):
    
  516.     """
    
  517.     Tests for AnonymousUser delegating to backend.
    
  518.     """
    
  519. 
    
  520.     def setUp(self):
    
  521.         self.user1 = AnonymousUser()
    
  522. 
    
  523.     def test_has_perm(self):
    
  524.         self.assertIs(self.user1.has_perm("perm", TestObj()), False)
    
  525.         self.assertIs(self.user1.has_perm("anon", TestObj()), True)
    
  526. 
    
  527.     def test_has_perms(self):
    
  528.         self.assertIs(self.user1.has_perms(["anon"], TestObj()), True)
    
  529.         self.assertIs(self.user1.has_perms(["anon", "perm"], TestObj()), False)
    
  530. 
    
  531.     def test_has_perms_perm_list_invalid(self):
    
  532.         msg = "perm_list must be an iterable of permissions."
    
  533.         with self.assertRaisesMessage(ValueError, msg):
    
  534.             self.user1.has_perms("perm")
    
  535.         with self.assertRaisesMessage(ValueError, msg):
    
  536.             self.user1.has_perms(object())
    
  537. 
    
  538.     def test_has_module_perms(self):
    
  539.         self.assertIs(self.user1.has_module_perms("app1"), True)
    
  540.         self.assertIs(self.user1.has_module_perms("app2"), False)
    
  541. 
    
  542.     def test_get_all_permissions(self):
    
  543.         self.assertEqual(self.user1.get_all_permissions(TestObj()), {"anon"})
    
  544. 
    
  545. 
    
  546. @override_settings(AUTHENTICATION_BACKENDS=[])
    
  547. class NoBackendsTest(TestCase):
    
  548.     """
    
  549.     An appropriate error is raised if no auth backends are provided.
    
  550.     """
    
  551. 
    
  552.     @classmethod
    
  553.     def setUpTestData(cls):
    
  554.         cls.user = User.objects.create_user("test", "[email protected]", "test")
    
  555. 
    
  556.     def test_raises_exception(self):
    
  557.         msg = (
    
  558.             "No authentication backends have been defined. "
    
  559.             "Does AUTHENTICATION_BACKENDS contain anything?"
    
  560.         )
    
  561.         with self.assertRaisesMessage(ImproperlyConfigured, msg):
    
  562.             self.user.has_perm(("perm", TestObj()))
    
  563. 
    
  564. 
    
  565. @override_settings(
    
  566.     AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.SimpleRowlevelBackend"]
    
  567. )
    
  568. class InActiveUserBackendTest(TestCase):
    
  569.     """
    
  570.     Tests for an inactive user
    
  571.     """
    
  572. 
    
  573.     @classmethod
    
  574.     def setUpTestData(cls):
    
  575.         cls.user1 = User.objects.create_user("test", "[email protected]", "test")
    
  576.         cls.user1.is_active = False
    
  577.         cls.user1.save()
    
  578. 
    
  579.     def test_has_perm(self):
    
  580.         self.assertIs(self.user1.has_perm("perm", TestObj()), False)
    
  581.         self.assertIs(self.user1.has_perm("inactive", TestObj()), True)
    
  582. 
    
  583.     def test_has_module_perms(self):
    
  584.         self.assertIs(self.user1.has_module_perms("app1"), False)
    
  585.         self.assertIs(self.user1.has_module_perms("app2"), False)
    
  586. 
    
  587. 
    
  588. class PermissionDeniedBackend:
    
  589.     """
    
  590.     Always raises PermissionDenied in `authenticate`, `has_perm` and `has_module_perms`.
    
  591.     """
    
  592. 
    
  593.     def authenticate(self, request, username=None, password=None):
    
  594.         raise PermissionDenied
    
  595. 
    
  596.     def has_perm(self, user_obj, perm, obj=None):
    
  597.         raise PermissionDenied
    
  598. 
    
  599.     def has_module_perms(self, user_obj, app_label):
    
  600.         raise PermissionDenied
    
  601. 
    
  602. 
    
  603. class PermissionDeniedBackendTest(TestCase):
    
  604.     """
    
  605.     Other backends are not checked once a backend raises PermissionDenied
    
  606.     """
    
  607. 
    
  608.     backend = "auth_tests.test_auth_backends.PermissionDeniedBackend"
    
  609. 
    
  610.     @classmethod
    
  611.     def setUpTestData(cls):
    
  612.         cls.user1 = User.objects.create_user("test", "[email protected]", "test")
    
  613. 
    
  614.     def setUp(self):
    
  615.         self.user_login_failed = []
    
  616.         signals.user_login_failed.connect(self.user_login_failed_listener)
    
  617. 
    
  618.     def tearDown(self):
    
  619.         signals.user_login_failed.disconnect(self.user_login_failed_listener)
    
  620. 
    
  621.     def user_login_failed_listener(self, sender, credentials, **kwargs):
    
  622.         self.user_login_failed.append(credentials)
    
  623. 
    
  624.     @modify_settings(AUTHENTICATION_BACKENDS={"prepend": backend})
    
  625.     def test_permission_denied(self):
    
  626.         "user is not authenticated after a backend raises permission denied #2550"
    
  627.         self.assertIsNone(authenticate(username="test", password="test"))
    
  628.         # user_login_failed signal is sent.
    
  629.         self.assertEqual(
    
  630.             self.user_login_failed,
    
  631.             [{"password": "********************", "username": "test"}],
    
  632.         )
    
  633. 
    
  634.     @modify_settings(AUTHENTICATION_BACKENDS={"append": backend})
    
  635.     def test_authenticates(self):
    
  636.         self.assertEqual(authenticate(username="test", password="test"), self.user1)
    
  637. 
    
  638.     @modify_settings(AUTHENTICATION_BACKENDS={"prepend": backend})
    
  639.     def test_has_perm_denied(self):
    
  640.         content_type = ContentType.objects.get_for_model(Group)
    
  641.         perm = Permission.objects.create(
    
  642.             name="test", content_type=content_type, codename="test"
    
  643.         )
    
  644.         self.user1.user_permissions.add(perm)
    
  645. 
    
  646.         self.assertIs(self.user1.has_perm("auth.test"), False)
    
  647.         self.assertIs(self.user1.has_module_perms("auth"), False)
    
  648. 
    
  649.     @modify_settings(AUTHENTICATION_BACKENDS={"append": backend})
    
  650.     def test_has_perm(self):
    
  651.         content_type = ContentType.objects.get_for_model(Group)
    
  652.         perm = Permission.objects.create(
    
  653.             name="test", content_type=content_type, codename="test"
    
  654.         )
    
  655.         self.user1.user_permissions.add(perm)
    
  656. 
    
  657.         self.assertIs(self.user1.has_perm("auth.test"), True)
    
  658.         self.assertIs(self.user1.has_module_perms("auth"), True)
    
  659. 
    
  660. 
    
  661. class NewModelBackend(ModelBackend):
    
  662.     pass
    
  663. 
    
  664. 
    
  665. class ChangedBackendSettingsTest(TestCase):
    
  666.     """
    
  667.     Tests for changes in the settings.AUTHENTICATION_BACKENDS
    
  668.     """
    
  669. 
    
  670.     backend = "auth_tests.test_auth_backends.NewModelBackend"
    
  671. 
    
  672.     TEST_USERNAME = "test_user"
    
  673.     TEST_PASSWORD = "test_password"
    
  674.     TEST_EMAIL = "[email protected]"
    
  675. 
    
  676.     @classmethod
    
  677.     def setUpTestData(cls):
    
  678.         User.objects.create_user(cls.TEST_USERNAME, cls.TEST_EMAIL, cls.TEST_PASSWORD)
    
  679. 
    
  680.     @override_settings(AUTHENTICATION_BACKENDS=[backend])
    
  681.     def test_changed_backend_settings(self):
    
  682.         """
    
  683.         Removing a backend configured in AUTHENTICATION_BACKENDS makes already
    
  684.         logged-in users disconnect.
    
  685.         """
    
  686.         # Get a session for the test user
    
  687.         self.assertTrue(
    
  688.             self.client.login(
    
  689.                 username=self.TEST_USERNAME,
    
  690.                 password=self.TEST_PASSWORD,
    
  691.             )
    
  692.         )
    
  693.         # Prepare a request object
    
  694.         request = HttpRequest()
    
  695.         request.session = self.client.session
    
  696.         # Remove NewModelBackend
    
  697.         with self.settings(
    
  698.             AUTHENTICATION_BACKENDS=["django.contrib.auth.backends.ModelBackend"]
    
  699.         ):
    
  700.             # Get the user from the request
    
  701.             user = get_user(request)
    
  702. 
    
  703.             # Assert that the user retrieval is successful and the user is
    
  704.             # anonymous as the backend is not longer available.
    
  705.             self.assertIsNotNone(user)
    
  706.             self.assertTrue(user.is_anonymous)
    
  707. 
    
  708. 
    
  709. class TypeErrorBackend:
    
  710.     """
    
  711.     Always raises TypeError.
    
  712.     """
    
  713. 
    
  714.     @sensitive_variables("password")
    
  715.     def authenticate(self, request, username=None, password=None):
    
  716.         raise TypeError
    
  717. 
    
  718. 
    
  719. class SkippedBackend:
    
  720.     def authenticate(self):
    
  721.         # Doesn't accept any credentials so is skipped by authenticate().
    
  722.         pass
    
  723. 
    
  724. 
    
  725. class SkippedBackendWithDecoratedMethod:
    
  726.     @sensitive_variables()
    
  727.     def authenticate(self):
    
  728.         pass
    
  729. 
    
  730. 
    
  731. class AuthenticateTests(TestCase):
    
  732.     @classmethod
    
  733.     def setUpTestData(cls):
    
  734.         cls.user1 = User.objects.create_user("test", "[email protected]", "test")
    
  735. 
    
  736.     def setUp(self):
    
  737.         self.sensitive_password = "mypassword"
    
  738. 
    
  739.     @override_settings(
    
  740.         AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.TypeErrorBackend"]
    
  741.     )
    
  742.     def test_type_error_raised(self):
    
  743.         """A TypeError within a backend is propagated properly (#18171)."""
    
  744.         with self.assertRaises(TypeError):
    
  745.             authenticate(username="test", password="test")
    
  746. 
    
  747.     @override_settings(
    
  748.         AUTHENTICATION_BACKENDS=["auth_tests.test_auth_backends.TypeErrorBackend"]
    
  749.     )
    
  750.     def test_authenticate_sensitive_variables(self):
    
  751.         try:
    
  752.             authenticate(username="testusername", password=self.sensitive_password)
    
  753.         except TypeError:
    
  754.             exc_info = sys.exc_info()
    
  755.         rf = RequestFactory()
    
  756.         response = technical_500_response(rf.get("/"), *exc_info)
    
  757.         self.assertNotContains(response, self.sensitive_password, status_code=500)
    
  758.         self.assertContains(response, "TypeErrorBackend", status_code=500)
    
  759.         self.assertContains(
    
  760.             response,
    
  761.             '<tr><td>credentials</td><td class="code">'
    
  762.             "<pre>&#39;********************&#39;</pre></td></tr>",
    
  763.             html=True,
    
  764.             status_code=500,
    
  765.         )
    
  766. 
    
  767.     def test_clean_credentials_sensitive_variables(self):
    
  768.         try:
    
  769.             # Passing in a list to cause an exception
    
  770.             _clean_credentials([1, self.sensitive_password])
    
  771.         except TypeError:
    
  772.             exc_info = sys.exc_info()
    
  773.         rf = RequestFactory()
    
  774.         response = technical_500_response(rf.get("/"), *exc_info)
    
  775.         self.assertNotContains(response, self.sensitive_password, status_code=500)
    
  776.         self.assertContains(
    
  777.             response,
    
  778.             '<tr><td>credentials</td><td class="code">'
    
  779.             "<pre>&#39;********************&#39;</pre></td></tr>",
    
  780.             html=True,
    
  781.             status_code=500,
    
  782.         )
    
  783. 
    
  784.     @override_settings(
    
  785.         AUTHENTICATION_BACKENDS=(
    
  786.             "auth_tests.test_auth_backends.SkippedBackend",
    
  787.             "django.contrib.auth.backends.ModelBackend",
    
  788.         )
    
  789.     )
    
  790.     def test_skips_backends_without_arguments(self):
    
  791.         """
    
  792.         A backend (SkippedBackend) is ignored if it doesn't accept the
    
  793.         credentials as arguments.
    
  794.         """
    
  795.         self.assertEqual(authenticate(username="test", password="test"), self.user1)
    
  796. 
    
  797.     @override_settings(
    
  798.         AUTHENTICATION_BACKENDS=(
    
  799.             "auth_tests.test_auth_backends.SkippedBackendWithDecoratedMethod",
    
  800.             "django.contrib.auth.backends.ModelBackend",
    
  801.         )
    
  802.     )
    
  803.     def test_skips_backends_with_decorated_method(self):
    
  804.         self.assertEqual(authenticate(username="test", password="test"), self.user1)
    
  805. 
    
  806. 
    
  807. class ImproperlyConfiguredUserModelTest(TestCase):
    
  808.     """
    
  809.     An exception from within get_user_model() is propagated and doesn't
    
  810.     raise an UnboundLocalError (#21439).
    
  811.     """
    
  812. 
    
  813.     @classmethod
    
  814.     def setUpTestData(cls):
    
  815.         cls.user1 = User.objects.create_user("test", "[email protected]", "test")
    
  816. 
    
  817.     def setUp(self):
    
  818.         self.client.login(username="test", password="test")
    
  819. 
    
  820.     @override_settings(AUTH_USER_MODEL="thismodel.doesntexist")
    
  821.     def test_does_not_shadow_exception(self):
    
  822.         # Prepare a request object
    
  823.         request = HttpRequest()
    
  824.         request.session = self.client.session
    
  825. 
    
  826.         msg = (
    
  827.             "AUTH_USER_MODEL refers to model 'thismodel.doesntexist' "
    
  828.             "that has not been installed"
    
  829.         )
    
  830.         with self.assertRaisesMessage(ImproperlyConfigured, msg):
    
  831.             get_user(request)
    
  832. 
    
  833. 
    
  834. class ImportedModelBackend(ModelBackend):
    
  835.     pass
    
  836. 
    
  837. 
    
  838. class CustomModelBackend(ModelBackend):
    
  839.     pass
    
  840. 
    
  841. 
    
  842. class OtherModelBackend(ModelBackend):
    
  843.     pass
    
  844. 
    
  845. 
    
  846. class ImportedBackendTests(TestCase):
    
  847.     """
    
  848.     #23925 - The backend path added to the session should be the same
    
  849.     as the one defined in AUTHENTICATION_BACKENDS setting.
    
  850.     """
    
  851. 
    
  852.     backend = "auth_tests.backend_alias.ImportedModelBackend"
    
  853. 
    
  854.     @override_settings(AUTHENTICATION_BACKENDS=[backend])
    
  855.     def test_backend_path(self):
    
  856.         username = "username"
    
  857.         password = "password"
    
  858.         User.objects.create_user(username, "email", password)
    
  859.         self.assertTrue(self.client.login(username=username, password=password))
    
  860.         request = HttpRequest()
    
  861.         request.session = self.client.session
    
  862.         self.assertEqual(request.session[BACKEND_SESSION_KEY], self.backend)
    
  863. 
    
  864. 
    
  865. class SelectingBackendTests(TestCase):
    
  866.     backend = "auth_tests.test_auth_backends.CustomModelBackend"
    
  867.     other_backend = "auth_tests.test_auth_backends.OtherModelBackend"
    
  868.     username = "username"
    
  869.     password = "password"
    
  870. 
    
  871.     def assertBackendInSession(self, backend):
    
  872.         request = HttpRequest()
    
  873.         request.session = self.client.session
    
  874.         self.assertEqual(request.session[BACKEND_SESSION_KEY], backend)
    
  875. 
    
  876.     @override_settings(AUTHENTICATION_BACKENDS=[backend])
    
  877.     def test_backend_path_login_without_authenticate_single_backend(self):
    
  878.         user = User.objects.create_user(self.username, "email", self.password)
    
  879.         self.client._login(user)
    
  880.         self.assertBackendInSession(self.backend)
    
  881. 
    
  882.     @override_settings(AUTHENTICATION_BACKENDS=[backend, other_backend])
    
  883.     def test_backend_path_login_without_authenticate_multiple_backends(self):
    
  884.         user = User.objects.create_user(self.username, "email", self.password)
    
  885.         expected_message = (
    
  886.             "You have multiple authentication backends configured and "
    
  887.             "therefore must provide the `backend` argument or set the "
    
  888.             "`backend` attribute on the user."
    
  889.         )
    
  890.         with self.assertRaisesMessage(ValueError, expected_message):
    
  891.             self.client._login(user)
    
  892. 
    
  893.     def test_non_string_backend(self):
    
  894.         user = User.objects.create_user(self.username, "email", self.password)
    
  895.         expected_message = (
    
  896.             "backend must be a dotted import path string (got "
    
  897.             "<class 'django.contrib.auth.backends.ModelBackend'>)."
    
  898.         )
    
  899.         with self.assertRaisesMessage(TypeError, expected_message):
    
  900.             self.client._login(user, backend=ModelBackend)
    
  901. 
    
  902.     @override_settings(AUTHENTICATION_BACKENDS=[backend, other_backend])
    
  903.     def test_backend_path_login_with_explicit_backends(self):
    
  904.         user = User.objects.create_user(self.username, "email", self.password)
    
  905.         self.client._login(user, self.other_backend)
    
  906.         self.assertBackendInSession(self.other_backend)
    
  907. 
    
  908. 
    
  909. @override_settings(
    
  910.     AUTHENTICATION_BACKENDS=["django.contrib.auth.backends.AllowAllUsersModelBackend"]
    
  911. )
    
  912. class AllowAllUsersModelBackendTest(TestCase):
    
  913.     """
    
  914.     Inactive users may authenticate with the AllowAllUsersModelBackend.
    
  915.     """
    
  916. 
    
  917.     user_credentials = {"username": "test", "password": "test"}
    
  918. 
    
  919.     @classmethod
    
  920.     def setUpTestData(cls):
    
  921.         cls.user = User.objects.create_user(
    
  922.             email="[email protected]", is_active=False, **cls.user_credentials
    
  923.         )
    
  924. 
    
  925.     def test_authenticate(self):
    
  926.         self.assertFalse(self.user.is_active)
    
  927.         self.assertEqual(authenticate(**self.user_credentials), self.user)
    
  928. 
    
  929.     def test_get_user(self):
    
  930.         self.client.force_login(self.user)
    
  931.         request = HttpRequest()
    
  932.         request.session = self.client.session
    
  933.         user = get_user(request)
    
  934.         self.assertEqual(user, self.user)