abstract cbv mixin that gives access mixins the same customizable functionality override this method to override the loginurl attribute override this method to override the permissiondeniedmessage attribute override this method to override the redirectfieldname attribute if the login url is the same scheme and net location then use the path as the next url verify that the current user is authenticated def dispatchself request args kwargs if not request user isauthenticated return self handlenopermission return super dispatchrequest args kwargs class permissionrequiredmixinaccessmixin override this method to override the permissionrequired attribute must return an iterable override this method to customize the way permissions are checked deny a request with a permission error if the testfunc method returns false override this method to use a different testfunc method abstract cbv mixin that gives access mixins the same customizable functionality override this method to override the login_url attribute override this method to override the permission_denied_message attribute override this method to override the redirect_field_name attribute if the login url is the same scheme and net location then use the path as the next url verify that the current user is authenticated verify that the current user has all specified permissions override this method to override the permission_required attribute must return an iterable override this method to customize the way permissions are checked deny a request with a permission error if the test_func method returns false override this method to use a different test_func method
from urllib.parse import urlparse

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.shortcuts import resolve_url


class AccessMixin:
    

    login_url = None
    permission_denied_message = ""
    raise_exception = False
    redirect_field_name = REDIRECT_FIELD_NAME

    def get_login_url(self):
        
        login_url = self.login_url or settings.LOGIN_URL
        if not login_url:
            raise ImproperlyConfigured(
                f"{self.__class__.__name__} is missing the login_url attribute. Define "
                f"{self.__class__.__name__}.login_url, settings.LOGIN_URL, or override "
                f"{self.__class__.__name__}.get_login_url()."
            )
        return str(login_url)

    def get_permission_denied_message(self):
        
        return self.permission_denied_message

    def get_redirect_field_name(self):
        
        return self.redirect_field_name

    def handle_no_permission(self):
        if self.raise_exception or self.request.user.is_authenticated:
            raise PermissionDenied(self.get_permission_denied_message())

        path = self.request.build_absolute_uri()
        resolved_login_url = resolve_url(self.get_login_url())
        
        
        login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
        current_scheme, current_netloc = urlparse(path)[:2]
        if (not login_scheme or login_scheme == current_scheme) and (
            not login_netloc or login_netloc == current_netloc
        ):
            path = self.request.get_full_path()
        return redirect_to_login(
            path,
            resolved_login_url,
            self.get_redirect_field_name(),
        )


class LoginRequiredMixin(AccessMixin):
    

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return self.handle_no_permission()
        return super().dispatch(request, *args, **kwargs)


class PermissionRequiredMixin(AccessMixin):
    

    permission_required = None

    def get_permission_required(self):
        
        if self.permission_required is None:
            raise ImproperlyConfigured(
                f"{self.__class__.__name__} is missing the "
                f"permission_required attribute. Define "
                f"{self.__class__.__name__}.permission_required, or override "
                f"{self.__class__.__name__}.get_permission_required()."
            )
        if isinstance(self.permission_required, str):
            perms = (self.permission_required,)
        else:
            perms = self.permission_required
        return perms

    def has_permission(self):
        
        perms = self.get_permission_required()
        return self.request.user.has_perms(perms)

    def dispatch(self, request, *args, **kwargs):
        if not self.has_permission():
            return self.handle_no_permission()
        return super().dispatch(request, *args, **kwargs)


class UserPassesTestMixin(AccessMixin):
    

    def test_func(self):
        raise NotImplementedError(
            "{} is missing the implementation of the test_func() method.".format(
                self.__class__.__name__
            )
        )

    def get_test_func(self):
        
        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().dispatch(request, *args, **kwargs)