def _create_listener(self, content_type, body, *args, **kwargs): if content_type != 'application/json': raise qvarn.NotJson(content_type) rt = self._listener_coll.get_type() validator = qvarn.Validator() try: validator.validate_against_prototype(rt.get_type(), body, rt.get_latest_prototype()) except qvarn.ValidationError as e: qvarn.log.log('error', msg_text=str(e), body=body) return qvarn.bad_request_response(str(e)) if 'type' not in body: body['type'] = 'listener' rtype = self._parent_coll.get_type_name() if body.get('listen_on_type', rtype) != rtype: return qvarn.bad_request_response( 'listen_on_type does not have value {}'.format(rtype)) body['listen_on_type'] = rtype id_allowed = self._api.is_id_allowed(kwargs.get('claims', {})) if id_allowed: result_body = self._listener_coll.post_with_id(body) else: result_body = self._listener_coll.post(body) location = self._get_new_resource_location(result_body) qvarn.log.log('debug', msg_text='POST a new listener, result', body=result_body, location=location) return qvarn.created_response(result_body, location)
def __init__(self): self._store = None self._validator = qvarn.Validator() self._baseurl = None self._rt_coll = None self._notifs = None self._alog = None
def put(self, obj, claims=None, access_params=None): v = qvarn.Validator() v.validate_resource_update(obj, self.get_type()) old = self.get(obj['id'], claims=claims, access_params=access_params) if old['revision'] != obj['revision']: raise WrongRevision(obj['revision'], old['revision']) new_obj = dict(obj) new_obj['revision'] = self._invent_id('revision') self._store.remove_objects(obj_id=new_obj['id'], subpath='') self._create_object(new_obj, obj_id=new_obj['id'], subpath='') return new_obj
def _update(self, content_type, body, *args, **kwargs): qvarn.log.log('trace', msg_text='_update', kwargs=kwargs) claims = kwargs.get('claims') params = self.get_access_params(self._coll.get_type_name(), claims) if content_type != 'application/json': raise qvarn.NotJson(content_type) if 'type' not in body: body['type'] = self._coll.get_type_name() if 'id' not in body: body['id'] = kwargs['id'] validator = qvarn.Validator() try: validator.validate_resource_update(body, self._coll.get_type()) except qvarn.ValidationError as e: qvarn.log.log('error', msg_text=str(e), body=body) return qvarn.bad_request_response(str(e)) obj_id = kwargs['id'] # FIXME: the following test should be enabled once we # no longer need test-api. if False and body['id'] != obj_id: raise qvarn.IdMismatch(body['id'], obj_id) try: result_body = self._coll.put(body, claims=claims, access_params=params) except qvarn.WrongRevision as e: return qvarn.conflict_response(str(e)) except qvarn.NoSuchResource as e: # We intentionally say bad request, instead of not found. # This is to be compatible with old Qvarn. This may get # changed later. return qvarn.bad_request_response(str(e)) self._notify(result_body['id'], result_body['revision'], 'updated') self._log_access( result_body, result_body.get('type'), 'PUT', # FIXME: add header getting to apifw bottle.request.get_header('Authorization', ''), bottle.request.get_header('Qvarn-Token', ''), bottle.request.get_header('Qvarn-Access-By', ''), bottle.request.get_header('Qvarn-Why', None)) return qvarn.ok_response(result_body)
def _put_subresource(self, content_type, body, *args, **kwargs): claims = kwargs.get('claims') params = self.get_access_params(self._parent_coll.get_type_name(), claims) if content_type != 'application/json': raise qvarn.NotJson(content_type) obj_id = kwargs['id'] if 'revision' not in body: return qvarn.bad_request_response('must have revision') revision = body.pop('revision') id_allowed = self._api.is_id_allowed(kwargs.get('claims', {})) rt = self._parent_coll.get_type() validator = qvarn.Validator() try: validator.validate_subresource(self._subpath, rt, body) except qvarn.ValidationError as e: qvarn.log.log('error', msg_text=str(e), body=body) return qvarn.bad_request_response(str(e)) try: if id_allowed: func = self._parent_coll.put_subresource_no_new_revision else: func = self._parent_coll.put_subresource result_body = func(body, subpath=self._subpath, obj_id=obj_id, revision=revision, claims=claims, access_params=params) except qvarn.WrongRevision as e: return qvarn.conflict_response(str(e)) except qvarn.NoSuchResource as e: return qvarn.no_such_resource_response(str(e)) return qvarn.ok_response(result_body)
def _create(self, content_type, body, *args, **kwargs): if content_type != 'application/json': raise qvarn.NotJson(content_type) if 'type' not in body: body['type'] = self._coll.get_type_name() id_allowed = self._api.is_id_allowed(kwargs.get('claims', {})) validator = qvarn.Validator() try: if id_allowed: validator.validate_new_resource_with_id( body, self._coll.get_type()) else: validator.validate_new_resource(body, self._coll.get_type()) except (qvarn.HasId, qvarn.HasRevision) as e: qvarn.log.log('error', msg_text=str(e), body=body) return qvarn.bad_request_response(str(e)) except qvarn.ValidationError as e: qvarn.log.log('error', msg_text=str(e), body=body) return qvarn.bad_request_response(str(e)) result_body = self._coll.post_with_id(body) location = '{}{}/{}'.format(self._baseurl, self._coll.get_type().get_path(), result_body['id']) self._notify(result_body['id'], result_body['revision'], 'created') self._log_access( result_body, result_body.get('type'), 'POST', # FIXME: add header getting to apifw bottle.request.get_header('Authorization', ''), bottle.request.get_header('Qvarn-Token', ''), bottle.request.get_header('Qvarn-Access-By', ''), bottle.request.get_header('Qvarn-Why', None)) return qvarn.created_response(result_body, location)
def setUp(self): self.spec = { 'type': 'foo', 'path': '/foos', 'versions': [ { 'version': 'v0', 'prototype': { 'type': '', 'id': '', 'revision': '', 'foo': '', }, 'subpaths': { 'sub': { 'prototype': { 'subfield': '', }, }, }, }, ] } self.resource_type = qvarn.ResourceType() self.resource_type.from_spec(self.spec) self.validator = qvarn.Validator() self.resource = { 'type': 'foo', 'id': 'resource-1', 'revision': 'revision-1', 'foo': 'this is foo', } self.subresource = { 'subfield': 'bananarama', }
def _update_listener(self, content_type, body, *args, **kwargs): claims = kwargs.get('claims') params = self.get_access_params(self._listener_coll.get_type_name(), claims) if content_type != 'application/json': raise qvarn.NotJson(content_type) if 'type' not in body: body['type'] = 'listener' listener_id = kwargs['listener_id'] if 'id' not in body: body['id'] = listener_id validator = qvarn.Validator() try: validator.validate_resource_update(body, self._listener_coll.get_type()) except qvarn.ValidationError as e: qvarn.log.log('error', msg_text=str(e), body=body) return qvarn.bad_request_response(str(e)) try: result_body = self._listener_coll.put(body, claims=claims, access_params=params) except qvarn.WrongRevision as e: return qvarn.conflict_response(str(e)) except qvarn.NoSuchResource as e: # We intentionally say bad request, instead of not found. # This is to be compatible with old Qvarn. This may get # changed later. return qvarn.bad_request_response(str(e)) return qvarn.ok_response(result_body)
def post_with_id(self, obj): # pragma: no cover v = qvarn.Validator() v.validate_new_resource_with_id(obj, self.get_type()) result = self._post_helper(obj) return result
def post(self, obj): v = qvarn.Validator() v.validate_new_resource(obj, self.get_type()) return self._post_helper(obj)