def _destroy(self, trail, request, response): try: name = '/'.join(trail) msg = self._parse_maybe_body(request, name) except Exception as e: raise HTTPError(406, str(e)) basename = self._db_container_key(None, trail) try: keylist = self.root.store.list(basename) if keylist is None: raise HTTPError(404) if len(keylist) != 0: raise HTTPError(409) ret = self.root.store.cut(basename.rstrip('/')) except CSStoreError: raise HTTPError(500) if ret is False: raise HTTPError(404) output = msg.reply(None) if output is None: response['code'] = 204 else: response['output'] = output response['code'] = 200
def _int_del_key(self, trail, request, response): key = self._db_key(trail) try: ret = self.root.store.cut(key) except CSStoreError: raise HTTPError(500) if ret is False: raise HTTPError(404) response['code'] = 204
def _db_container_key(self, default, trail): f = None if len(trail) > 1: f = self._db_key(trail) elif len(trail) == 1 and trail[0] != '': raise HTTPError(403) elif default is None: # No dfault namespace, fail raise HTTPError(403) else: # Use the default namespace f = self._db_key([default, '']) return f
def _int_get_key(self, trail, request, response): try: name = '/'.join(trail) msg = self._parse_query(request, name) except Exception as e: raise HTTPError(406, str(e)) key = self._db_key(trail) try: output = self.root.store.get(key) if output is None: raise HTTPError(404) response['output'] = msg.reply(output) except CSStoreError: raise HTTPError(500)
def _create(self, trail, request, response): default = request.get('default_namespace', None) basename = self._db_container_key(None, trail) try: ok = self._parent_exists(default, trail[:-1]) if not ok: raise HTTPError(404) self.root.store.set(basename, '') except CSStoreExists: raise HTTPError(409) except CSStoreError: raise HTTPError(500) response['code'] = 201
def _list(self, trail, request, response): try: name = '/'.join(trail) msg = self._parse_query(request, name) except Exception as e: raise HTTPError(406, str(e)) default = request.get('default_namespace', None) basename = self._db_container_key(default, trail) try: keylist = self.root.store.list(basename) self.logger.debug('list %s returned %r', basename, keylist) if keylist is None: raise HTTPError(404) response['output'] = msg.reply(json.dumps(keylist)) except CSStoreError: raise HTTPError(500)
def DELETE(self, request, response): trail = request.get('trail', []) if len(trail) == 0: raise HTTPError(405) if trail[-1] == '': self._destroy(trail, request, response) else: self._del_key(trail, request, response)
def _int_get_key(self, trail, request, response): # default to simple query = request.get('query', '') if len(query) == 0: query = {'type': 'simple', 'value': ''} try: name = '/'.join(trail) msg = self._parse(request, query, name) except Exception as e: raise HTTPError(406, str(e)) key = self._db_key(trail) try: output = self.root.store.get(key) if output is None: raise HTTPError(404) response['output'] = msg.reply(output) except CSStoreError: raise HTTPError(500)
def _destroy(self, trail, request, response): basename = self._db_container_key(None, trail) try: keylist = self.root.store.list(basename) if keylist is None: raise HTTPError(404) if basename not in keylist: # uh ? raise HTTPError(409) if len(keylist) != 1: raise HTTPError(409) ret = self.root.store.cut(basename) except CSStoreError: raise HTTPError(500) if ret is False: raise HTTPError(404) response['code'] = 204
def _list(self, trail, request, response): default = request.get('default_namespace', None) basename = self._db_container_key(default, trail) userfilter = request.get('query', dict()).get('filter', '') try: keylist = self.root.store.list(basename + userfilter) if keylist is None: raise HTTPError(404) # remove the base container itself output = list() for k in keylist: if k == basename: continue # strip away the internal prefix for storing keys name = k[len('keys/'):] output.append(name) response['output'] = json.dumps(output) except CSStoreError: raise HTTPError(500)
def _find_handler(self, request): base = self command = request.get('command', 'GET') if command not in SUPPORTED_COMMANDS: raise HTTPError(501) trail = request.get('trail', None) if trail is not None: for comp in trail: subs = getattr(base, 'subs', {}) if comp in subs: base = subs[comp] trail.pop(0) else: break handler = getattr(base, command) if handler is None: raise HTTPError(400) return handler
def _int_del_key(self, trail, request, response): try: name = '/'.join(trail) msg = self._parse_maybe_body(request, name) except Exception as e: raise HTTPError(406, str(e)) key = self._db_key(trail) try: ret = self.root.store.cut(key) except CSStoreError: raise HTTPError(500) if ret is False: raise HTTPError(404) output = msg.reply(None) if output is None: response['code'] = 204 else: response['output'] = output response['code'] = 200
def _create(self, trail, request, response): try: name = '/'.join(trail) msg = self._parse_maybe_body(request, name) except Exception as e: raise HTTPError(406, str(e)) default = request.get('default_namespace', None) basename = self._db_container_key(None, trail) try: if len(trail) > 2: ok = self._parent_exists(default, trail[:-1]) if not ok: raise HTTPError(404) self.root.store.span(basename) except CSStoreExists: raise HTTPError(409) except CSStoreError: raise HTTPError(500) output = msg.reply(None) if output is not None: response['output'] = output response['code'] = 201
def _parent_exists(self, default, trail): # check that the containers exist basename = self._db_container_key(trail[0], trail[:-1] + ['']) try: keylist = self.root.store.list(basename) except CSStoreError: raise HTTPError(500) self.logger.debug('parent_exists: %s (%s, %r) -> %r', basename, default, trail, keylist) if keylist is not None: return True # create default namespace if it is the only missing piece if len(trail) == 2 and default == trail[0]: container = self._db_container_key(default, '') self.root.store.span(container) return True return False
def _parent_exists(self, default, trail): # check that the containers exist basename = self._db_container_key(trail[0], '') try: keylist = self.root.store.list(basename) except CSStoreError: raise HTTPError(500) # create default namespace if it is the only missing piece if keylist is None and len(trail) == 2 and default == trail[0]: container = self._db_container_key(default, '') self.root.store.set(container, '') return True # check if any parent is missing for n in range(1, len(trail)): c = self._db_key(trail[:n] + ['']) if c not in keylist: return False return True
def _int_set_key(self, trail, request, response): content_type = request.get('headers', dict()).get('Content-Type', '') if content_type.split(';')[0].strip() != 'application/json': raise HTTPError(400, 'Invalid Content-Type') body = request.get('body') if body is None: raise HTTPError(400) value = bytes(body).decode('utf-8') try: name = '/'.join(trail) msg = self._parse(request, json.loads(value), name) except UnknownMessageType as e: raise HTTPError(406, str(e)) except UnallowedMessage as e: raise HTTPError(406, str(e)) except Exception as e: raise HTTPError(400, str(e)) # must _db_key first as access control is done here for now # otherwise users would e able to probe containers in namespaces # they do not have access to. key = self._db_key(trail) try: default = request.get('default_namespace', None) ok = self._parent_exists(default, trail) if not ok: raise HTTPError(404) ok = self.root.store.set(key, msg.payload) except CSStoreExists: raise HTTPError(409) except CSStoreError: raise HTTPError(500) response['code'] = 201
def _db_key(self, trail): if len(trail) < 2: raise HTTPError(403) return os.path.join('keys', *trail)
def check_authz(self, req): if self.authz.handle(req) is False: raise HTTPError(403)
def check_authz(self, req): req['client_id'] = 'test' req['path'] = '/'.join([''] + req.get('trail', [])) if self.authz.handle(req) is False: raise HTTPError(403)
def _parse_body(self, request, name): body = request.get('body') if body is None: raise HTTPError(400) value = json.loads(bytes(body).decode('utf-8')) return self._parse(request, value, name)
def handle(self, request): raise HTTPError(403)
def _request(self, cmd, request, response, path, **kwargs): if self.uuid in request['headers'].get('X-LOOP-CUSTODIA', ''): raise HTTPError(502, "Loop detected") reply = cmd(path, **kwargs) self._response(reply, response)
def POST(self, request, response): trail = request.get('trail', []) if len(trail) > 0 and trail[-1] == '': self._create(trail, request, response) else: raise HTTPError(405)
def PUT(self, request, response): trail = request.get('trail', []) if len(trail) == 0 or trail[-1] == '': raise HTTPError(405) else: self._set_key(trail, request, response)
def _response(self, reply, response): if reply.status_code < 200 or reply.status_code > 299: raise HTTPError(reply.status_code) response['code'] = reply.status_code if reply.content: response['output'] = reply.content