示例#1
0
 def validate_domain_struct(self):
     """ Validates that Eve configuration settings conform to the
     requirements.
     """
     try:
         domain = self.config['DOMAIN']
     except:
         raise ConfigException('DOMAIN dictionary missing or wrong.')
     if not isinstance(domain, dict):
         raise ConfigException('DOMAIN must be a dict.')
示例#2
0
def validate_info():
    v = Validator()
    schema = {
        'title': {
            'required': True,
            'type': 'string'
        },
        'version': {
            'required': True,
            'type': 'string'
        },
        'description': {
            'type': 'string'
        },
        'termsOfService': {
            'type': 'string'
        },
        'contact': {
            'type': 'dict',
            'schema': {
                'name': {
                    'type': 'string'
                },
                'url': {
                    'type': 'string',
                    'validator': _validate_url
                },
                'email': {
                    'type': 'string',
                    'regex': '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
                }
            }
        },
        'license': {
            'type': 'dict',
            'schema': {
                'name': {
                    'type': 'string',
                    'required': True
                },
                'url': {
                    'type': 'string',
                    'validator': _validate_url
                }
            }
        },
    }
    if eve_swagger.INFO not in app.config:
        raise ConfigException('%s setting is required in Eve configuration.' %
                              eve_swagger.INFO)

    if not v.validate(app.config[eve_swagger.INFO], schema):
        raise ConfigException('%s is misconfigured: %s' %
                              (eve_swagger.INFO, v.errors))
示例#3
0
    def _validate_resource_settings(self, resource, settings):
        """ Validates one resource in configuration settings.

        :param resource: name of the resource which settings refer to.
        :param settings: settings of resource to be validated.

        .. versionchanged:: 0.4
           validate that auth_field is not set to ID_FIELD. See #266.

        .. versionadded:: 0.2
        """
        self.validate_methods(
            self.supported_resource_methods,
            settings["resource_methods"],
            "[%s] resource " % resource,
        )
        self.validate_methods(
            self.supported_item_methods,
            settings["item_methods"],
            "[%s] item " % resource,
        )

        # while a resource schema is optional for read-only access,
        # it is mandatory for write-access to resource/items.
        if (
            "POST" in settings["resource_methods"]
            or "PATCH" in settings["item_methods"]
        ):
            if len(settings["schema"]) == 0:
                raise ConfigException(
                    "A resource schema must be provided "
                    "when POST or PATCH methods are allowed "
                    "for a resource [%s]." % resource
                )

        self.validate_roles("allowed_roles", settings, resource)
        self.validate_roles("allowed_read_roles", settings, resource)
        self.validate_roles("allowed_write_roles", settings, resource)
        self.validate_roles("allowed_item_roles", settings, resource)
        self.validate_roles("allowed_item_read_roles", settings, resource)
        self.validate_roles("allowed_item_write_roles", settings, resource)

        if settings["auth_field"] == settings["id_field"]:
            raise ConfigException(
                '"%s": auth_field cannot be set to id_field '
                "(%s)" % (resource, settings["id_field"])
            )

        self.validate_schema(resource, settings["schema"])
示例#4
0
    def __init__(self, ext):
        """
        Constructor.

        :param ext: instance of :class:`EveMongoengine`.
        """
        # get authentication info
        username = ext.app.config.get("MONGO_USERNAME", None)
        password = ext.app.config.get("MONGO_PASSWORD", None)
        auth = (username, password)
        if any(auth) and not all(auth):
            raise ConfigException("Must set both USERNAME and PASSWORD "
                                  "or neither")
        # try to connect to db
        self.conn = connect(
            ext.app.config["MONGO_DBNAME"],
            host=ext.app.config["MONGO_HOST"],
            port=ext.app.config["MONGO_PORT"],
        )
        self.models = ext.models
        self.app = ext.app
        # create dummy driver instead of PyMongo, which causes errors
        # when instantiating after config was initialized
        self.driver = type("Driver", (), {})()
        self.driver.db = get_db()
        # authenticate
        if any(auth):
            self.driver.db.authenticate(username, password)
        # helper object for managing PATCHes, which are a bit dirty
        self.updater = MongoengineUpdater(self)
        # map resource -> Mongoengine class
        self.cls_map = ResourceClassMap(self)
示例#5
0
文件: flaskapp.py 项目: mpuhacz/eve
    def _set_resource_projection(self, ds, schema, settings):
        """ Set datasource projection for a resource

        .. versionchanged:: 0.6.3
           Fix: If datasource source is specified no fields are included by
           default. Closes #842.

        .. versionadded:: 0.6.2
        """

        projection = ds.get('projection', {})

        # check if any exclusion projection is defined
        exclusion = any(((k, v) for k, v in projection.items() if v == 0)) \
            if projection else None

        # If no exclusion projection is defined, enhance the projection
        # with automatic fields. Using both inclusion and exclusion will
        # be rejected by Mongo
        if not exclusion and len(schema) and \
           settings['allow_unknown'] is False:
            if not projection:
                projection.update(dict((field, 1) for (field) in schema))

            # enable retrieval of actual schema fields only. Eventual db
            # fields not included in the schema won't be returned.
            # despite projection, automatic fields are always included.
            projection[settings['id_field']] = 1
            projection[self.config['LAST_UPDATED']] = 1
            projection[self.config['DATE_CREATED']] = 1
            projection[self.config['ETAG']] = 1
            if settings['versioning'] is True:
                projection[self.config['VERSION']] = 1
                projection[settings['id_field'] +
                           self.config['VERSION_ID_SUFFIX']] = 1
        else:
            # all fields are returned.
            projection = None
        ds.setdefault('projection', projection)

        if settings['soft_delete'] is True and not exclusion and \
                ds['projection'] is not None:
            ds['projection'][self.config['DELETED']] = 1

        # list of all media fields for the resource
        if isinstance(schema, dict):
            settings['_media'] = [
                field for field, definition in schema.items()
                if isinstance(definition, dict) and (
                    definition.get('type') == 'media' or
                    (definition.get('type') == 'list'
                     and definition.get('schema', {}).get('type') == 'media'))
            ]
        else:
            settings['_media'] = []

        if settings['_media'] and not self.media:
            raise ConfigException('A media storage class of type '
                                  ' eve.io.media.MediaStorage must be defined '
                                  'for "media" fields to be properly stored.')
示例#6
0
    def find_list_of_ids(self, resource, ids, client_projection=None):
        """
        Retrieves a list of documents based on a list of primary keys. The primary key is the field defined in 
        `ID_FIELD`. This is a separate function to allow us to use per-database optimizations for this type of query.

        :param resource: resource name.
        :param ids: a list of ids corresponding to the documents to retrieve
        :param client_projection: a specific projection to use
        :return: a list of documents matching the ids in `ids` from the collection specified in `resource` 
        """
        item_title = self.app.config["DOMAIN"][resource][
            "item_title"].capitalize()

        if item_title in self.node_base_classes_names:
            node_class = self.get_node_class(item_title)
            results = self.find_nodes(node_class, req=ParsedRequest())
        elif resource in self.node_types:
            node_class = self.get_node_class(
                class_name=item_title, base_classes=self.node_base_classes)
            results = self.find_nodes(node_class)
        else:
            raise ConfigException(
                "Resource {} wasn't found in neither node or relation types.".
                format(resource))

        return Neo4jResult(
            [result for result in results if result["id"] in ids])
示例#7
0
    def find_one(self, resource, req, **lookup):
        """ 
        Retrieves a single document/record. Consumed when a request hits an
        item endpoint (`/people/id/`).

        :param resource: resource being accessed. You should then use the ``datasource`` helper function to retrieve  
            both the db collection/table and base query (filter), if any.
        :param req: an instance of ``eve.utils.ParsedRequest``. This contains all the constraints that must be fulfilled
            in order to satisfy the original request (where and sort parts, paging, etc). As we are going to only look for 
            one document here, the only req attribute that you want to process here is``req.projection``.

        :param **lookup: the lookup fields. This will most likely be a record id or, if alternate lookup is supported by
        the API, the corresponding query.
        """
        item_title = self.app.config["DOMAIN"][resource][
            "item_title"].capitalize()

        if item_title in self.node_base_classes_names:
            node_class = self.get_node_class(item_title)
            results = self.find_nodes(node_class, req)
        elif resource in self.node_types:
            node_class = self.get_node_class(
                class_name=item_title, base_classes=self.node_base_classes)
            results = self.find_nodes(node_class, req)
        else:
            raise ConfigException(
                "Resource {} wasn't found in neither node or relation types.".
                format(resource))

        return Neo4jResult([results[0]], parsed_request=req)
示例#8
0
    def find(self, resource, req, sub_resource_lookup):
        """
        Retrieves a set of documents (rows), matching the current request.
        Consumed when a request hits a collection/document endpoint
        (`/people/`).

        :param resource: resource being accessed. You should then use the ``datasource`` helper function to retrieve 
            both the db collection/table and base query (filter), if any.
        :param req: an instance of ``eve.utils.ParsedRequest``. This contains all the constraints that must be fulfilled
            in order to satisfy the original request (where and sort parts, paging, etc). Be warned that `where` and 
            `sort` expressions will need proper parsing, according to the syntax that you want to support with your 
            driver. For example ``eve.io.Mongo`` supports both Python and Mongo-like query syntaxes.
        :param sub_resource_lookup: sub-resource lookup from the endpoint url.
        """
        item_title = self.app.config["DOMAIN"][resource][
            "item_title"].capitalize()

        if item_title in self.node_base_classes_names:
            node_class = self.get_node_class(item_title)
            results = self.find_nodes(node_class, req)
        elif resource in self.node_types:
            node_class = self.get_node_class(
                class_name=item_title, base_classes=self.node_base_classes)
            results = self.find_nodes(node_class, req)
        else:
            raise ConfigException(
                "Resource {} wasn't found in neither node or relation types.".
                format(resource))

        return Neo4jResult(results, parsed_request=req)
示例#9
0
    def _validate_resource_settings(self, resource, settings):
        """ Validates one resource in configuration settings.

        :param resource: name of the resource which settings refer to.
        :param settings: settings of resource to be validated.

        .. versionadded:: 0.2
        """
        self.validate_methods(self.supported_resource_methods,
                              settings['resource_methods'],
                              '[%s] resource ' % resource)
        self.validate_methods(self.supported_item_methods,
                              settings['item_methods'],
                              '[%s] item ' % resource)

        # while a resource schema is optional for read-only access,
        # it is mandatory for write-access to resource/items.
        if 'POST' in settings['resource_methods'] or \
           'PATCH' in settings['item_methods']:
            if len(settings['schema']) == 0:
                raise ConfigException('A resource schema must be provided '
                                      'when POST or PATCH methods are allowed'
                                      'for a resource [%s].' % resource)

        self.validate_roles('allowed_roles', settings, resource)
        self.validate_roles('allowed_item_roles', settings, resource)
        self.validate_schema(resource, settings['schema'])
示例#10
0
    def __init__(self, ext):
        """
        Constructor.

        :param ext: instance of :class:`EveMongoengine`.
        """
        # get authentication info
        username = ext.app.config['MONGO_USERNAME']
        password = ext.app.config['MONGO_PASSWORD']
        auth = (username, password)
        if any(auth) and not all(auth):
            raise ConfigException('Must set both USERNAME and PASSWORD '
                                  'or neither')
        # try to connect to db
        self.conn = connect(ext.app.config['MONGO_DBNAME'],
                            host=ext.app.config['MONGO_HOST'],
                            port=ext.app.config['MONGO_PORT'])
        self.models = ext.models
        self.app = ext.app
        # create dummy driver instead of PyMongo, which causes errors
        # when instantiating after config was initialized
        self.driver = type('Driver', (), {})()
        self.driver.db = get_db()
        # authenticate
        if any(auth):
            self.driver.db.authenticate(username, password)
示例#11
0
 def _get_column(self, column_name):
     try:
         return self._mapper.columns[column_name]
     except KeyError:
         raise ConfigException("{model}.{column_name} does not exist."
                               .format(model=self.model.__name__,
                                       column_name=column_name))
示例#12
0
 def validate_roles(self, directive, candidate, resource):
     """
         The same as eve's, but letting roles to be sets, which is a more adequate type that easies some code.
     """
     roles = candidate[directive]
     if not isinstance(roles, set) and not isinstance(roles, list):
         raise ConfigException("'%s' must be set"
                               "[%s]." % (directive, resource))
 def id_field(self, id_field):
     pk_columns = [c.name for c in self._mapper.primary_key]
     if not (len(pk_columns) == 1 and pk_columns[0] == id_field):
         column = self._get_column(id_field)
         if not column.unique:
             raise ConfigException(
                 "{model}.{id_field} is not unique.".format(
                     model=self.model.__name__, id_field=id_field))
     self._id_field = id_field
示例#14
0
 def item_lookup_field(self, item_lookup_field):
     if item_lookup_field != self.id_field:
         column = self._get_column(item_lookup_field)
         if not column.unique:
             raise ConfigException(
                 "{model}.{item_lookup_field} is not unique."
                 .format(model=self.model.__name__,
                         item_lookup_field=item_lookup_field))
     self._item_lookup_field = item_lookup_field
示例#15
0
 def _deduce_id_field(self):
     pk_columns = [c.name for c in self.model.__mapper__.primary_key]
     if len(pk_columns) == 1:
         return pk_columns[0]
     else:
         raise ConfigException(
             "{model}'s primary key consists of zero or multiple columns, "
             "thus we cannot deduce which one to use. Please manually "
             "specify a unique column to use as `id_field`: "
             "`ResourceConfig({model}, id_field=...)`"
             .format(model=self.model.__name__))
示例#16
0
    def _set_resource_projection(self, ds, schema, settings):
        """ Set datasource projection for a resource

        .. versionadded:: 0.7
        """

        projection = ds.get('projection', {})

        # check if any exclusion projection is defined
        exclusion = any(((k, v) for k, v in projection.items() if v == 0))

        # If no exclusion projection is defined, enhance the projection
        # with automatic fields. Using both inclusion and exclusion will
        # be rejected by Mongo
        if not exclusion and len(schema) and \
                settings['allow_unknown'] is False:
            # enable retrieval of actual schema fields only. Eventual db
            # fields not included in the schema won't be returned.
            # despite projection, automatic fields are always included.
            projection[settings['id_field']] = 1
            projection[self.config['LAST_UPDATED']] = 1
            projection[self.config['DATE_CREATED']] = 1
            projection[self.config['ETAG']] = 1
            if settings['versioning'] is True:
                projection[self.config['VERSION']] = 1
                projection[settings['id_field'] +
                           self.config['VERSION_ID_SUFFIX']] = 1
            projection.update(dict((field, 1) for (field) in schema))
        else:
            # all fields are returned.
            projection = None
        ds.setdefault('projection', projection)

        if settings['soft_delete'] is True and not exclusion and \
                ds['projection'] is not None:
            ds['projection'][self.config['DELETED']] = 1

        # 'defaults' helper set contains the names of fields with default
        # values in their schema definition.

        # TODO support default values for embedded documents.
        settings['defaults'] = build_defaults(schema)

        # list of all media fields for the resource
        settings['_media'] = [
            field for field, definition in schema.items()
            if definition.get('type') == 'media'
        ]

        if settings['_media'] and not self.media:
            raise ConfigException('A media storage class of type '
                                  ' eve.io.media.MediaStorage must be defined '
                                  'for "media" fields to be properly stored.')
示例#17
0
文件: flaskapp.py 项目: marchon/eve
 def validate_schema(self, schema):
     # TODO are there other mandatory settings items? Validate them here
     offender = None
     if eve.DATE_CREATED in schema:
         offender = eve.DATE_CREATED
     if eve.LAST_UPDATED in schema:
         offender = eve.LAST_UPDATED
     if eve.ID_FIELD in schema:
         offender = eve.ID_FIELD
     if offender:
         raise ConfigException('"%s" field not allowed in schema (will be '
                               'handled automatically).' % offender)
示例#18
0
    def _validate_resource_settings(self, resource, settings):
        """ Validates one resource in configuration settings.

        :param resource: name of the resource which settings refer to.
        :param settings: settings of resource to be validated.

        .. versionchanged:: 0.4
           validate that auth_field is not set to ID_FIELD. See #266.

        .. versionadded:: 0.2
        """
        self.validate_methods(self.supported_resource_methods,
                              settings['resource_methods'],
                              '[%s] resource ' % resource)
        self.validate_methods(self.supported_item_methods,
                              settings['item_methods'],
                              '[%s] item ' % resource)

        # while a resource schema is optional for read-only access,
        # it is mandatory for write-access to resource/items.
        if 'POST' in settings['resource_methods'] or \
           'PATCH' in settings['item_methods']:
            if len(settings['schema']) == 0:
                raise ConfigException('A resource schema must be provided '
                                      'when POST or PATCH methods are allowed '
                                      'for a resource [%s].' % resource)

        self.validate_roles('allowed_roles', settings, resource)
        self.validate_roles('allowed_read_roles', settings, resource)
        self.validate_roles('allowed_write_roles', settings, resource)
        self.validate_roles('allowed_item_roles', settings, resource)
        self.validate_roles('allowed_item_read_roles', settings, resource)
        self.validate_roles('allowed_item_write_roles', settings, resource)

        if settings['auth_field'] == self.config['ID_FIELD']:
            raise ConfigException('"%s": auth_field cannot be set to ID_FIELD '
                                  '(%s)' % (resource, self.config['ID_FIELD']))

        self.validate_schema(resource, settings['schema'])
示例#19
0
    def validate_methods(self, allowed, proposed, item):
        """Compares allowed and proposed methods, raising a `ConfigException`
        when they don't match.

        :param allowed: a list of supported (allowed) methods.
        :param proposed: a list of proposed methods.
        :param item: name of the item to which the methods would be applied.
                     Used when raising the exception.
        """
        diff = set(proposed) - set(allowed)
        if diff:
            raise ConfigException("Unallowed %s method(s): %s. "
                                  "Supported: %s" %
                                  (item, ", ".join(diff), ", ".join(allowed)))
 def _get_resource(self):
     try:
         return self._related_resource_configs[(self._model, self._name)]
     except LookupError:
         try:
             relationship = self._mapper.relationships[
                 self._field.target_collection]
             return self._related_resource_configs[relationship.argument()]
         except LookupError:
             model = self._mapper.class_
             raise ConfigException(
                 'Cannot determine related resource for {model}.{field}. '
                 'Please specify `related_resources` manually.'.format(
                     model=model.__name__, field=self._name))
示例#21
0
    def validate_config(self):
        """ Makes sure that REST methods expressed in the configuration
        settings are supported.

        .. versionchanged:: 0.1.0
        Support for PUT method.

        .. versionchanged:: 0.0.4
           Support for 'allowed_roles' and 'allowed_item_roles'

        .. versionchanged:: 0.0.2
            Support for DELETE resource method.
        """

        supported_resource_methods = ['GET', 'POST', 'DELETE']
        supported_item_methods = ['GET', 'PATCH', 'DELETE', 'PUT']

        # make sure that global resource methods are supported.
        self.validate_methods(supported_resource_methods,
                              self.config.get('RESOURCE_METHODS'),
                              'resource')

        # make sure that global item methods are supported.
        self.validate_methods(supported_item_methods,
                              self.config.get('ITEM_METHODS'),
                              'item')

        # make sure that individual resource/item methods are supported.
        for resource, settings in self.config['DOMAIN'].items():
            self.validate_methods(supported_resource_methods,
                                  settings['resource_methods'],
                                  '[%s] resource ' % resource)
            self.validate_methods(supported_item_methods,
                                  settings['item_methods'],
                                  '[%s] item ' % resource)

            # while a resource schema is optional for read-only access,
            # it is mandatory for write-access to resource/items.
            if 'POST' in settings['resource_methods'] or \
               'PATCH' in settings['item_methods']:
                if len(settings['schema']) == 0:
                    raise ConfigException('A resource schema must be provided '
                                          'when POST or PATCH methods are '
                                          'allowed for a resource [%s].' %
                                          resource)

            self.validate_roles('allowed_roles', settings, resource)
            self.validate_roles('allowed_item_roles', settings, resource)
            self.validate_schema(resource, settings['schema'])
示例#22
0
    def validate_roles(self, directive, candidate, resource):
        """ Validates that user role directives are syntactically and formally
        adequate.

        :param directive: either 'allowed_[read_|write_]roles' or
                          'allow_item_[read_|write_]roles'.
        :param candidate: the candidate setting to be validated.
        :param resource: name of the resource to which the candidate settings
                         refer to.

        .. versionadded:: 0.0.4
        """
        roles = candidate[directive]
        if not isinstance(roles, list):
            raise ConfigException("'%s' must be list" "[%s]." % (directive, resource))
示例#23
0
    def validate_roles(self, directive, candidate, resource):
        """ Validates that user role directives are syntactically and formally
        adeguate.

        :param directive: either 'allowed_roles' or 'allow_item_roles'.
        :param candidate: the candidate setting to be validated.
        :param resource: name of the resource to which the candidate settings
                         refer to.

        .. versionadded:: 0.0.4
        """
        roles = candidate[directive]
        if roles is not None and (not isinstance(roles, list) or not
                                  len(roles)):
            raise ConfigException("'%s' must be a non-empty list, or None "
                                  "[%s]." % (directive, resource))
 def _get_resource(self):
     try:
         return self._related_resource_configs[(self._model, self._name)]
     except LookupError:
         try:
             arg = self._relationship.argument
             if isinstance(arg, DeclarativeMeta):
                 return self._related_resource_configs[arg]
             elif callable(arg):
                 return self._related_resource_configs[arg()]
             else:
                 return self._related_resource_configs[arg.class_]
         except LookupError:
             raise ConfigException(
                 'Cannot determine related resource for {model}.{field}. '
                 'Please specify `related_resources` manually.'.format(
                     model=self._model.__name__, field=self._name))
示例#25
0
    def check_auth(self, token, allowed_roles, resource, method):
        """ Check if API request is authorized.

        Examines token in header and checks Redis cache to see if token is
        valid. If so, request is allowed.

        :param token: OAuth 2.0 access token submitted.
        :param allowed_roles: Allowed user roles.
        :param resource: Resource being requested.
        :param method: HTTP method being executed (POST, GET, etc.)
        """
        if not token:
            return False

        user_id = self.redis.get(token)
        if not user_id:
            return False

        # now switching to the user-reserved mongo instance.

        mongo_prefix = 'MONGO%s' % user_id

        # TODO remove defaulting to localhost so exception is raised
        # if db host is not available. Right now, unless redis hodls a
        # key for the user, all dbs are hosted on localhost.
        host = self.redis.get(user_id) or 'localhost'
        if not host:
            raise ConfigException('Cannot locate host for user database %s' %
                                  user_id)

        uri = 'mongodb://%s/%s' % (host, user_id)

        current_app.config['%s_URI' % mongo_prefix] = uri

        self.set_mongo_prefix(mongo_prefix)

        return True
示例#26
0
    def _set_resource_projection(self, ds, schema, settings):
        """ Set datasource projection for a resource

        .. versionchanged:: 0.6.3
           Fix: If datasource source is specified no fields are included by
           default. Closes #842.

        .. versionadded:: 0.6.2
        """
        # get existing or empty projection setting
        projection = ds.get("projection", {})

        # If exclusion projections are defined, they are use for
        # concealing fields (rather than actual mongo exlusions).
        # If inclusion projections are defined, exclusion projections are
        # just ignored.
        # Enhance the projection with automatic fields.
        if len(schema) and settings["allow_unknown"] is False:
            inclusion_projection = dict(
                [(k, v) for k, v in projection.items() if v == 1]
            )
            exclusion_projection = dict(
                [(k, v) for k, v in projection.items() if v == 0]
            )
            # if inclusion project is empty, add all fields not excluded
            if not inclusion_projection:
                projection.update(
                    dict(
                        (field, 1)
                        for (field) in schema
                        if field not in exclusion_projection
                    )
                )
            # enable retrieval of actual schema fields only. Eventual db
            # fields not included in the schema won't be returned.
            # despite projection, automatic fields are always included.
            projection[settings["id_field"]] = 1
            projection[self.config["LAST_UPDATED"]] = 1
            projection[self.config["DATE_CREATED"]] = 1
            projection[self.config["ETAG"]] = 1
            if settings["versioning"] is True:
                projection[self.config["VERSION"]] = 1
                projection[settings["id_field"] + self.config["VERSION_ID_SUFFIX"]] = 1

        ds.setdefault("projection", projection)

        if settings["soft_delete"] is True and projection:
            projection[self.config["DELETED"]] = 1

        # set projection and projection is always a dictionary
        ds["projection"] = projection

        # list of all media fields for the resource
        if isinstance(schema, dict):
            settings["_media"] = [
                field
                for field, definition in schema.items()
                if isinstance(definition, dict)
                and (
                    definition.get("type") == "media"
                    or (
                        definition.get("type") == "list"
                        and definition.get("schema", {}).get("type") == "media"
                    )
                )
            ]
        else:
            settings["_media"] = []

        if settings["_media"] and not self.media:
            raise ConfigException(
                "A media storage class of type "
                " eve.io.media.MediaStorage must be defined "
                'for "media" fields to be properly stored.'
            )
示例#27
0
    def _set_resource_defaults(self, resource, settings):
        """ Low-level method which sets default values for one resource.

        .. versionchanged:: 0.5
           Don't set default projection if 'allow_unknown' is active (#497).
           'internal_resource'

        .. versionchanged:: 0.3
           Set projection to None when schema is not provided for the resource.
           Support for '_media' helper.

        .. versionchanged:: 0.2
           'resource_title',
           'default_sort',
           'embedded_fields'.
           Support for endpoint-level authenticatoin classes.
        """
        settings.setdefault('url', resource)
        settings.setdefault('resource_methods',
                            self.config['RESOURCE_METHODS'])
        settings.setdefault('public_methods',
                            self.config['PUBLIC_METHODS'])
        settings.setdefault('allowed_roles', self.config['ALLOWED_ROLES'])
        settings.setdefault('allowed_read_roles',
                            self.config['ALLOWED_READ_ROLES'])
        settings.setdefault('allowed_write_roles',
                            self.config['ALLOWED_WRITE_ROLES'])
        settings.setdefault('cache_control', self.config['CACHE_CONTROL'])
        settings.setdefault('cache_expires', self.config['CACHE_EXPIRES'])

        settings.setdefault('item_lookup_field',
                            self.config['ITEM_LOOKUP_FIELD'])
        settings.setdefault('item_url', self.config['ITEM_URL'])
        settings.setdefault('resource_title', settings['url'])
        settings.setdefault('item_title',
                            resource.rstrip('s').capitalize())
        settings.setdefault('item_lookup', self.config['ITEM_LOOKUP'])
        settings.setdefault('public_item_methods',
                            self.config['PUBLIC_ITEM_METHODS'])
        settings.setdefault('allowed_item_roles',
                            self.config['ALLOWED_ITEM_ROLES'])
        settings.setdefault('allowed_item_read_roles',
                            self.config['ALLOWED_ITEM_READ_ROLES'])
        settings.setdefault('allowed_item_write_roles',
                            self.config['ALLOWED_ITEM_WRITE_ROLES'])
        settings.setdefault('allowed_filters',
                            self.config['ALLOWED_FILTERS'])
        settings.setdefault('sorting', self.config['SORTING'])
        settings.setdefault('embedding', self.config['EMBEDDING'])
        settings.setdefault('embedded_fields', [])
        settings.setdefault('pagination', self.config['PAGINATION'])
        settings.setdefault('projection', self.config['PROJECTION'])
        settings.setdefault('versioning', self.config['VERSIONING'])
        settings.setdefault('internal_resource',
                            self.config['INTERNAL_RESOURCE'])
        # TODO make sure that this we really need the test below
        if settings['item_lookup']:
            item_methods = self.config['ITEM_METHODS']
        else:
            item_methods = eve.ITEM_METHODS
        settings.setdefault('item_methods', item_methods)
        settings.setdefault('auth_field',
                            self.config['AUTH_FIELD'])
        settings.setdefault('allow_unknown', self.config['ALLOW_UNKNOWN'])
        settings.setdefault('extra_response_fields',
                            self.config['EXTRA_RESPONSE_FIELDS'])
        settings.setdefault('mongo_write_concern',
                            self.config['MONGO_WRITE_CONCERN'])
        settings.setdefault('hateoas',
                            self.config['HATEOAS'])
        settings.setdefault('authentication', self.auth if self.auth else None)
        # empty schemas are allowed for read-only access to resources
        schema = settings.setdefault('schema', {})
        self.set_schema_defaults(schema)

        datasource = {}
        settings.setdefault('datasource', datasource)
        settings['datasource'].setdefault('source', resource)
        settings['datasource'].setdefault('filter', None)
        settings['datasource'].setdefault('default_sort', None)

        if len(schema) and settings['allow_unknown'] is False:
            # enable retrieval of actual schema fields only. Eventual db
            # fields not included in the schema won't be returned.
            projection = {}
            # despite projection, automatic fields are always included.
            projection[self.config['ID_FIELD']] = 1
            projection[self.config['LAST_UPDATED']] = 1
            projection[self.config['DATE_CREATED']] = 1
            projection[self.config['ETAG']] = 1
            if settings['versioning'] is True:
                projection[self.config['VERSION']] = 1
                projection[
                    self.config['ID_FIELD'] +
                    self.config['VERSION_ID_SUFFIX']] = 1
            projection.update(dict((field, 1) for (field) in schema))
        else:
            # all fields are returned.
            projection = None
        settings['datasource'].setdefault('projection', projection)

        # 'defaults' helper set contains the names of fields with default
        # values in their schema definition.

        # TODO support default values for embedded documents.
        settings['defaults'] = build_defaults(schema)

        # list of all media fields for the resource
        settings['_media'] = [field for field, definition in schema.items() if
                              definition.get('type') == 'media']

        if settings['_media'] and not self.media:
            raise ConfigException('A media storage class of type '
                                  ' eve.io.media.MediaStorage but be defined '
                                  'for "media" fields to be properly stored.')
示例#28
0
    def _set_resource_defaults(self, resource, settings):
        """ Low-level method which sets default values for one resource.

        .. versionchanged:: 0.6.2
           Fix: startup crash when both SOFT_DELETE and ALLOW_UNKNOWN are True.

           (#722).
        .. versionchanged:: 0.6.1
           Fix: inclusive projection defined for a datasource is ignored
           (#722).

        .. versionchanged:: 0.6
           Support for 'mongo_indexes'.

        .. versionchanged:: 0.5
           Don't set default projection if 'allow_unknown' is active (#497).
           'internal_resource'

        .. versionchanged:: 0.3
           Set projection to None when schema is not provided for the resource.
           Support for '_media' helper.

        .. versionchanged:: 0.2
           'resource_title',
           'default_sort',
           'embedded_fields'.
           Support for endpoint-level authenticatoin classes.
        """
        settings.setdefault('url', resource)
        settings.setdefault('resource_methods',
                            self.config['RESOURCE_METHODS'])
        settings.setdefault('public_methods',
                            self.config['PUBLIC_METHODS'])
        settings.setdefault('allowed_roles', self.config['ALLOWED_ROLES'])
        settings.setdefault('allowed_read_roles',
                            self.config['ALLOWED_READ_ROLES'])
        settings.setdefault('allowed_write_roles',
                            self.config['ALLOWED_WRITE_ROLES'])
        settings.setdefault('cache_control', self.config['CACHE_CONTROL'])
        settings.setdefault('cache_expires', self.config['CACHE_EXPIRES'])

        settings.setdefault('id_field', self.config['ID_FIELD'])
        settings.setdefault('item_lookup_field',
                            self.config['ITEM_LOOKUP_FIELD'])
        settings.setdefault('item_url', self.config['ITEM_URL'])
        settings.setdefault('resource_title', settings['url'])
        settings.setdefault('item_title',
                            resource.rstrip('s').capitalize())
        settings.setdefault('item_lookup', self.config['ITEM_LOOKUP'])
        settings.setdefault('public_item_methods',
                            self.config['PUBLIC_ITEM_METHODS'])
        settings.setdefault('allowed_item_roles',
                            self.config['ALLOWED_ITEM_ROLES'])
        settings.setdefault('allowed_item_read_roles',
                            self.config['ALLOWED_ITEM_READ_ROLES'])
        settings.setdefault('allowed_item_write_roles',
                            self.config['ALLOWED_ITEM_WRITE_ROLES'])
        settings.setdefault('allowed_filters',
                            self.config['ALLOWED_FILTERS'])
        settings.setdefault('sorting', self.config['SORTING'])
        settings.setdefault('embedding', self.config['EMBEDDING'])
        settings.setdefault('embedded_fields', [])
        settings.setdefault('pagination', self.config['PAGINATION'])
        settings.setdefault('projection', self.config['PROJECTION'])
        settings.setdefault('versioning', self.config['VERSIONING'])
        settings.setdefault('soft_delete', self.config['SOFT_DELETE'])
        settings.setdefault('bulk_enabled', self.config['BULK_ENABLED'])
        settings.setdefault('internal_resource',
                            self.config['INTERNAL_RESOURCE'])
        settings.setdefault('etag_ignore_fields', None)
        # TODO make sure that this we really need the test below
        if settings['item_lookup']:
            item_methods = self.config['ITEM_METHODS']
        else:
            item_methods = eve.ITEM_METHODS
        settings.setdefault('item_methods', item_methods)
        settings.setdefault('auth_field',
                            self.config['AUTH_FIELD'])
        settings.setdefault('allow_unknown', self.config['ALLOW_UNKNOWN'])
        settings.setdefault('transparent_schema_rules',
                            self.config['TRANSPARENT_SCHEMA_RULES'])
        settings.setdefault('extra_response_fields',
                            self.config['EXTRA_RESPONSE_FIELDS'])
        settings.setdefault('mongo_write_concern',
                            self.config['MONGO_WRITE_CONCERN'])
        settings.setdefault('mongo_indexes', {})
        settings.setdefault('hateoas',
                            self.config['HATEOAS'])
        settings.setdefault('authentication', self.auth if self.auth else None)
        # empty schemas are allowed for read-only access to resources
        schema = settings.setdefault('schema', {})
        self.set_schema_defaults(schema, settings['id_field'])

        # 'defaults' helper set contains the names of fields with default
        # values in their schema definition.

        # TODO support default values for embedded documents.
        settings['defaults'] = build_defaults(schema)

        # list of all media fields for the resource
        settings['_media'] = [field for field, definition in schema.items() if
                              definition.get('type') == 'media']

        if settings['_media'] and not self.media:
            raise ConfigException('A media storage class of type '
                                  ' eve.io.media.MediaStorage but be defined '
                                  'for "media" fields to be properly stored.')

        self._set_resource_datasource(resource, schema, settings)
示例#29
0
    def _set_resource_defaults(self, resource, settings):
        """ Low-level method which sets default values for one resource.

        .. versionchanged:: 0.6.2
           Fix: startup crash when both SOFT_DELETE and ALLOW_UNKNOWN are True.

           (#722).
        .. versionchanged:: 0.6.1
           Fix: inclusive projection defined for a datasource is ignored
           (#722).

        .. versionchanged:: 0.6
           Support for 'mongo_indexes'.

        .. versionchanged:: 0.5
           Don't set default projection if 'allow_unknown' is active (#497).
           'internal_resource'

        .. versionchanged:: 0.3
           Set projection to None when schema is not provided for the resource.
           Support for '_media' helper.

        .. versionchanged:: 0.2
           'resource_title',
           'default_sort',
           'embedded_fields'.
           Support for endpoint-level authenticatoin classes.
        """
        settings.setdefault('url', resource)
        settings.setdefault('resource_methods',
                            self.config['RESOURCE_METHODS'])
        settings.setdefault('public_methods',
                            self.config['PUBLIC_METHODS'])
        settings.setdefault('allowed_roles', self.config['ALLOWED_ROLES'])
        settings.setdefault('allowed_read_roles',
                            self.config['ALLOWED_READ_ROLES'])
        settings.setdefault('allowed_write_roles',
                            self.config['ALLOWED_WRITE_ROLES'])
        settings.setdefault('cache_control', self.config['CACHE_CONTROL'])
        settings.setdefault('cache_expires', self.config['CACHE_EXPIRES'])

        settings.setdefault('id_field', self.config['ID_FIELD'])
        settings.setdefault('item_lookup_field',
                            self.config['ITEM_LOOKUP_FIELD'])
        settings.setdefault('item_url', self.config['ITEM_URL'])
        settings.setdefault('resource_title', settings['url'])
        settings.setdefault('item_title',
                            resource.rstrip('s').capitalize())
        settings.setdefault('item_lookup', self.config['ITEM_LOOKUP'])
        settings.setdefault('public_item_methods',
                            self.config['PUBLIC_ITEM_METHODS'])
        settings.setdefault('allowed_item_roles',
                            self.config['ALLOWED_ITEM_ROLES'])
        settings.setdefault('allowed_item_read_roles',
                            self.config['ALLOWED_ITEM_READ_ROLES'])
        settings.setdefault('allowed_item_write_roles',
                            self.config['ALLOWED_ITEM_WRITE_ROLES'])
        settings.setdefault('allowed_filters',
                            self.config['ALLOWED_FILTERS'])
        settings.setdefault('sorting', self.config['SORTING'])
        settings.setdefault('embedding', self.config['EMBEDDING'])
        settings.setdefault('embedded_fields', [])
        settings.setdefault('pagination', self.config['PAGINATION'])
        settings.setdefault('projection', self.config['PROJECTION'])
        settings.setdefault('versioning', self.config['VERSIONING'])
        settings.setdefault('soft_delete', self.config['SOFT_DELETE'])
        settings.setdefault('bulk_enabled', self.config['BULK_ENABLED'])
        settings.setdefault('internal_resource',
                            self.config['INTERNAL_RESOURCE'])
        settings.setdefault('etag_ignore_fields', None)
        # TODO make sure that this we really need the test below
        if settings['item_lookup']:
            item_methods = self.config['ITEM_METHODS']
        else:
            item_methods = eve.ITEM_METHODS
        settings.setdefault('item_methods', item_methods)
        settings.setdefault('auth_field',
                            self.config['AUTH_FIELD'])
        settings.setdefault('allow_unknown', self.config['ALLOW_UNKNOWN'])
        settings.setdefault('transparent_schema_rules',
                            self.config['TRANSPARENT_SCHEMA_RULES'])
        settings.setdefault('extra_response_fields',
                            self.config['EXTRA_RESPONSE_FIELDS'])
        settings.setdefault('mongo_write_concern',
                            self.config['MONGO_WRITE_CONCERN'])
        settings.setdefault('mongo_indexes', {})
        settings.setdefault('hateoas',
                            self.config['HATEOAS'])
        settings.setdefault('authentication', self.auth if self.auth else None)
        # empty schemas are allowed for read-only access to resources
        schema = settings.setdefault('schema', {})
        self.set_schema_defaults(schema, settings['id_field'])

        datasource = {}
        settings.setdefault('datasource', datasource)

        ds = settings['datasource']
        ds.setdefault('source', resource)
        ds.setdefault('filter', None)
        ds.setdefault('default_sort', None)

        projection = ds.get('projection', {})

        # check if any exclusion projection is defined
        exclusion = any(((k, v) for k, v in projection.items() if v == 0))

        # If no exclusion projection is defined, enhance the projection
        # with automatic fields. Using both inclusion and exclusion will
        # be rejected by Mongo
        if not exclusion and len(schema) and \
           settings['allow_unknown'] is False:
            if not projection:
                projection.update(dict((field, 1) for (field) in schema))

            # enable retrieval of actual schema fields only. Eventual db
            # fields not included in the schema won't be returned.
            # despite projection, automatic fields are always included.
            projection[settings['id_field']] = 1
            projection[self.config['LAST_UPDATED']] = 1
            projection[self.config['DATE_CREATED']] = 1
            projection[self.config['ETAG']] = 1
            if settings['versioning'] is True:
                projection[self.config['VERSION']] = 1
                projection[
                    settings['id_field'] +
                    self.config['VERSION_ID_SUFFIX']] = 1
        else:
            # all fields are returned.
            projection = None
        ds.setdefault('projection', projection)

        if settings['soft_delete'] is True and not exclusion and \
                ds['projection'] is not None:
            ds['projection'][self.config['DELETED']] = 1

        # 'defaults' helper set contains the names of fields with default
        # values in their schema definition.

        # TODO support default values for embedded documents.
        settings['defaults'] = build_defaults(schema)

        # list of all media fields for the resource
        settings['_media'] = [field for field, definition in schema.items() if
                              definition.get('type') == 'media']

        if settings['_media'] and not self.media:
            raise ConfigException('A media storage class of type '
                                  ' eve.io.media.MediaStorage but be defined '
                                  'for "media" fields to be properly stored.')