def _find_notifications(self, listener_id): cond = qvarn.All( qvarn.Equal('type', 'notification'), qvarn.Equal('listener_id', listener_id), ) obj_ids = [keys['obj_id'] for keys, _ in self._store.get_matches(cond)] qvarn.log.log('trace', msg_text='Found notifications', notifications=obj_ids) return obj_ids
def _get_resource_type_given_path(self, path): cond = qvarn.All( qvarn.Equal('path', path), qvarn.Equal('type', 'resource_type'), ) results = self._store.get_matches(cond=cond) qvarn.log.log('trace', msg_text='_get_resource_type_given_path', results=results, path=path) return [obj for _, obj in results]
def _get_notifications_list(self, *args, **kwargs): def timestamp(pair): _, obj = pair return obj['timestamp'] listener_id = kwargs['listener_id'] cond = qvarn.All(qvarn.Equal('type', 'notification'), qvarn.Equal('listener_id', listener_id)) pairs = self._store.get_matches(cond) ordered = sorted(pairs, key=timestamp) body = {'resources': [{'id': keys['obj_id']} for keys, _ in ordered]} return qvarn.ok_response(body)
def _get_a_notification(self, *args, **kwargs): listener_id = kwargs['listener_id'] notification_id = kwargs['notification_id'] cond = qvarn.All( qvarn.Equal('type', 'notification'), qvarn.Equal('listener_id', listener_id), qvarn.Equal('id', notification_id), ) pairs = self._store.get_matches(cond) if not pairs: return qvarn.no_such_resource_response(notification_id) if len(pairs) > 1: raise qvarn.TooManyResources(notification_id) return qvarn.ok_response(pairs[0][1])
def _delete_notification(self, *args, **kwargs): listener_id = kwargs['listener_id'] notification_id = kwargs['notification_id'] cond = qvarn.All( qvarn.Equal('type', 'notification'), qvarn.Equal('listener_id', listener_id), qvarn.Equal('id', notification_id), ) for keys, _ in self._store.get_matches(cond): values = { key: keys[key] for key in keys if isinstance(keys[key], str) } self._store.remove_objects(**values) return qvarn.ok_response({})
def test_returns_query_for_simple_equal(self): cond = qvarn.Equal('foo', 'bar') counter = slog.Counter() all_cond = qvarn.All() query, values = qvarn.sql_select(counter, cond, all_cond, 'TRUE') self.assertTrue(isinstance(query, str)) self.assertTrue(isinstance(values, dict))
def test_finds_objects(self): store = self.create_store(key=str) store.create_object(self.obj1, key='1st') store.create_object(self.obj2, key='2nd') cond = qvarn.Equal('name', self.obj1['name']) objs = store.get_matches(cond) self.assertEqual(objs, [({'key': '1st'}, self.obj1)])
def test_returns_query_for_anded_conditions(self): cond1 = qvarn.Equal('foo1', 'bar1') cond2 = qvarn.NotEqual('foo2', 'bar2') cond = qvarn.All(cond1, cond2) counter = slog.Counter() all_cond = qvarn.All() query, values = qvarn.sql_select(counter, cond, all_cond, 'TRUE') self.assertTrue(isinstance(query, str)) self.assertTrue(isinstance(values, dict))
def _get_resource_type_given_type(self, type_name): cond = qvarn.All( qvarn.Equal('id', type_name), qvarn.Equal('type', 'resource_type'), ) results = self._store.get_matches(cond=cond) qvarn.log.log('trace', msg_text='_get_resource_type_given_type', results=results, type_name=type_name) objs = [obj for _, obj in results] if not objs: # pragma: no cover raise qvarn.NoSuchResourceType(type_name) elif len(objs) > 1: # pragma: no cover raise qvarn.TooManyResourceTypes(type_name) rt = qvarn.ResourceType() rt.from_spec(objs[0]['spec']) return rt
def list(self, claims=None, access_params=None): oftype = qvarn.Equal('type', self.get_type_name()) allowed = None if self._store.have_fine_grained_access_control(): # pragma: no cover assert claims is not None assert access_params is not None allowed = qvarn.AccessIsAllowed( access_params, self._store.get_allow_rules()) matches = self._store.get_matches( oftype, allow_cond=allowed, subpath='') return { 'resources': [ {'id': obj['id']} for _, obj in matches if obj['type'] == self.get_type_name() ] }
def test_finds_objects_matching_deeply_in_object(self): obj1 = { 'foo': 'foo-1', 'bar': 'blah', 'bars': [ { 'foo': 'bars.0', 'bar': 'yo', }, { 'foo': 'bars.1', 'bar': 'bleurgh', }, ], } obj2 = { 'foo': 'foo-2', 'bar': 'bother', 'bars': [], } keys1 = { 'key': '1st', } keys2 = { 'key': '2nd', } store = self.create_store(key=str) store.create_object(obj1, **keys1) store.create_object(obj2, **keys2) cond = qvarn.Equal('bar', 'yo') objs = store.get_matches(cond) self.assertEqual(objs, [(keys1, obj1)])
def search(self, search_criteria, claims=None, access_params=None): if not search_criteria: raise NoSearchCriteria() p = qvarn.SearchParser() sp = p.parse(search_criteria) if sp.cond is None: sp.cond = qvarn.Equal('type', self.get_type_name()) def pick_all(obj): return obj def pick_id(obj): return { 'id': obj['id'], } def pick_some_from_object(obj, fields): return { key: obj[key] for key in obj if key in fields } def pick_some(fields): return lambda obj: pick_some_from_object(obj, fields) if sp.show_all: pick_fields = pick_all elif sp.show_fields: show_what = sp.show_fields + ['id'] pick_fields = pick_some(show_what) else: pick_fields = pick_id # FIXME: This is needed because Qvarn API stupidly requires # all fields to actually be defined by the resource type. If # we drop that, we can drop this check, but that needs to be a # managed transition, and for now we can't just drop it. self._check_fields_are_allowed(sp.cond) unsorted = self._find_matches( sp.cond, claims=claims, access_params=access_params) if sp.sort_keys: result = self._sort_objects(unsorted, sp.sort_keys) else: result = unsorted if sp.offset is None and sp.limit is None: chosen = result elif sp.offset is None and sp.limit is not None: chosen = result[:sp.limit] elif sp.offset is not None and sp.limit is None: chosen = result[sp.offset:] elif sp.offset is not None and sp.limit is not None: chosen = result[sp.offset:sp.offset+sp.limit] picked = [pick_fields(o) for o in chosen] qvarn.log.log( 'trace', msg_text='Collection.search, sorted', result=picked) return picked
def find_listeners(self, rid, change): # pragma: no cover cond = qvarn.Equal('type', 'listener') pairs = self._store.get_matches(cond) for _, obj in pairs: if self.listener_matches(obj, rid, change): yield obj