Source code for augeias.views

import uuid

from pyramid.response import Response
from pyramid.httpexceptions import HTTPLengthRequired, HTTPBadRequest, HTTPNotFound
from pyramid.view import view_config

from augeias.stores.error import NotFoundException


@view_config(context=NotFoundException, renderer='json')
def failed_not_found(exc, request):
    request.response.status_int = 404
    return {'message': exc.value}


[docs]class ValidationFailure(Exception): def __init__(self, msg): self.msg = msg
@view_config(context=ValidationFailure, renderer='json') def failed_validation(exc, request): request.response.status_int = 400 return {'message': 'Failed validation: %s' % exc.msg} class AugeiasView(object): def __init__(self, request): self.request = request @view_config(route_name='home', renderer='json') def my_view(self): return {'project': 'augeias'} @view_config(route_name='list_collections', permission='view') def list_collections(self): res = Response(content_type='application/json', status=200) res.json_body = [c for c in self.request.registry.collections] return res @view_config(route_name='update_object', permission='edit') def update_object(self): ''' Update an object in the data store. The input object data may be: - an object stream (Content-Type: application/octet-stream), - or a store location (host url, collection_key, container_key and object_key) within the same Augeias instance (Content-Type: application/json). ''' object_data = _get_object_data(self.request) collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] object_key = self.request.matchdict['object_key'] if len(object_key) < 3: raise ValidationFailure('The object key must be 3 characters long') collection.object_store.update_object(container_key, object_key, object_data) res = Response(content_type='application/json', status=200) res.json_body = { 'container_key': container_key, 'object_key': object_key, 'uri': collection.uri_generator.generate_object_uri( collection=collection.name, container=container_key, object=object_key) } return res @view_config(route_name='create_object_and_id', permission='edit') def create_object_and_id(self): '''create an object in the data store and generate an id''' object_data = _get_object_data(self.request) collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] object_key = str(uuid.uuid4()) collection.object_store.update_object(container_key, object_key, object_data) res = Response(content_type='application/json', status=201) res.json_body = { 'container_key': container_key, 'object_key': object_key, 'uri': collection.uri_generator.generate_object_uri( collection=collection.name, container=container_key, object=object_key) } return res @view_config(route_name='delete_object', permission='edit') def delete_object(self): '''delete an object from the data store''' collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] object_key = self.request.matchdict['object_key'] collection.object_store.delete_object(container_key, object_key) res = Response(content_type='application/json', status=200) res.json_body = { 'container_key': container_key, 'object_key': object_key, 'uri': collection.uri_generator.generate_object_uri( collection=collection.name, container=container_key, object=object_key) } return res @view_config(route_name='get_object', permission='view') def get_object(self): '''retrieve an object from the data store''' collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] object_key = self.request.matchdict['object_key'] object_data = collection.object_store.get_object(container_key, object_key) content_type = collection.object_store.get_object_info(container_key, object_key)['mime'] res = Response(content_type=content_type, status=200) res.body = object_data return res @view_config(route_name='get_object_info', permission='view') def get_object_info(self): '''retrieve object info (mimetype, size, time last modification) from the data store''' collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] object_key = self.request.matchdict['object_key'] res = Response(content_type='application/json', status=200) res.json_body = collection.object_store.get_object_info(container_key, object_key) return res @view_config(route_name='list_object_keys_for_container', permission='view') def list_object_keys_for_container(self): '''list all object keys for a container in the data store''' collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] res = Response(content_type='application/json', status=200) res.json_body = collection.object_store.list_object_keys_for_container(container_key) return res @view_config(route_name='get_container_data', permission='view') def get_container_data(self): """Get a container from the data store as zip.""" parameters = self.request.GET collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] zip_file = collection.object_store.get_container_data( container_key, translations=parameters ) filename = str(container_key) + '.zip' disposition = ('attachment; filename={}'.format(filename)) res = Response(content_type='application/zip', status=200, content_disposition=disposition) res.body = zip_file.read() return res @view_config(route_name='create_container', permission='edit') def create_container(self): '''create a new container in the data store''' collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] collection.object_store.create_container(container_key) res = Response(content_type='application/json', status=200) res.json_body = { 'container_key': container_key, 'uri': collection.uri_generator.generate_container_uri( collection=collection.name, container=container_key) } return res @view_config(route_name='create_container_and_id', permission='edit') def create_container_and_id(self): '''create a new container in the data store and generate an id''' collection = _retrieve_collection(self.request) container_key = str(uuid.uuid4()) collection.object_store.create_container(container_key) res = Response(content_type='application/json', status=201) res.json_body = { 'container_key': container_key, 'uri': collection.uri_generator.generate_container_uri( collection=collection.name, container=container_key) } return res @view_config(route_name='delete_container', permission='edit') def delete_container(self): '''delete a container in the data store''' collection = _retrieve_collection(self.request) container_key = self.request.matchdict['container_key'] collection.object_store.delete_container(container_key) res = Response(content_type='application/json', status=200) res.json_body = { 'container_key': container_key, 'uri': collection.uri_generator.generate_container_uri( collection=collection.name, container=container_key) } return res # HELPERS def _is_integer(s): try: int(s) # python 2.7 'auto-promotes' int to long if required return True except ValueError: return False def _get_object_data(request): if request.content_type == 'application/json': return _get_object_data_from_json_body(request) else: return _get_object_data_from_stream(request) def _get_object_data_from_stream(request): if 'Content-Length' not in request.headers or not _is_integer(request.headers['Content-Length']): raise HTTPLengthRequired content_length = int(request.headers['Content-Length']) object_data = request.body_file if content_length == 0: raise HTTPBadRequest('body is empty') return object_data def _get_object_data_from_json_body(request): ''' The json body contains the location of the input object. The body must include be the host url, collection_key, container_key and object_key. ''' json_data = _get_json_from_request(request) required_keys = ['host_url', 'collection_key', 'container_key', 'object_key'] missing_keys = set(required_keys) - set(json_data.keys()) if missing_keys: raise HTTPBadRequest('\n'.join('{} is Required.'.format(key) for key in missing_keys)) if request.host_url != json_data['host_url']: raise ValidationFailure('Host must be equal to the current host url {}.'.format(request.host)) collection = request.registry.collections.get(json_data['collection_key']) if not collection: raise HTTPBadRequest('Collection {} was not found'.format(json_data['collection_key'])) try: object_data = collection.object_store.get_object(json_data['container_key'], json_data['object_key']) except NotFoundException: raise HTTPBadRequest('Container - object ({0} - {1}) combination was not found in Collection {2}'.format( json_data['container_key'], json_data['object_key'], json_data['collection_key'])) return object_data def _get_json_from_request(request): try: return request.json_body except AttributeError as e: raise HTTPBadRequest(detail="Request has no json body. \n%s" % e) # pragma: no cover except ValueError as e: raise HTTPBadRequest(detail="Request has incorrect json body. \n%s" % e) def _retrieve_collection(request): collection_name = request.matchdict['collection_key'] if collection_name in request.registry.collections: collection = request.registry.collections[collection_name] else: raise HTTPNotFound('collection not found') return collection