예제 #1
0
파일: storage.py 프로젝트: truthadjustr/h
def create_annotation(request, data, group_service):
    """
    Create an annotation from passed data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: a dictionary of annotation properties
    :type data: dict

    :param group_service: a service object that adheres to ``h.interfaces.IGroupService``
    :type group_service: h.interfaces.IGroupService

    :returns: the created and flushed annotation
    :rtype: dict
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data['document']['document_uri_dicts']
    document_meta_dicts = data['document']['document_meta_dicts']
    del data['document']

    # Replies must have the same group as their parent.
    if data['references']:
        top_level_annotation_id = data['references'][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data['groupid'] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                'references.0: ' + _('Annotation {id} does not exist').format(
                    id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data['groupid'])
    if group is None or not request.has_permission('write', context=group):
        raise schemas.ValidationError('group: ' +
                                      _('You may not create annotations '
                                        'in the specified group!'))

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(request.db,
                                        annotation.target_uri,
                                        document_meta_dicts,
                                        document_uri_dicts,
                                        created=created,
                                        updated=updated)
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    return annotation
예제 #2
0
def update_annotation(request, id_, data, group_service):
    """
    Update an existing annotation and its associated document metadata.

    Update the annotation identified by ``id_`` with the given
    data. Create, delete and update document metadata as appropriate.

    :param request: the request object

    :param id_: the ID of the annotation to be updated, this is assumed to be a
        validated ID of an annotation that does already exist in the database
    :type id_: string

    :param data: the validated data with which to update the annotation
    :type data: dict

    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the updated annotation
    :rtype: h.models.Annotation

    """
    updated = datetime.utcnow()

    # Remove any 'document' field first so that we don't try to save it on the
    # annotation object.
    document = data.pop("document", None)

    annotation = request.db.query(models.Annotation).get(id_)
    annotation.updated = updated

    group = group_service.find(annotation.groupid)
    if group is None:
        raise schemas.ValidationError(
            "group: " + _("Invalid group specified for annotation"))
    if data.get("target_uri", None):
        _validate_group_scope(group, data["target_uri"])

    annotation.extra.update(data.pop("extra", {}))

    for key, value in data.items():
        setattr(annotation, key, value)

    if document:
        document_uri_dicts = document["document_uri_dicts"]
        document_meta_dicts = document["document_meta_dicts"]
        document = update_document_metadata(
            request.db,
            annotation.target_uri,
            document_meta_dicts,
            document_uri_dicts,
            updated=updated,
        )
        annotation.document = document

    request.find_service(name="search_index")._queue.add_by_id(
        id_, tag="storage.update_annotation", schedule_in=60)

    return annotation
예제 #3
0
파일: storage.py 프로젝트: djalmabright/h
def _validate_group_scope(group, target_uri):
    if not group.scopes:
        return
    # The scope (origin) of the target URI must match at least one
    # of a group's defined scopes, if the group has any
    group_scopes = [scope.origin for scope in group.scopes]
    if not group_scope_match(target_uri, group_scopes):
        raise schemas.ValidationError('group scope: ' +
                                      _('Annotations for this target URI '
                                        'are not allowed in this group'))
예제 #4
0
파일: storage.py 프로젝트: djalmabright/h
def update_annotation(request, id_, data, group_service):
    """
    Update an existing annotation and its associated document metadata.

    Update the annotation identified by id_ with the given
    data. Create, delete and update document metadata as appropriate.

    :param request: the request object

    :param id_: the ID of the annotation to be updated, this is assumed to be a
        validated ID of an annotation that does already exist in the database
    :type id_: string

    :param data: the validated data with which to update the annotation
    :type data: dict

    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the updated annotation
    :rtype: h.models.Annotation

    """
    updated = datetime.utcnow()

    # Remove any 'document' field first so that we don't try to save it on the
    # annotation object.
    document = data.pop('document', None)

    annotation = request.db.query(models.Annotation).get(id_)
    annotation.updated = updated

    group = group_service.find(annotation.groupid)
    if group is None:
        raise schemas.ValidationError(
            'group: ' + _('Invalid group specified for annotation'))
    if request.feature('filter_groups_by_scope') and data.get(
            'target_uri', None):
        _validate_group_scope(group, data['target_uri'])

    annotation.extra.update(data.pop('extra', {}))

    for key, value in data.items():
        setattr(annotation, key, value)

    if document:
        document_uri_dicts = document['document_uri_dicts']
        document_meta_dicts = document['document_meta_dicts']
        document = update_document_metadata(request.db,
                                            annotation.target_uri,
                                            document_meta_dicts,
                                            document_uri_dicts,
                                            updated=updated)
        annotation.document = document

    return annotation
예제 #5
0
def _validate_group_scope(group, target_uri):
    # If no scopes are present, or if the group is configured to allow
    # annotations outside of its scope, there's nothing to do here
    if not group.scopes or group.enforce_scope is False:
        return
    # The target URI must match at least one
    # of a group's defined scopes, if the group has any
    group_scopes = [scope.scope for scope in group.scopes]
    if not url_in_scope(target_uri, group_scopes):
        raise schemas.ValidationError("group scope: " +
                                      _("Annotations for this target URI "
                                        "are not allowed in this group"))
예제 #6
0
def create_annotation(request, data):
    """
    Create an annotation from already-validated data.

    :param request: the request object
    :param data: an annotation data dict that has already been validated by
        :py:class:`h.schemas.annotation.CreateAnnotationSchema`

    :returns: the created and flushed annotation
    """
    document_data = data.pop("document", {})

    # Replies must have the same group as their parent.
    if data["references"]:
        root_annotation_id = data["references"][0]

        if root_annotation := fetch_annotation(request.db, root_annotation_id):
            data["groupid"] = root_annotation.groupid
        else:
            raise schemas.ValidationError(
                "references.0: " + _("Annotation {id} does not exist").format(
                    id=root_annotation_id))
예제 #7
0
def create_annotation(request, data, group_service):
    """
    Create an annotation from already-validated data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: an annotation data dict that has already been validated by
        :py:class:`h.schemas.annotation.CreateAnnotationSchema`
    :type data: dict

    :param group_service: a service object that implements
        :py:class:`h.interfaces.IGroupService`
    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the created and flushed annotation
    :rtype: :py:class:`h.models.Annotation`
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data["document"]["document_uri_dicts"]
    document_meta_dicts = data["document"]["document_meta_dicts"]
    del data["document"]

    # Replies must have the same group as their parent.
    if data["references"]:
        top_level_annotation_id = data["references"][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data["groupid"] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                "references.0: " + _("Annotation {id} does not exist").format(
                    id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data["groupid"])
    if group is None or not request.has_permission("write", context=group):
        raise schemas.ValidationError("group: " +
                                      _("You may not create annotations "
                                        "in the specified group!"))

    _validate_group_scope(group, data["target_uri"])

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(
        request.db,
        annotation.target_uri,
        document_meta_dicts,
        document_uri_dicts,
        created=created,
        updated=updated,
    )
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    request.find_service(name="search_index")._queue.add_by_id(
        annotation.id, tag="storage.create_annotation", schedule_in=60)

    return annotation
예제 #8
0
        if root_annotation := fetch_annotation(request.db, root_annotation_id):
            data["groupid"] = root_annotation.groupid
        else:
            raise schemas.ValidationError(
                "references.0: " + _("Annotation {id} does not exist").format(
                    id=root_annotation_id))

    # Create the annotation and enable relationship loading so we can access
    # the group, even though we've not added this to the session yet
    annotation = models.Annotation(**data)
    request.db.enable_relationship_loading(annotation)

    group = annotation.group
    if not group:
        raise schemas.ValidationError(
            "group: " + _(f"Invalid group id {annotation.groupid}"))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in.
    if not request.has_permission(Permission.Group.WRITE,
                                  context=GroupContext(group)):
        raise schemas.ValidationError(
            "group: " +
            _("You may not create annotations in the specified group!"))

    _validate_group_scope(group, data["target_uri"])

    annotation.created = annotation.updated = datetime.utcnow()
    annotation.document = update_document_metadata(
        request.db,
        annotation.target_uri,
예제 #9
0
def create_annotation(request, data, group_service):
    """
    Create an annotation from already-validated data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: an annotation data dict that has already been validated by
        :py:class:`h.schemas.annotation.CreateAnnotationSchema`
    :type data: dict

    :param group_service: a service object that implements
        :py:class:`h.interfaces.IGroupService`
    :type group_service: :py:class:`h.interfaces.IGroupService`

    :returns: the created and flushed annotation
    :rtype: :py:class:`h.models.Annotation`
    """
    created = updated = datetime.utcnow()

    document_uri_dicts = data['document']['document_uri_dicts']
    document_meta_dicts = data['document']['document_meta_dicts']
    del data['document']

    # Replies must have the same group as their parent.
    if data['references']:
        top_level_annotation_id = data['references'][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data['groupid'] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                'references.0: ' + _('Annotation {id} does not exist').format(
                    id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in. If the application didn't configure
    # a groupfinder we will allow writing this annotation without any
    # further checks.
    group = group_service.find(data['groupid'])
    if group is None or not request.has_permission('write', context=group):
        raise schemas.ValidationError('group: ' +
                                      _('You may not create annotations '
                                        'in the specified group!'))

    if request.feature('filter_groups_by_scope') and group.scopes:
        # The scope (origin) of the target URI must match at least one
        # of a group's defined scopes, if the group has any
        group_scopes = [scope.origin for scope in group.scopes]
        if not group_scope_match(data['target_uri'], group_scopes):
            raise schemas.ValidationError('group scope: ' +
                                          _('Annotations for this target URI '
                                            'are not allowed in this group'))

    annotation = models.Annotation(**data)
    annotation.created = created
    annotation.updated = updated

    document = update_document_metadata(request.db,
                                        annotation.target_uri,
                                        document_meta_dicts,
                                        document_uri_dicts,
                                        created=created,
                                        updated=updated)
    annotation.document = document

    request.db.add(annotation)
    request.db.flush()

    return annotation