Exemplo n.º 1
0
    async def get_schema(self, schema, context, result, behavior):
        read_permissions = merged_tagged_value_dict(schema, read_permission.key)
        schema_serial = {}
        for name, field in get_fields(schema).items():

            if not self.check_permission(read_permissions.get(name)):
                continue

            if behavior:
                # omit/include for behaviors need full name
                dotted_name = schema.__identifier__ + '.' + name
            else:
                dotted_name = name

            if ('*' not in self.include and (dotted_name in self.omit or (
                    len(self.include) > 0 and (
                        dotted_name not in self.include and
                        schema.__identifier__ not in self.include)))):
                # make sure the fields aren't filtered
                continue

            value = await self.serialize_field(context, field)
            if not behavior:
                result[name] = value
            else:
                schema_serial[name] = value

        if behavior and len(schema_serial) > 0:
            result[schema.__identifier__] = schema_serial
Exemplo n.º 2
0
    async def get_schema(self, schema, context, result, behavior):
        read_permissions = merged_tagged_value_dict(schema,
                                                    read_permission.key)
        schema_serial = {}
        for name, field in get_fields(schema).items():

            if not self.check_permission(read_permissions.get(name)):
                continue

            if behavior:
                # omit/include for behaviors need full name
                dotted_name = schema.__identifier__ + '.' + name
            else:
                dotted_name = name

            if ('*' not in self.include
                    and (dotted_name in self.omit or
                         (len(self.include) > 0 and
                          (dotted_name not in self.include
                           and schema.__identifier__ not in self.include)))):
                # make sure the fields aren't filtered
                continue

            value = await self.serialize_field(context, field)
            if not behavior:
                result[name] = value
            else:
                schema_serial[name] = value

        if behavior and len(schema_serial) > 0:
            result[schema.__identifier__] = schema_serial
Exemplo n.º 3
0
def fhir_field_from_schema(
    schema: Interface, resource_type: str = None
) -> Union[FhirField, None]:
    """ """
    index_fields: dict

    if resource_type:
        index_fields = directives.merged_tagged_value_dict(schema, directives.index.key)

    for name, field in get_fields_in_order(schema):

        if IFhirField.providedBy(field):
            if resource_type:
                catalog_info = index_fields.get(name, None)
                if catalog_info is None:
                    continue
                if catalog_info.get("resource_type", None) is None:
                    continue

                if catalog_info["resource_type"] != resource_type:
                    continue

            return field

    return None
Exemplo n.º 4
0
async def get_all_indices(context, request):
    base_url = IAbsoluteURL(context, request)()
    result = {"@id": base_url, "types": {}, "behaviors": {}}
    for type_name, type_schema in FACTORY_CACHE.items():
        indices = merged_tagged_value_dict(type_schema.schema, index.key)
        result["types"][type_name] = {
            key: value["type"]
            for key, value in indices.items()
        }  # noqa

    for behavior, utility in get_utilities_for(IBehavior):
        indices = merged_tagged_value_dict(utility.interface, index.key)
        result["behaviors"][behavior] = {
            key: value["type"]
            for key, value in indices.items()
        }  # noqa
    return result
Exemplo n.º 5
0
def get_indexes():
    """ Get all the indexes
    """

    global INDEXES_CACHE
    if INDEXES_CACHE is None:
        mapping = {}
        for type_name, type_schema in FACTORY_CACHE.items():
            mapping.update(
                merged_tagged_value_dict(type_schema.schema, index.key))
        for _, utility in get_utilities_for(IBehavior):
            mapping.update(
                merged_tagged_value_dict(utility.interface, index.key))
        INDEXES_CACHE = mapping
    else:
        INDEXES_CACHE
    return INDEXES_CACHE
Exemplo n.º 6
0
    async def __call__(self, indexes=None, schemas=None):
        # For each type
        values = {
            'type_name': self.content.type_name,
            'tid': self.content.__serial__
        }
        if schemas is None:
            schemas = iter_schemata(self.content)

        for schema in schemas:
            behavior = schema(self.content)
            loaded = False
            for field_name, index_data in merged_tagged_value_dict(schema, index.key).items():
                index_name = index_data.get('index_name', field_name)
                if index_name in values or index_name in self.attempts:
                    # you can override indexers so we do not want to index
                    # the same value more than once
                    continue

                self.attempts.append(index_name)

                try:
                    # accessors we always reindex since we can't know if updated
                    # from the indexes param--they are "fake" like indexes, not fields
                    if 'accessor' in index_data:
                        if (indexes is None or
                                (len(set(index_data.get('fields', [])) & set(indexes)) > 0)):
                            if not loaded:
                                await self.load_behavior(behavior)
                                loaded = True
                            values[index_name] = await apply_coroutine(
                                index_data['accessor'], behavior)
                    elif (indexes is None or field_name in indexes or
                            isinstance(getattr(type(self.content), field_name, None), property)):
                        if not loaded:
                            await self.load_behavior(behavior)
                            loaded = True
                        # in this case, properties are also dynamic so we have to make sure
                        # to allow for them to be reindexed every time.
                        values[index_name] = self.get_data(behavior, schema, field_name)
                except NoIndexField:
                    pass

            for metadata_name in merged_tagged_value_list(schema, metadata.key):
                if (indexes is not None and metadata_name not in indexes and
                        not isinstance(getattr(type(self.content), metadata_name, None), property)):
                    # in this case, properties are also dynamic so we have to make sure
                    # to allow for them to be reindexed every time.
                    continue  # skip
                if not loaded:
                    await self.load_behavior(behavior)
                    loaded = True
                try:
                    values[metadata_name] = self.get_data(behavior, schema, metadata_name)
                except NoIndexField:
                    pass
        return values
Exemplo n.º 7
0
async def get_field_value(context, request):
    field_name = request.matchdict["dotted_name"]

    if "." in field_name:
        # behavior field lookup
        iface_dotted = ".".join(field_name.split(".")[:-1])
        field_name = field_name.split(".")[-1]

        try:
            schema = resolve_dotted_name(iface_dotted)
        except ModuleNotFoundError:
            return HTTPNotFound(
                content={"reason": f"Could resolve: {iface_dotted}"})
        try:
            field = schema[field_name]
        except KeyError:
            return HTTPNotFound(content={"reason": f"No field: {field_name}"})

        try:
            behavior = await get_behavior(context, schema)
        except AttributeError:
            return HTTPNotFound(
                content={"reason": f"Could not load behavior: {iface_dotted}"})
        if behavior is None:
            return HTTPNotFound(
                content={"reason": f"Not valid behavior: {iface_dotted}"})
        field = field.bind(behavior)
        field_context = behavior
    else:
        # main object field
        factory = get_cached_factory(context.type_name)
        schema = factory.schema
        try:
            field = schema[field_name]
        except KeyError:
            return HTTPNotFound(content={"reason": f"No field: {field_name}"})
        field = field.bind(context)
        field_context = context

    # check permission
    read_permissions = merged_tagged_value_dict(schema, read_permission.key)
    serializer = get_multi_adapter((context, request),
                                   IResourceSerializeToJson)

    if not serializer.check_permission(read_permissions.get(field_name)):
        return HTTPUnauthorized(
            content={"reason": "You are not authorized to render this field"})

    field_renderer = query_multi_adapter((context, request, field),
                                         IFieldValueRenderer)
    if field_renderer is None:
        return await serializer.serialize_field(field_context, field)
    else:
        return await field_renderer()
 def __init__(self):
     self.data_adapter = DefaultCatalogDataAdapter(None)
     self.mappings = {}
     for type_name, schema in get_utilities_for(IResourceFactory):
         self.mappings[type_name] = {}
         for schema in iter_schemata_for_type(type_name):
             for field_name, index_data in merged_tagged_value_dict(
                     schema, directives.index.key).items():
                 index_name = index_data.get('index_name', field_name)
                 self.mappings[type_name][index_name] = {
                     'schema': schema,
                     'properties': index_data
                 }
Exemplo n.º 9
0
    async def get_schema(self, schema, context, result, behavior):
        read_permissions = merged_tagged_value_dict(schema,
                                                    read_permission.key)
        schema_serial = {}
        for name, field in getFields(schema).items():

            if not self.check_permission(read_permissions.get(name)):
                continue
            serializer = queryMultiAdapter((field, context, self.request),
                                           IResourceFieldSerializer)
            value = await serializer()
            if not behavior:
                result[name] = value
            else:
                schema_serial[name] = value

        if behavior:
            result[schema.__identifier__] = schema_serial
Exemplo n.º 10
0
    async def __call__(self):
        # For each type
        values = {}

        for schema in iter_schemata_for_type(self.content.portal_type):
            behavior = schema(self.content)
            for index_name, index_data in merged_tagged_value_dict(
                    schema, index.key).items():
                try:
                    if 'accessor' in index_data:
                        values[index_name] = await apply_coroutine(
                            index_data['accessor'], behavior)
                    else:
                        values[index_name] = self.get_data(
                            behavior, schema, index_name)
                except NoIndexField:
                    pass
            for metadata_name in merged_tagged_value_list(
                    schema, metadata.key):
                values[metadata_name] = self.get_data(behavior, schema,
                                                      metadata_name)

        return values
Exemplo n.º 11
0
    async def set_schema(
            self, schema, obj, data, errors,
            validate_all=False, behavior=False):
        write_permissions = merged_tagged_value_dict(schema, write_permission.key)

        for name, field in get_fields(schema).items():

            if field.readonly:
                continue

            if behavior:
                found = False
                if schema.__identifier__ in data:
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False

            f = schema.get(name)
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    continue

                try:
                    value = await self.get_value(f, obj, data_value)
                except ValueError as e:
                    errors.append({
                        'message': e.message, 'field': name, 'error': e})
                except ValidationError as e:
                    errors.append({
                        'message': e.doc(), 'field': name, 'error': e})
                except ValueDeserializationError as e:
                    errors.append({
                        'message': e.message, 'field': name, 'error': e})
                except Invalid as e:
                    errors.append({
                        'message': e.args[0], 'field': name, 'error': e})
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await apply_coroutine(field.set, obj, value)
                    except Exception:
                        logger.warning(
                            'Error setting data on field, falling back to setattr',
                            exc_info=True)
                        setattr(obj, name, value)
            else:
                if f.required and not hasattr(obj, name):
                    errors.append({
                        'message': 'Required parameter', 'field': name,
                        'error': ValueError('Required parameter')})

        if validate_all:
            invariant_errors = []
            try:
                schema.validateInvariants(object, invariant_errors)
            except Invalid:
                # Just collect errors
                pass
            validation = [(None, e) for e in invariant_errors]

            if len(validation):
                for e in validation:
                    errors.append({
                        'message': e[1].doc(),
                        'field': e[0],
                        'error': e
                    })
Exemplo n.º 12
0
def get_index_fields(type_name):
    mapping = {}
    for schema in get_all_possible_schemas_for_type(type_name):
        # create mapping for content type
        mapping.update(merged_tagged_value_dict(schema, index.key))
    return mapping
Exemplo n.º 13
0
def get_index_fields(type_name):
    mapping = {}
    for schema in get_all_possible_schemas_for_type(type_name):
        # create mapping for content type
        mapping.update(merged_tagged_value_dict(schema, index.key))
    return mapping
Exemplo n.º 14
0
    async def set_schema(
        self,
        schema: Type[Interface],
        obj: IResource,
        data: Dict[str, Any],
        errors: List[Dict[str, Any]],
        validate_all: bool = False,
        behavior: bool = False,
    ):
        write_permissions = merged_tagged_value_dict(schema,
                                                     write_permission.key)
        changed = False
        for name, field in get_fields(schema).items():

            if name in RESERVED_ATTRS:
                continue

            if field.readonly:
                continue

            if behavior:
                found = False
                if data.get(schema.__identifier__):
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    raise Unauthorized("Write permission not allowed")

                try:
                    field = field.bind(obj)
                    value = await self.get_value(field, obj, data_value)
                except ValueError as e:
                    errors.append({
                        "message": "Value error",
                        "field": name,
                        "error": e
                    })
                except ValidationError as e:
                    errors.append(e.json())
                except ValueDeserializationError as e:
                    errors.append({
                        "message": e.message,
                        "field": name,
                        "error": e
                    })
                except Invalid as e:
                    errors.append({
                        "message": e.args[0],
                        "field": name,
                        "error": e
                    })
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await apply_coroutine(field.set, obj, value)
                        changed = True
                    except ValidationError as e:
                        errors.append(e.json())
                    except ValueDeserializationError as e:
                        errors.append({
                            "message": e.message,
                            "field": name,
                            "error": e
                        })
                    except AttributeError:
                        logger.warning(
                            f"AttributeError setting data on field {name}",
                            exc_info=True)
                    except Exception:
                        logger.warning(
                            f"Unhandled error setting data on field, {schema} {name}",
                            exc_info=True)
                        errors.append({
                            "message":
                            "Unhandled exception",
                            "field":
                            name,
                            "error":
                            ValueDeserializationError(field, value,
                                                      "Unhandled error"),
                        })
            else:
                if validate_all and field.required and getattr(
                        obj, name, None) is None:
                    errors.append({
                        "message": "Required parameter",
                        "field": name,
                        "error": ValueError("Required parameter"),
                    })

        for error in await validate_invariants(schema, obj):
            if isinstance(error, ValidationError):
                errors.append({
                    "message": error.doc(),
                    "value": error.value,
                    "field": error.field_name,
                    "error": error.errors,
                })
            else:
                if len(getattr(error, "args", [])) > 0 and isinstance(
                        error.args[0], str):
                    message = error.args[0]
                else:
                    message = error.__doc__
                errors.append({"message": message, "error": error})

        if changed:
            obj.register()
Exemplo n.º 15
0
    async def set_schema(self,
                         schema,
                         obj,
                         data,
                         errors,
                         validate_all=False,
                         behavior=False):
        write_permissions = merged_tagged_value_dict(schema,
                                                     write_permission.key)

        for name, field in get_fields(schema).items():
            if name in RESERVED_ATTRS:
                continue

            if field.readonly:
                continue

            if behavior:
                found = False
                if schema.__identifier__ in data:
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    raise Unauthorized('Write permission not allowed')

                try:
                    field = field.bind(obj)
                    value = await self.get_value(field, obj, data_value)
                except ValueError as e:
                    errors.append({
                        'message': 'Value error',
                        'field': name,
                        'error': e
                    })
                except ValidationError as e:
                    errors.append({
                        'message': e.doc(),
                        'field': name,
                        'error': e
                    })
                except ValueDeserializationError as e:
                    errors.append({
                        'message': e.message,
                        'field': name,
                        'error': e
                    })
                except Invalid as e:
                    errors.append({
                        'message': e.args[0],
                        'field': name,
                        'error': e
                    })
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await notify(BeforeFieldModifiedEvent(field, value))
                        await apply_coroutine(field.set, obj, value)
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(),
                            'field': name,
                            'error': e
                        })
                    except ValueDeserializationError as e:
                        errors.append({
                            'message': e.message,
                            'field': name,
                            'error': e
                        })
                    except AttributeError:
                        logger.warning(
                            f'AttributeError setting data on field {name}',
                            exc_info=True)
                    except Exception:
                        if not isinstance(getattr(type(obj), name, None),
                                          property):
                            # we can not set data on properties
                            logger.warning(
                                'Error setting data on field, falling back to setattr',
                                exc_info=True)
                            setattr(obj, name, value)
                        else:
                            logger.warning('Error setting data on field',
                                           exc_info=True)
            else:
                if validate_all and field.required and getattr(
                        obj, name, None) is None:
                    errors.append({
                        'message': 'Required parameter',
                        'field': name,
                        'error': ValueError('Required parameter')
                    })

        if validate_all:
            invariant_errors = []
            try:
                schema.validateInvariants(object, invariant_errors)
            except Invalid:
                # Just collect errors
                pass
            validation = [(None, e) for e in invariant_errors]

            if len(validation):
                for error in validation:
                    errors.append({
                        'message': error[1].doc(),
                        'field': error[0],
                        'error': error
                    })
Exemplo n.º 16
0
    async def set_schema(
            self, schema, obj, data, errors,
            validate_all=False, behavior=False):
        write_permissions = merged_tagged_value_dict(schema, write_permission.key)

        for name, field in get_fields(schema).items():
            if name in RESERVED_ATTRS:
                continue

            if field.readonly:
                continue

            if behavior:
                found = False
                if schema.__identifier__ in data:
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    raise Unauthorized('Write permission not allowed')

                try:
                    field = field.bind(obj)
                    value = await self.get_value(field, obj, data_value)
                except ValueError as e:
                    errors.append({
                        'message': 'Value error', 'field': name, 'error': e})
                except ValidationError as e:
                    errors.append({
                        'message': e.doc(), 'field': name, 'error': e})
                except ValueDeserializationError as e:
                    errors.append({
                        'message': e.message, 'field': name, 'error': e})
                except Invalid as e:
                    errors.append({
                        'message': e.args[0], 'field': name, 'error': e})
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await apply_coroutine(field.set, obj, value)
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(), 'field': name, 'error': e})
                    except ValueDeserializationError as e:
                        errors.append({
                            'message': e.message, 'field': name, 'error': e})
                    except AttributeError:
                        logger.warning(
                            f'AttributeError setting data on field {name}', exc_info=True)
                    except Exception:
                        if not isinstance(getattr(type(obj), name, None), property):
                            # we can not set data on properties
                            logger.warning(
                                'Error setting data on field, falling back to setattr',
                                exc_info=True)
                            setattr(obj, name, value)
                        else:
                            logger.warning(
                                'Error setting data on field', exc_info=True)
            else:
                if validate_all and field.required and getattr(obj, name, None) is None:
                    errors.append({
                        'message': 'Required parameter', 'field': name,
                        'error': ValueError('Required parameter')})

        if validate_all:
            invariant_errors = []
            try:
                schema.validateInvariants(object, invariant_errors)
            except Invalid:
                # Just collect errors
                pass
            validation = [(None, e) for e in invariant_errors]

            if len(validation):
                for error in validation:
                    errors.append({
                        'message': error[1].doc(),
                        'field': error[0],
                        'error': error
                    })
Exemplo n.º 17
0
    async def set_schema(self,
                         schema,
                         obj,
                         data,
                         errors,
                         validate_all=False,
                         behavior=False):
        write_permissions = merged_tagged_value_dict(schema,
                                                     write_permission.key)
        for name, field in getFields(schema).items():

            if field.readonly:
                continue

            if behavior:
                data_value = data[schema.__identifier__][name] if name in data[
                    schema.__identifier__] else None  # noqa
                found = True if name in data[schema.__identifier__] else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False

            f = schema.get(name)
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    continue

                # Deserialize to field value
                deserializer = queryMultiAdapter((f, obj, self.request),
                                                 IResourceFieldDeserializer)
                if deserializer is None:
                    continue

                try:
                    value = deserializer(data_value)
                except ValueError as e:
                    errors.append({
                        'message': e.message,
                        'field': name,
                        'error': e
                    })
                except ValidationError as e:
                    errors.append({
                        'message': e.doc(),
                        'field': name,
                        'error': e
                    })
                except Invalid as e:
                    errors.append({
                        'message': e.args[0],
                        'field': name,
                        'error': e
                    })
                else:
                    try:
                        field.set(obj, value)
                    except:  # noqa
                        setattr(obj, name, value)
            else:
                if f.required and not hasattr(obj, name):
                    errors.append({
                        'message': 'Required parameter',
                        'field': name,
                        'error': ValueError('Required parameter')
                    })

        if validate_all:
            invariant_errors = []
            try:
                schema.validateInvariants(object, invariant_errors)
            except Invalid:
                # Just collect errors
                pass
            validation = [(None, e) for e in invariant_errors]

            if len(validation):
                for e in validation:
                    errors.append({
                        'message': e[1].doc(),
                        'field': e[0],
                        'error': e
                    })