Source code for superdjango.ui.views.access

# Imports

from django.core.exceptions import PermissionDenied
from django.http import Http404, HttpResponseRedirect
from django.utils.translation import gettext_lazy as _
import logging
import re

log = logging.getLogger(__name__)

# Exports

__all__ = (
    "UIAccessMixin",
)

# Mixins


[docs]class UIAccessMixin(object): """A UI-enabled mixin for checking user access to a view. The primary difference between this mixin and ``superdjango.views.AccessMixin`` is that access options are defined using the ``access_policy`` attribute of the ModelUI. """ error_messages = { 'access_denied': _("Access denied."), 'group_required': _("Group membership is required to access this page."), 'login_required': _("A login is required to access this page."), 'permission_required': _("Special permission is required to access this page."), 'ssl_required': _("The requested page must be accessed over a secure connection."), }
[docs] def dispatch(self, request, *args, **kwargs): """Dispatch with access checks. :param request: The current request object. :type request: django.http.request.HttpRequest Access is checked in the following order: 1. Check for SSL. 2. Check for an authenticated user. 3. Check for group membership. 4. Check for specific permissions. 5. Call ``self.ui.access_policy.check_other()``. See ``dispatch_other()``. """ # noinspection PyUnresolvedReferences if not self.ui.access_policy.check_ssl(request, *args, **kwargs): return self.dispatch_insecure(request) # noinspection PyUnresolvedReferences if not self.ui.access_policy.check_login(request, *args, **kwargs): return self.dispatch_access_denied(request, reason="login_required") # noinspection PyUnresolvedReferences if not self.ui.access_policy.check_group(request, *args, **kwargs): return self.dispatch_access_denied(request, reason="group_required") # noinspection PyUnresolvedReferences if not self.ui.access_policy.check_permission(request, *args, **kwargs): return self.dispatch_access_denied(request, reason="permission_required") # noinspection PyUnresolvedReferences if not self.ui.access_policy.check_other(request, *args, **kwargs): return self.dispatch_other(request) # noinspection PyUnresolvedReferences return super().dispatch(request, *args, *kwargs)
[docs] def dispatch_access_denied(self, request, reason="access_denied", redirect_url=None): """Handle authentication or permission issues during dispatch. :param request: The current request object. :type request: django.http.request.HttpRequest :param reason: A reason for the permission failure. :type reason: str :param redirect_url: The URL to which the user should be directed. :type redirect_url: str """ message = self._get_dispatch_message(reason) # noinspection PyUnresolvedReferences if self.ui.access_policy.raise_exception: raise PermissionDenied(message) # noinspection PyUnresolvedReferences if self.ui.logging_enabled: log.info(message) if redirect_url is not None: return HttpResponseRedirect(redirect_url) return self.redirect_to_login(request.get_full_path())
[docs] def dispatch_insecure(self, request, reason="ssl_required"): """Handle failed SSL connections. :param request: The current request object. :type request: django.http.request.HttpRequest :param reason: A reason for the permission failure. :type reason: str """ message = self._get_dispatch_message(reason) # noinspection PyUnresolvedReferences if self.ui.access_policy.raise_exception: raise Http404(message) # noinspection PyUnresolvedReferences if self.ui.logging_enabled: log.info(message) return HttpResponseRedirect(self.get_https_url(request))
[docs] def dispatch_other(self, request, reason="access_denied", redirect_url=None): """Responds to failed ``check_other()``. Override this method to provide your own handling. :param reason: A reason for the permission failure. :type reason: str :param request: The current request object. :type request: django.http.request.HttpRequest :param redirect_url: The URL to which the user should be directed. :type redirect_url: str .. note:: By default, this method simply calls ``dispatch_access_denied()``. """ return self.dispatch_access_denied(request, reason=reason, redirect_url=redirect_url)
# noinspection PyMethodMayBeStatic
[docs] def get_https_url(self, request): """Get the current URL with the HTTPS protocol. :param request: The current request object. :type request: django.http.request.HttpRequest """ url = request.build_absolute_uri(request.get_full_path()) return re.sub(r'^http', 'https', url)
# noinspection PyMethodMayBeStatic
[docs] def redirect_to_login(self, path): """Redirect to the login view using the given path as the next URL. :param path: The next URL after logging in. :type path: str """ # Import Django's utility here to avoid AppRegistryNotReady error. from django.contrib.auth.views import redirect_to_login return redirect_to_login(path)
def _get_dispatch_message(self, key): """Get the error message for the given dispatch error. :param key: The key name of the error message. :type key: str :rtype: str """ # noinspection PyUnresolvedReferences if key in self.ui.access_policy.error_messages: # noinspection PyUnresolvedReferences return self.ui.access_policy.error_messages[key] return self.error_messages[key]