Browse Source

introduce basic data filters

Davide Alberani 8 years ago
parent
commit
13c8cc3208
1 changed files with 41 additions and 10 deletions
  1. 41 10
      eventman_server.py

+ 41 - 10
eventman_server.py

@@ -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."""