Пример #1
0
        def _encode(inner_obj):
            encoded = inner_obj

            # encode resource objects with their specified serializer,
            # according to the highest level of access which the environment arguments allow
            if getattr(inner_obj, '_IS_RESOURCE', False):
                # determine the access level in this environment
                permission = self._access_level(obj, environment)
                # retrieve the serializer
                serializer = getattr(inner_obj, self.serialization_method_name, None)
                
                if serializer is not None:
                    # encode the resource using its serializer with the provided permission
                    serializer_kwargs = populate_args(serializer, {'permission': permission}, environment)
                    encoded = serializer(**serializer_kwargs)
                else:
                    raise ValueError("Unable to serialize: object '" + obj.__name__ + "' has no method '" + self.serialization_method_name + "'")
            elif isinstance(inner_obj, collections.Mapping):
                # recurse on dictionary-like objects
                encoded = {}
                for key, val in inner_obj.iteritems():
                    encoded[key] = _encode(val)
            elif isinstance(inner_obj, collections.Iterable):
                # recurse on array-like objects
                encoded = []
                for val in inner_obj:
                    encoded.append(_encode(val))

            return encoded
Пример #2
0
    def _commit(self, name, instance, environment, encode=True):
        commit_result = None
        # commit changes to the resource
        if self.is_transactional.get(name, True):
            commit_method = getattr(instance, self.commit_method_name, None)
            if commit_method is not None:
                commit_kwargs = populate_args(commit_method, environment)
                commit_result = commit_result(**commit_kwargs)
                if encode:
                    commit_result = self.encode(commit_result, environment)

        return commit_result
Пример #3
0
    def _access_level(self, resource_instance, environment):
        """Determine a resource's most restrictive access permission for a given environment"""

        # determine if the resource instance has a method to provide the 
        # highest level of access this environment can give
        access_level_method = getattr(resource_instance, self.access_level_method_name, None)
        if access_level_method is not None:
            access_level_kwargs = populate_args(access_level_method, environment)
            access_level = access_level_method(**access_level_kwargs)
        else:
            # fall back on calling its access method in the provided
            # permissions order
            access_method = getattr(resource_instance, self.access_method_name, None)
            access_level = None

            if access_method is not None:
                for permission in self.permission_order:
                    access_kwargs = populate_args(access_method, {'permission': permission}, environment)
                    if access_method(**access_kwargs):
                        access_method = permission
                        break

        return access_level
Пример #4
0
    def _call(self, class_obj, parent, methods, access_method_name, environment, allowed_method_types=None, encode=True):
        """Performs access and permission checking, calls each specified method 
        (its arguments are combined with the provided environment).
        """

        # look up the access method to check for access
        access_method = getattr(parent, access_method_name, None)
        if access_method is None:
            raise ResourceMethodNotFoundError("'" + class_obj.__name__ + "' is missing an access method")

        # check if this is an acceptable method of execution as per allowed_method_types
        if allowed_method_types is not None and method._method_type not in allowed_method_types:
            raise ResourceNotAllowedError("'" + class_obj.__name__ + "' is not allowed to access '" + method_name + "' in this manner")

        # check that access can be granted to call this method
        permission = method._permission
        access_kwargs = populate_args(access_method, {'permission': permission}, environment)
        if not access_method(**access_kwargs):
            raise ResourceAccessDeniedError("'" + class_obj.__name__ + "' has denied access to '" + method_name + "'")

        result = []

        for method_data in methods:
            if isinstance(method_data, basestring):
                method_name = method_data
                sent_arguments = {}
            else:
                method_name = method_data.get('method')
                sent_arguments = method_data.get('args')

            method_name = method_name.lower()

            if method_name in self.method_names:
                err = ResourceMethodNotFoundError("'" + class_obj.__name__ + "' cannot export method '" + method_name + "'")
                err.method = method_name
                err.args = sent_arguments
                raise err
            
            class_method = getattr(class_obj, method_name, None)
            if isinstance(class_method, property):
                # this "method" is a decorated property
                num_args = len(sent_arguments)


                try:
                    if num_args == 0:
                        result.append(getattr(parent, method_name))
                    elif method_name in sent_arguments:
                        value = sent_arguments[method_name]
                        setattr(parent, method_name, value)
                        result.append(value)
                except Exception as original_err:
                    # pass on the error information
                    trace = sys.exc_info()[2]
                    err = ResourceMethodFailedError("'" + class_obj.__name__ + "' failed to execute '" + method_name + "'")
                    err.method = method_name
                    err.args = sent_arguments
                    err.error = original_err
                    err.trace = trace
                    raise err, None, trace

            elif callable(class_method):
                # this is a callable method
                # lookup the method and ensure it is exported
                method = getattr(parent, method_name, None)
                if method is None or not getattr(method, '_is_exported', False):
                    err = ResourceMethodNotFoundError("'" + class_obj.__name__ + "' has no exported method '" + method_name + "'")
                    err.method = method_name
                    err.args = sent_arguments
                    raise err

                method_kwargs = populate_args(method, sent_arguments, environment)
                
                try:
                    call_result = method(**method_kwargs)
                except Exception as original_err:
                    # pass on the error information
                    trace = sys.exc_info()[2]
                    err = ResourceMethodFailedError("'" + class_obj.__name__ + "' failed to execute '" + method_name + "'")
                    err.method = method_name
                    err.args = sent_arguments
                    err.error = original_err
                    err.trace = trace
                    raise err, None, trace

                result.append(call_result)
            else:
                err = ResourceMethodNotFoundError("'" + class_obj.__name__ + "' has no method or decorated property '" + method_name + "'")
                err.method = method_name
                err.args = sent_arguments
                raise err

        if encode:
            result = self.encode(result, environment)

        return result