You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

117 lines
4.0 KiB

  1. from django.conf import settings
  2. from django.contrib.auth import REDIRECT_FIELD_NAME
  3. from django.contrib.auth.views import redirect_to_login
  4. from django.core.exceptions import ImproperlyConfigured, PermissionDenied
  5. from django.utils import six
  6. from django.utils.encoding import force_text
  7. class AccessMixin(object):
  8. """
  9. Abstract CBV mixin that gives access mixins the same customizable
  10. functionality.
  11. """
  12. login_url = None
  13. permission_denied_message = ''
  14. raise_exception = False
  15. redirect_field_name = REDIRECT_FIELD_NAME
  16. def get_login_url(self):
  17. """
  18. Override this method to override the login_url attribute.
  19. """
  20. login_url = self.login_url or settings.LOGIN_URL
  21. if not login_url:
  22. raise ImproperlyConfigured(
  23. '{0} is missing the login_url attribute. Define {0}.login_url, settings.LOGIN_URL, or override '
  24. '{0}.get_login_url().'.format(self.__class__.__name__)
  25. )
  26. return force_text(login_url)
  27. def get_permission_denied_message(self):
  28. """
  29. Override this method to override the permission_denied_message attribute.
  30. """
  31. return self.permission_denied_message
  32. def get_redirect_field_name(self):
  33. """
  34. Override this method to override the redirect_field_name attribute.
  35. """
  36. return self.redirect_field_name
  37. def handle_no_permission(self):
  38. if self.raise_exception:
  39. raise PermissionDenied(self.get_permission_denied_message())
  40. return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
  41. class LoginRequiredMixin(AccessMixin):
  42. """
  43. CBV mixin which verifies that the current user is authenticated.
  44. """
  45. def dispatch(self, request, *args, **kwargs):
  46. if not request.user.is_authenticated():
  47. return self.handle_no_permission()
  48. return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
  49. class PermissionRequiredMixin(AccessMixin):
  50. """
  51. CBV mixin which verifies that the current user has all specified
  52. permissions.
  53. """
  54. permission_required = None
  55. def get_permission_required(self):
  56. """
  57. Override this method to override the permission_required attribute.
  58. Must return an iterable.
  59. """
  60. if self.permission_required is None:
  61. raise ImproperlyConfigured(
  62. '{0} is missing the permission_required attribute. Define {0}.permission_required, or override '
  63. '{0}.get_permission_required().'.format(self.__class__.__name__)
  64. )
  65. if isinstance(self.permission_required, six.string_types):
  66. perms = (self.permission_required, )
  67. else:
  68. perms = self.permission_required
  69. return perms
  70. def has_permission(self):
  71. """
  72. Override this method to customize the way permissions are checked.
  73. """
  74. perms = self.get_permission_required()
  75. return self.request.user.has_perms(perms)
  76. def dispatch(self, request, *args, **kwargs):
  77. if not self.has_permission():
  78. return self.handle_no_permission()
  79. return super(PermissionRequiredMixin, self).dispatch(request, *args, **kwargs)
  80. class UserPassesTestMixin(AccessMixin):
  81. """
  82. CBV Mixin that allows you to define a test function which must return True
  83. if the current user can access the view.
  84. """
  85. def test_func(self):
  86. raise NotImplementedError(
  87. '{0} is missing the implementation of the test_func() method.'.format(self.__class__.__name__)
  88. )
  89. def get_test_func(self):
  90. """
  91. Override this method to use a different test_func method.
  92. """
  93. return self.test_func
  94. def dispatch(self, request, *args, **kwargs):
  95. user_test_result = self.get_test_func()()
  96. if not user_test_result:
  97. return self.handle_no_permission()
  98. return super(UserPassesTestMixin, self).dispatch(request, *args, **kwargs)