def _wrapped_view(*args, **kwargs): # View functions take request as the first argument, # but view methods take (self, request) as the first two arguments. # This correctly identifies the request in either case, # and provides a meaningful error message if no request is found. for arg in args[:2]: if isinstance(arg, HttpRequest): request = arg break else: raise TypeError("%s() missing 1 required positional argument: " "'request'" % view_func.__name__) # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, str): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = apps.get_model(*splitted) elif issubclass(model.__class__, (Model, ModelBase, QuerySet)): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] obj = get_object_or_404(model, **lookup_dict) response = get_40x_or_None(request, perms=[perm], obj=obj, login_url=login_url, redirect_field_name=redirect_field_name, return_403=return_403, return_404=return_404, accept_global_perms=accept_global_perms) if response: return response return view_func(*args, **kwargs)
def _wrapped_view(request, *args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, basestring): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = get_model(*splitted) elif type(model) in (Model, ModelBase, QuerySet): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] obj = get_object_or_404(model, **lookup_dict) # Handles both original and with object provided permission check # as ``obj`` defaults to None if not request.user.has_perm(perm, obj): if return_403: if guardian_settings.RENDER_403: try: response = render_to_response( guardian_settings.TEMPLATE_403, {}, RequestContext(request)) response.status_code = 403 return response except TemplateDoesNotExist, e: if settings.DEBUG: raise e elif guardian_settings.RAISE_403: raise PermissionDenied return HttpResponseForbidden() else: path = urlquote(request.get_full_path()) tup = login_url, redirect_field_name, path return HttpResponseRedirect("%s?%s=%s" % tup)
def _wrapped_view(request, *args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: project_type, project_key = lookup_variables[ 0], lookup_variables[1] project_key_value = kwargs[project_key] project_type_value = kwargs[project_type] # Parse model if project_type_value in settings.G3WADMIN_PROJECT_APPS: model = apps.get_model(project_type_value, 'Project') else: raise GuardianError("{} no in G3W_PROJECT_APPS: ".format( project_type_value, settings.G3WADMIN_PROJECT_APPS)) if project_key_value.isdigit(): lookup_dict = {'pk': int(project_key_value)} else: lookup_dict = {'slug': project_key_value} obj = get_object_or_404(model, **lookup_dict) # ad app to perm perms = [project_type_value + "." + perm] response = get_40x_or_None(request, perms=perms, obj=obj, login_url=login_url, redirect_field_name=redirect_field_name, return_403=return_403, accept_global_perms=accept_global_perms) if response: return response return view_func(request, *args, **kwargs)
def _wrapped_view(request, *args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, str): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = apps.get_model(*splitted) elif issubclass(model.__class__, (Model, ModelBase, QuerySet)): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] obj = get_object_or_404(model, **lookup_dict) response = get_40x_or_None(request, perms=[perm], obj=obj, login_url=login_url, redirect_field_name=redirect_field_name, return_403=return_403, return_404=return_404, accept_global_perms=accept_global_perms) if response: return response return view_func(request, *args, **kwargs)
def permission_required_by_user_backend(user, perm, user_tuple, **kwargs): """ Check if perm to check is in user perms fo ouser """ model, lookups = user_tuple[0], user_tuple[1:] lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] ouser = get_object_or_404(model, **lookup_dict) perms = get_perms_by_user_backend(user, ouser) return perm in perms
def permission_required_for_anonymous_user(perm, user_tuple, **kwargs): """ Check if anonymous user has perms on object """ model, lookups = user_tuple[0], user_tuple[1:] lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] perms = get_perms(get_anonymous_user(), get_object_or_404(model, **lookup_dict)) return perm in perms
def test_error_classes(self): self.assertTrue(isinstance(GuardianError(), Exception)) guardian_errors = [NotUserNorGroup] for err in guardian_errors: self._test_error_class(err())
def permission_required(perm, lookup_variables=None, **kwargs): """ Decorator for views that checks whether a user has a particular permission enabled. Optionally, instances for which check should be made may be passed as an second argument or as a tuple parameters same as those passed to ``get_object_or_404`` but must be provided as pairs of strings. This way decorator can fetch i.e. ``User`` instance based on performed request and check permissions on it (without this, one would need to fetch user instance at view's logic and check permission inside a view). :param login_url: if denied, user would be redirected to location set by this parameter. Defaults to ``django.conf.settings.LOGIN_URL``. :param redirect_field_name: name of the parameter passed if redirected. Defaults to ``django.contrib.auth.REDIRECT_FIELD_NAME``. :param return_403: if set to ``True`` then instead of redirecting to the login page, response with status code 403 is returned ( ``django.http.HttpResponseForbidden`` instance or rendered template - see :setting:`GUARDIAN_RENDER_403`). Defaults to ``False``. :param return_404: if set to ``True`` then instead of redirecting to the login page, response with status code 404 is returned ( ``django.http.HttpResponseNotFound`` instance or rendered template - see :setting:`GUARDIAN_RENDER_404`). Defaults to ``False``. :param accept_global_perms: if set to ``True``, then *object level permission* would be required **only if user does NOT have global permission** for target *model*. If turned on, makes this decorator like an extension over standard ``django.contrib.admin.decorators.permission_required`` as it would check for global permissions first. Defaults to ``False``. Examples:: @permission_required('auth.change_user', return_403=True) def my_view(request): return HttpResponse('Hello') @permission_required('auth.change_user', (User, 'username', 'username')) def my_view(request, username): ''' auth.change_user permission would be checked based on given 'username'. If view's parameter would be named ``name``, we would rather use following decorator:: @permission_required('auth.change_user', (User, 'username', 'name')) ''' user = get_object_or_404(User, username=username) return user.get_absolute_url() @permission_required('auth.change_user', (User, 'username', 'username', 'groups__name', 'group_name')) def my_view(request, username, group_name): ''' Similar to the above example, here however we also make sure that one of user's group is named same as request's ``group_name`` param. ''' user = get_object_or_404(User, username=username, group__name=group_name) return user.get_absolute_url() """ login_url = kwargs.pop('login_url', settings.LOGIN_URL) redirect_field_name = kwargs.pop('redirect_field_name', REDIRECT_FIELD_NAME) return_403 = kwargs.pop('return_403', False) return_404 = kwargs.pop('return_404', False) accept_global_perms = kwargs.pop('accept_global_perms', False) # Check if perm is given as string in order not to decorate # view function itself which makes debugging harder if not isinstance(perm, str): raise GuardianError( "First argument must be in format: " "'app_label.codename or a callable which return similar string'") def decorator(view_func): def _wrapped_view(*args, **kwargs): # View functions take request as the first argument, # but view methods take (self, request) as the first two arguments. # This correctly identifies the request in either case, # and provides a meaningful error message if no request is found. for arg in args[:2]: if isinstance(arg, HttpRequest): request = arg break else: raise TypeError("%s() missing 1 required positional argument: " "'request'" % view_func.__name__) # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, str): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = apps.get_model(*splitted) elif issubclass(model.__class__, (Model, ModelBase, QuerySet)): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] obj = get_object_or_404(model, **lookup_dict) response = get_40x_or_None(request, perms=[perm], obj=obj, login_url=login_url, redirect_field_name=redirect_field_name, return_403=return_403, return_404=return_404, accept_global_perms=accept_global_perms) if response: return response return view_func(*args, **kwargs) return wraps(view_func)(_wrapped_view) return decorator
def permission_required(perm, lookup_variables=None, **kwargs): """ Decorator for views that checks whether a user has a particular permission enabled. Optionally, instances for which check should be made may be passed as an second argument or as a tuple parameters same as those passed to ``get_object_or_404`` but must be provided as pairs of strings. :param login_url: if denied, user would be redirected to location set by this parameter. Defaults to ``django.conf.settings.LOGIN_URL``. :param redirect_field_name: name of the parameter passed if redirected. Defaults to ``django.contrib.auth.REDIRECT_FIELD_NAME``. :param return_403: if set to ``True`` then instead of redirecting to the login page, response with status code 403 is returned ( ``django.http.HttpResponseForbidden`` instance). Defaults to ``False``. Examples:: @permission_required('auth.change_user', return_403=True) def my_view(request): return HttpResponse('Hello') @permission_required('auth.change_user', (User, 'username', 'username')) def my_view(request, username): user = get_object_or_404(User, username=username) return user.get_absolute_url() @permission_required('auth.change_user', (User, 'username', 'username', 'groups__name', 'group_name')) def my_view(request, username, group_name): user = get_object_or_404(User, username=username, group__name=group_name) return user.get_absolute_url() """ login_url = kwargs.pop('login_url', settings.LOGIN_URL) redirect_field_name = kwargs.pop('redirect_field_name', REDIRECT_FIELD_NAME) return_403 = kwargs.pop('return_403', False) # Check if perm is given as string in order not to decorate # view function itself which makes debugging harder if not isinstance(perm, basestring): raise GuardianError( "First argument must be in format: " "'app_label.codename or a callable which return similar string'") def decorator(view_func): def _wrapped_view(request, *args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, basestring): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = get_model(*splitted) elif type(model) in (Model, ModelBase, QuerySet): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] obj = get_object_or_404(model, **lookup_dict) # Handles both original and with object provided permission check # as ``obj`` defaults to None if not request.user.has_perm(perm, obj): if return_403: return HttpResponseForbidden() else: path = urlquote(request.get_full_path()) tup = login_url, redirect_field_name, path return HttpResponseRedirect("%s?%s=%s" % tup) return view_func(request, *args, **kwargs) return wraps(view_func)(_wrapped_view) return decorator
def wrapped(*args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None request = None if 'request' in kwargs: request = kwargs['request'] elif 'bundle' in kwargs: request = kwargs['bundle'].request else: for arg in args: if isinstance(arg, HttpRequest): request = arg break elif isinstance(arg, Bundle) and isinstance( arg.request, HttpRequest): request = arg.request break if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, basestring): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = get_model(*splitted) elif issubclass(model.__class__, (Model, ModelBase, QuerySet)): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] if not check_static: try: obj = get_object_or_404(model, **lookup_dict) except Http404: raise ImmediateHttpResponse( response=http.HttpNotFound()) has_perms = False if request: if check_static: has_perms = model.static_has_perms(perm, request.user) else: has_perms = obj.has_perms(perm, request.user) if not has_perms: raise ImmediateHttpResponse(response=http.HttpForbidden()) return view_func(*args, **kwargs)
def permission_required(perm, lookup_variables=None, **kwargs): """ Decorator for views that checks whether a user has a particular permission enabled. Optionally, instances for which check should be made may be passed as an second argument or as a tuple parameters. :param check_static: if set to ``Model``, the permissions will be checked in calling to Model.static_has_perms() instead of calling to has_perms(). Defaults to ``None``. Examples:: @permission_required('join', (Agora, 'id', 'id')) def join(self, request): agora = get_object_or_404(Agora, id=id) agora.members.append(request.user) return self.success() @permission_required('create', check_static=Agora) def obj_create(self, bundle, request=None, **kwargs): user = get_object_or_404(User, username=username) return user.get_absolute_url() """ check_static = kwargs.pop('check_static', None) if check_static: lookup_variables = [check_static] # Check if perm is given as string in order not to decorate # view function itself which makes debugging harder if not isinstance(perm, basestring): raise GuardianError( "First argument must be in format: " "'app_label.codename or a callable which return similar string'") def decorator(view_func): def wrapped(*args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None request = None if 'request' in kwargs: request = kwargs['request'] elif 'bundle' in kwargs: request = kwargs['bundle'].request else: for arg in args: if isinstance(arg, HttpRequest): request = arg break elif isinstance(arg, Bundle) and isinstance( arg.request, HttpRequest): request = arg.request break if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, basestring): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = get_model(*splitted) elif issubclass(model.__class__, (Model, ModelBase, QuerySet)): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] if not check_static: try: obj = get_object_or_404(model, **lookup_dict) except Http404: raise ImmediateHttpResponse( response=http.HttpNotFound()) has_perms = False if request: if check_static: has_perms = model.static_has_perms(perm, request.user) else: has_perms = obj.has_perms(perm, request.user) if not has_perms: raise ImmediateHttpResponse(response=http.HttpForbidden()) return view_func(*args, **kwargs) return wraps(view_func)(wrapped) return decorator
def project_type_permission_required(perm, lookup_variables=None, **kwargs): """ Decorator for views that checks whether a user has a particular permission enabled. Optionally, instances for which check should be made may be passed as an second argument or as a tuple parameters same as those passed to ``get_object_or_404`` but must be provided as pairs of strings. This way decorator can fetch i.e. ``User`` instance based on performed request and check permissions on it (without this, one would need to fetch user instance at view's logic and check permission inside a view). :param login_url: if denied, user would be redirected to location set by this parameter. Defaults to ``django.conf.settings.LOGIN_URL``. :param redirect_field_name: name of the parameter passed if redirected. Defaults to ``django.contrib.auth.REDIRECT_FIELD_NAME``. :param return_403: if set to ``True`` then instead of redirecting to the login page, response with status code 403 is returned ( ``django.http.HttpResponseForbidden`` instance or rendered template - see :setting:`GUARDIAN_RENDER_403`). Defaults to ``False``. :param accept_global_perms: if set to ``True``, then *object level permission* would be required **only if user does NOT have global permission** for target *model*. If turned on, makes this decorator like an extension over standard ``django.contrib.admin.decorators.permission_required`` as it would check for global permissions first. Defaults to ``False``. Examples:: @permission_required('qdjango.edit_notes', ('qdjango', '2')) def my_view(request, username): ... """ login_url = kwargs.pop('login_url', settings.LOGIN_URL) redirect_field_name = kwargs.pop('redirect_field_name', REDIRECT_FIELD_NAME) return_403 = kwargs.pop('return_403', False) accept_global_perms = kwargs.pop('accept_global_perms', False) # Check if perm is given as string in order not to decorate # view function itself which makes debugging harder if not isinstance(perm, basestring): raise GuardianError( "First argument must be in format: " "'app_label.codename or a callable which return similar string'") def decorator(view_func): def _wrapped_view(request, *args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: project_type, project_key = lookup_variables[ 0], lookup_variables[1] project_key_value = kwargs[project_key] project_type_value = kwargs[project_type] # Parse model if project_type_value in settings.G3WADMIN_PROJECT_APPS: model = apps.get_model(project_type_value, 'Project') else: raise GuardianError("{} no in G3W_PROJECT_APPS: ".format( project_type_value, settings.G3WADMIN_PROJECT_APPS)) if project_key_value.isdigit(): lookup_dict = {'pk': int(project_key_value)} else: lookup_dict = {'slug': project_key_value} obj = get_object_or_404(model, **lookup_dict) # ad app to perm perms = [project_type_value + "." + perm] response = get_40x_or_None(request, perms=perms, obj=obj, login_url=login_url, redirect_field_name=redirect_field_name, return_403=return_403, accept_global_perms=accept_global_perms) if response: return response return view_func(request, *args, **kwargs) return wraps(view_func)(_wrapped_view) return decorator
def permission_required(perm, lookup_variables=None, **kwargs): """ Decorator for views that checks whether a user has a particular permission enabled. Optionally, instances for which check should be made may be passed as an second argument or as a tuple parameters same as those passed to ``get_object_or_404`` but must be provided as pairs of strings. :param login_url: if denied, user would be redirected to location set by this parameter. Defaults to ``django.conf.settings.LOGIN_URL``. :param redirect_field_name: name of the parameter passed if redirected. Defaults to ``django.contrib.auth.REDIRECT_FIELD_NAME``. :param return_403: if set to ``True`` then instead of redirecting to the login page, response with status code 403 is returned ( ``django.http.HttpResponseForbidden`` instance or rendered template - see :setting:`GUARDIAN_RENDER_403`). Defaults to ``False``. :param accept_global_perms: if set to ``True``, then *object level permission* would be required **only if user does NOT have global permission** for target *model*. If turned on, makes this decorator like an extension over standard ``django.contrib.admin.decorators.permission_required`` as it would check for global permissions first. Defaults to ``False``. Examples:: @permission_required('auth.change_user', return_403=True) def my_view(request): return HttpResponse('Hello') @permission_required('auth.change_user', (User, 'username', 'username')) def my_view(request, username): user = get_object_or_404(User, username=username) return user.get_absolute_url() @permission_required('auth.change_user', (User, 'username', 'username', 'groups__name', 'group_name')) def my_view(request, username, group_name): user = get_object_or_404(User, username=username, group__name=group_name) return user.get_absolute_url() """ login_url = kwargs.pop('login_url', settings.LOGIN_URL) redirect_field_name = kwargs.pop('redirect_field_name', REDIRECT_FIELD_NAME) return_403 = kwargs.pop('return_403', False) accept_global_perms = kwargs.pop('accept_global_perms', False) # Check if perm is given as string in order not to decorate # view function itself which makes debugging harder if not isinstance(perm, basestring): raise GuardianError( "First argument must be in format: " "'app_label.codename or a callable which return similar string'") def decorator(view_func): def _wrapped_view(request, *args, **kwargs): # if more than one parameter is passed to the decorator we try to # fetch object for which check would be made obj = None if lookup_variables: model, lookups = lookup_variables[0], lookup_variables[1:] # Parse model if isinstance(model, basestring): splitted = model.split('.') if len(splitted) != 2: raise GuardianError( "If model should be looked up from " "string it needs format: 'app_label.ModelClass'") model = get_model(*splitted) elif type(model) in (Model, ModelBase, QuerySet): pass else: raise GuardianError( "First lookup argument must always be " "a model, string pointing at app/model or queryset. " "Given: %s (type: %s)" % (model, type(model))) # Parse lookups if len(lookups) % 2 != 0: raise GuardianError( "Lookup variables must be provided " "as pairs of lookup_string and view_arg") lookup_dict = {} for lookup, view_arg in zip(lookups[::2], lookups[1::2]): if view_arg not in kwargs: raise GuardianError("Argument %s was not passed " "into view function" % view_arg) lookup_dict[lookup] = kwargs[view_arg] obj = get_object_or_404(model, **lookup_dict) response = get_403_or_None(request, perms=[perm], obj=obj, login_url=login_url, redirect_field_name=redirect_field_name, return_403=return_403, accept_global_perms=accept_global_perms) if response: return response return view_func(request, *args, **kwargs) return wraps(view_func)(_wrapped_view) return decorator