Beispiel #1
0
async def get(request: web.Request):
    hooks = request.app.hooks
    docid = request.match_info['dataset']
    etag_if_none_match = conditional.parse_if_header(
        request, conditional.HEADER_IF_NONE_MATCH)
    if etag_if_none_match == '*':
        raise web.HTTPBadRequest(
            body='Endpoint does not support * in the If-None-Match header.')
    # Now we know etag_if_none_match is either None or a set.
    try:
        doc, etag = await hooks.storage_retrieve(app=request.app,
                                                 docid=docid,
                                                 etags=etag_if_none_match)
    except KeyError:
        raise web.HTTPNotFound()
    if doc is None:
        return web.Response(status=304, headers={'Etag': etag})
    canonical_doc = await hooks.mds_canonicalize(app=request.app, data=doc)
    canonical_doc = await hooks.mds_after_storage(app=request.app,
                                                  data=canonical_doc,
                                                  doc_id=docid)

    if canonical_doc['ams:status'] not in ('beschikbaar', 'in_onderzoek'):
        scopes = request.authz_scopes if hasattr(request,
                                                 "authz_scopes") else {}
        extra_read_access = 'CAT/R' in scopes
        if not extra_read_access:
            return web.HTTPForbidden()

    return web.json_response(canonical_doc,
                             headers={
                                 'Etag': etag,
                                 'content_type': 'application/ld+json'
                             })
Beispiel #2
0
async def link_redirect(request: web.Request):
    dataset = request.match_info['dataset']
    distribution = request.match_info['distribution']
    etag_if_none_match = conditional.parse_if_header(
        request, conditional.HEADER_IF_NONE_MATCH)
    if etag_if_none_match == '*':
        raise web.HTTPBadRequest(
            body='Endpoint does not support * in the If-None-Match header.')

    try:
        doc, etag = await request.app.hooks.storage_retrieve(
            app=request.app, docid=dataset, etags=etag_if_none_match)
    except KeyError:
        raise web.HTTPNotFound()
    if doc is None:
        raise web.HTTPNotModified(headers={'ETag': etag})
    headers = {'ETag': etag}
    resource_url = None
    for dist in doc.get('dcat:distribution', []):
        if dist.get('dc:identifier', None) == distribution:
            resource_url = dist.get('dcat:accessURL', None)
            break
    if resource_url is None:
        raise web.HTTPNotFound(headers=headers)
    raise web.HTTPTemporaryRedirect(location=resource_url, headers=headers)
Beispiel #3
0
async def delete(request: web.Request):
    given_id = request.match_info['dataset']
    etag_if_match = conditional.parse_if_header(request,
                                                conditional.HEADER_IF_MATCH)
    if etag_if_match is None or etag_if_match == '*':
        raise web.HTTPBadRequest(
            text='Must provide a If-Match header containing one or more ETags.'
        )
    try:
        await request.app.hooks.storage_delete(app=request.app,
                                               docid=given_id,
                                               etags=etag_if_match)
    except KeyError:
        raise web.HTTPNotFound()
    return web.Response(status=204, content_type='text/plain')
Beispiel #4
0
async def put(request: web.Request):
    hooks = request.app.hooks
    scopes = request.authz_scopes

    is_redact_only = 'CAT/W' not in scopes

    # Grab the document from the request body and canonicalize it.
    try:
        doc = await request.json()
    except json.decoder.JSONDecodeError:
        raise web.HTTPBadRequest(text='invalid json')
    doc['ams:modifiedby'] = request.authz_subject
    canonical_doc = await hooks.mds_canonicalize(app=request.app, data=doc)

    if is_redact_only and canonical_doc['ams:status'] == 'beschikbaar':
        raise web.HTTPForbidden()

    # Make sure the docid in the path corresponds to the ids given in the
    # document, if any. The assumption is that request.path (which corresponds
    # to the path part of the incoming HTTP request) is the path as seen by
    # the client. This is not necessarily true.
    doc_id = request.match_info['dataset']

    # Let the metadata plugin grab the full-text search representation
    searchable_text = await hooks.mds_full_text_search_representation(
        data=canonical_doc)

    # Figure out the mode (insert / update) of the request.
    etag_if_match = conditional.parse_if_header(request,
                                                conditional.HEADER_IF_MATCH)
    etag_if_none_match = conditional.parse_if_header(
        request, conditional.HEADER_IF_NONE_MATCH)
    # Can't accept a value in both headers
    if etag_if_match is not None and etag_if_none_match is not None:
        raise web.HTTPBadRequest(
            body='Endpoint supports either If-Match or If-None-Match in a '
            'single request, not both')

    # If-Match: {etag, ...} is for updates
    if etag_if_match is not None:
        if etag_if_match == '*':
            raise web.HTTPBadRequest(
                body='Endpoint does not support If-Match: *. Must provide one '
                'or more Etags.')
        try:
            old_doc, _etag = await hooks.storage_retrieve(app=request.app,
                                                          docid=doc_id,
                                                          etags=None)
        except KeyError:
            _logger.exception('precondition failed')
            raise web.HTTPPreconditionFailed()
        canonical_doc = await hooks.mds_before_storage(app=request.app,
                                                       data=canonical_doc,
                                                       old_data=old_doc)
        try:
            new_etag = await hooks.storage_update(
                app=request.app,
                docid=doc_id,
                doc=canonical_doc,
                searchable_text=searchable_text,
                etags=etag_if_match,
                iso_639_1_code="nl")
        except ValueError:
            _logger.exception('precondition failed')
            raise web.HTTPPreconditionFailed()
        await notify_data_changed(request.app)
        retval = web.Response(status=204, headers={'Etag': new_etag})

    else:
        # If-None-Match: * is for creates
        if etag_if_none_match != '*':
            raise web.HTTPBadRequest(
                body='For inserts of new documents, provide If-None-Match: *')
        canonical_doc = await hooks.mds_before_storage(app=request.app,
                                                       data=canonical_doc)
        try:
            new_etag = await hooks.storage_create(
                app=request.app,
                docid=doc_id,
                doc=canonical_doc,
                searchable_text=searchable_text,
                iso_639_1_code="nl")
        except KeyError:
            _logger.exception('precondition failed')
            raise web.HTTPPreconditionFailed()
        await notify_data_changed(request.app)
        retval = web.Response(status=201,
                              headers={'Etag': new_etag},
                              content_type='text/plain')

    return retval