Browse Source

fix #151: introduce generic trigger for CRUD operations

Davide Alberani 7 years ago
parent
commit
3ce3cf08c8
3 changed files with 33 additions and 5 deletions
  1. 4 1
      backend.py
  2. 6 1
      docs/DEVELOPMENT.md
  3. 23 3
      eventman_server.py

+ 4 - 1
backend.py

@@ -239,6 +239,9 @@ class EventManDB(object):
         :type _id_or_query: str or :class:`~bson.objectid.ObjectId` or dict
         :param force: force the deletion of all documents, when `_id_or_query` is empty
         :type force: bool
+
+        :returns: how many documents were removed
+        :rtype: int
         """
         if not _id_or_query and not force:
             return
@@ -246,5 +249,5 @@ class EventManDB(object):
         if not isinstance(_id_or_query, dict):
             _id_or_query = {'_id': _id_or_query}
         _id_or_query = convert(_id_or_query)
-        db[collection].remove(_id_or_query)
+        return db[collection].remove(_id_or_query)
 

+ 6 - 1
docs/DEVELOPMENT.md

@@ -90,7 +90,12 @@ Sometimes we have to execute one or more scripts in reaction to an action.
 
 In the **data/triggers** we have a series of directories; scripts inside of them will be executed when the related action was performed on the GUI or calling the controller.
 
-Available triggers:
+In the data/trigger directory you can create a directory named with this schema: *crudAction_document[_resource]*, where crudAction is one in "create", "update", "delete" (there're no triggers for "read"). So, for example you can create scripts in directories named:
+- create\_user
+- delete\_event
+- update\_event\_tickets
+
+We also have some special triggers, which will contain more information (for example: both the old and the new ticket, updating one):
 - **update\_ticket\_in\_event**: executed every time a ticket in a given event is updated.
 - **attends**: executed only when a person is marked as attending an event.
 

+ 23 - 3
eventman_server.py

@@ -416,6 +416,9 @@ class CollectionHandler(BaseHandler):
         now = datetime.datetime.now()
         user_info = self.current_user_info
         user_id = user_info.get('_id')
+        env = {}
+        if id_ is not None:
+            env['%s_ID' % self.document.upper()] = id_
         if crud_method == 'create':
             data['created_by'] = user_id
             data['created_at'] = now
@@ -431,6 +434,11 @@ class CollectionHandler(BaseHandler):
                 data = self.apply_filter(data, 'input_%s_%s' % (method, resource))
                 output = handler(id_, resource_id, data, **kwargs)
                 output = self.apply_filter(output, 'get_%s' % resource)
+                env['RESOURCE'] = resource
+                if resource_id:
+                    env['%s_ID' % resource] = resource_id
+                self.run_triggers('%s_%s_%s' % ('create' if resource_id is None else 'update', self.document, resource),
+                                  stdin_data=output, env=env)
                 self.write(output)
                 return
             return self.build_error(status=404, message='unable to access resource: %s' % resource)
@@ -441,6 +449,7 @@ class CollectionHandler(BaseHandler):
             data = self.apply_filter(data, 'input_%s' % method)
             merged, newData = self.db.update(self.collection, id_, data)
             newData = self.apply_filter(newData, method)
+            self.run_triggers('update_%s' % self.document, stdin_data=newData, env=env)
         else:
             permission = '%s|%s' % (self.collection, crud_method)
             if not self.has_permission(permission):
@@ -448,6 +457,7 @@ class CollectionHandler(BaseHandler):
             data = self.apply_filter(data, 'input_%s_all' % method)
             newData = self.db.add(self.collection, data, _id=self.gen_id())
             newData = self.apply_filter(newData, '%s_all' % method)
+            self.run_triggers('create_%s' % self.document, stdin_data=newData, env=env)
         self.write(newData)
 
     # PUT (update an existing document) is handled by the POST (create a new document) method;
@@ -457,6 +467,9 @@ class CollectionHandler(BaseHandler):
     @gen.coroutine
     @authenticated
     def delete(self, id_=None, resource=None, resource_id=None, **kwargs):
+        env = {}
+        if id_ is not None:
+            env['%s_ID' % self.document.upper()] = id_
         if resource:
             # Handle access to sub-resources.
             permission = '%s:%s%s|delete' % (self.document, resource, '-all' if resource_id is None else '')
@@ -464,14 +477,21 @@ class CollectionHandler(BaseHandler):
                 return self.build_error(status=401, message='insufficient permissions: %s' % permission)
             method = getattr(self, 'handle_delete_%s' % resource, None)
             if method and callable(method):
-                self.write(method(id_, resource_id, **kwargs))
+                output = method(id_, resource_id, **kwargs)
+                env['RESOURCE'] = resource
+                if resource_id:
+                    env['%s_ID' % resource] = resource_id
+                self.run_triggers('delete_%s_%s' % (self.document, resource), stdin_data=env, env=env)
+                self.write(output)
                 return
             return self.build_error(status=404, message='unable to access resource: %s' % resource)
-        if id_:
+        if id_ is not None:
             permission = '%s|delete' % self.document
             if not self.has_permission(permission):
                 return self.build_error(status=401, message='insufficient permissions: %s' % permission)
-            self.db.delete(self.collection, id_)
+            howMany = self.db.delete(self.collection, id_)
+            env['DELETED_ITEMS'] = howMany
+            self.run_triggers('delete_%s' % self.document, stdin_data=env, env=env)
         else:
             self.write({'success': False})
         self.write({'success': True})