test_mixins.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. from unittest import mock
  2. from django.contrib.auth import models
  3. from django.contrib.auth.mixins import (
  4. LoginRequiredMixin, PermissionRequiredMixin, UserPassesTestMixin,
  5. )
  6. from django.contrib.auth.models import AnonymousUser
  7. from django.core.exceptions import PermissionDenied
  8. from django.http import HttpResponse
  9. from django.test import RequestFactory, TestCase
  10. from django.views.generic import View
  11. class AlwaysTrueMixin(UserPassesTestMixin):
  12. def test_func(self):
  13. return True
  14. class AlwaysFalseMixin(UserPassesTestMixin):
  15. def test_func(self):
  16. return False
  17. class EmptyResponseView(View):
  18. def get(self, request, *args, **kwargs):
  19. return HttpResponse()
  20. class AlwaysTrueView(AlwaysTrueMixin, EmptyResponseView):
  21. pass
  22. class AlwaysFalseView(AlwaysFalseMixin, EmptyResponseView):
  23. pass
  24. class StackedMixinsView1(LoginRequiredMixin, PermissionRequiredMixin, EmptyResponseView):
  25. permission_required = ['auth_tests.add_customuser', 'auth_tests.change_customuser']
  26. raise_exception = True
  27. class StackedMixinsView2(PermissionRequiredMixin, LoginRequiredMixin, EmptyResponseView):
  28. permission_required = ['auth_tests.add_customuser', 'auth_tests.change_customuser']
  29. raise_exception = True
  30. class AccessMixinTests(TestCase):
  31. factory = RequestFactory()
  32. def test_stacked_mixins_success(self):
  33. user = models.User.objects.create(username='joe', password='qwerty')
  34. perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
  35. user.user_permissions.add(*perms)
  36. request = self.factory.get('/rand')
  37. request.user = user
  38. view = StackedMixinsView1.as_view()
  39. response = view(request)
  40. self.assertEqual(response.status_code, 200)
  41. view = StackedMixinsView2.as_view()
  42. response = view(request)
  43. self.assertEqual(response.status_code, 200)
  44. def test_stacked_mixins_missing_permission(self):
  45. user = models.User.objects.create(username='joe', password='qwerty')
  46. perms = models.Permission.objects.filter(codename__in=('add_customuser',))
  47. user.user_permissions.add(*perms)
  48. request = self.factory.get('/rand')
  49. request.user = user
  50. view = StackedMixinsView1.as_view()
  51. with self.assertRaises(PermissionDenied):
  52. view(request)
  53. view = StackedMixinsView2.as_view()
  54. with self.assertRaises(PermissionDenied):
  55. view(request)
  56. @mock.patch.object(models.User, 'is_authenticated', False)
  57. def test_stacked_mixins_not_logged_in(self):
  58. user = models.User.objects.create(username='joe', password='qwerty')
  59. perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
  60. user.user_permissions.add(*perms)
  61. request = self.factory.get('/rand')
  62. request.user = user
  63. view = StackedMixinsView1.as_view()
  64. with self.assertRaises(PermissionDenied):
  65. view(request)
  66. view = StackedMixinsView2.as_view()
  67. with self.assertRaises(PermissionDenied):
  68. view(request)
  69. class UserPassesTestTests(TestCase):
  70. factory = RequestFactory()
  71. def _test_redirect(self, view=None, url='/accounts/login/?next=/rand'):
  72. if not view:
  73. view = AlwaysFalseView.as_view()
  74. request = self.factory.get('/rand')
  75. request.user = AnonymousUser()
  76. response = view(request)
  77. self.assertEqual(response.status_code, 302)
  78. self.assertEqual(response.url, url)
  79. def test_default(self):
  80. self._test_redirect()
  81. def test_custom_redirect_url(self):
  82. class AView(AlwaysFalseView):
  83. login_url = '/login/'
  84. self._test_redirect(AView.as_view(), '/login/?next=/rand')
  85. def test_custom_redirect_parameter(self):
  86. class AView(AlwaysFalseView):
  87. redirect_field_name = 'goto'
  88. self._test_redirect(AView.as_view(), '/accounts/login/?goto=/rand')
  89. def test_no_redirect_parameter(self):
  90. class AView(AlwaysFalseView):
  91. redirect_field_name = None
  92. self._test_redirect(AView.as_view(), '/accounts/login/')
  93. def test_raise_exception(self):
  94. class AView(AlwaysFalseView):
  95. raise_exception = True
  96. request = self.factory.get('/rand')
  97. request.user = AnonymousUser()
  98. with self.assertRaises(PermissionDenied):
  99. AView.as_view()(request)
  100. def test_raise_exception_custom_message(self):
  101. msg = "You don't have access here"
  102. class AView(AlwaysFalseView):
  103. raise_exception = True
  104. permission_denied_message = msg
  105. request = self.factory.get('/rand')
  106. request.user = AnonymousUser()
  107. view = AView.as_view()
  108. with self.assertRaises(PermissionDenied) as cm:
  109. view(request)
  110. self.assertEqual(cm.exception.args[0], msg)
  111. def test_raise_exception_custom_message_function(self):
  112. msg = "You don't have access here"
  113. class AView(AlwaysFalseView):
  114. raise_exception = True
  115. def get_permission_denied_message(self):
  116. return msg
  117. request = self.factory.get('/rand')
  118. request.user = AnonymousUser()
  119. view = AView.as_view()
  120. with self.assertRaises(PermissionDenied) as cm:
  121. view(request)
  122. self.assertEqual(cm.exception.args[0], msg)
  123. def test_user_passes(self):
  124. view = AlwaysTrueView.as_view()
  125. request = self.factory.get('/rand')
  126. request.user = AnonymousUser()
  127. response = view(request)
  128. self.assertEqual(response.status_code, 200)
  129. class LoginRequiredMixinTests(TestCase):
  130. factory = RequestFactory()
  131. @classmethod
  132. def setUpTestData(cls):
  133. cls.user = models.User.objects.create(username='joe', password='qwerty')
  134. def test_login_required(self):
  135. """
  136. login_required works on a simple view wrapped in a login_required
  137. decorator.
  138. """
  139. class AView(LoginRequiredMixin, EmptyResponseView):
  140. pass
  141. view = AView.as_view()
  142. request = self.factory.get('/rand')
  143. request.user = AnonymousUser()
  144. response = view(request)
  145. self.assertEqual(response.status_code, 302)
  146. self.assertEqual('/accounts/login/?next=/rand', response.url)
  147. request = self.factory.get('/rand')
  148. request.user = self.user
  149. response = view(request)
  150. self.assertEqual(response.status_code, 200)
  151. class PermissionsRequiredMixinTests(TestCase):
  152. factory = RequestFactory()
  153. @classmethod
  154. def setUpTestData(cls):
  155. cls.user = models.User.objects.create(username='joe', password='qwerty')
  156. perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
  157. cls.user.user_permissions.add(*perms)
  158. def test_many_permissions_pass(self):
  159. class AView(PermissionRequiredMixin, EmptyResponseView):
  160. permission_required = ['auth_tests.add_customuser', 'auth_tests.change_customuser']
  161. request = self.factory.get('/rand')
  162. request.user = self.user
  163. resp = AView.as_view()(request)
  164. self.assertEqual(resp.status_code, 200)
  165. def test_single_permission_pass(self):
  166. class AView(PermissionRequiredMixin, EmptyResponseView):
  167. permission_required = 'auth_tests.add_customuser'
  168. request = self.factory.get('/rand')
  169. request.user = self.user
  170. resp = AView.as_view()(request)
  171. self.assertEqual(resp.status_code, 200)
  172. def test_permissioned_denied_redirect(self):
  173. class AView(PermissionRequiredMixin, EmptyResponseView):
  174. permission_required = [
  175. 'auth_tests.add_customuser', 'auth_tests.change_customuser', 'non-existent-permission',
  176. ]
  177. request = self.factory.get('/rand')
  178. request.user = self.user
  179. resp = AView.as_view()(request)
  180. self.assertEqual(resp.status_code, 302)
  181. def test_permissioned_denied_exception_raised(self):
  182. class AView(PermissionRequiredMixin, EmptyResponseView):
  183. permission_required = [
  184. 'auth_tests.add_customuser', 'auth_tests.change_customuser', 'non-existent-permission',
  185. ]
  186. raise_exception = True
  187. request = self.factory.get('/rand')
  188. request.user = self.user
  189. with self.assertRaises(PermissionDenied):
  190. AView.as_view()(request)