decorator for views that checks that the user passes the given test redirecting to the login page if necessary the test should be a callable that takes the user object and returns true if the user passes if the login url is the same scheme and net location then just use the path as the next url decorator for views that checks that the user is logged in redirecting to the login page if necessary decorator for views that checks whether a user has a particular permission enabled redirecting to the login page if necessary if the raiseexception parameter is given the permissiondenied exception is raised first check if the user has the permission even anon users in case the 403 handler should be called raise the exception as the last resort show the login form decorator for views that checks that the user passes the given test redirecting to the log in page if necessary the test should be a callable that takes the user object and returns true if the user passes if the login url is the same scheme and net location then just use the path as the next url decorator for views that checks that the user is logged in redirecting to the log in page if necessary decorator for views that checks whether a user has a particular permission enabled redirecting to the log in page if necessary if the raise_exception parameter is given the permissiondenied exception is raised first check if the user has the permission even anon users in case the 403 handler should be called raise the exception as the last resort show the login form
from functools import wraps
from urllib.parse import urlparse

from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import PermissionDenied
from django.shortcuts import resolve_url


def user_passes_test(
    test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME
):
    

    def decorator(view_func):
        @wraps(view_func)
        def _wrapper_view(request, *args, **kwargs):
            if test_func(request.user):
                return view_func(request, *args, **kwargs)
            path = request.build_absolute_uri()
            resolved_login_url = resolve_url(login_url or settings.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 = request.get_full_path()
            from django.contrib.auth.views import redirect_to_login

            return redirect_to_login(path, resolved_login_url, redirect_field_name)

        return _wrapper_view

    return decorator


def login_required(
    function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None
):
    
    actual_decorator = user_passes_test(
        lambda u: u.is_authenticated,
        login_url=login_url,
        redirect_field_name=redirect_field_name,
    )
    if function:
        return actual_decorator(function)
    return actual_decorator


def permission_required(perm, login_url=None, raise_exception=False):
    

    def check_perms(user):
        if isinstance(perm, str):
            perms = (perm,)
        else:
            perms = perm
        
        if user.has_perms(perms):
            return True
        
        if raise_exception:
            raise PermissionDenied
        
        return False

    return user_passes_test(check_perms, login_url=login_url)