introduce basic data filters

This commit is contained in:
Davide Alberani 2016-06-11 00:47:29 +02:00
parent 63a09b7b17
commit 13c8cc3208

View file

@ -67,8 +67,8 @@ class BaseHandler(tornado.web.RequestHandler):
"""Base class for request handlers."""
permissions = {
'event|read': True,
'events-all|read': True,
'event:tickets|all': True,
'events-all|read': True,
'person|create': True
}
@ -215,10 +215,19 @@ class CollectionHandler(BaseHandler):
operation='increment')
return doc.get('seq', 0)
def gen_id(self, seq='ids'):
def gen_id(self, seq='ids', random_alpha=32):
"""Generate a unique, non-guessable ID.
:param seq: the scope of the ever-incrementing sequence
:type seq: str
:param random_alpha: number of random lowercase alphanumeric chars
:type random_alpha: int
:return: unique ID
:rtype: str"""
t = str(time.time()).replace('.', '_')
seq = str(self.get_next_seq(seq))
rand = ''.join([random.choice(self._id_chars) for x in xrange(32)])
rand = ''.join([random.choice(self._id_chars) for x in xrange(random_alpha)])
return '-'.join((t, seq, rand))
def _filter_results(self, results, params):
@ -275,6 +284,12 @@ class CollectionHandler(BaseHandler):
continue
return ret
def apply_filter(self, output, filter_name):
filter_method = getattr(self, filter_name, None)
if filter_method is not None:
output = filter_method(output)
return output
@gen.coroutine
@authenticated
def get(self, id_=None, resource=None, resource_id=None, acl=True, **kwargs):
@ -285,9 +300,8 @@ class CollectionHandler(BaseHandler):
return self.build_error(status=401, message='insufficient permissions: %s' % permission)
method = getattr(self, 'handle_get_%s' % resource, None)
if method and callable(method):
output = method(id_, resource_id, **kwargs)
if output is not None:
self.write(output)
output = method(id_, resource_id, **kwargs) or {}
self.write(output)
return
return self.build_error(status=404, message='unable to access resource: %s' % resource)
if id_ is not None:
@ -295,7 +309,9 @@ class CollectionHandler(BaseHandler):
permission = '%s|read' % self.document
if acl and not self.has_permission(permission):
return self.build_error(status=401, message='insufficient permissions: %s' % permission)
self.write(self.db.get(self.collection, id_))
output = self.db.get(self.collection, id_)
output = self.apply_filter(output, 'filter_get')
self.write(output)
else:
# return an object containing the list of all objects in the collection;
# e.g.: {'events': [{'_id': 'obj1-id, ...}, {'_id': 'obj2-id, ...}, ...]}
@ -304,7 +320,9 @@ class CollectionHandler(BaseHandler):
permission = '%s-all|read' % self.collection
if acl and not self.has_permission(permission):
return self.build_error(status=401, message='insufficient permissions: %s' % permission)
self.write({self.collection: self.db.query(self.collection, self.arguments)})
output = {self.collection: self.db.query(self.collection, self.arguments)}
output = self.apply_filter(output, 'filter_get_all')
self.write(output)
@gen.coroutine
@authenticated
@ -322,12 +340,12 @@ class CollectionHandler(BaseHandler):
self.write(handler(id_, resource_id, data, **kwargs))
return
if id_ is None:
permission = '%s|%s' % (self.document, 'create' if method == 'post' else 'update')
permission = '%s-all|%s' % (self.collection, 'create' if method == 'post' else 'update')
if not self.has_permission(permission):
return self.build_error(status=401, message='insufficient permissions: %s' % permission)
newData = self.db.add(self.collection, data, _id=self.gen_id())
else:
permission = '%s|%s' % (self.collection, 'create' if method == 'post' else 'update')
permission = '%s|%s' % (self.document, 'create' if method == 'post' else 'update')
if not self.has_permission(permission):
return self.build_error(status=401, message='insufficient permissions: %s' % permission)
merged, newData = self.db.update(self.collection, id_, data)
@ -478,6 +496,19 @@ class EventsHandler(CollectionHandler):
collection = 'events'
object_id = 'event_id'
def filter_get(self, output):
if not self.has_permission('persons-all|read'):
if 'persons' in output:
output['persons'] = []
return output
def filter_get_all(self, output):
if not self.has_permission('persons-all|read'):
for event in output.get('events') or []:
if 'persons' in event:
event['persons'] = []
return output
def _get_person_data(self, person_id_or_query, persons):
"""Filter a list of persons returning the first item with a given person_id
or which set of keys specified in a dictionary match their respective values."""