diff --git a/coffee/engine.coffee b/coffee/engine.coffee index cd5b942..1177cb2 100644 --- a/coffee/engine.coffee +++ b/coffee/engine.coffee @@ -15,6 +15,10 @@ db = require './persistence' # - [Dynamic Modules](dynamic-modules.html) dynmod = require './dynamic-modules' +# - External Modules: +# [js-select](https://www.npmjs.org/package/js-select) +jsonQuery = require 'js-select' + listUserRules = {} isRunning = false @@ -36,14 +40,25 @@ exports = module.exports = ( args ) => ### -Add an event handler (eh) that listens for rules. - -@public addRuleListener ( *eh* ) -@param {function} eh +This is a helper function for the unit tests so we can verify that action +modules are loaded correctly +#TODO we should change this to functions returning true or false rather than returning +#the whole list +@public getListUserRules () ### +exports.getListUserRules = () -> + listUserRules + +### +An event associated to rules happened and is captured here. Such events +are basically CRUD on rules. + +@public internalEvent ( *evt* ) +@param {Object} evt +### exports.internalEvent = ( evt ) => - if not listUserRules[evt.user] + if not listUserRules[evt.user] and evt.event isnt 'del' listUserRules[evt.user] = rules: {} actions: {} @@ -52,20 +67,42 @@ exports.internalEvent = ( evt ) => oRule = evt.rule if evt.event is 'new' or ( evt.event is 'init' and not oUser.rules[oRule.id] ) oUser.rules[oRule.id] = oRule - updateActionModules oRule + updateActionModules oRule, false -updateActionModules = ( oNewRule ) -> + if evt.event is 'del' and oUser + delete oUser.rules[oRule.id] + updateActionModules oRule, true + + +### +As soon as changes were made to the rule set we need to ensure that the aprropriate action +invoker modules are loaded, updated or deleted. + +@private updateActionModules ( *oNewRule* ) +@param {Object} oNewRule +### +updateActionModules = ( oNewRule, isDeleteOp ) -> # Remove all action invoker modules that are not required anymore fRemoveNotRequired = ( oUser ) -> # Check whether the action is still existing in a rule fRequired = ( actionName ) -> - return true for nmRl, oRl of oUser.rules when actionName in oRl.actions - return false + # return true for nmRl, oRl of oUser.rules when actionName in oRl.actions + for nmRl, oRl of oUser.rules + for action in oRl.actions + mod = (action.split ' -> ')[0] + if mod is actionName + return true + false + # Go thorugh all actions and check whether the action is still required - delete oUser.actions[action] for action of oUser.actions when not fRequired action + for action of oUser.actions + req = fRequired action + if not req + delete oUser.actions[action] + # delete oUser.actions[action] for action of oUser.actions when not fRequired action fRemoveNotRequired oUser for name, oUser of listUserRules @@ -78,7 +115,7 @@ updateActionModules = ( oNewRule ) -> # Load the action invoker module if it was part of the updated rule or if it's new fAddIfNewOrNotExisting = ( actionName ) -> moduleName = (actionName.split ' -> ')[0] - if not oUser.actions[moduleName] or oRule.id is oNewRule.id + if not isDeleteOp and ( not oUser.actions[moduleName] or oRule.id is oNewRule.id ) db.actionInvokers.getModule moduleName, ( err, obj ) -> params = {} res = dynmod.compileString obj.data, userName, moduleName, params, obj.lang @@ -88,6 +125,8 @@ updateActionModules = ( oNewRule ) -> # Go thorugh all actions and check whether the action is still required fCheckRules oRl for nmRl, oRl of oUser.rules + if JSON.stringify( oUser.rules ) is "{}" # TODO check whether this is really doing what it is supposed to do + delete listUserRules[userName] fAddRequired userName, oUser for userName, oUser of listUserRules @@ -106,8 +145,8 @@ Checks whether all conditions of the rule are met by the event. @param {Object} rule ### validConditions = ( evt, rule ) -> - conds = rule.conditions - return false for prop of conds when not evt[prop] or evt[prop] isnt conds[prop] + for prop in rule.conditions + return false if jsonQuery( evt, prop ).nodes().length is 0 return true ### @@ -116,78 +155,16 @@ Handles retrieved events. @private processEvent ( *evt* ) @param {Object} evt ### -processEvent = ( evt ) -> - @log.info('EN | processing event: ' + evt.event + '(' + evt.eventid + ')'); - # var actions = checkEvent(evt); - # console.log('found actions to invoke:'); - # console.log(actions); - # for(var user in actions) { - # for(var module in actions[user]) { - # for(var i = 0; i < actions[user][module]['functions'].length; i++) { - # var act = { - # module: module, - # function: actions[user][module]['functions'][i] - # } - # invokeAction(evt, user, act); - -# */ -# function checkEvent(evt) { -# var actions = {}, tEvt; -# for(var user in listRules) { -# actions[user] = {}; -# for(var rule in listRules[user]) { -# //TODO this needs to get depth safe, not only data but eventually also -# // on one level above (eventid and other meta) -# tEvt = listRules[user][rule].event; -# if(tEvt.module + ' -> ' + tEvt.function === evt.event && validConditions(evt.payload, listRules[user][rule])) { -# log.info('EN', 'Rule "' + rule + '" fired'); -# var oAct = listRules[user][rule].actions; -# console.log (oAct); -# for(var module in oAct) { -# if(!actions[user][module]) { -# actions[user][module] = { -# functions: [] -# }; -# } -# for(var i = 0; i < oAct[module]['functions'].length; i++ ){ -# console.log ('processing action ' + i + ', ' + oAct[module]['functions'][i]); -# actions[user][module]['functions'].push(oAct[module]['functions'][i]); -# // if(actions[user].indexOf(arrAct[i]) === -1) actions[user].push(arrAct[i]); -# } -# } -# } -# } -# } -# return actions; -# } - -# /** -# * Invoke an action according to its type. -# * @param {Object} evt The event that invoked the action -# * @param {Object} action The action to be invoked -# */ -# function invokeAction( evt, user, action ) { -# console.log('invoking action'); -# var actionargs = {}; -# //FIXME internal events, such as loopback ha sno arrow -# //TODO this requires change. the module property will be the identifier -# // in the actions object (or shall we allow several times the same action?) -# console.log(action.module); -# console.log(listActionModules); -# var srvc = listActionModules[user][action.module]; -# console.log(srvc); -# if(srvc && srvc[action.function]) { -# //FIXME preprocessing not only on data -# //FIXME no preprocessing at all, why don't we just pass the whole event to the action?' -# // preprocessActionArguments(evt.payload, action.arguments, actionargs); -# try { -# if(srvc[action.function]) srvc[action.function](evt.payload); -# } catch(err) { -# log.error('EN', 'during action execution: ' + err); -# } -# } -# else log.info('EN', 'No api interface found for: ' + action.module); -# } +processEvent = ( evt ) => + @log.info 'EN | processing event: ' + evt.event + '(' + evt.eventid + ')' + for userName, oUser of listUserRules + for ruleName, oRule of oUser.rules + if evt.event is oRule.event and validConditions evt, oRule + @log.info 'EN | EVENT FIRED: ' + evt.event + '(' + evt.eventid + ') for rule ' + ruleName + # fStoreAction userName, action for action in oRule.actions + for action in oRule.actions + arr = action.split ' -> ' + listUserRules[userName]['actions'][arr[0]][arr[1]] evt exports.shutDown = () -> isRunning = false \ No newline at end of file diff --git a/js-coffee/components-manager.js b/js-coffee/components-manager.js index 416fe2f..f1b93bf 100644 --- a/js-coffee/components-manager.js +++ b/js-coffee/components-manager.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Components Manager @@ -6,12 +7,10 @@ Components Manager > The components manager takes care of the dynamic JS modules and the rules. > Event Poller and Action Invoker modules are loaded as strings and stored in the database, > then compiled into node modules and rules and used in the engine and event poller. -*/ - + */ (function() { - var commandFunctions, db, dynmod, eventEmitter, events, exports, forgeModule, fs, getModuleParams, getModules, hasRequiredParams, path, - _this = this; + var commandFunctions, db, dynmod, eventEmitter, events, exports, forgeModule, fs, getModuleParams, getModules, hasRequiredParams, path; db = require('./persistence'); @@ -25,61 +24,67 @@ Components Manager eventEmitter = new events.EventEmitter(); + /* Module call ----------- Initializes the Components Manager and constructs a new Event Emitter. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + _this.log = args.logger; + db(args); + dynmod(args); + return module.exports; + }; + })(this); - exports = module.exports = function(args) { - _this.log = args.logger; - db(args); - dynmod(args); - return module.exports; - }; /* Add an event handler (eh) that listens for rules. @public addRuleListener ( *eh* ) @param {function} eh - */ + */ - - exports.addRuleListener = function(eh) { - eventEmitter.addListener('rule', eh); - return db.getAllActivatedRuleIdsPerUser(function(err, objUsers) { - var fGoThroughUsers, rules, user, _results; - fGoThroughUsers = function(user, rules) { - var fFetchRule, rule, _i, _len, _results; - fFetchRule = function(rule) { - var _this = this; - return db.getRule(rule, function(err, oRule) { - return eventEmitter.emit('rule', { - event: 'init', - user: user, - rule: JSON.parse(oRule) - }); - }); + exports.addRuleListener = (function(_this) { + return function(eh) { + eventEmitter.addListener('rule', eh); + return db.getAllActivatedRuleIdsPerUser(function(err, objUsers) { + var fGoThroughUsers, rules, user, _results; + fGoThroughUsers = function(user, rules) { + var fFetchRule, rule, _i, _len, _results; + fFetchRule = function(rule) { + return db.getRule(rule, (function(_this) { + return function(err, oRule) { + return eventEmitter.emit('rule', { + event: 'init', + user: user, + rule: JSON.parse(oRule) + }); + }; + })(this)); + }; + _results = []; + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + _results.push(fFetchRule(rule)); + } + return _results; }; _results = []; - for (_i = 0, _len = rules.length; _i < _len; _i++) { - rule = rules[_i]; - _results.push(fFetchRule(rule)); + for (user in objUsers) { + rules = objUsers[user]; + _results.push(fGoThroughUsers(user, rules)); } return _results; - }; - _results = []; - for (user in objUsers) { - rules = objUsers[user]; - _results.push(fGoThroughUsers(user, rules)); - } - return _results; - }); - }; + }); + }; + })(this); + /* Processes a user request coming through the request-handler. @@ -94,8 +99,7 @@ Components Manager @param {Object} user @param {Object} oReq @param {function} callback - */ - + */ exports.processRequest = function(user, oReq, callback) { var dat, err; @@ -140,8 +144,7 @@ Components Manager getModules = function(user, oPayload, dbMod, callback) { return dbMod.getAvailableModuleIds(user.username, function(err, arrNames) { - var answReq, fGetFunctions, id, oRes, sem, _i, _len, _results, - _this = this; + var answReq, fGetFunctions, id, oRes, sem, _i, _len, _results; oRes = {}; answReq = function() { return callback({ @@ -153,16 +156,18 @@ Components Manager if (sem === 0) { return answReq(); } else { - fGetFunctions = function(id) { - return dbMod.getModule(id, function(err, oModule) { - if (oModule) { - oRes[id] = JSON.parse(oModule.functions); - } - if (--sem === 0) { - return answReq(); - } - }); - }; + fGetFunctions = (function(_this) { + return function(id) { + return dbMod.getModule(id, function(err, oModule) { + if (oModule) { + oRes[id] = JSON.parse(oModule.functions); + } + if (--sem === 0) { + return answReq(); + } + }); + }; + })(this); _results = []; for (_i = 0, _len = arrNames.length; _i < _len; _i++) { id = arrNames[_i]; @@ -186,41 +191,43 @@ Components Manager } }; - forgeModule = function(user, oPayload, dbMod, callback) { - var answ; - answ = hasRequiredParams(['id', 'params', 'lang', 'data'], oPayload); - if (answ.code !== 200) { - return callback(answ); - } else { - return dbMod.getModule(oPayload.id, function(err, mod) { - var cm, funcs, id, name, src, _ref; - if (mod) { - answ.code = 409; - answ.message = 'Event Poller module name already existing: ' + oPayload.id; - } else { - src = oPayload.data; - cm = dynmod.compileString(src, user.username, oPayload.id, {}, oPayload.lang); - answ = cm.answ; - if (answ.code === 200) { - funcs = []; - _ref = cm.module; - for (name in _ref) { - id = _ref[name]; - funcs.push(name); - } - _this.log.info("CM | Storing new module with functions " + (funcs.join())); - answ.message = "Event Poller module successfully stored! Found following function(s): " + funcs; - oPayload.functions = JSON.stringify(funcs); - dbMod.storeModule(user.username, oPayload); - if (oPayload["public"] === 'true') { - dbMod.publish(oPayload.id); + forgeModule = (function(_this) { + return function(user, oPayload, dbMod, callback) { + var answ; + answ = hasRequiredParams(['id', 'params', 'lang', 'data'], oPayload); + if (answ.code !== 200) { + return callback(answ); + } else { + return dbMod.getModule(oPayload.id, function(err, mod) { + var cm, funcs, id, name, src, _ref; + if (mod) { + answ.code = 409; + answ.message = 'Event Poller module name already existing: ' + oPayload.id; + } else { + src = oPayload.data; + cm = dynmod.compileString(src, user.username, oPayload.id, {}, oPayload.lang); + answ = cm.answ; + if (answ.code === 200) { + funcs = []; + _ref = cm.module; + for (name in _ref) { + id = _ref[name]; + funcs.push(name); + } + _this.log.info("CM | Storing new module with functions " + (funcs.join())); + answ.message = "Event Poller module successfully stored! Found following function(s): " + funcs; + oPayload.functions = JSON.stringify(funcs); + dbMod.storeModule(user.username, oPayload); + if (oPayload["public"] === 'true') { + dbMod.publish(oPayload.id); + } } } - } - return callback(answ); - }); - } - }; + return callback(answ); + }); + } + }; + })(this); commandFunctions = { get_public_key: function(user, oPayload, callback) { diff --git a/js-coffee/config.js b/js-coffee/config.js index 4c48e7a..e984a2e 100644 --- a/js-coffee/config.js +++ b/js-coffee/config.js @@ -1,20 +1,20 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Configuration ============= > Loads the configuration file and acts as an interface to it. -*/ - + */ (function() { - var exports, fetchProp, fs, loadConfigFile, path, - _this = this; + var exports, fetchProp, fs, loadConfigFile, path; fs = require('fs'); path = require('path'); + /* Module call ----------- @@ -24,21 +24,23 @@ Configuration be generated) and configPath for a custom configuration file path. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + args = args != null ? args : {}; + if (args.nolog) { + _this.nolog = true; + } + if (args.configPath) { + loadConfigFile(args.configPath); + } else { + loadConfigFile(path.join('config', 'system.json')); + } + return module.exports; + }; + })(this); - exports = module.exports = function(args) { - args = args != null ? args : {}; - if (args.nolog) { - _this.nolog = true; - } - if (args.configPath) { - loadConfigFile(args.configPath); - } else { - loadConfigFile(path.join('config', 'system.json')); - } - return module.exports; - }; /* Tries to load a configuration file from the path relative to this module's parent folder. @@ -46,97 +48,102 @@ Configuration @private loadConfigFile @param {String} configPath - */ + */ - - loadConfigFile = function(configPath) { - var confProperties, e, prop, _i, _len; - _this.config = null; - confProperties = ['log', 'http-port', 'db-port']; - try { - _this.config = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', configPath))); - _this.isReady = true; - for (_i = 0, _len = confProperties.length; _i < _len; _i++) { - prop = confProperties[_i]; - if (!_this.config[prop]) { - _this.isReady = false; + loadConfigFile = (function(_this) { + return function(configPath) { + var confProperties, e, prop, _i, _len; + _this.config = null; + confProperties = ['log', 'http-port', 'db-port']; + try { + _this.config = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', configPath))); + _this.isReady = true; + for (_i = 0, _len = confProperties.length; _i < _len; _i++) { + prop = confProperties[_i]; + if (!_this.config[prop]) { + _this.isReady = false; + } + } + if (!_this.isReady && !_this.nolog) { + return console.error("Missing property in config file, requires:\n" + (" - " + (confProperties.join("\n - ")))); + } + } catch (_error) { + e = _error; + _this.isReady = false; + if (!_this.nolog) { + return console.error("Failed loading config file: " + e.message); } } - if (!_this.isReady && !_this.nolog) { - return console.error("Missing property in config file, requires:\n" + (" - " + (confProperties.join("\n - ")))); - } - } catch (_error) { - e = _error; - _this.isReady = false; - if (!_this.nolog) { - return console.error("Failed loading config file: " + e.message); - } - } - }; + }; + })(this); + /* Fetch a property from the configuration @private fetchProp( *prop* ) @param {String} prop - */ + */ + fetchProp = (function(_this) { + return function(prop) { + var _ref; + return (_ref = _this.config) != null ? _ref[prop] : void 0; + }; + })(this); - fetchProp = function(prop) { - var _ref; - return (_ref = _this.config) != null ? _ref[prop] : void 0; - }; /* ***Returns*** true if the config file is ready, else false @public isReady() - */ + */ + exports.isReady = (function(_this) { + return function() { + return _this.isReady; + }; + })(this); - exports.isReady = function() { - return _this.isReady; - }; /* ***Returns*** the HTTP port @public getHttpPort() - */ - + */ exports.getHttpPort = function() { return fetchProp('http-port'); }; + /* ***Returns*** the DB port* @public getDBPort() - */ - + */ exports.getDbPort = function() { return fetchProp('db-port'); }; + /* ***Returns*** the log conf object @public getLogConf() - */ - + */ exports.getLogConf = function() { return fetchProp('log'); }; + /* ***Returns*** the crypto key @public getCryptoKey() - */ - + */ exports.getKeygenPassphrase = function() { return fetchProp('keygen-passphrase'); diff --git a/js-coffee/dynamic-modules.js b/js-coffee/dynamic-modules.js index 5192bd4..a6942da 100644 --- a/js-coffee/dynamic-modules.js +++ b/js-coffee/dynamic-modules.js @@ -1,16 +1,15 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Dynamic Modules =============== > Compiles CoffeeScript modules and loads JS modules in a VM, together > with only a few allowed node.js modules. -*/ - + */ (function() { - var cryptico, cs, exports, needle, vm, - _this = this; + var cryptico, cs, exports, needle, vm; vm = require('vm'); @@ -20,31 +19,36 @@ Dynamic Modules cryptico = require('my-cryptico'); + /* Module call ----------- Initializes the dynamic module handler. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + var numBits, passPhrase; + _this.log = args.logger; + if (!_this.strPublicKey && args['keygen']) { + passPhrase = args['keygen']; + numBits = 1024; + _this.oPrivateRSAkey = cryptico.generateRSAKey(passPhrase, numBits); + _this.strPublicKey = cryptico.publicKeyString(_this.oPrivateRSAkey); + _this.log.info("Public Key generated: " + _this.strPublicKey); + } + return module.exports; + }; + })(this); - exports = module.exports = function(args) { - var numBits, passPhrase; - _this.log = args.logger; - if (!_this.strPublicKey && args['keygen']) { - passPhrase = args['keygen']; - numBits = 1024; - _this.oPrivateRSAkey = cryptico.generateRSAKey(passPhrase, numBits); - _this.strPublicKey = cryptico.publicKeyString(_this.oPrivateRSAkey); - _this.log.info("Public Key generated: " + _this.strPublicKey); - } - return module.exports; - }; + exports.getPublicKey = (function(_this) { + return function() { + return _this.strPublicKey; + }; + })(this); - exports.getPublicKey = function() { - return _this.strPublicKey; - }; /* Try to run a JS module from a string, together with the @@ -56,43 +60,44 @@ Dynamic Modules @param {String} id @param {Object} params @param {String} lang - */ + */ - - exports.compileString = function(src, userId, modId, params, lang) { - var answ, err, ret, sandbox; - answ = { - code: 200, - message: 'Successfully compiled' - }; - if (lang === 'CoffeeScript') { + exports.compileString = (function(_this) { + return function(src, userId, modId, params, lang) { + var answ, err, ret, sandbox; + answ = { + code: 200, + message: 'Successfully compiled' + }; + if (lang === 'CoffeeScript') { + try { + src = cs.compile(src); + } catch (_error) { + err = _error; + answ.code = 400; + answ.message = 'Compilation of CoffeeScript failed at line ' + err.location.first_line; + } + } + sandbox = { + id: userId + '.' + modId + '.vm', + params: params, + needle: needle, + log: console.log, + exports: {} + }; try { - src = cs.compile(src); + vm.runInNewContext(src, sandbox, sandbox.id); } catch (_error) { err = _error; answ.code = 400; - answ.message = 'Compilation of CoffeeScript failed at line ' + err.location.first_line; + answ.message = 'Loading Module failed: ' + err.message; } - } - sandbox = { - id: userId + '.' + modId + '.vm', - params: params, - needle: needle, - log: console.log, - exports: {} + ret = { + answ: answ, + module: sandbox.exports + }; + return ret; }; - try { - vm.runInNewContext(src, sandbox, sandbox.id); - } catch (_error) { - err = _error; - answ.code = 400; - answ.message = 'Loading Module failed: ' + err.message; - } - ret = { - answ: answ, - module: sandbox.exports - }; - return ret; - }; + })(this); }).call(this); diff --git a/js-coffee/engine.js b/js-coffee/engine.js index 8bd0866..ce344b1 100644 --- a/js-coffee/engine.js +++ b/js-coffee/engine.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Engine @@ -6,85 +7,123 @@ Engine > The heart of the WebAPI ECA System. The engine loads action invoker modules > corresponding to active rules actions and invokes them if an appropriate event > is retrieved. -*/ - + */ (function() { - var db, dynmod, exports, isRunning, listUserRules, pollQueue, processEvent, updateActionModules, validConditions, - _this = this, - __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + var db, dynmod, exports, isRunning, jsonQuery, listUserRules, pollQueue, processEvent, updateActionModules, validConditions; db = require('./persistence'); dynmod = require('./dynamic-modules'); + jsonQuery = require('js-select'); + listUserRules = {}; isRunning = false; + /* Module call ----------- Initializes the Engine and starts polling the event queue for new events. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + if (!isRunning) { + isRunning = true; + _this.log = args.logger; + db(args); + dynmod(args); + pollQueue(); + return module.exports; + } + }; + })(this); - exports = module.exports = function(args) { - if (!isRunning) { - isRunning = true; - _this.log = args.logger; - db(args); - dynmod(args); - pollQueue(); - return module.exports; - } - }; /* - Add an event handler (eh) that listens for rules. - - @public addRuleListener ( *eh* ) - @param {function} eh - */ + This is a helper function for the unit tests so we can verify that action + modules are loaded correctly + *TODO we should change this to functions returning true or false rather than returning + *the whole list + @public getListUserRules () + */ - - exports.internalEvent = function(evt) { - var oRule, oUser; - if (!listUserRules[evt.user]) { - listUserRules[evt.user] = { - rules: {}, - actions: {} - }; - } - oUser = listUserRules[evt.user]; - oRule = evt.rule; - if (evt.event === 'new' || (evt.event === 'init' && !oUser.rules[oRule.id])) { - oUser.rules[oRule.id] = oRule; - return updateActionModules(oRule); - } + exports.getListUserRules = function() { + return listUserRules; }; - updateActionModules = function(oNewRule) { + + /* + An event associated to rules happened and is captured here. Such events + are basically CRUD on rules. + + @public internalEvent ( *evt* ) + @param {Object} evt + */ + + exports.internalEvent = (function(_this) { + return function(evt) { + var oRule, oUser; + if (!listUserRules[evt.user] && evt.event !== 'del') { + listUserRules[evt.user] = { + rules: {}, + actions: {} + }; + } + oUser = listUserRules[evt.user]; + oRule = evt.rule; + if (evt.event === 'new' || (evt.event === 'init' && !oUser.rules[oRule.id])) { + oUser.rules[oRule.id] = oRule; + updateActionModules(oRule, false); + } + if (evt.event === 'del' && oUser) { + delete oUser.rules[oRule.id]; + return updateActionModules(oRule, true); + } + }; + })(this); + + + /* + As soon as changes were made to the rule set we need to ensure that the aprropriate action + invoker modules are loaded, updated or deleted. + + @private updateActionModules ( *oNewRule* ) + @param {Object} oNewRule + */ + + updateActionModules = function(oNewRule, isDeleteOp) { var fAddRequired, fRemoveNotRequired, name, oUser, userName, _results; fRemoveNotRequired = function(oUser) { - var action, fRequired, _results; + var action, fRequired, req, _results; fRequired = function(actionName) { - var nmRl, oRl, _ref; + var action, mod, nmRl, oRl, _i, _len, _ref, _ref1; _ref = oUser.rules; for (nmRl in _ref) { oRl = _ref[nmRl]; - if (__indexOf.call(oRl.actions, actionName) >= 0) { - return true; + _ref1 = oRl.actions; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + action = _ref1[_i]; + mod = (action.split(' -> '))[0]; + if (mod === actionName) { + return true; + } } } return false; }; _results = []; for (action in oUser.actions) { - if (!fRequired(action)) { + req = fRequired(action); + if (!req) { _results.push(delete oUser.actions[action]); + } else { + _results.push(void 0); } } return _results; @@ -94,13 +133,13 @@ Engine fRemoveNotRequired(oUser); } fAddRequired = function(userName, oUser) { - var fCheckRules, nmRl, oRl, _ref, _results; + var fCheckRules, nmRl, oRl, _ref; fCheckRules = function(oRule) { var action, fAddIfNewOrNotExisting, _i, _len, _ref, _results; fAddIfNewOrNotExisting = function(actionName) { var moduleName; moduleName = (actionName.split(' -> '))[0]; - if (!oUser.actions[moduleName] || oRule.id === oNewRule.id) { + if (!isDeleteOp && (!oUser.actions[moduleName] || oRule.id === oNewRule.id)) { return db.actionInvokers.getModule(moduleName, function(err, obj) { var params, res; params = {}; @@ -118,12 +157,13 @@ Engine return _results; }; _ref = oUser.rules; - _results = []; for (nmRl in _ref) { oRl = _ref[nmRl]; - _results.push(fCheckRules(oRl)); + fCheckRules(oRl); + } + if (JSON.stringify(oUser.rules) === "{}") { + return delete listUserRules[userName]; } - return _results; }; _results = []; for (userName in listUserRules) { @@ -144,37 +184,71 @@ Engine } }; + /* Checks whether all conditions of the rule are met by the event. @private validConditions ( *evt, rule* ) @param {Object} evt @param {Object} rule - */ - + */ validConditions = function(evt, rule) { - var conds, prop; - conds = rule.conditions; - for (prop in conds) { - if (!evt[prop] || evt[prop] !== conds[prop]) { + var prop, _i, _len, _ref; + _ref = rule.conditions; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + prop = _ref[_i]; + if (jsonQuery(evt, prop).nodes().length === 0) { return false; } } return true; }; + /* Handles retrieved events. @private processEvent ( *evt* ) @param {Object} evt - */ + */ - - processEvent = function(evt) { - return this.log.info('EN | processing event: ' + evt.event + '(' + evt.eventid + ')'); - }; + processEvent = (function(_this) { + return function(evt) { + var action, arr, oRule, oUser, ruleName, userName, _results; + _this.log.info('EN | processing event: ' + evt.event + '(' + evt.eventid + ')'); + _results = []; + for (userName in listUserRules) { + oUser = listUserRules[userName]; + _results.push((function() { + var _ref, _results1; + _ref = oUser.rules; + _results1 = []; + for (ruleName in _ref) { + oRule = _ref[ruleName]; + if (evt.event === oRule.event && validConditions(evt, oRule)) { + this.log.info('EN | EVENT FIRED: ' + evt.event + '(' + evt.eventid + ') for rule ' + ruleName); + _results1.push((function() { + var _i, _len, _ref1, _results2; + _ref1 = oRule.actions; + _results2 = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + action = _ref1[_i]; + arr = action.split(' -> '); + _results2.push(listUserRules[userName]['actions'][arr[0]][arr[1]](evt)); + } + return _results2; + })()); + } else { + _results1.push(void 0); + } + } + return _results1; + }).call(_this)); + } + return _results; + }; + })(this); exports.shutDown = function() { return isRunning = false; diff --git a/js-coffee/persistence.js b/js-coffee/persistence.js index 0e141a1..6ed7f23 100644 --- a/js-coffee/persistence.js +++ b/js-coffee/persistence.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Persistence @@ -18,55 +19,58 @@ Persistence > 'action-invokers' and then stored in the db with the key 'action-invoker:' + ID > (e.g. action-invoker:probinder). > -*/ - + */ (function() { var IndexedModules, exports, getSetRecords, redis, replyHandler, - _this = this, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; redis = require('redis'); + /* Module call ----------- Initializes the DB connection with the given `db-port` property in the `args` object. @param {Object} args - */ + */ - - exports = module.exports = function(args) { - if (!_this.db) { - if (!args['db-port']) { - args['db-port'] = 6379; + exports = module.exports = (function(_this) { + return function(args) { + if (!_this.db) { + if (!args['db-port']) { + args['db-port'] = 6379; + } + _this.log = args.logger; + exports.eventPollers = new IndexedModules('event-poller', _this.log); + exports.actionInvokers = new IndexedModules('action-invoker', _this.log); + return exports.initPort(args['db-port']); } - _this.log = args.logger; - exports.eventPollers = new IndexedModules('event-poller', _this.log); - exports.actionInvokers = new IndexedModules('action-invoker', _this.log); - return exports.initPort(args['db-port']); - } - }; + }; + })(this); - exports.initPort = function(port) { - var _ref; - _this.connRefused = false; - if ((_ref = _this.db) != null) { - _ref.quit(); - } - _this.db = redis.createClient(port, 'localhost', { - connect_timeout: 2000 - }); - _this.db.on('error', function(err) { - if (err.message.indexOf('ECONNREFUSED') > -1) { - _this.connRefused = true; - return _this.log.error(err, 'DB | Wrong port?'); + exports.initPort = (function(_this) { + return function(port) { + var _ref; + _this.connRefused = false; + if ((_ref = _this.db) != null) { + _ref.quit(); } - }); - exports.eventPollers.setDB(_this.db); - return exports.actionInvokers.setDB(_this.db); - }; + _this.db = redis.createClient(port, 'localhost', { + connect_timeout: 2000 + }); + _this.db.on('error', function(err) { + if (err.message.indexOf('ECONNREFUSED') > -1) { + _this.connRefused = true; + return _this.log.error(err, 'DB | Wrong port?'); + } + }); + exports.eventPollers.setDB(_this.db); + return exports.actionInvokers.setDB(_this.db); + }; + })(this); + /* Checks whether the db is connected and passes either an error on failure after @@ -74,104 +78,114 @@ Persistence @public isConnected( *cb* ) @param {function} cb - */ + */ - - exports.isConnected = function(cb) { - var fCheckConnection, numAttempts; - if (!_this.db) { - return cb(new Error('DB | DB initialization did not occur or failed miserably!')); - } else { - if (_this.db.connected) { - return cb(); + exports.isConnected = (function(_this) { + return function(cb) { + var fCheckConnection, numAttempts; + if (!_this.db) { + return cb(new Error('DB | DB initialization did not occur or failed miserably!')); } else { - numAttempts = 0; - fCheckConnection = function() { - var _ref; - if (_this.connRefused) { - if ((_ref = _this.db) != null) { - _ref.quit(); - } - return cb(new Error('DB | Connection refused! Wrong port?')); - } else { - if (_this.db.connected) { - _this.log.info('DB | Successfully connected to DB!'); - return cb(); - } else if (numAttempts++ < 10) { - return setTimeout(fCheckConnection, 100); + if (_this.db.connected) { + return cb(); + } else { + numAttempts = 0; + fCheckConnection = function() { + var _ref; + if (_this.connRefused) { + if ((_ref = _this.db) != null) { + _ref.quit(); + } + return cb(new Error('DB | Connection refused! Wrong port?')); } else { - return cb(new Error('DB | Connection to DB failed!')); + if (_this.db.connected) { + _this.log.info('DB | Successfully connected to DB!'); + return cb(); + } else if (numAttempts++ < 10) { + return setTimeout(fCheckConnection, 100); + } else { + return cb(new Error('DB | Connection to DB failed!')); + } } - } - }; - return setTimeout(fCheckConnection, 100); + }; + return setTimeout(fCheckConnection, 100); + } } - } - }; + }; + })(this); + /* Abstracts logging for simple action replies from the DB. @private replyHandler( *action* ) @param {String} action - */ + */ - - replyHandler = function(action) { - return function(err, reply) { - if (err) { - return _this.log.warn(err, "during '" + action + "'"); - } else { - return _this.log.info("DB | " + action + ": " + reply); - } + replyHandler = (function(_this) { + return function(action) { + return function(err, reply) { + if (err) { + return _this.log.warn(err, "during '" + action + "'"); + } else { + return _this.log.info("DB | " + action + ": " + reply); + } + }; }; - }; + })(this); + /* Push an event into the event queue. @public pushEvent( *oEvent* ) @param {Object} oEvent - */ + */ + exports.pushEvent = (function(_this) { + return function(oEvent) { + if (oEvent) { + _this.log.info("DB | Event pushed into the queue: '" + oEvent.eventid + "'"); + return _this.db.rpush('event_queue', JSON.stringify(oEvent)); + } else { + return _this.log.warn('DB | Why would you give me an empty event...'); + } + }; + })(this); - exports.pushEvent = function(oEvent) { - if (oEvent) { - _this.log.info("DB | Event pushed into the queue: '" + oEvent.eventid + "'"); - return _this.db.rpush('event_queue', JSON.stringify(oEvent)); - } else { - return _this.log.warn('DB | Why would you give me an empty event...'); - } - }; /* Pop an event from the event queue and pass it to cb(err, obj). @public popEvent( *cb* ) @param {function} cb - */ + */ - - exports.popEvent = function(cb) { - var makeObj; - makeObj = function(pcb) { - return function(err, obj) { - return pcb(err, JSON.parse(obj)); + exports.popEvent = (function(_this) { + return function(cb) { + var makeObj; + makeObj = function(pcb) { + return function(err, obj) { + return pcb(err, JSON.parse(obj)); + }; }; + return _this.db.lpop('event_queue', makeObj(cb)); }; - return _this.db.lpop('event_queue', makeObj(cb)); - }; + })(this); + /* Purge the event queue. @public purgeEventQueue() - */ + */ + exports.purgeEventQueue = (function(_this) { + return function() { + return _this.db.del('event_queue', replyHandler('purging event queue')); + }; + })(this); - exports.purgeEventQueue = function() { - return _this.db.del('event_queue', replyHandler('purging event queue')); - }; /* Fetches all linked data set keys from a linking set, fetches the single @@ -183,50 +197,51 @@ Persistence per set entry @param {function} cb the callback(err, obj) function that receives all the retrieved data or an error - */ + */ - - getSetRecords = function(set, fSingle, cb) { - _this.log.info("DB | Fetching set records: '" + set + "'"); - return _this.db.smembers(set, function(err, arrReply) { - var fCallback, objReplies, reply, semaphore, _i, _len, _results; - if (err) { - _this.log.warn(err, "DB | fetching '" + set + "'"); - return cb(err); - } else if (arrReply.length === 0) { - return cb(); - } else { - semaphore = arrReply.length; - objReplies = {}; - setTimeout(function() { - if (semaphore > 0) { - return cb(new Error("Timeout fetching '" + set + "'")); - } - }, 2000); - fCallback = function(prop) { - return function(err, data) { - --semaphore; - if (err) { - _this.log.warn(err, "DB | fetching single element: '" + prop + "'"); - } else if (!data) { - _this.log.warn(new Error("Empty key in DB: '" + prop + "'")); - } else { - objReplies[prop] = data; - } - if (semaphore === 0) { - return cb(null, objReplies); + getSetRecords = (function(_this) { + return function(set, fSingle, cb) { + _this.log.info("DB | Fetching set records: '" + set + "'"); + return _this.db.smembers(set, function(err, arrReply) { + var fCallback, objReplies, reply, semaphore, _i, _len, _results; + if (err) { + _this.log.warn(err, "DB | fetching '" + set + "'"); + return cb(err); + } else if (arrReply.length === 0) { + return cb(); + } else { + semaphore = arrReply.length; + objReplies = {}; + setTimeout(function() { + if (semaphore > 0) { + return cb(new Error("Timeout fetching '" + set + "'")); } + }, 2000); + fCallback = function(prop) { + return function(err, data) { + --semaphore; + if (err) { + _this.log.warn(err, "DB | fetching single element: '" + prop + "'"); + } else if (!data) { + _this.log.warn(new Error("Empty key in DB: '" + prop + "'")); + } else { + objReplies[prop] = data; + } + if (semaphore === 0) { + return cb(null, objReplies); + } + }; }; - }; - _results = []; - for (_i = 0, _len = arrReply.length; _i < _len; _i++) { - reply = arrReply[_i]; - _results.push(fSingle(reply, fCallback(reply))); + _results = []; + for (_i = 0, _len = arrReply.length; _i < _len; _i++) { + reply = arrReply[_i]; + _results.push(fSingle(reply, fCallback(reply))); + } + return _results; } - return _results; - } - }); - }; + }); + }; + })(this); IndexedModules = (function() { function IndexedModules(setname, log) { @@ -255,14 +270,14 @@ Persistence return this.log.info("DB | (IdxedMods) Registered new DB connection for '" + this.setname + "'"); }; + /* Stores a module and links it to the user. @private storeModule( *userId, oModule* ) @param {String} userId @param {object} oModule - */ - + */ IndexedModules.prototype.storeModule = function(userId, oModule) { this.log.info("DB | (IdxedMods) " + this.setname + ".storeModule( " + userId + ", oModule )"); @@ -319,22 +334,24 @@ Persistence }; IndexedModules.prototype.deleteModule = function(mId) { - var _this = this; this.log.info("DB | (IdxedMods) " + this.setname + ".deleteModule( " + mId + " )"); this.db.srem("" + this.setname + "s", mId, replyHandler("srem '" + mId + "' from " + this.setname + "s")); this.db.del("" + this.setname + ":" + mId, replyHandler("del of '" + this.setname + ":" + mId + "'")); this.unpublish(mId); - return this.db.smembers("" + this.setname + ":" + mId + ":users", function(err, obj) { - var userId, _i, _len, _results; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - userId = obj[_i]; - _results.push(_this.unlinkModule(mId, userId)); - } - return _results; - }); + return this.db.smembers("" + this.setname + ":" + mId + ":users", (function(_this) { + return function(err, obj) { + var userId, _i, _len, _results; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + userId = obj[_i]; + _results.push(_this.unlinkModule(mId, userId)); + } + return _results; + }; + })(this)); }; + /* Stores user params for a module. They are expected to be RSA encrypted with helps of the provided cryptico JS library and will only be decrypted right before the module is loaded! @@ -343,8 +360,7 @@ Persistence @param {String} mId @param {String} userId @param {object} encData - */ - + */ IndexedModules.prototype.storeUserParams = function(mId, userId, encData) { this.log.info("DB | (IdxedMods) " + this.setname + ".storeUserParams( " + mId + ", " + userId + ", encData )"); @@ -374,9 +390,10 @@ Persistence })(); + /* - ## Rules - */ + *# Rules + */ /* @@ -385,39 +402,45 @@ Persistence @public getRule( *ruleId, cb* ) @param {String} ruleId @param {function} cb - */ + */ + exports.getRule = (function(_this) { + return function(ruleId, cb) { + _this.log.info("DB | getRule: '" + ruleId + "'"); + return _this.db.get("rule:" + ruleId, cb); + }; + })(this); - exports.getRule = function(ruleId, cb) { - _this.log.info("DB | getRule: '" + ruleId + "'"); - return _this.db.get("rule:" + ruleId, cb); - }; /* Fetch all rules and pass them to cb(err, obj). @public getRules( *cb* ) @param {function} cb - */ + */ + exports.getRules = (function(_this) { + return function(cb) { + _this.log.info('DB | Fetching all Rules'); + return getSetRecords('rules', exports.getRule, cb); + }; + })(this); - exports.getRules = function(cb) { - _this.log.info('DB | Fetching all Rules'); - return getSetRecords('rules', exports.getRule, cb); - }; /* Fetch all rule IDs and hand it to cb(err, obj). @public getRuleIds( *cb* ) @param {function} cb - */ + */ + exports.getRuleIds = (function(_this) { + return function(cb) { + _this.log.info('DB | Fetching all Rule IDs'); + return _this.db.smembers('rules', cb); + }; + })(this); - exports.getRuleIds = function(cb) { - _this.log.info('DB | Fetching all Rule IDs'); - return _this.db.smembers('rules', cb); - }; /* Store a string representation of a rule in the DB. @@ -425,14 +448,16 @@ Persistence @public storeRule( *ruleId, data* ) @param {String} ruleId @param {String} data - */ + */ + exports.storeRule = (function(_this) { + return function(ruleId, data) { + _this.log.info("DB | storeRule: '" + ruleId + "'"); + _this.db.sadd('rules', "" + ruleId, replyHandler("storing rule key '" + ruleId + "'")); + return _this.db.set("rule:" + ruleId, data, replyHandler("storing rule '" + ruleId + "'")); + }; + })(this); - exports.storeRule = function(ruleId, data) { - _this.log.info("DB | storeRule: '" + ruleId + "'"); - _this.db.sadd('rules', "" + ruleId, replyHandler("storing rule key '" + ruleId + "'")); - return _this.db.set("rule:" + ruleId, data, replyHandler("storing rule '" + ruleId + "'")); - }; /* Delete a string representation of a rule. @@ -440,40 +465,42 @@ Persistence @public deleteRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.deleteRule = (function(_this) { + return function(ruleId) { + _this.log.info("DB | deleteRule: '" + ruleId + "'"); + _this.db.srem("rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "'")); + _this.db.del("rule:" + ruleId, replyHandler("Deleting rule '" + ruleId + "'")); + _this.db.smembers("rule:" + ruleId + ":users", function(err, obj) { + var delLinkedUserRule, id, _i, _len, _results; + delLinkedUserRule = function(userId) { + return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in linked user '" + userId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delLinkedUserRule(id)); + } + return _results; + }); + _this.db.del("rule:" + ruleId + ":users", replyHandler("Deleting rule '" + ruleId + "' users")); + _this.db.smembers("rule:" + ruleId + ":active-users", function(err, obj) { + var delActiveUserRule, id, _i, _len, _results; + delActiveUserRule = function(userId) { + return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in active user '" + userId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delActiveUserRule(id)); + } + return _results; + }); + return _this.db.del("rule:" + ruleId + ":active-users", replyHandler("Deleting rule '" + ruleId + "' active users")); + }; + })(this); - exports.deleteRule = function(ruleId) { - _this.log.info("DB | deleteRule: '" + ruleId + "'"); - _this.db.srem("rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "'")); - _this.db.del("rule:" + ruleId, replyHandler("Deleting rule '" + ruleId + "'")); - _this.db.smembers("rule:" + ruleId + ":users", function(err, obj) { - var delLinkedUserRule, id, _i, _len, _results; - delLinkedUserRule = function(userId) { - return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in linked user '" + userId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delLinkedUserRule(id)); - } - return _results; - }); - _this.db.del("rule:" + ruleId + ":users", replyHandler("Deleting rule '" + ruleId + "' users")); - _this.db.smembers("rule:" + ruleId + ":active-users", function(err, obj) { - var delActiveUserRule, id, _i, _len, _results; - delActiveUserRule = function(userId) { - return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in active user '" + userId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delActiveUserRule(id)); - } - return _results; - }); - return _this.db.del("rule:" + ruleId + ":active-users", replyHandler("Deleting rule '" + ruleId + "' active users")); - }; /* Associate a rule to a user. @@ -481,14 +508,16 @@ Persistence @public linkRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.linkRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | linkRule: '" + ruleId + "' for user '" + userId + "'"); + _this.db.sadd("rule:" + ruleId + ":users", userId, replyHandler("storing user '" + userId + "' for rule key '" + ruleId + "'")); + return _this.db.sadd("user:" + userId + ":rules", ruleId, replyHandler("storing rule key '" + ruleId + "' for user '" + userId + "'")); + }; + })(this); - exports.linkRule = function(ruleId, userId) { - _this.log.info("DB | linkRule: '" + ruleId + "' for user '" + userId + "'"); - _this.db.sadd("rule:" + ruleId + ":users", userId, replyHandler("storing user '" + userId + "' for rule key '" + ruleId + "'")); - return _this.db.sadd("user:" + userId + ":rules", ruleId, replyHandler("storing rule key '" + ruleId + "' for user '" + userId + "'")); - }; /* Get rules linked to a user and hand it to cb(err, obj). @@ -496,13 +525,15 @@ Persistence @public getUserLinkRule( *userId, cb* ) @param {String} userId @param {function} cb - */ + */ + exports.getUserLinkedRules = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUserLinkedRules: for user '" + userId + "'"); + return _this.db.smembers("user:" + userId + ":rules", cb); + }; + })(this); - exports.getUserLinkedRules = function(userId, cb) { - _this.log.info("DB | getUserLinkedRules: for user '" + userId + "'"); - return _this.db.smembers("user:" + userId + ":rules", cb); - }; /* Get users linked to a rule and hand it to cb(err, obj). @@ -510,13 +541,15 @@ Persistence @public getRuleLinkedUsers( *ruleId, cb* ) @param {String} ruleId @param {function} cb - */ + */ + exports.getRuleLinkedUsers = (function(_this) { + return function(ruleId, cb) { + _this.log.info("DB | getRuleLinkedUsers: for rule '" + ruleId + "'"); + return _this.db.smembers("rule:" + ruleId + ":users", cb); + }; + })(this); - exports.getRuleLinkedUsers = function(ruleId, cb) { - _this.log.info("DB | getRuleLinkedUsers: for rule '" + ruleId + "'"); - return _this.db.smembers("rule:" + ruleId + ":users", cb); - }; /* Delete an association of a rule to a user. @@ -524,14 +557,16 @@ Persistence @public unlinkRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.unlinkRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | unlinkRule: '" + ruleId + ":" + userId + "'"); + _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("removing user '" + userId + "' for rule key '" + ruleId + "'")); + return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("removing rule key '" + ruleId + "' for user '" + userId + "'")); + }; + })(this); - exports.unlinkRule = function(ruleId, userId) { - _this.log.info("DB | unlinkRule: '" + ruleId + ":" + userId + "'"); - _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("removing user '" + userId + "' for rule key '" + ruleId + "'")); - return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("removing rule key '" + ruleId + "' for user '" + userId + "'")); - }; /* Activate a rule. @@ -539,14 +574,16 @@ Persistence @public activateRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.activateRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | activateRule: '" + ruleId + "' for '" + userId + "'"); + _this.db.sadd("rule:" + ruleId + ":active-users", userId, replyHandler("storing activated user '" + userId + "' in rule '" + ruleId + "'")); + return _this.db.sadd("user:" + userId + ":active-rules", ruleId, replyHandler("storing activated rule '" + ruleId + "' in user '" + userId + "'")); + }; + })(this); - exports.activateRule = function(ruleId, userId) { - _this.log.info("DB | activateRule: '" + ruleId + "' for '" + userId + "'"); - _this.db.sadd("rule:" + ruleId + ":active-users", userId, replyHandler("storing activated user '" + userId + "' in rule '" + ruleId + "'")); - return _this.db.sadd("user:" + userId + ":active-rules", ruleId, replyHandler("storing activated rule '" + ruleId + "' in user '" + userId + "'")); - }; /* Get rules activated for a user and hand it to cb(err, obj). @@ -554,13 +591,15 @@ Persistence @public getUserLinkRule( *userId, cb* ) @param {String} userId @param {function} cb - */ + */ + exports.getUserActivatedRules = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUserActivatedRules: for user '" + userId + "'"); + return _this.db.smembers("user:" + userId + ":active-rules", cb); + }; + })(this); - exports.getUserActivatedRules = function(userId, cb) { - _this.log.info("DB | getUserActivatedRules: for user '" + userId + "'"); - return _this.db.smembers("user:" + userId + ":active-rules", cb); - }; /* Get users activated for a rule and hand it to cb(err, obj). @@ -568,13 +607,15 @@ Persistence @public getRuleActivatedUsers ( *ruleId, cb* ) @param {String} ruleId @param {function} cb - */ + */ + exports.getRuleActivatedUsers = (function(_this) { + return function(ruleId, cb) { + _this.log.info("DB | getRuleActivatedUsers: for rule '" + ruleId + "'"); + return _this.db.smembers("rule:" + ruleId + ":active-users", cb); + }; + })(this); - exports.getRuleActivatedUsers = function(ruleId, cb) { - _this.log.info("DB | getRuleActivatedUsers: for rule '" + ruleId + "'"); - return _this.db.smembers("rule:" + ruleId + ":active-users", cb); - }; /* Deactivate a rule. @@ -582,55 +623,59 @@ Persistence @public deactivateRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.deactivateRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | deactivateRule: '" + ruleId + "' for '" + userId + "'"); + _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("removing activated user '" + userId + "' in rule '" + ruleId + "'")); + return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("removing activated rule '" + ruleId + "' in user '" + userId + "'")); + }; + })(this); - exports.deactivateRule = function(ruleId, userId) { - _this.log.info("DB | deactivateRule: '" + ruleId + "' for '" + userId + "'"); - _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("removing activated user '" + userId + "' in rule '" + ruleId + "'")); - return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("removing activated rule '" + ruleId + "' in user '" + userId + "'")); - }; /* Fetch all active ruleIds and pass them to cb(err, obj). @public getAllActivatedRuleIds( *cb* ) @param {function} cb - */ + */ - - exports.getAllActivatedRuleIdsPerUser = function(cb) { - _this.log.info("DB | Fetching all active rules"); - return _this.db.smembers('users', function(err, obj) { - var fFetchActiveUserRules, result, semaphore, user, _i, _len, _results; - result = {}; - if (obj.length === 0) { - return cb(null, result); - } else { - semaphore = obj.length; - fFetchActiveUserRules = function(userId) { - return _this.db.smembers("user:" + user + ":active-rules", function(err, obj) { - if (obj.length > 0) { - result[userId] = obj; - } - if (--semaphore === 0) { - return cb(null, result); - } - }); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - user = obj[_i]; - _results.push(fFetchActiveUserRules(user)); + exports.getAllActivatedRuleIdsPerUser = (function(_this) { + return function(cb) { + _this.log.info("DB | Fetching all active rules"); + return _this.db.smembers('users', function(err, obj) { + var fFetchActiveUserRules, result, semaphore, user, _i, _len, _results; + result = {}; + if (obj.length === 0) { + return cb(null, result); + } else { + semaphore = obj.length; + fFetchActiveUserRules = function(userId) { + return _this.db.smembers("user:" + user + ":active-rules", function(err, obj) { + if (obj.length > 0) { + result[userId] = obj; + } + if (--semaphore === 0) { + return cb(null, result); + } + }); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + user = obj[_i]; + _results.push(fFetchActiveUserRules(user)); + } + return _results; } - return _results; - } - }); - }; + }); + }; + })(this); + /* - ## Users - */ + *# Users + */ /* @@ -639,32 +684,36 @@ Persistence @public storeUser( *objUser* ) @param {Object} objUser - */ + */ + exports.storeUser = (function(_this) { + return function(objUser) { + _this.log.info("DB | storeUser: '" + objUser.username + "'"); + if (objUser && objUser.username && objUser.password) { + _this.db.sadd('users', objUser.username, replyHandler("storing user key '" + objUser.username + "'")); + objUser.password = objUser.password; + return _this.db.hmset("user:" + objUser.username, objUser, replyHandler("storing user properties '" + objUser.username + "'")); + } else { + return _this.log.warn(new Error('DB | username or password was missing')); + } + }; + })(this); - exports.storeUser = function(objUser) { - _this.log.info("DB | storeUser: '" + objUser.username + "'"); - if (objUser && objUser.username && objUser.password) { - _this.db.sadd('users', objUser.username, replyHandler("storing user key '" + objUser.username + "'")); - objUser.password = objUser.password; - return _this.db.hmset("user:" + objUser.username, objUser, replyHandler("storing user properties '" + objUser.username + "'")); - } else { - return _this.log.warn(new Error('DB | username or password was missing')); - } - }; /* Fetch all user IDs and pass them to cb(err, obj). @public getUserIds( *cb* ) @param {function} cb - */ + */ + exports.getUserIds = (function(_this) { + return function(cb) { + _this.log.info("DB | getUserIds"); + return _this.db.smembers("users", cb); + }; + })(this); - exports.getUserIds = function(cb) { - _this.log.info("DB | getUserIds"); - return _this.db.smembers("users", cb); - }; /* Fetch a user by id and pass it to cb(err, obj). @@ -672,66 +721,70 @@ Persistence @public getUser( *userId, cb* ) @param {String} userId @param {function} cb - */ + */ + exports.getUser = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUser: '" + userId + "'"); + return _this.db.hgetall("user:" + userId, cb); + }; + })(this); - exports.getUser = function(userId, cb) { - _this.log.info("DB | getUser: '" + userId + "'"); - return _this.db.hgetall("user:" + userId, cb); - }; /* Deletes a user and all his associated linked and active rules. @public deleteUser( *userId* ) @param {String} userId - */ + */ + exports.deleteUser = (function(_this) { + return function(userId) { + _this.log.info("DB | deleteUser: '" + userId + "'"); + _this.db.srem("users", userId, replyHandler("Deleting user key '" + userId + "'")); + _this.db.del("user:" + userId, replyHandler("Deleting user '" + userId + "'")); + _this.db.smembers("user:" + userId + ":rules", function(err, obj) { + var delLinkedRuleUser, id, _i, _len, _results; + delLinkedRuleUser = function(ruleId) { + return _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in linked rule '" + ruleId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delLinkedRuleUser(id)); + } + return _results; + }); + _this.db.del("user:" + userId + ":rules", replyHandler("Deleting user '" + userId + "' rules")); + _this.db.smembers("user:" + userId + ":active-rules", function(err, obj) { + var delActivatedRuleUser, id, _i, _len, _results; + delActivatedRuleUser = function(ruleId) { + return _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("Deleting user key '" + userId + "' in active rule '" + ruleId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delActivatedRuleUser(id)); + } + return _results; + }); + _this.db.del("user:" + userId + ":active-rules", replyHandler("Deleting user '" + userId + "' rules")); + _this.db.smembers("user:" + userId + ":roles", function(err, obj) { + var delRoleUser, id, _i, _len, _results; + delRoleUser = function(roleId) { + return _this.db.srem("role:" + roleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in role '" + roleId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delRoleUser(id)); + } + return _results; + }); + return _this.db.del("user:" + userId + ":roles", replyHandler("Deleting user '" + userId + "' roles")); + }; + })(this); - exports.deleteUser = function(userId) { - _this.log.info("DB | deleteUser: '" + userId + "'"); - _this.db.srem("users", userId, replyHandler("Deleting user key '" + userId + "'")); - _this.db.del("user:" + userId, replyHandler("Deleting user '" + userId + "'")); - _this.db.smembers("user:" + userId + ":rules", function(err, obj) { - var delLinkedRuleUser, id, _i, _len, _results; - delLinkedRuleUser = function(ruleId) { - return _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in linked rule '" + ruleId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delLinkedRuleUser(id)); - } - return _results; - }); - _this.db.del("user:" + userId + ":rules", replyHandler("Deleting user '" + userId + "' rules")); - _this.db.smembers("user:" + userId + ":active-rules", function(err, obj) { - var delActivatedRuleUser, id, _i, _len, _results; - delActivatedRuleUser = function(ruleId) { - return _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("Deleting user key '" + userId + "' in active rule '" + ruleId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delActivatedRuleUser(id)); - } - return _results; - }); - _this.db.del("user:" + userId + ":active-rules", replyHandler("Deleting user '" + userId + "' rules")); - _this.db.smembers("user:" + userId + ":roles", function(err, obj) { - var delRoleUser, id, _i, _len, _results; - delRoleUser = function(roleId) { - return _this.db.srem("role:" + roleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in role '" + roleId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delRoleUser(id)); - } - return _results; - }); - return _this.db.del("user:" + userId + ":roles", replyHandler("Deleting user '" + userId + "' roles")); - }; /* Checks the credentials and on success returns the user object to the @@ -743,34 +796,36 @@ Persistence @param {String} userId @param {String} password @param {function} cb - */ + */ - - exports.loginUser = function(userId, password, cb) { - var fCheck; - _this.log.info("DB | User '" + userId + "' tries to log in"); - fCheck = function(pw) { - return function(err, obj) { - if (err) { - return cb(err, null); - } else if (obj && obj.password) { - if (pw === obj.password) { - _this.log.info("DB | User '" + obj.username + "' logged in!"); - return cb(null, obj); + exports.loginUser = (function(_this) { + return function(userId, password, cb) { + var fCheck; + _this.log.info("DB | User '" + userId + "' tries to log in"); + fCheck = function(pw) { + return function(err, obj) { + if (err) { + return cb(err, null); + } else if (obj && obj.password) { + if (pw === obj.password) { + _this.log.info("DB | User '" + obj.username + "' logged in!"); + return cb(null, obj); + } else { + return cb(new Error('Wrong credentials!'), null); + } } else { - return cb(new Error('Wrong credentials!'), null); + return cb(new Error('User not found!'), null); } - } else { - return cb(new Error('User not found!'), null); - } + }; }; + return _this.db.hgetall("user:" + userId, fCheck(password)); }; - return _this.db.hgetall("user:" + userId, fCheck(password)); - }; + })(this); + /* - ## User Roles - */ + *# User Roles + */ /* @@ -779,15 +834,17 @@ Persistence @public storeUserRole( *userId, role* ) @param {String} userId @param {String} role - */ + */ + exports.storeUserRole = (function(_this) { + return function(userId, role) { + _this.log.info("DB | storeUserRole: '" + userId + ":" + role + "'"); + _this.db.sadd('roles', role, replyHandler("adding role '" + role + "' to role index set")); + _this.db.sadd("user:" + userId + ":roles", role, replyHandler("adding role '" + role + "' to user '" + userId + "'")); + return _this.db.sadd("role:" + role + ":users", userId, replyHandler("adding user '" + userId + "' to role '" + role + "'")); + }; + })(this); - exports.storeUserRole = function(userId, role) { - _this.log.info("DB | storeUserRole: '" + userId + ":" + role + "'"); - _this.db.sadd('roles', role, replyHandler("adding role '" + role + "' to role index set")); - _this.db.sadd("user:" + userId + ":roles", role, replyHandler("adding role '" + role + "' to user '" + userId + "'")); - return _this.db.sadd("role:" + role + ":users", userId, replyHandler("adding user '" + userId + "' to role '" + role + "'")); - }; /* Fetch all roles of a user and pass them to cb(err, obj). @@ -795,13 +852,15 @@ Persistence @public getUserRoles( *userId* ) @param {String} userId @param {function} cb - */ + */ + exports.getUserRoles = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUserRoles: '" + userId + "'"); + return _this.db.smembers("user:" + userId + ":roles", cb); + }; + })(this); - exports.getUserRoles = function(userId, cb) { - _this.log.info("DB | getUserRoles: '" + userId + "'"); - return _this.db.smembers("user:" + userId + ":roles", cb); - }; /* Fetch all users of a role and pass them to cb(err, obj). @@ -809,13 +868,15 @@ Persistence @public getUserRoles( *role* ) @param {String} role @param {function} cb - */ + */ + exports.getRoleUsers = (function(_this) { + return function(role, cb) { + _this.log.info("DB | getRoleUsers: '" + role + "'"); + return _this.db.smembers("role:" + role + ":users", cb); + }; + })(this); - exports.getRoleUsers = function(role, cb) { - _this.log.info("DB | getRoleUsers: '" + role + "'"); - return _this.db.smembers("role:" + role + ":users", cb); - }; /* Remove a role from a user. @@ -823,25 +884,28 @@ Persistence @public removeRoleFromUser( *role, userId* ) @param {String} role @param {String} userId - */ + */ + exports.removeUserRole = (function(_this) { + return function(userId, role) { + _this.log.info("DB | removeRoleFromUser: role '" + role + "', user '" + userId + "'"); + _this.db.srem("user:" + userId + ":roles", role, replyHandler("Removing role '" + role + "' from user '" + userId + "'")); + return _this.db.srem("role:" + role + ":users", userId, replyHandler("Removing user '" + userId + "' from role '" + role + "'")); + }; + })(this); - exports.removeUserRole = function(userId, role) { - _this.log.info("DB | removeRoleFromUser: role '" + role + "', user '" + userId + "'"); - _this.db.srem("user:" + userId + ":roles", role, replyHandler("Removing role '" + role + "' from user '" + userId + "'")); - return _this.db.srem("role:" + role + ":users", userId, replyHandler("Removing user '" + userId + "' from role '" + role + "'")); - }; /* Shuts down the db link. @public shutDown() - */ + */ - - exports.shutDown = function() { - var _ref; - return (_ref = _this.db) != null ? _ref.quit() : void 0; - }; + exports.shutDown = (function(_this) { + return function() { + var _ref; + return (_ref = _this.db) != null ? _ref.quit() : void 0; + }; + })(this); }).call(this); diff --git a/js-coffee/webapi-eca.js b/js-coffee/webapi-eca.js index 5a89e07..a0eaa22 100644 --- a/js-coffee/webapi-eca.js +++ b/js-coffee/webapi-eca.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* WebAPI-ECA Engine @@ -9,12 +10,10 @@ WebAPI-ECA Engine > node webapi-eca [opt] > > See below in the optimist CLI preparation for allowed optional parameters `[opt]`. -*/ - + */ (function() { - var argv, cm, conf, cp, db, engine, fs, http, init, logconf, logger, nameEP, opt, optimist, path, procCmds, shutDown, usage, - _this = this; + var argv, cm, conf, cp, db, engine, fs, http, init, logconf, logger, nameEP, opt, optimist, path, procCmds, shutDown, usage; logger = require('./logging'); @@ -40,10 +39,10 @@ WebAPI-ECA Engine procCmds = {}; + /* Let's prepare the optimist CLI optional arguments `[opt]`: - */ - + */ usage = 'This runs your webapi-based ECA engine'; @@ -130,72 +129,76 @@ WebAPI-ECA Engine this.log.info('RS | STARTING SERVER'); + /* This function is invoked right after the module is loaded and starts the server. @private init() - */ + */ - - init = function() { - var args; - args = { - logger: _this.log, - logconf: logconf + init = (function(_this) { + return function() { + var args; + args = { + logger: _this.log, + logconf: logconf + }; + args['http-port'] = parseInt(argv.w || conf.getHttpPort()); + args['db-port'] = parseInt(argv.d || conf.getDbPort()); + args['keygen'] = conf.getKeygenPassphrase(); + _this.log.info('RS | Initialzing DB'); + db(args); + return db.isConnected(function(err) { + var cliArgs, poller; + if (err) { + _this.log.error('RS | No DB connection, shutting down system!'); + return shutDown(); + } else { + _this.log.info('RS | Initialzing engine'); + engine(args); + _this.log.info('RS | Forking a child process for the event poller'); + cliArgs = [args.logconf['mode'], args.logconf['io-level'], args.logconf['file-level'], args.logconf['file-path'], args.logconf['nolog']]; + poller = cp.fork(path.resolve(__dirname, nameEP), cliArgs); + _this.log.info('RS | Initialzing module manager'); + cm(args); + cm.addRuleListener(engine.internalEvent); + cm.addRuleListener(function(evt) { + return poller.send(evt); + }); + _this.log.info('RS | Initialzing http listener'); + args['request-service'] = cm.processRequest; + args['shutdown-function'] = shutDown; + return http(args); + } + }); }; - args['http-port'] = parseInt(argv.w || conf.getHttpPort()); - args['db-port'] = parseInt(argv.d || conf.getDbPort()); - args['keygen'] = conf.getKeygenPassphrase(); - _this.log.info('RS | Initialzing DB'); - db(args); - return db.isConnected(function(err) { - var cliArgs, poller; - if (err) { - _this.log.error('RS | No DB connection, shutting down system!'); - return shutDown(); - } else { - _this.log.info('RS | Initialzing engine'); - engine(args); - _this.log.info('RS | Forking a child process for the event poller'); - cliArgs = [args.logconf['mode'], args.logconf['io-level'], args.logconf['file-level'], args.logconf['file-path'], args.logconf['nolog']]; - poller = cp.fork(path.resolve(__dirname, nameEP), cliArgs); - _this.log.info('RS | Initialzing module manager'); - cm(args); - cm.addRuleListener(engine.internalEvent); - cm.addRuleListener(function(evt) { - return poller.send(evt); - }); - _this.log.info('RS | Initialzing http listener'); - args['request-service'] = cm.processRequest; - args['shutdown-function'] = shutDown; - return http(args); - } - }); - }; + })(this); + /* Shuts down the server. @private shutDown() - */ + */ + shutDown = (function(_this) { + return function() { + _this.log.warn('RS | Received shut down command!'); + if (db != null) { + db.shutDown(); + } + engine.shutDown(); + return process.exit(); + }; + })(this); - shutDown = function() { - _this.log.warn('RS | Received shut down command!'); - if (db != null) { - db.shutDown(); - } - engine.shutDown(); - return process.exit(); - }; /* - ## Process Commands + *# Process Commands When the server is run as a child process, this function handles messages from the parent process (e.g. the testing suite) - */ - + */ process.on('message', function(cmd) { return typeof procCmds[cmd] === "function" ? procCmds[cmd]() : void 0; diff --git a/package.json b/package.json index 5608ae1..7812640 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "crypto-js": "3.1.2", "express": "3.4.8", "groc": "0.6.1", + "js-select": "0.6.0", "mustache": "0.8.1", "needle": "0.6.3", "nodeunit": "0.8.4", diff --git a/testing/files/testObjects.json b/testing/files/testObjects.json index c068b50..fae6abe 100644 --- a/testing/files/testObjects.json +++ b/testing/files/testObjects.json @@ -11,6 +11,15 @@ }, "eventTwo":{ "event": "test_2" + }, + "eventReal":{ + "event": "epOne -> newMail", + "payload": { + "property": "test_1", + "nestedProperty": { + "more": "really nested" + } + } } }, "eps": { @@ -43,10 +52,10 @@ "aiTwo": { "id":"aiTwo", "lang":"CoffeeScript", - "data":"# Send a mail through emailyak\nexports.sendMail = ( args ) ->\n\turl = 'https://api.emailyak.com/v1/' + params.apikey + '/json/send/email/'\n\tpayload =\n\t FromAddress : \"testsender@mscliveweb.simpleyak.com\",\n\t ToAddress: \"dominic.bosch@gmail.com\",\n\t Subject: \"TestMAIL\",\n\t TextBody: \"Hello\"\n\t\n\tneedle.post url, payload, ( err, resp, body ) ->\n\t\tif err\n\t\t\tlog err\n\t\tif resp.statusCode isnt 200\n\t\t\tlog 'Request not successful:'\n\t\t\tlog body\n", + "data":"# Send a mail through emailyak\nexports.otherEvent = ( args ) ->\n\turl = 'https://api.emailyak.com/v1/' + params.apikey + '/json/send/email/'\n\tpayload =\n\t FromAddress : \"testsender@mscliveweb.simpleyak.com\",\n\t ToAddress: \"dominic.bosch@gmail.com\",\n\t Subject: \"TestMAIL\",\n\t TextBody: \"Hello\"\n\t\n\tneedle.post url, payload, ( err, resp, body ) ->\n\t\tif err\n\t\t\tlog err\n\t\tif resp.statusCode isnt 200\n\t\t\tlog 'Request not successful:'\n\t\t\tlog body\n", "public":"false", "params":"[\"apikey\",\"andmore\"]", - "functions":"[\"sendMail\"]" + "functions":"[\"otherEvent\"]" } }, "userparams": { @@ -58,32 +67,32 @@ "ruleOne": { "id": "ruleOne_id", "event": "custom-test-1", - "conditions": { - "property": "yourValue" - }, + "conditions": [], "actions": [] }, "ruleTwo": { "id": "ruleTwo_id", "event": "custom-test-2", - "conditions": { - "property": "yourValue2" - }, + "conditions": [], "actions": [] }, "ruleThree": { "id": "ruleThree_id", "event": "custom-test-3", - "conditions": { - "property": "yourValue3" - }, + "conditions": [], "actions": [] }, "ruleReal": { "id": "ruleReal", "event": "epOne -> newMail", - "conditions": {}, + "conditions": [".more:val(\"really nested\")"], "actions": ["aiOne -> sendMail"] + }, + "ruleRealTwo": { + "id": "ruleRealTwo", + "event": "epOne -> newMail", + "conditions": [], + "actions": ["aiTwo -> otherEvent"] } }, "users": { diff --git a/testing/test_components-manager.coffee b/testing/test_components-manager.coffee index 65f8b44..a67206b 100644 --- a/testing/test_components-manager.coffee +++ b/testing/test_components-manager.coffee @@ -79,7 +79,6 @@ exports.testListener = ( test ) => cm.addRuleListener ( evt ) => strEvt = JSON.stringify evt.rule - console.log evt if evt.event is 'init' if strEvt is strRuleOne or strEvt is strRuleTwo test.ok true, 'Dummy true to fill expected tests!' diff --git a/testing/test_engine.coffee b/testing/test_engine.coffee index e6df5f0..a43a74b 100644 --- a/testing/test_engine.coffee +++ b/testing/test_engine.coffee @@ -22,63 +22,136 @@ engine opts db = require path.join '..', 'js-coffee', 'persistence' db opts +listRules = engine.getListUserRules() + oUser = objects.users.userOne -oRuleOne = objects.rules.ruleOne -oRuleTwo = objects.rules.ruleTwo oRuleReal = objects.rules.ruleReal -oEpOne = objects.eps.epOne -oEpTwo = objects.eps.epTwo +oRuleRealTwo = objects.rules.ruleRealTwo oAiOne = objects.ais.aiOne +oAiTwo = objects.ais.aiTwo exports.tearDown = ( cb ) -> - db.deleteRule oRuleOne.id - db.deleteRule oRuleTwo.id db.deleteRule oRuleReal.id db.actionInvokers.deleteModule oAiOne.id + db.actionInvokers.deleteModule oAiTwo.id + # TODO if user is deleted all his modules should be unlinked and deleted db.deleteUser oUser.username + + engine.internalEvent + event: 'del' + user: oUser.username + rule: oRuleReal + + engine.internalEvent + event: 'del' + user: oUser.username + rule: oRuleRealTwo + setTimeout cb, 100 exports.ruleEvents = - # init: first registration, multiple registration - # actions loaded and added correctly - # new: new actions added - # old actions removed - # delete: all actions removed if not required anymore - testInit: ( test ) -> + testInitAddDeleteMultiple: ( test ) -> + test.expect 2 + 2 * oRuleReal.actions.length + oRuleRealTwo.actions.length + db.storeUser oUser - test.done() - strRuleOne = JSON.stringify oRuleOne - strRuleTwo = JSON.stringify oRuleTwo - strRuleReal = JSON.stringify oRuleReal - - db.actionInvokers.storeModule oUser.username, oAiOne - - db.storeRule oRuleOne.id, strRuleOne - db.linkRule oRuleOne.id, oUser.username - db.activateRule oRuleOne.id, oUser.username - - db.storeRule oRuleTwo.id, strRuleTwo - db.linkRule oRuleTwo.id, oUser.username - db.activateRule oRuleTwo.id, oUser.username - - db.storeRule oRuleReal.id, strRuleReal + db.storeRule oRuleReal.id, JSON.stringify oRuleReal db.linkRule oRuleReal.id, oUser.username db.activateRule oRuleReal.id, oUser.username + db.actionInvokers.storeModule oUser.username, oAiOne + db.actionInvokers.storeModule oUser.username, oAiTwo - db.getAllActivatedRuleIdsPerUser ( err, obj ) => - @existingRules = obj - console.log 'existing' - console.log obj + test.strictEqual listRules[oUser.username], undefined, 'Initial user object exists!?' + + engine.internalEvent + event: 'new' + user: oUser.username + rule: oRuleReal + + fWaitForPersistence = () -> + + for act in oRuleReal.actions + mod = ( act.split ' -> ' )[0] + test.ok listRules[oUser.username].actions[mod], 'Missing action!' engine.internalEvent - event: 'init' + event: 'new' user: oUser.username - rule: oRuleReal + rule: oRuleRealTwo - fCheckRules = () -> - db.getAllActivatedRuleIdsPerUser ( err, obj ) => - console.log 'after init' - console.log obj - console.log @existingRules is obj + fWaitAgainForPersistence = () -> + + for act in oRuleRealTwo.actions + mod = ( act.split ' -> ' )[0] + test.ok listRules[oUser.username].actions[mod], 'Missing action!' + + engine.internalEvent + event: 'del' + user: oUser.username + rule: oRuleRealTwo + + for act in oRuleReal.actions + mod = ( act.split ' -> ' )[0] + test.ok listRules[oUser.username].actions[mod], 'Missing action!' + + engine.internalEvent + event: 'del' + user: oUser.username + rule: oRuleReal + + test.strictEqual listRules[oUser.username], undefined, 'Final user object exists!?' + test.done() + + setTimeout fWaitAgainForPersistence, 200 + + setTimeout fWaitForPersistence, 200 + +# #TODO +# testUpdate: ( test ) -> +# test.expect 0 + +# test.done() + +# db.storeUser oUser +# db.storeRule oRuleReal.id, JSON.stringify oRuleReal +# db.linkRule oRuleReal.id, oUser.username +# db.activateRule oRuleReal.id, oUser.username +# db.actionInvokers.storeModule oUser.username, oAiOne + + +# db.getAllActivatedRuleIdsPerUser ( err, obj ) -> +# console.log 'existing' +# console.log obj + +# engine.internalEvent +# event: 'init' +# user: oUser.username +# rule: oRuleReal + +# fCheckRules = () -> +# db.getAllActivatedRuleIdsPerUser ( err, obj ) -> +# console.log 'after init' +# console.log obj + +# setTimeout fCheckRules, 500 + +exports.engine = + matchingEvent: ( test ) -> + + db.storeUser oUser + db.storeRule oRuleReal.id, JSON.stringify oRuleReal + db.linkRule oRuleReal.id, oUser.username + db.activateRule oRuleReal.id, oUser.username + db.actionInvokers.storeModule oUser.username, oAiOne + + engine.internalEvent + event: 'new' + user: oUser.username + rule: oRuleReal + + fWaitForPersistence = () -> + evt = objects.events.eventReal + evt.eventid = 'event_testid' + db.pushEvent evt + setTimeout fWaitForPersistence, 200 + setTimeout test.done, 500 - setTimeout fCheckRules, 500 \ No newline at end of file diff --git a/webpages/handlers/js/forge_action_invoker.js b/webpages/handlers/js/forge_action_invoker.js index 5d412ac..0ff2b84 100644 --- a/webpages/handlers/js/forge_action_invoker.js +++ b/webpages/handlers/js/forge_action_invoker.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 (function() { var fOnLoad; diff --git a/webpages/handlers/js/forge_event_poller.js b/webpages/handlers/js/forge_event_poller.js index 4585629..28e3262 100644 --- a/webpages/handlers/js/forge_event_poller.js +++ b/webpages/handlers/js/forge_event_poller.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 (function() { var fOnLoad; diff --git a/webpages/handlers/js/forge_rule.js b/webpages/handlers/js/forge_rule.js index 2b8e274..3fed0f6 100644 --- a/webpages/handlers/js/forge_rule.js +++ b/webpages/handlers/js/forge_rule.js @@ -1,4 +1,4 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 (function() { var fOnLoad, strPublicKey; @@ -183,7 +183,7 @@ table.append(tr); if ($('#ap_' + arrAI[0]).length === 0) { div = $('
').attr('id', 'ap_' + arrAI[0]); - div.append($('
').attr('class', 'underlined').text(arrAI[0])); + div.append($('
')).attr('class', 'underlined').text(arrAI[0]); $('#action_params').append(div); fFetchActionParams(div, arrAI[0]); }