test_models.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. from unittest import mock
  2. from django.conf.global_settings import PASSWORD_HASHERS
  3. from django.contrib.auth import get_user_model
  4. from django.contrib.auth.base_user import AbstractBaseUser
  5. from django.contrib.auth.hashers import get_hasher
  6. from django.contrib.auth.models import (
  7. AbstractUser, AnonymousUser, Group, Permission, User, UserManager,
  8. )
  9. from django.contrib.contenttypes.models import ContentType
  10. from django.core import mail
  11. from django.db.models.signals import post_save
  12. from django.test import SimpleTestCase, TestCase, override_settings
  13. from .models import IntegerUsernameUser
  14. from .models.with_custom_email_field import CustomEmailField
  15. class NaturalKeysTestCase(TestCase):
  16. def test_user_natural_key(self):
  17. staff_user = User.objects.create_user(username='staff')
  18. self.assertEqual(User.objects.get_by_natural_key('staff'), staff_user)
  19. self.assertEqual(staff_user.natural_key(), ('staff',))
  20. def test_group_natural_key(self):
  21. users_group = Group.objects.create(name='users')
  22. self.assertEqual(Group.objects.get_by_natural_key('users'), users_group)
  23. class LoadDataWithoutNaturalKeysTestCase(TestCase):
  24. fixtures = ['regular.json']
  25. def test_user_is_created_and_added_to_group(self):
  26. user = User.objects.get(username='my_username')
  27. group = Group.objects.get(name='my_group')
  28. self.assertEqual(group, user.groups.get())
  29. class LoadDataWithNaturalKeysTestCase(TestCase):
  30. fixtures = ['natural.json']
  31. def test_user_is_created_and_added_to_group(self):
  32. user = User.objects.get(username='my_username')
  33. group = Group.objects.get(name='my_group')
  34. self.assertEqual(group, user.groups.get())
  35. class LoadDataWithNaturalKeysAndMultipleDatabasesTestCase(TestCase):
  36. databases = {'default', 'other'}
  37. def test_load_data_with_user_permissions(self):
  38. # Create test contenttypes for both databases
  39. default_objects = [
  40. ContentType.objects.db_manager('default').create(
  41. model='examplemodela',
  42. app_label='app_a',
  43. ),
  44. ContentType.objects.db_manager('default').create(
  45. model='examplemodelb',
  46. app_label='app_b',
  47. ),
  48. ]
  49. other_objects = [
  50. ContentType.objects.db_manager('other').create(
  51. model='examplemodelb',
  52. app_label='app_b',
  53. ),
  54. ContentType.objects.db_manager('other').create(
  55. model='examplemodela',
  56. app_label='app_a',
  57. ),
  58. ]
  59. # Now we create the test UserPermission
  60. Permission.objects.db_manager("default").create(
  61. name="Can delete example model b",
  62. codename="delete_examplemodelb",
  63. content_type=default_objects[1],
  64. )
  65. Permission.objects.db_manager("other").create(
  66. name="Can delete example model b",
  67. codename="delete_examplemodelb",
  68. content_type=other_objects[0],
  69. )
  70. perm_default = Permission.objects.get_by_natural_key(
  71. 'delete_examplemodelb',
  72. 'app_b',
  73. 'examplemodelb',
  74. )
  75. perm_other = Permission.objects.db_manager('other').get_by_natural_key(
  76. 'delete_examplemodelb',
  77. 'app_b',
  78. 'examplemodelb',
  79. )
  80. self.assertEqual(perm_default.content_type_id, default_objects[1].id)
  81. self.assertEqual(perm_other.content_type_id, other_objects[0].id)
  82. class UserManagerTestCase(TestCase):
  83. def test_create_user(self):
  84. email_lowercase = 'normal@normal.com'
  85. user = User.objects.create_user('user', email_lowercase)
  86. self.assertEqual(user.email, email_lowercase)
  87. self.assertEqual(user.username, 'user')
  88. self.assertFalse(user.has_usable_password())
  89. def test_create_user_email_domain_normalize_rfc3696(self):
  90. # According to https://tools.ietf.org/html/rfc3696#section-3
  91. # the "@" symbol can be part of the local part of an email address
  92. returned = UserManager.normalize_email(r'Abc\@DEF@EXAMPLE.com')
  93. self.assertEqual(returned, r'Abc\@DEF@example.com')
  94. def test_create_user_email_domain_normalize(self):
  95. returned = UserManager.normalize_email('normal@DOMAIN.COM')
  96. self.assertEqual(returned, 'normal@domain.com')
  97. def test_create_user_email_domain_normalize_with_whitespace(self):
  98. returned = UserManager.normalize_email(r'email\ with_whitespace@D.COM')
  99. self.assertEqual(returned, r'email\ with_whitespace@d.com')
  100. def test_empty_username(self):
  101. with self.assertRaisesMessage(ValueError, 'The given username must be set'):
  102. User.objects.create_user(username='')
  103. def test_create_user_is_staff(self):
  104. email = 'normal@normal.com'
  105. user = User.objects.create_user('user', email, is_staff=True)
  106. self.assertEqual(user.email, email)
  107. self.assertEqual(user.username, 'user')
  108. self.assertTrue(user.is_staff)
  109. def test_create_super_user_raises_error_on_false_is_superuser(self):
  110. with self.assertRaisesMessage(ValueError, 'Superuser must have is_superuser=True.'):
  111. User.objects.create_superuser(
  112. username='test', email='test@test.com',
  113. password='test', is_superuser=False,
  114. )
  115. def test_create_superuser_raises_error_on_false_is_staff(self):
  116. with self.assertRaisesMessage(ValueError, 'Superuser must have is_staff=True.'):
  117. User.objects.create_superuser(
  118. username='test', email='test@test.com',
  119. password='test', is_staff=False,
  120. )
  121. def test_make_random_password(self):
  122. allowed_chars = 'abcdefg'
  123. password = UserManager().make_random_password(5, allowed_chars)
  124. self.assertEqual(len(password), 5)
  125. for char in password:
  126. self.assertIn(char, allowed_chars)
  127. class AbstractBaseUserTests(SimpleTestCase):
  128. def test_has_usable_password(self):
  129. """
  130. Passwords are usable even if they don't correspond to a hasher in
  131. settings.PASSWORD_HASHERS.
  132. """
  133. self.assertIs(User(password='some-gibbberish').has_usable_password(), True)
  134. def test_normalize_username(self):
  135. self.assertEqual(IntegerUsernameUser().normalize_username(123), 123)
  136. def test_clean_normalize_username(self):
  137. # The normalization happens in AbstractBaseUser.clean()
  138. ohm_username = 'iamtheΩ' # U+2126 OHM SIGN
  139. for model in ('auth.User', 'auth_tests.CustomUser'):
  140. with self.subTest(model=model), self.settings(AUTH_USER_MODEL=model):
  141. User = get_user_model()
  142. user = User(**{User.USERNAME_FIELD: ohm_username, 'password': 'foo'})
  143. user.clean()
  144. username = user.get_username()
  145. self.assertNotEqual(username, ohm_username)
  146. self.assertEqual(username, 'iamtheΩ') # U+03A9 GREEK CAPITAL LETTER OMEGA
  147. def test_default_email(self):
  148. user = AbstractBaseUser()
  149. self.assertEqual(user.get_email_field_name(), 'email')
  150. def test_custom_email(self):
  151. user = CustomEmailField()
  152. self.assertEqual(user.get_email_field_name(), 'email_address')
  153. class AbstractUserTestCase(TestCase):
  154. def test_email_user(self):
  155. # valid send_mail parameters
  156. kwargs = {
  157. "fail_silently": False,
  158. "auth_user": None,
  159. "auth_password": None,
  160. "connection": None,
  161. "html_message": None,
  162. }
  163. abstract_user = AbstractUser(email='foo@bar.com')
  164. abstract_user.email_user(
  165. subject="Subject here",
  166. message="This is a message",
  167. from_email="from@domain.com",
  168. **kwargs
  169. )
  170. self.assertEqual(len(mail.outbox), 1)
  171. message = mail.outbox[0]
  172. self.assertEqual(message.subject, "Subject here")
  173. self.assertEqual(message.body, "This is a message")
  174. self.assertEqual(message.from_email, "from@domain.com")
  175. self.assertEqual(message.to, [abstract_user.email])
  176. def test_last_login_default(self):
  177. user1 = User.objects.create(username='user1')
  178. self.assertIsNone(user1.last_login)
  179. user2 = User.objects.create_user(username='user2')
  180. self.assertIsNone(user2.last_login)
  181. def test_user_clean_normalize_email(self):
  182. user = User(username='user', password='foo', email='foo@BAR.com')
  183. user.clean()
  184. self.assertEqual(user.email, 'foo@bar.com')
  185. def test_user_double_save(self):
  186. """
  187. Calling user.save() twice should trigger password_changed() once.
  188. """
  189. user = User.objects.create_user(username='user', password='foo')
  190. user.set_password('bar')
  191. with mock.patch('django.contrib.auth.password_validation.password_changed') as pw_changed:
  192. user.save()
  193. self.assertEqual(pw_changed.call_count, 1)
  194. user.save()
  195. self.assertEqual(pw_changed.call_count, 1)
  196. @override_settings(PASSWORD_HASHERS=PASSWORD_HASHERS)
  197. def test_check_password_upgrade(self):
  198. """
  199. password_changed() shouldn't be called if User.check_password()
  200. triggers a hash iteration upgrade.
  201. """
  202. user = User.objects.create_user(username='user', password='foo')
  203. initial_password = user.password
  204. self.assertTrue(user.check_password('foo'))
  205. hasher = get_hasher('default')
  206. self.assertEqual('pbkdf2_sha256', hasher.algorithm)
  207. old_iterations = hasher.iterations
  208. try:
  209. # Upgrade the password iterations
  210. hasher.iterations = old_iterations + 1
  211. with mock.patch('django.contrib.auth.password_validation.password_changed') as pw_changed:
  212. user.check_password('foo')
  213. self.assertEqual(pw_changed.call_count, 0)
  214. self.assertNotEqual(initial_password, user.password)
  215. finally:
  216. hasher.iterations = old_iterations
  217. class IsActiveTestCase(TestCase):
  218. """
  219. Tests the behavior of the guaranteed is_active attribute
  220. """
  221. def test_builtin_user_isactive(self):
  222. user = User.objects.create(username='foo', email='foo@bar.com')
  223. # is_active is true by default
  224. self.assertIs(user.is_active, True)
  225. user.is_active = False
  226. user.save()
  227. user_fetched = User.objects.get(pk=user.pk)
  228. # the is_active flag is saved
  229. self.assertFalse(user_fetched.is_active)
  230. @override_settings(AUTH_USER_MODEL='auth_tests.IsActiveTestUser1')
  231. def test_is_active_field_default(self):
  232. """
  233. tests that the default value for is_active is provided
  234. """
  235. UserModel = get_user_model()
  236. user = UserModel(username='foo')
  237. self.assertIs(user.is_active, True)
  238. # you can set the attribute - but it will not save
  239. user.is_active = False
  240. # there should be no problem saving - but the attribute is not saved
  241. user.save()
  242. user_fetched = UserModel._default_manager.get(pk=user.pk)
  243. # the attribute is always true for newly retrieved instance
  244. self.assertIs(user_fetched.is_active, True)
  245. class TestCreateSuperUserSignals(TestCase):
  246. """
  247. Simple test case for ticket #20541
  248. """
  249. def post_save_listener(self, *args, **kwargs):
  250. self.signals_count += 1
  251. def setUp(self):
  252. self.signals_count = 0
  253. post_save.connect(self.post_save_listener, sender=User)
  254. def tearDown(self):
  255. post_save.disconnect(self.post_save_listener, sender=User)
  256. def test_create_user(self):
  257. User.objects.create_user("JohnDoe")
  258. self.assertEqual(self.signals_count, 1)
  259. def test_create_superuser(self):
  260. User.objects.create_superuser("JohnDoe", "mail@example.com", "1")
  261. self.assertEqual(self.signals_count, 1)
  262. class AnonymousUserTests(SimpleTestCase):
  263. no_repr_msg = "Django doesn't provide a DB representation for AnonymousUser."
  264. def setUp(self):
  265. self.user = AnonymousUser()
  266. def test_properties(self):
  267. self.assertIsNone(self.user.pk)
  268. self.assertEqual(self.user.username, '')
  269. self.assertEqual(self.user.get_username(), '')
  270. self.assertIs(self.user.is_anonymous, True)
  271. self.assertIs(self.user.is_authenticated, False)
  272. self.assertIs(self.user.is_staff, False)
  273. self.assertIs(self.user.is_active, False)
  274. self.assertIs(self.user.is_superuser, False)
  275. self.assertEqual(self.user.groups.all().count(), 0)
  276. self.assertEqual(self.user.user_permissions.all().count(), 0)
  277. self.assertEqual(self.user.get_user_permissions(), set())
  278. self.assertEqual(self.user.get_group_permissions(), set())
  279. def test_str(self):
  280. self.assertEqual(str(self.user), 'AnonymousUser')
  281. def test_eq(self):
  282. self.assertEqual(self.user, AnonymousUser())
  283. self.assertNotEqual(self.user, User('super', 'super@example.com', 'super'))
  284. def test_hash(self):
  285. self.assertEqual(hash(self.user), 1)
  286. def test_int(self):
  287. msg = (
  288. 'Cannot cast AnonymousUser to int. Are you trying to use it in '
  289. 'place of User?'
  290. )
  291. with self.assertRaisesMessage(TypeError, msg):
  292. int(self.user)
  293. def test_delete(self):
  294. with self.assertRaisesMessage(NotImplementedError, self.no_repr_msg):
  295. self.user.delete()
  296. def test_save(self):
  297. with self.assertRaisesMessage(NotImplementedError, self.no_repr_msg):
  298. self.user.save()
  299. def test_set_password(self):
  300. with self.assertRaisesMessage(NotImplementedError, self.no_repr_msg):
  301. self.user.set_password('password')
  302. def test_check_password(self):
  303. with self.assertRaisesMessage(NotImplementedError, self.no_repr_msg):
  304. self.user.check_password('password')
  305. class GroupTests(SimpleTestCase):
  306. def test_str(self):
  307. g = Group(name='Users')
  308. self.assertEqual(str(g), 'Users')
  309. class PermissionTests(TestCase):
  310. def test_str(self):
  311. p = Permission.objects.get(codename='view_customemailfield')
  312. self.assertEqual(str(p), 'auth_tests | custom email field | Can view custom email field')