test_mixins.py 8.3 KB

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