summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
Diffstat (limited to 'django')
-rw-r--r--django/contrib/auth/mixins.py110
1 files changed, 110 insertions, 0 deletions
diff --git a/django/contrib/auth/mixins.py b/django/contrib/auth/mixins.py
new file mode 100644
index 0000000000..00fc9cb727
--- /dev/null
+++ b/django/contrib/auth/mixins.py
@@ -0,0 +1,110 @@
+from django.conf import settings
+from django.contrib.auth import REDIRECT_FIELD_NAME
+from django.contrib.auth.views import redirect_to_login
+from django.core.exceptions import ImproperlyConfigured, PermissionDenied
+from django.utils import six
+from django.utils.encoding import force_text
+
+
+class AccessMixin(object):
+ """
+ Abstract CBV mixin that gives access mixins the same customizable
+ functionality.
+ """
+ login_url = None
+ permission_denied_message = ''
+ raise_exception = False
+ redirect_field_name = REDIRECT_FIELD_NAME
+
+ def get_login_url(self):
+ """
+ Override this method to override the login_url attribute.
+ """
+ login_url = self.login_url or settings.LOGIN_URL
+ if not login_url:
+ raise ImproperlyConfigured(
+ '{0} is missing the login_url attribute. Define {0}.login_url, settings.LOGIN_URL, or override '
+ '{0}.get_login_url().'.format(self.__class__.__name__)
+ )
+ return force_text(login_url)
+
+ def get_permission_denied_message(self):
+ """
+ Override this method to override the permission_denied_message attribute.
+ """
+ return self.permission_denied_message
+
+ def get_redirect_field_name(self):
+ """
+ Override this method to override the redirect_field_name attribute.
+ """
+ return self.redirect_field_name
+
+ def handle_no_permission(self):
+ if self.raise_exception:
+ raise PermissionDenied(self.get_permission_denied_message())
+ return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
+
+
+class LoginRequiredMixin(AccessMixin):
+ """
+ CBV mixin which verifies that the current user is authenticated.
+ """
+ def dispatch(self, request, *args, **kwargs):
+ if not request.user.is_authenticated():
+ return self.handle_no_permission()
+ return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
+
+
+class PermissionRequiredMixin(AccessMixin):
+ """
+ CBV mixin which verifies that the current user has all specified
+ permissions.
+ """
+ permission_required = None
+
+ def get_permission_required(self):
+ """
+ Override this method to override the permission_required attribute.
+ Must return an iterable.
+ """
+ if self.permission_required is None:
+ raise ImproperlyConfigured(
+ '{0} is missing the permission_required attribute. Define {0}.permission_required, or override '
+ '{0}.get_permission_required().'.format(self.__class__.__name__)
+ )
+ if isinstance(self.permission_required, six.string_types):
+ perms = (self.permission_required, )
+ else:
+ perms = self.permission_required
+ return perms
+
+ def dispatch(self, request, *args, **kwargs):
+ perms = self.get_permission_required()
+ if not request.user.has_perms(perms):
+ return self.handle_no_permission()
+ return super(PermissionRequiredMixin, self).dispatch(request, *args, **kwargs)
+
+
+class UserPassesTestMixin(AccessMixin):
+ """
+ CBV Mixin that allows you to define a test function which must return True
+ if the current user can access the view.
+ """
+
+ def test_func(self):
+ raise NotImplementedError(
+ '{0} is missing the implementation of the test_func() method.'.format(self.__class__.__name__)
+ )
+
+ def get_test_func(self):
+ """
+ Override this method to use a different test_func method.
+ """
+ return self.test_func
+
+ def dispatch(self, request, *args, **kwargs):
+ user_test_result = self.get_test_func()()
+ if not user_test_result:
+ return self.handle_no_permission()
+ return super(UserPassesTestMixin, self).dispatch(request, *args, **kwargs)