test_mixins.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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
  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.add_customuser', 'auth.change_customuser']
  25. raise_exception = True
  26. class StackedMixinsView2(PermissionRequiredMixin, LoginRequiredMixin, EmptyResponseView):
  27. permission_required = ['auth.add_customuser', 'auth.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. def test_stacked_mixins_not_logged_in(self):
  56. user = models.User.objects.create(username='joe', password='qwerty')
  57. user.is_authenticated = lambda: False
  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. self.assertRaises(PermissionDenied, AView.as_view(), request)
  98. def test_raise_exception_custom_message(self):
  99. msg = "You don't have access here"
  100. class AView(AlwaysFalseView):
  101. raise_exception = True
  102. permission_denied_message = msg
  103. request = self.factory.get('/rand')
  104. request.user = AnonymousUser()
  105. view = AView.as_view()
  106. with self.assertRaises(PermissionDenied) as cm:
  107. view(request)
  108. self.assertEqual(cm.exception.args[0], msg)
  109. def test_raise_exception_custom_message_function(self):
  110. msg = "You don't have access here"
  111. class AView(AlwaysFalseView):
  112. raise_exception = True
  113. def get_permission_denied_message(self):
  114. return msg
  115. request = self.factory.get('/rand')
  116. request.user = AnonymousUser()
  117. view = AView.as_view()
  118. with self.assertRaises(PermissionDenied) as cm:
  119. view(request)
  120. self.assertEqual(cm.exception.args[0], msg)
  121. def test_user_passes(self):
  122. view = AlwaysTrueView.as_view()
  123. request = self.factory.get('/rand')
  124. request.user = AnonymousUser()
  125. response = view(request)
  126. self.assertEqual(response.status_code, 200)
  127. class LoginRequiredMixinTests(TestCase):
  128. factory = RequestFactory()
  129. @classmethod
  130. def setUpTestData(cls):
  131. cls.user = models.User.objects.create(username='joe', password='qwerty')
  132. def test_login_required(self):
  133. """
  134. Check that login_required works on a simple view wrapped in a
  135. login_required decorator.
  136. """
  137. class AView(LoginRequiredMixin, EmptyResponseView):
  138. pass
  139. view = AView.as_view()
  140. request = self.factory.get('/rand')
  141. request.user = AnonymousUser()
  142. response = view(request)
  143. self.assertEqual(response.status_code, 302)
  144. self.assertEqual('/accounts/login/?next=/rand', response.url)
  145. request = self.factory.get('/rand')
  146. request.user = self.user
  147. response = view(request)
  148. self.assertEqual(response.status_code, 200)
  149. class PermissionsRequiredMixinTests(TestCase):
  150. factory = RequestFactory()
  151. @classmethod
  152. def setUpTestData(cls):
  153. cls.user = models.User.objects.create(username='joe', password='qwerty')
  154. perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
  155. cls.user.user_permissions.add(*perms)
  156. def test_many_permissions_pass(self):
  157. class AView(PermissionRequiredMixin, EmptyResponseView):
  158. permission_required = ['auth.add_customuser', 'auth.change_customuser']
  159. request = self.factory.get('/rand')
  160. request.user = self.user
  161. resp = AView.as_view()(request)
  162. self.assertEqual(resp.status_code, 200)
  163. def test_single_permission_pass(self):
  164. class AView(PermissionRequiredMixin, EmptyResponseView):
  165. permission_required = 'auth.add_customuser'
  166. request = self.factory.get('/rand')
  167. request.user = self.user
  168. resp = AView.as_view()(request)
  169. self.assertEqual(resp.status_code, 200)
  170. def test_permissioned_denied_redirect(self):
  171. class AView(PermissionRequiredMixin, EmptyResponseView):
  172. permission_required = ['auth.add_customuser', 'auth.change_customuser', 'non-existent-permission']
  173. request = self.factory.get('/rand')
  174. request.user = self.user
  175. resp = AView.as_view()(request)
  176. self.assertEqual(resp.status_code, 302)
  177. def test_permissioned_denied_exception_raised(self):
  178. class AView(PermissionRequiredMixin, EmptyResponseView):
  179. permission_required = ['auth.add_customuser', 'auth.change_customuser', 'non-existent-permission']
  180. raise_exception = True
  181. request = self.factory.get('/rand')
  182. request.user = self.user
  183. self.assertRaises(PermissionDenied, AView.as_view(), request)