diff --git a/coffee/components-manager.coffee b/coffee/components-manager.coffee
index 31640f8..5129aa5 100644
--- a/coffee/components-manager.coffee
+++ b/coffee/components-manager.coffee
@@ -144,22 +144,23 @@ forgeModule = ( user, oPayload, dbMod, callback ) =>
dbMod.getModule oPayload.id, ( err, mod ) =>
if mod
answ.code = 409
- answ.message = 'Event Poller module name already existing: ' + oPayload.id
+ answ.message = 'Module name already existing: ' + oPayload.id
+ callback answ
else
src = oPayload.data
- cm = dynmod.compileString src, user.username, oPayload.id, {}, oPayload.lang
- answ = cm.answ
- if answ.code is 200
- funcs = []
- funcs.push name for name, id of cm.module
- @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 is 'true'
- dbMod.publish oPayload.id
- callback answ
+ dynmod.compileString src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, ( cm ) =>
+ answ = cm.answ
+ if answ.code is 200
+ funcs = []
+ funcs.push name for name, id of cm.module
+ @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 is 'true'
+ dbMod.publish oPayload.id
+ callback answ
commandFunctions =
get_public_key: ( user, oPayload, callback ) ->
@@ -174,19 +175,47 @@ commandFunctions =
getModules user, oPayload, db.actionInvokers, callback
get_event_poller_params: ( user, oPayload, callback ) ->
- getModuleParams user, oPayload, db.eventPollers, callback
+ getModuleParams user, oPayload, db.eventPollers, callback
get_action_invoker_params: ( user, oPayload, callback ) ->
- getModuleParams user, oPayload, db.actionInvokers, callback
+ getModuleParams user, oPayload, db.actionInvokers, callback
forge_event_poller: ( user, oPayload, callback ) ->
- forgeModule user, oPayload, db.eventPollers, callback
+ forgeModule user, oPayload, db.eventPollers, callback
forge_action_invoker: ( user, oPayload, callback ) ->
- forgeModule user, oPayload, db.actionInvokers, callback
+ forgeModule user, oPayload, db.actionInvokers, callback
get_rules: ( user, oPayload, callback ) ->
- console.log 'CM | Implement get_rules'
+ db.getUserLinkedRules user.username, ( err, obj ) ->
+ callback
+ code: 200
+ message: obj
+
+ get_rule_log: ( user, oPayload, callback ) ->
+ answ = hasRequiredParams [ 'id' ], oPayload
+ if answ.code isnt 200
+ callback answ
+ else
+ db.getLog user.username, oPayload.id, ( err, obj ) ->
+ callback
+ code: 200
+ message: obj
+
+ delete_rule: ( user, oPayload, callback ) ->
+ answ = hasRequiredParams [ 'id' ], oPayload
+ if answ.code isnt 200
+ callback answ
+ else
+ db.deleteRule oPayload.id
+ eventEmitter.emit 'rule',
+ event: 'del'
+ user: user.username
+ rule: null
+ ruleId: oPayload.id
+ callback
+ code: 200
+ message: 'OK!'
# A rule needs to be in following format:
# - id
@@ -224,5 +253,5 @@ commandFunctions =
rule: rule
answ =
code: 200
- message: 'Rule stored and activated!'
+ message: "Rule '#{ rule.id }' stored and activated!"
callback answ
\ No newline at end of file
diff --git a/coffee/dynamic-modules.coffee b/coffee/dynamic-modules.coffee
index 3ab7530..100b6f1 100644
--- a/coffee/dynamic-modules.coffee
+++ b/coffee/dynamic-modules.coffee
@@ -8,6 +8,8 @@ Dynamic Modules
# **Loads Modules:**
+db = require './persistence'
+
# - Node.js Modules: [vm](http://nodejs.org/api/vm.html) and
# [events](http://nodejs.org/api/events.html)
vm = require 'vm'
@@ -31,11 +33,12 @@ exports = module.exports = ( args ) =>
@log = args.logger
# FIXME this can't come through the arguments
if not @strPublicKey and args[ 'keygen' ]
+ db args
passPhrase = args[ 'keygen' ]
numBits = 1024
@oPrivateRSAkey = cryptico.generateRSAKey passPhrase, numBits
@strPublicKey = cryptico.publicKeyString @oPrivateRSAkey
- @log.info "Public Key generated: #{ @strPublicKey }"
+ @log.info "DM | Public Key generated: #{ @strPublicKey }"
# plainText = "Matt, I need you to help me with my Starcraft strategy."
# oEncrypted = cryptico.encrypt plainText, strPublicKey
@@ -61,7 +64,7 @@ compile it first into JS.
@param {Object} params
@param {String} lang
###
-exports.compileString = ( src, userId, modId, params, lang ) =>
+exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) =>
answ =
code: 200
message: 'Successfully compiled'
@@ -73,26 +76,48 @@ exports.compileString = ( src, userId, modId, params, lang ) =>
answ.code = 400
answ.message = 'Compilation of CoffeeScript failed at line ' +
err.location.first_line
- #FIXME not log but debug module is required to provide information to the user
- sandbox =
- id: userId + '.' + modId + '.vm'
- params: params
- needle: needle
- log: console.log
- # console: console #TODO remove!
- exports: {}
- #TODO child_process to run module!
- #Define max runtime per loop as 10 seconds, after that the child will be killed
- #it can still be active after that if there was a timing function or a callback used...
- #kill the child each time? how to determine whether there's still a token in the module?
- try
- vm.runInNewContext src, sandbox, sandbox.id
- # TODO We should investigate memory usage and garbage collection (global.gc())?
- # Start Node with the flags —nouse_idle_notification and —expose_gc, and then when you want to run the GC, just call global.gc().
- catch err
- answ.code = 400
- answ.message = 'Loading Module failed: ' + err.message
- ret =
- answ: answ
- module: sandbox.exports
- ret
\ No newline at end of file
+
+ logFunction = ( uId, rId, mId ) ->
+ ( msg ) ->
+ db.appendLog uId, rId, mId, msg
+ db.resetLog userId, ruleId
+
+ fTryToLoad = ( params ) =>
+ if params
+ try
+ oDecrypted = cryptico.decrypt params, @oPrivateRSAkey
+ params = JSON.parse oDecrypted.plaintext
+ catch err
+ @log.warn "DM | Error during parsing of user defined params for #{ userId }, #{ ruleId }, #{ modId }"
+ params = {}
+ else
+ params = {}
+ sandbox =
+ id: userId + '.' + modId + '.vm'
+ params: params
+ needle: needle
+ log: logFunction userId, ruleId, modId
+ # debug: console.log
+ exports: {}
+
+ #TODO child_process to run module!
+ #Define max runtime per loop as 10 seconds, after that the child will be killed
+ #it can still be active after that if there was a timing function or a callback used...
+ #kill the child each time? how to determine whether there's still a token in the module?
+ try
+ vm.runInNewContext src, sandbox, sandbox.id
+ # TODO We should investigate memory usage and garbage collection (global.gc())?
+ # Start Node with the flags —nouse_idle_notification and —expose_gc, and then when you want to run the GC, just call global.gc().
+ catch err
+ console.log err
+ answ.code = 400
+ answ.message = 'Loading Module failed: ' + err.message
+ cb
+ answ: answ
+ module: sandbox.exports
+
+ if dbMod
+ dbMod.getUserParams modId, userId, ( err, obj ) ->
+ fTryToLoad obj
+ else
+ fTryToLoad()
diff --git a/coffee/engine.coffee b/coffee/engine.coffee
index 1177cb2..2009ea0 100644
--- a/coffee/engine.coffee
+++ b/coffee/engine.coffee
@@ -19,6 +19,25 @@ dynmod = require './dynamic-modules'
# [js-select](https://www.npmjs.org/package/js-select)
jsonQuery = require 'js-select'
+###
+This is ging to have a structure like:
+An object of users with their active rules and the required action modules
+"user-1":
+ "rule-1":
+ "rule": oRule-1
+ "actions":
+ "action-1": oAction-1
+ "action-2": oAction-2
+ "rule-2":
+ "rule": oRule-2
+ "actions":
+ "action-1": oAction-1
+"user-2":
+ "rule-3":
+ "rule": oRule-3
+ "actions":
+ "action-3": oAction-3
+###
listUserRules = {}
isRunning = false
@@ -35,7 +54,7 @@ exports = module.exports = ( args ) =>
@log = args.logger
db args
dynmod args
- pollQueue()
+ setTimeout pollQueue, 10 # Very important, this forks a token for the poll task
module.exports
@@ -59,50 +78,48 @@ are basically CRUD on rules.
###
exports.internalEvent = ( evt ) =>
if not listUserRules[evt.user] and evt.event isnt 'del'
- listUserRules[evt.user] =
- rules: {}
- actions: {}
+ listUserRules[evt.user] = {}
oUser = listUserRules[evt.user]
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, false
+ if evt.event is 'new' or ( evt.event is 'init' and not oUser[oRule.id] )
+ oUser[oRule.id] =
+ rule: oRule
+ actions: {}
+ updateActionModules oRule.id
if evt.event is 'del' and oUser
- delete oUser.rules[oRule.id]
- updateActionModules oRule, true
+ delete oUser[evt.ruleId]
+
+ # If a user is empty after all the updates above, we remove her from the list
+ if JSON.stringify( oUser ) is "{}"
+ delete listUserRules[evt.user]
+
###
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
+@private updateActionModules ( *updatedRuleId* )
+@param {Object} updatedRuleId
###
-updateActionModules = ( oNewRule, isDeleteOp ) ->
+updateActionModules = ( updatedRuleId ) ->
# Remove all action invoker modules that are not required anymore
fRemoveNotRequired = ( oUser ) ->
- # Check whether the action is still existing in a rule
+ # Check whether the action is still existing in the rule
fRequired = ( actionName ) ->
- # 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
+ for action in oUser[updatedRuleId].rule.actions
+ # Since the event is in the format 'module -> function' we need to split the string
+ if (action.split ' -> ')[0] is actionName
+ return true
false
-
- # Go thorugh all actions and check whether the action is still required
- 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
+ # Go thorugh all loaded action modules and check whether the action is still required
+ for action of oUser[updatedRuleId].rule.actions
+ delete oUser[updatedRuleId].actions[action] if not fRequired action
fRemoveNotRequired oUser for name, oUser of listUserRules
@@ -110,26 +127,35 @@ updateActionModules = ( oNewRule, isDeleteOp ) ->
fAddRequired = ( userName, oUser ) ->
# Check whether the action is existing in a rule and load if not
- fCheckRules = ( oRule ) ->
+ fCheckRules = ( oMyRule ) ->
# 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 isDeleteOp and ( not oUser.actions[moduleName] or oRule.id is oNewRule.id )
+ if not oMyRule.actions[moduleName] or oMyRule.rule.id is updatedRuleId
db.actionInvokers.getModule moduleName, ( err, obj ) ->
- params = {}
- res = dynmod.compileString obj.data, userName, moduleName, params, obj.lang
- oUser.actions[moduleName] = res.module
+ # we compile the module and pass:
+ dynmod.compileString obj.data, # code
+ userName, # userId
+ oMyRule.rule.id, # ruleId
+ moduleName, # moduleId
+ obj.lang, # script language
+ db.actionInvokers, # the DB interface
+ ( result ) ->
+ if not result.answ is 200
+ @log.error "EN | Compilation of code failed! #{ userName },
+ #{ oMyRule.rule.id }, #{ moduleName }"
+ oMyRule.actions[moduleName] = result.module
- fAddIfNewOrNotExisting action for action in oRule.actions
+ fAddIfNewOrNotExisting action for action in oMyRule.rule.actions
- # 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]
+ # Go thorugh all rules and check whether the action is still required
+ fCheckRules oRl for nmRl, oRl of oUser
+ # load all required modules for all users
fAddRequired userName, oUser for userName, oUser of listUserRules
+
pollQueue = () ->
if isRunning
db.popEvent ( err, obj ) ->
@@ -145,6 +171,8 @@ Checks whether all conditions of the rule are met by the event.
@param {Object} rule
###
validConditions = ( evt, rule ) ->
+ if rule.conditions.length is 0
+ return true
for prop in rule.conditions
return false if jsonQuery( evt, prop ).nodes().length is 0
return true
@@ -156,15 +184,27 @@ Handles retrieved events.
@param {Object} evt
###
processEvent = ( evt ) =>
+
+ fSearchAndInvokeAction = ( node, arrPath, evt, depth ) ->
+ if not node
+ @log.error "EN | Didn't find property in user rule list: " + arrPath.join ', ' + " at depth " + depth
+ return
+ if depth is arrPath.length
+ try
+ node evt.payload
+ catch err
+ @log.info "EN | ERROR IN ACTION INVOKER: " + err.message
+ else
+ fSearchAndInvokeAction node[arrPath[depth]], arrPath, evt, depth + 1
+
@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
+ for ruleName, oMyRule of oUser
+ if evt.event is oMyRule.rule.event and validConditions evt, oMyRule.rule
@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
+ for action in oMyRule.rule.actions
arr = action.split ' -> '
- listUserRules[userName]['actions'][arr[0]][arr[1]] evt
+ fSearchAndInvokeAction listUserRules, [ userName, ruleName, 'actions', arr[0], arr[1]], evt, 0
exports.shutDown = () ->
isRunning = false
\ No newline at end of file
diff --git a/coffee/persistence.coffee b/coffee/persistence.coffee
index 8ca80ae..44abdf0 100644
--- a/coffee/persistence.coffee
+++ b/coffee/persistence.coffee
@@ -202,7 +202,6 @@ class IndexedModules
setDB: ( @db ) ->
@log.info "DB | (IdxedMods) Registered new DB connection for '#{ @setname }'"
-
###
Stores a module and links it to the user.
@@ -252,7 +251,7 @@ class IndexedModules
#TODO add testing
getModuleParams: ( mId, cb ) =>
- @log.info "DB | (IdxedMods) #{ @setname }.getModule( #{ mId } )"
+ @log.info "DB | (IdxedMods) #{ @setname }.getModuleParams( #{ mId } )"
@db.hget "#{ @setname }:#{ mId }", "params", cb
#TODO add testing
@@ -277,13 +276,7 @@ class IndexedModules
@unpublish mId
@db.smembers "#{ @setname }:#{ mId }:users", ( err, obj ) =>
@unlinkModule mId, userId for userId in obj
- # TODO remove from public modules
- # TODO remove parameters
- # @log.info "DB | linkModule(#{ @setname }): #{ mId } to #{ userId }"
- # @db.sadd "#{ @setname }:#{ mId }:users", userId,
- # replyHandler "Linking '#{ @setname }:#{ mId }:users' #{ userId }"
- # @db.sadd "user:#{ userId }:#{ @setname }s", mId,
- # replyHandler "Linking 'user:#{ userId }:#{ @setname }s' #{ mId }"
+ @deleteUserParams mId, userId for userId in obj
###
Stores user params for a module. They are expected to be RSA encrypted with helps of
@@ -303,8 +296,7 @@ class IndexedModules
getUserParams: ( mId, userId, cb ) =>
@log.info "DB | (IdxedMods) #{ @setname }.getUserParams( #{ mId }, #{ userId } )"
- @db.get "#{ @setname }-params:#{ mId }:#{ userId }", ( err, data ) ->
- cb err, data
+ @db.get "#{ @setname }-params:#{ mId }:#{ userId }", cb
getUserParamsIds: ( cb ) =>
@log.info "DB | (IdxedMods) #{ @setname }.getUserParamsIds()"
@@ -322,6 +314,41 @@ class IndexedModules
## Rules
###
+
+###
+Appends a log entry.
+
+@public log( *userId, ruleId, message* )
+@param {String} userId
+@param {String} ruleId
+@param {String} message
+###
+exports.appendLog = ( userId, ruleId, moduleId, message ) =>
+ @db.append "#{ userId }:#{ ruleId }",
+ "[#{ ( new Date ).toISOString() }] {#{ moduleId }} #{ message }\n"
+
+###
+Retrieves a log entry.
+
+@public getLog( *userId, ruleId* )
+@param {String} userId
+@param {String} ruleId
+@param {function} cb
+###
+exports.getLog = ( userId, ruleId, cb ) =>
+ @db.get "#{ userId }:#{ ruleId }", cb
+
+###
+Resets a log entry.
+
+@public resetLog( *userId, ruleId* )
+@param {String} userId
+@param {String} ruleId
+###
+exports.resetLog = ( userId, ruleId ) =>
+ @db.del "#{ userId }:#{ ruleId }",
+ replyHandler "RESET LOG '#{ userId }:#{ ruleId }'"
+
###
Query the DB for a rule and pass it to cb(err, obj).
diff --git a/js-coffee/components-manager.js b/js-coffee/components-manager.js
index f1b93bf..c6e5322 100644
--- a/js-coffee/components-manager.js
+++ b/js-coffee/components-manager.js
@@ -199,31 +199,34 @@ Components Manager
return callback(answ);
} else {
return dbMod.getModule(oPayload.id, function(err, mod) {
- var cm, funcs, id, name, src, _ref;
+ var src;
if (mod) {
answ.code = 409;
- answ.message = 'Event Poller module name already existing: ' + oPayload.id;
+ answ.message = 'Module name already existing: ' + oPayload.id;
+ return callback(answ);
} 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);
+ return dynmod.compileString(src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, function(cm) {
+ var funcs, id, name, _ref;
+ 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);
+ }
}
- _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);
});
}
};
@@ -255,7 +258,45 @@ Components Manager
return forgeModule(user, oPayload, db.actionInvokers, callback);
},
get_rules: function(user, oPayload, callback) {
- return console.log('CM | Implement get_rules');
+ return db.getUserLinkedRules(user.username, function(err, obj) {
+ return callback({
+ code: 200,
+ message: obj
+ });
+ });
+ },
+ get_rule_log: function(user, oPayload, callback) {
+ var answ;
+ answ = hasRequiredParams(['id'], oPayload);
+ if (answ.code !== 200) {
+ return callback(answ);
+ } else {
+ return db.getLog(user.username, oPayload.id, function(err, obj) {
+ return callback({
+ code: 200,
+ message: obj
+ });
+ });
+ }
+ },
+ delete_rule: function(user, oPayload, callback) {
+ var answ;
+ answ = hasRequiredParams(['id'], oPayload);
+ if (answ.code !== 200) {
+ return callback(answ);
+ } else {
+ db.deleteRule(oPayload.id);
+ eventEmitter.emit('rule', {
+ event: 'del',
+ user: user.username,
+ rule: null,
+ ruleId: oPayload.id
+ });
+ return callback({
+ code: 200,
+ message: 'OK!'
+ });
+ }
},
forge_rule: function(user, oPayload, callback) {
var answ;
@@ -297,7 +338,7 @@ Components Manager
});
answ = {
code: 200,
- message: 'Rule stored and activated!'
+ message: "Rule '" + rule.id + "' stored and activated!"
};
}
return callback(answ);
diff --git a/js-coffee/dynamic-modules.js b/js-coffee/dynamic-modules.js
index a6942da..19ae4a0 100644
--- a/js-coffee/dynamic-modules.js
+++ b/js-coffee/dynamic-modules.js
@@ -9,7 +9,9 @@ Dynamic Modules
*/
(function() {
- var cryptico, cs, exports, needle, vm;
+ var cryptico, cs, db, exports, needle, vm;
+
+ db = require('./persistence');
vm = require('vm');
@@ -33,11 +35,12 @@ Dynamic Modules
var numBits, passPhrase;
_this.log = args.logger;
if (!_this.strPublicKey && args['keygen']) {
+ db(args);
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);
+ _this.log.info("DM | Public Key generated: " + _this.strPublicKey);
}
return module.exports;
};
@@ -63,8 +66,8 @@ Dynamic Modules
*/
exports.compileString = (function(_this) {
- return function(src, userId, modId, params, lang) {
- var answ, err, ret, sandbox;
+ return function(src, userId, ruleId, modId, lang, dbMod, cb) {
+ var answ, err, fTryToLoad, logFunction;
answ = {
code: 200,
message: 'Successfully compiled'
@@ -78,25 +81,53 @@ Dynamic Modules
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: {}
+ logFunction = function(uId, rId, mId) {
+ return function(msg) {
+ return db.appendLog(uId, rId, mId, msg);
+ };
};
- try {
- vm.runInNewContext(src, sandbox, sandbox.id);
- } catch (_error) {
- err = _error;
- answ.code = 400;
- answ.message = 'Loading Module failed: ' + err.message;
+ db.resetLog(userId, ruleId);
+ fTryToLoad = function(params) {
+ var oDecrypted, sandbox;
+ if (params) {
+ try {
+ oDecrypted = cryptico.decrypt(params, _this.oPrivateRSAkey);
+ params = JSON.parse(oDecrypted.plaintext);
+ } catch (_error) {
+ err = _error;
+ _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + ruleId + ", " + modId);
+ params = {};
+ }
+ } else {
+ params = {};
+ }
+ sandbox = {
+ id: userId + '.' + modId + '.vm',
+ params: params,
+ needle: needle,
+ log: logFunction(userId, ruleId, modId),
+ exports: {}
+ };
+ try {
+ vm.runInNewContext(src, sandbox, sandbox.id);
+ } catch (_error) {
+ err = _error;
+ console.log(err);
+ answ.code = 400;
+ answ.message = 'Loading Module failed: ' + err.message;
+ }
+ return cb({
+ answ: answ,
+ module: sandbox.exports
+ });
+ };
+ if (dbMod) {
+ return dbMod.getUserParams(modId, userId, function(err, obj) {
+ return fTryToLoad(obj);
+ });
+ } else {
+ return fTryToLoad();
}
- ret = {
- answ: answ,
- module: sandbox.exports
- };
- return ret;
};
})(this);
diff --git a/js-coffee/engine.js b/js-coffee/engine.js
index ce344b1..9b29b5e 100644
--- a/js-coffee/engine.js
+++ b/js-coffee/engine.js
@@ -18,6 +18,27 @@ Engine
jsonQuery = require('js-select');
+
+ /*
+ This is ging to have a structure like:
+ An object of users with their active rules and the required action modules
+ "user-1":
+ "rule-1":
+ "rule": oRule-1
+ "actions":
+ "action-1": oAction-1
+ "action-2": oAction-2
+ "rule-2":
+ "rule": oRule-2
+ "actions":
+ "action-1": oAction-1
+ "user-2":
+ "rule-3":
+ "rule": oRule-3
+ "actions":
+ "action-3": oAction-3
+ */
+
listUserRules = {};
isRunning = false;
@@ -38,7 +59,7 @@ Engine
_this.log = args.logger;
db(args);
dynmod(args);
- pollQueue();
+ setTimeout(pollQueue, 10);
return module.exports;
}
};
@@ -70,20 +91,22 @@ Engine
return function(evt) {
var oRule, oUser;
if (!listUserRules[evt.user] && evt.event !== 'del') {
- listUserRules[evt.user] = {
- rules: {},
- actions: {}
- };
+ listUserRules[evt.user] = {};
}
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 === 'new' || (evt.event === 'init' && !oUser[oRule.id])) {
+ oUser[oRule.id] = {
+ rule: oRule,
+ actions: {}
+ };
+ updateActionModules(oRule.id);
}
if (evt.event === 'del' && oUser) {
- delete oUser.rules[oRule.id];
- return updateActionModules(oRule, true);
+ delete oUser[evt.ruleId];
+ }
+ if (JSON.stringify(oUser) === "{}") {
+ return delete listUserRules[evt.user];
}
};
})(this);
@@ -93,35 +116,29 @@ Engine
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
+ @private updateActionModules ( *updatedRuleId* )
+ @param {Object} updatedRuleId
*/
- updateActionModules = function(oNewRule, isDeleteOp) {
+ updateActionModules = function(updatedRuleId) {
var fAddRequired, fRemoveNotRequired, name, oUser, userName, _results;
fRemoveNotRequired = function(oUser) {
- var action, fRequired, req, _results;
+ var action, fRequired, _results;
fRequired = function(actionName) {
- var action, mod, nmRl, oRl, _i, _len, _ref, _ref1;
- _ref = oUser.rules;
- for (nmRl in _ref) {
- oRl = _ref[nmRl];
- _ref1 = oRl.actions;
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
- action = _ref1[_i];
- mod = (action.split(' -> '))[0];
- if (mod === actionName) {
- return true;
- }
+ var action, _i, _len, _ref;
+ _ref = oUser[updatedRuleId].rule.actions;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ action = _ref[_i];
+ if ((action.split(' -> '))[0] === actionName) {
+ return true;
}
}
return false;
};
_results = [];
- for (action in oUser.actions) {
- req = fRequired(action);
- if (!req) {
- _results.push(delete oUser.actions[action]);
+ for (action in oUser[updatedRuleId].rule.actions) {
+ if (!fRequired(action)) {
+ _results.push(delete oUser[updatedRuleId].actions[action]);
} else {
_results.push(void 0);
}
@@ -133,22 +150,24 @@ Engine
fRemoveNotRequired(oUser);
}
fAddRequired = function(userName, oUser) {
- var fCheckRules, nmRl, oRl, _ref;
- fCheckRules = function(oRule) {
+ var fCheckRules, nmRl, oRl, _results;
+ fCheckRules = function(oMyRule) {
var action, fAddIfNewOrNotExisting, _i, _len, _ref, _results;
fAddIfNewOrNotExisting = function(actionName) {
var moduleName;
moduleName = (actionName.split(' -> '))[0];
- if (!isDeleteOp && (!oUser.actions[moduleName] || oRule.id === oNewRule.id)) {
+ if (!oMyRule.actions[moduleName] || oMyRule.rule.id === updatedRuleId) {
return db.actionInvokers.getModule(moduleName, function(err, obj) {
- var params, res;
- params = {};
- res = dynmod.compileString(obj.data, userName, moduleName, params, obj.lang);
- return oUser.actions[moduleName] = res.module;
+ return dynmod.compileString(obj.data, userName, oMyRule.rule.id, moduleName, obj.lang, db.actionInvokers, function(result) {
+ if (!result.answ === 200) {
+ this.log.error("EN | Compilation of code failed! " + userName + ", " + oMyRule.rule.id + ", " + moduleName);
+ }
+ return oMyRule.actions[moduleName] = result.module;
+ });
});
}
};
- _ref = oRule.actions;
+ _ref = oMyRule.rule.actions;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
action = _ref[_i];
@@ -156,14 +175,12 @@ Engine
}
return _results;
};
- _ref = oUser.rules;
- for (nmRl in _ref) {
- oRl = _ref[nmRl];
- fCheckRules(oRl);
- }
- if (JSON.stringify(oUser.rules) === "{}") {
- return delete listUserRules[userName];
+ _results = [];
+ for (nmRl in oUser) {
+ oRl = oUser[nmRl];
+ _results.push(fCheckRules(oRl));
}
+ return _results;
};
_results = [];
for (userName in listUserRules) {
@@ -195,6 +212,9 @@ Engine
validConditions = function(evt, rule) {
var prop, _i, _len, _ref;
+ if (rule.conditions.length === 0) {
+ return true;
+ }
_ref = rule.conditions;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
prop = _ref[_i];
@@ -215,27 +235,43 @@ Engine
processEvent = (function(_this) {
return function(evt) {
- var action, arr, oRule, oUser, ruleName, userName, _results;
+ var action, arr, fSearchAndInvokeAction, oMyRule, oUser, ruleName, userName, _results;
+ fSearchAndInvokeAction = function(node, arrPath, evt, depth) {
+ var err;
+ if (!node) {
+ this.log.error("EN | Didn't find property in user rule list: " + arrPath.join(', ' + " at depth " + depth));
+ return;
+ }
+ if (depth === arrPath.length) {
+ try {
+ return node(evt.payload);
+ } catch (_error) {
+ err = _error;
+ return this.log.info("EN | ERROR IN ACTION INVOKER: " + err.message);
+ }
+ } else {
+ return fSearchAndInvokeAction(node[arrPath[depth]], arrPath, evt, depth + 1);
+ }
+ };
_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;
+ var _results1;
_results1 = [];
- for (ruleName in _ref) {
- oRule = _ref[ruleName];
- if (evt.event === oRule.event && validConditions(evt, oRule)) {
+ for (ruleName in oUser) {
+ oMyRule = oUser[ruleName];
+ if (evt.event === oMyRule.rule.event && validConditions(evt, oMyRule.rule)) {
this.log.info('EN | EVENT FIRED: ' + evt.event + '(' + evt.eventid + ') for rule ' + ruleName);
_results1.push((function() {
- var _i, _len, _ref1, _results2;
- _ref1 = oRule.actions;
+ var _i, _len, _ref, _results2;
+ _ref = oMyRule.rule.actions;
_results2 = [];
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
- action = _ref1[_i];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ action = _ref[_i];
arr = action.split(' -> ');
- _results2.push(listUserRules[userName]['actions'][arr[0]][arr[1]](evt));
+ _results2.push(fSearchAndInvokeAction(listUserRules, [userName, ruleName, 'actions', arr[0], arr[1]], evt, 0));
}
return _results2;
})());
diff --git a/js-coffee/persistence.js b/js-coffee/persistence.js
index 6ed7f23..d60fd30 100644
--- a/js-coffee/persistence.js
+++ b/js-coffee/persistence.js
@@ -314,7 +314,7 @@ Persistence
};
IndexedModules.prototype.getModuleParams = function(mId, cb) {
- this.log.info("DB | (IdxedMods) " + this.setname + ".getModule( " + mId + " )");
+ this.log.info("DB | (IdxedMods) " + this.setname + ".getModuleParams( " + mId + " )");
return this.db.hget("" + this.setname + ":" + mId, "params", cb);
};
@@ -340,11 +340,15 @@ Persistence
this.unpublish(mId);
return this.db.smembers("" + this.setname + ":" + mId + ":users", (function(_this) {
return function(err, obj) {
- var userId, _i, _len, _results;
- _results = [];
+ var userId, _i, _j, _len, _len1, _results;
for (_i = 0, _len = obj.length; _i < _len; _i++) {
userId = obj[_i];
- _results.push(_this.unlinkModule(mId, userId));
+ _this.unlinkModule(mId, userId);
+ }
+ _results = [];
+ for (_j = 0, _len1 = obj.length; _j < _len1; _j++) {
+ userId = obj[_j];
+ _results.push(_this.deleteUserParams(mId, userId));
}
return _results;
};
@@ -370,9 +374,7 @@ Persistence
IndexedModules.prototype.getUserParams = function(mId, userId, cb) {
this.log.info("DB | (IdxedMods) " + this.setname + ".getUserParams( " + mId + ", " + userId + " )");
- return this.db.get("" + this.setname + "-params:" + mId + ":" + userId, function(err, data) {
- return cb(err, data);
- });
+ return this.db.get("" + this.setname + "-params:" + mId + ":" + userId, cb);
};
IndexedModules.prototype.getUserParamsIds = function(cb) {
@@ -396,6 +398,53 @@ Persistence
*/
+ /*
+ Appends a log entry.
+
+ @public log( *userId, ruleId, message* )
+ @param {String} userId
+ @param {String} ruleId
+ @param {String} message
+ */
+
+ exports.appendLog = (function(_this) {
+ return function(userId, ruleId, moduleId, message) {
+ return _this.db.append("" + userId + ":" + ruleId, "[" + ((new Date).toISOString()) + "] {" + moduleId + "} " + message + "\n");
+ };
+ })(this);
+
+
+ /*
+ Retrieves a log entry.
+
+ @public getLog( *userId, ruleId* )
+ @param {String} userId
+ @param {String} ruleId
+ @param {function} cb
+ */
+
+ exports.getLog = (function(_this) {
+ return function(userId, ruleId, cb) {
+ return _this.db.get("" + userId + ":" + ruleId, cb);
+ };
+ })(this);
+
+
+ /*
+ Resets a log entry.
+
+ @public resetLog( *userId, ruleId* )
+ @param {String} userId
+ @param {String} ruleId
+ */
+
+ exports.resetLog = (function(_this) {
+ return function(userId, ruleId) {
+ return _this.db.del("" + userId + ":" + ruleId, replyHandler("RESET LOG '" + userId + ":" + ruleId + "'"));
+ };
+ })(this);
+
+
/*
Query the DB for a rule and pass it to cb(err, obj).
diff --git a/testing/files/testObjects.json b/testing/files/testObjects.json
index fae6abe..48a0939 100644
--- a/testing/files/testObjects.json
+++ b/testing/files/testObjects.json
@@ -1,27 +1,4 @@
{
- "events": {
- "eventOne":{
- "event": "test_1",
- "payload": {
- "property": "test_1",
- "nestedProperty": {
- "more": "really nested"
- }
- }
- },
- "eventTwo":{
- "event": "test_2"
- },
- "eventReal":{
- "event": "epOne -> newMail",
- "payload": {
- "property": "test_1",
- "nestedProperty": {
- "more": "really nested"
- }
- }
- }
- },
"eps": {
"epOne": {
"id":"epOne",
@@ -44,18 +21,26 @@
"aiOne": {
"id":"aiOne",
"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":"exports.printToLog = ( evt ) ->\n\tlog evt.property",
"public":"false",
"params":"[\"apikey\"]",
- "functions":"[\"sendMail\"]"
+ "functions":"[\"printToLog\"]"
},
"aiTwo": {
"id":"aiTwo",
"lang":"CoffeeScript",
- "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",
+ "data":"# Send a mail through emailyak\nexports.otherEvent = ( evt ) ->\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":"[\"otherEvent\"]"
+ },
+ "aiThree": {
+ "id":"aiThree",
+ "lang":"CoffeeScript",
+ "data":"exports.printUserParamToLog = ( evt ) ->\n\tlog params.password",
+ "public":"false",
+ "params":"[\"password\"]",
+ "functions":"[\"printUserParamToLog\"]"
}
},
"userparams": {
@@ -63,6 +48,29 @@
"apikey": "testkey"
}
},
+ "events": {
+ "eventOne":{
+ "event": "test_1",
+ "payload": {
+ "property": "test_1",
+ "nestedProperty": {
+ "more": "really nested"
+ }
+ }
+ },
+ "eventTwo":{
+ "event": "test_2"
+ },
+ "eventReal":{
+ "event": "epOne -> newMail",
+ "payload": {
+ "property": "test_1",
+ "nestedProperty": {
+ "more": "really nested"
+ }
+ }
+ }
+ },
"rules": {
"ruleOne": {
"id": "ruleOne_id",
@@ -86,13 +94,19 @@
"id": "ruleReal",
"event": "epOne -> newMail",
"conditions": [".more:val(\"really nested\")"],
- "actions": ["aiOne -> sendMail"]
+ "actions": ["aiOne -> printToLog"]
},
"ruleRealTwo": {
"id": "ruleRealTwo",
"event": "epOne -> newMail",
"conditions": [],
"actions": ["aiTwo -> otherEvent"]
+ },
+ "ruleRealThree": {
+ "id": "ruleRealThree",
+ "event": "epOne -> newMail",
+ "conditions": [],
+ "actions": ["aiThree -> printUserParamToLog"]
}
},
"users": {
diff --git a/testing/test_dynamic-modules.coffee b/testing/test_dynamic-modules.coffee
index dd935e8..c2c7c20 100644
--- a/testing/test_dynamic-modules.coffee
+++ b/testing/test_dynamic-modules.coffee
@@ -1,5 +1,11 @@
fs = require 'fs'
path = require 'path'
+cryptico = require 'my-cryptico'
+
+passPhrase = 'UNIT TESTING PASSWORD'
+numBits = 1024
+oPrivateRSAkey = cryptico.generateRSAKey passPhrase, numBits
+strPublicKey = cryptico.publicKeyString oPrivateRSAkey
try
data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8'
@@ -15,27 +21,88 @@ log = logger.getLogger
nolog: true
opts =
logger: log
+ keygen: passPhrase
+
+db = require path.join '..', 'js-coffee', 'persistence'
+db opts
+
+engine = require path.join '..', 'js-coffee', 'engine'
+engine opts
dm = require path.join '..', 'js-coffee', 'dynamic-modules'
dm opts
+oUser = objects.users.userOne
+oRuleReal = objects.rules.ruleRealThree
+oAi = objects.ais.aiThree
+
+exports.tearDown = ( cb ) ->
+ db.storeUser oUser
+ db.deleteRule oRuleReal.id
+ db.actionInvokers.deleteModule oAi.id
+ setTimeout cb, 200
+
exports.testCompile = ( test ) ->
test.expect 5
- paramsOne =
- testParam: 'First Test'
- paramsTwo =
- testParam: 'Second Test'
+ paramOne = 'First Test'
+ code = "exports.testFunc = () ->\n\t'#{ paramOne }'"
+ dm.compileString code, 'userOne', 'ruleOne', 'moduleOne', 'CoffeeScript', null, ( result ) ->
+ test.strictEqual 200, result.answ.code
+ moduleOne = result.module
+ test.strictEqual paramOne, moduleOne.testFunc(), "Other result expected"
- code = "exports.testFunc = () ->\n\tparams.testParam"
- result = dm.compileString code, 'userOne', 'moduleOne', paramsOne, 'CoffeeScript'
- test.strictEqual 200, result.answ.code
- moduleOne = result.module
- test.strictEqual paramsOne.testParam, moduleOne.testFunc(), "Other result expected"
+ paramTwo = 'Second Test'
+ code = "exports.testFunc = () ->\n\t'#{ paramTwo }'"
+ dm.compileString code, 'userOne', 'ruleOne', 'moduleOne', 'CoffeeScript', null, ( result ) ->
+ test.strictEqual 200, result.answ.code
+ moduleTwo = result.module
+ test.strictEqual paramTwo, moduleTwo.testFunc(), "Other result expected"
+ test.notStrictEqual paramOne, moduleTwo.testFunc(), "Other result expected"
+ setTimeout test.done, 200
+
+
+exports.testCorrectUserParams = ( test ) ->
+ test.expect 1
+
+ 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, oAi
+
+ pw = 'This password should come out cleartext'
+ userparams = JSON.stringify password: pw
+ oEncrypted = cryptico.encrypt userparams, strPublicKey
+
+ db.actionInvokers.storeUserParams oAi.id, oUser.username, oEncrypted.cipher
+
+ engine.internalEvent
+ event: 'new'
+ user: oUser.username
+ rule: oRuleReal
+
+ fWaitForPersistence = () ->
+ evt = objects.events.eventReal
+ evt.eventid = 'event_testid'
+ db.pushEvent evt
+
+ fWaitAgain = () ->
+ db.getLog oUser.username, oRuleReal.id, ( err, data ) ->
+ try
+ logged = data.split( '] ' )[1]
+ test.strictEqual logged, "{#{ oAi.id }} " + pw + "\n", 'Did not log the right thing'
+ catch e
+ test.ok false, 'Parsing log failed'
+
+ engine.internalEvent
+ event: 'del'
+ user: oUser.username
+ rule: null
+ ruleId: oRuleReal.id
+ setTimeout test.done, 200
+
+ setTimeout fWaitAgain, 200
+
+ setTimeout fWaitForPersistence, 200
- result = dm.compileString code, 'userOne', 'moduleOne', paramsTwo, 'CoffeeScript'
- test.strictEqual 200, result.answ.code
- moduleTwo = result.module
- test.strictEqual paramsTwo.testParam, moduleTwo.testFunc(), "Other result expected"
- test.notStrictEqual paramsOne.testParam, moduleTwo.testFunc(), "Other result expected"
- test.done()
\ No newline at end of file
diff --git a/testing/test_engine.coffee b/testing/test_engine.coffee
index a43a74b..f240a33 100644
--- a/testing/test_engine.coffee
+++ b/testing/test_engine.coffee
@@ -11,8 +11,8 @@ catch err
console.log 'Error fetching standard objects file: ' + err.message
logger = require path.join '..', 'js-coffee', 'logging'
-log = logger.getLogger()
- # nolog: true
+log = logger.getLogger
+ nolog: true
opts =
logger: log
@@ -61,7 +61,7 @@ exports.ruleEvents =
db.actionInvokers.storeModule oUser.username, oAiTwo
test.strictEqual listRules[oUser.username], undefined, 'Initial user object exists!?'
-
+
engine.internalEvent
event: 'new'
user: oUser.username
@@ -71,7 +71,8 @@ exports.ruleEvents =
for act in oRuleReal.actions
mod = ( act.split ' -> ' )[0]
- test.ok listRules[oUser.username].actions[mod], 'Missing action!'
+ test.ok listRules[oUser.username][oRuleReal.id].actions[mod], 'Missing action!'
+
engine.internalEvent
event: 'new'
@@ -82,21 +83,23 @@ exports.ruleEvents =
for act in oRuleRealTwo.actions
mod = ( act.split ' -> ' )[0]
- test.ok listRules[oUser.username].actions[mod], 'Missing action!'
-
+ test.ok listRules[oUser.username][oRuleRealTwo.id].actions[mod], 'Missing action!'
+
engine.internalEvent
event: 'del'
user: oUser.username
- rule: oRuleRealTwo
+ rule: null
+ ruleId: oRuleRealTwo.id
for act in oRuleReal.actions
mod = ( act.split ' -> ' )[0]
- test.ok listRules[oUser.username].actions[mod], 'Missing action!'
-
+ test.ok listRules[oUser.username][oRuleReal.id].actions[mod], 'Missing action!'
+
engine.internalEvent
event: 'del'
user: oUser.username
- rule: oRuleReal
+ rule: null
+ ruleId: oRuleReal.id
test.strictEqual listRules[oUser.username], undefined, 'Final user object exists!?'
test.done()
@@ -135,7 +138,8 @@ exports.ruleEvents =
# setTimeout fCheckRules, 500
exports.engine =
- matchingEvent: ( test ) ->
+ testMatchingEvent: ( test ) ->
+ test.expect 1
db.storeUser oUser
db.storeRule oRuleReal.id, JSON.stringify oRuleReal
@@ -152,6 +156,16 @@ exports.engine =
evt = objects.events.eventReal
evt.eventid = 'event_testid'
db.pushEvent evt
- setTimeout fWaitForPersistence, 200
- setTimeout test.done, 500
+ fWaitAgain = () ->
+ db.getLog oUser.username, oRuleReal.id, ( err, data ) ->
+ try
+ logged = data.split( '] ' )[1]
+ test.strictEqual logged, "{#{ oAiOne.id }} " + evt.payload.property + "\n", 'Did not log the right thing'
+ catch e
+ test.ok false, 'Parsing log failed'
+ test.done()
+
+ setTimeout fWaitAgain, 200
+
+ setTimeout fWaitForPersistence, 200
diff --git a/webpages/handlers/coffee/admin.coffee b/webpages/handlers/coffee/admin.coffee
index d034aca..b2d33c4 100644
--- a/webpages/handlers/coffee/admin.coffee
+++ b/webpages/handlers/coffee/admin.coffee
@@ -3,18 +3,20 @@ fOnLoad = () ->
document.title = 'Administrate'
$( '#pagetitle' ).text 'Hi {{{user.username}}}, issue your commands please:'
$( '#but_submit' ).click () ->
- data =
- command: $( '#inp_command' ).val()
- $.post( 'admincommand', data )
- .done ( data ) ->
- $( '#info' ).text data.message
- $( '#info' ).attr 'class', 'success'
- .fail ( err ) ->
- if err.responseText is ''
- err.responseText = 'No Response from Server!'
- $( '#info' ).text 'Error: ' + err.responseText
- $( '#info' ).attr 'class', 'error'
- if err.status is 401
- window.location.href = 'admin'
+ data =
+ command: $( '#inp_command' ).val()
+ $.post( 'admincommand', data )
+ .done ( data ) ->
+ $( '#info' ).text data.message
+ $( '#info' ).attr 'class', 'success'
+ .fail ( err ) ->
+ fDelayed = () ->
+ if err.responseText is ''
+ err.responseText = 'No Response from Server!'
+ $( '#info' ).text 'Error: ' + err.responseText
+ $( '#info' ).attr 'class', 'error'
+ if err.status is 401
+ window.location.href = 'admin'
+ setTimeout fDelayed, 500
window.addEventListener 'load', fOnLoad, true
diff --git a/webpages/handlers/coffee/edit_rules.coffee b/webpages/handlers/coffee/edit_rules.coffee
new file mode 100644
index 0000000..29fd81b
--- /dev/null
+++ b/webpages/handlers/coffee/edit_rules.coffee
@@ -0,0 +1,63 @@
+
+fOnLoad = () ->
+ document.title = 'Edit Rules'
+ $( '#pagetitle' ).text "{{{user.username}}}, edit your Rules!"
+
+ fErrHandler = ( errMsg ) ->
+ ( err ) ->
+ fDelayed = () ->
+ if err.responseText is ''
+ msg = 'No Response from Server!'
+ else
+ try
+ oErr = JSON.parse err.responseText
+ msg = oErr.message
+ $( '#info' ).text errMsg + msg
+ $( '#info' ).attr 'class', 'error'
+ setTimeout fDelayed, 500
+
+ fFetchRules = () ->
+ $.post( '/usercommand', command: 'get_rules' )
+ .done fUpdateRuleList
+ .fail fErrHandler 'Did not retrieve rules! '
+
+ fUpdateRuleList = ( data ) ->
+ $( '#tableRules tr' ).remove()
+ for ruleName in data.message
+ tr = $ '
'
+ img = $( '
' ).attr( 'class', 'del' ).attr 'src', 'red_cross_small.png'
+ imgTwo = $( '
' ).attr( 'class', 'log' ).attr 'src', 'logicon.png'
+ inp = $( '' ).text ruleName
+ tr.append( $( '
' ).append img )
+ tr.append( $( ' | ' ).append imgTwo )
+ tr.append( $( ' | ' ).append inp )
+ $( '#tableRules' ).append tr
+
+ fFetchRules()
+
+ $( '#tableRules' ).on 'click', 'img.del', () ->
+ ruleName = $( 'div', $( this ).closest( 'tr' )).text()
+ if confirm "Do you really want to delete the rule '#{ ruleName }'?"
+ data =
+ command: 'delete_rule'
+ payload:
+ id: ruleName
+ data.payload = JSON.stringify data.payload
+ $.post( '/usercommand', data )
+ .done fFetchRules
+ .fail fErrHandler 'Could not delete rule! '
+
+ $( '#tableRules' ).on 'click', 'img.log', () ->
+ ruleName = $( 'div', $( this ).closest( 'tr' )).text()
+ data =
+ command: 'get_rule_log'
+ payload:
+ id: ruleName
+ data.payload = JSON.stringify data.payload
+ $.post( '/usercommand', data )
+ .done ( data ) ->
+ log = data.message.replace new RegExp("\n", 'g'), " "
+ $( '#log_col' ).html "#{ ruleName } Log:#{ log }"
+ .fail fErrHandler 'Could not get rule log! '
+
+window.addEventListener 'load', fOnLoad, true
diff --git a/webpages/handlers/coffee/forge_action_invoker.coffee b/webpages/handlers/coffee/forge_action_invoker.coffee
index 0380058..9e94f0f 100644
--- a/webpages/handlers/coffee/forge_action_invoker.coffee
+++ b/webpages/handlers/coffee/forge_action_invoker.coffee
@@ -68,15 +68,17 @@ fOnLoad = () ->
$( '#info' ).text data.message
$( '#info' ).attr 'class', 'success'
.fail ( err ) ->
- if err.responseText is ''
- msg = 'No Response from Server!'
- else
- try
- oErr = JSON.parse err.responseText
- msg = oErr.message
- $( '#info' ).text 'Action Invoker not stored! ' + msg
- $( '#info' ).attr 'class', 'error'
- if err.status is 401
- window.location.href = 'forge?page=forge_action_invoker'
+ fDelayed = () ->
+ if err.responseText is ''
+ msg = 'No Response from Server!'
+ else
+ try
+ oErr = JSON.parse err.responseText
+ msg = oErr.message
+ $( '#info' ).text 'Action Invoker not stored! ' + msg
+ $( '#info' ).attr 'class', 'error'
+ if err.status is 401
+ window.location.href = 'forge?page=forge_action_invoker'
+ setTimeout fDelayed, 500
window.addEventListener 'load', fOnLoad, true
diff --git a/webpages/handlers/coffee/forge_event.coffee b/webpages/handlers/coffee/forge_event.coffee
index a627521..30535d2 100644
--- a/webpages/handlers/coffee/forge_event.coffee
+++ b/webpages/handlers/coffee/forge_event.coffee
@@ -20,12 +20,15 @@ fOnLoad = () ->
$( '#info' ).text data.message
$( '#info' ).attr 'class', 'success'
.fail ( err ) ->
- if err.responseText is ''
- err.responseText = 'No Response from Server!'
- $( '#info' ).text 'Error in upload: ' + err.responseText
- $( '#info' ).attr 'class', 'error'
- if err.status is 401
- window.location.href = 'forge?page=forge_event'
+ fDelayed = () ->
+ if err.responseText is ''
+ err.responseText = 'No Response from Server!'
+ $( '#info' ).text 'Error in upload: ' + err.responseText
+ $( '#info' ).attr 'class', 'error'
+ if err.status is 401
+ window.location.href = 'forge?page=forge_event'
+ setTimeout fDelayed, 500
+
catch err
$( '#info' ).text 'You have errors in your JSON object! ' + err
$( '#info' ).attr 'class', 'error'
diff --git a/webpages/handlers/coffee/forge_event_poller.coffee b/webpages/handlers/coffee/forge_event_poller.coffee
index 3b31051..2deb55e 100644
--- a/webpages/handlers/coffee/forge_event_poller.coffee
+++ b/webpages/handlers/coffee/forge_event_poller.coffee
@@ -68,15 +68,17 @@ fOnLoad = () ->
$( '#info' ).text data.message
$( '#info' ).attr 'class', 'success'
.fail ( err ) ->
- if err.responseText is ''
- msg = 'No Response from Server!'
- else
- try
- oErr = JSON.parse err.responseText
- msg = oErr.message
- $( '#info' ).text 'Event Poller not stored! ' + msg
- $( '#info' ).attr 'class', 'error'
- if err.status is 401
- window.location.href = 'forge?page=forge_event_poller'
+ fDelayed = () ->
+ if err.responseText is ''
+ msg = 'No Response from Server!'
+ else
+ try
+ oErr = JSON.parse err.responseText
+ msg = oErr.message
+ $( '#info' ).text 'Event Poller not stored! ' + msg
+ $( '#info' ).attr 'class', 'error'
+ if err.status is 401
+ window.location.href = 'forge?page=forge_event_poller'
+ setTimeout fDelayed, 500
window.addEventListener 'load', fOnLoad, true
diff --git a/webpages/handlers/coffee/forge_rule.coffee b/webpages/handlers/coffee/forge_rule.coffee
index 80b3b2f..a61b6d1 100644
--- a/webpages/handlers/coffee/forge_rule.coffee
+++ b/webpages/handlers/coffee/forge_rule.coffee
@@ -14,32 +14,35 @@ fOnLoad = () ->
# Fetch Event Poller user-specific parameters
fFetchEventParams = ( name ) ->
- arr = name.split ' -> '
- obj =
- command: 'get_event_poller_params'
- payload:
- id: arr[0]
- obj.payload = JSON.stringify( obj.payload );
- $.post( '/usercommand', obj )
- .done ( data ) ->
- if data.message
- arrParams = JSON.parse data.message
- $( '#event_poller_params table' ).remove()
- if arrParams.length > 0
- table = $ ''
- $( '#event_poller_params' ).append table
- fAppendParam = ( name ) ->
- tr = $( '' )
- tr.append $( '| ' ).css 'width', '20px'
- tr.append $( ' | ' ).attr( 'class', 'key' ).text name
- inp = $( '' ).attr( 'type', 'password' ).attr 'id', "#{ name }"
- tr.append $( ' | ' ).text( ' :' ).append inp
- table.append tr
- fAppendParam name for name in arrParams
- .fail ( err ) ->
- console.log err
- $( '#info' ).text 'Error fetching event poller params'
- $( '#info' ).attr 'class', 'error'
+ if name
+ arr = name.split ' -> '
+ obj =
+ command: 'get_event_poller_params'
+ payload:
+ id: arr[0]
+ obj.payload = JSON.stringify( obj.payload );
+ $.post( '/usercommand', obj )
+ .done ( data ) ->
+ if data.message
+ arrParams = JSON.parse data.message
+ $( '#event_poller_params table' ).remove()
+ if arrParams.length > 0
+ table = $ ''
+ $( '#event_poller_params' ).append table
+ fAppendParam = ( name ) ->
+ tr = $( '' )
+ tr.append $( '| ' ).css 'width', '20px'
+ tr.append $( ' | ' ).attr( 'class', 'key' ).text name
+ inp = $( '' ).attr( 'type', 'password' ).attr 'id', "#{ name }"
+ tr.append $( ' | ' ).text( ' :' ).append inp
+ table.append tr
+ fAppendParam name for name in arrParams
+ .fail ( err ) ->
+ fDelayed = () ->
+ console.log err
+ $( '#info' ).text 'Error fetching event poller params'
+ $( '#info' ).attr 'class', 'error'
+ setTimeout fDelayed, 500
#FIXME Add possibility for custom event via text input
@@ -65,9 +68,11 @@ fOnLoad = () ->
fAppendEvents id, events for id, events of oEps
fFetchEventParams $( '#select_event option:selected' ).text()
.fail ( err ) ->
- console.log err
- $( '#info' ).text 'Error fetching event poller'
- $( '#info' ).attr 'class', 'error'
+ fDelayed = () ->
+ console.log err
+ $( '#info' ).text 'Error fetching event poller'
+ $( '#info' ).attr 'class', 'error'
+ setTimeout fDelayed, 500
$( '#select_event' ).change () ->
fFetchEventParams $( this ).val()
@@ -91,10 +96,12 @@ fOnLoad = () ->
fAppendAction act for act in actions
fAppendActions id, actions for id, actions of oAis
- .fail ( err ) ->
+ .fail ( err ) ->
console.log err
- $( '#info' ).text 'Error fetching event poller'
- $( '#info' ).attr 'class', 'error'
+ fDelayed = () ->
+ $( '#info' ).text 'Error fetching event poller'
+ $( '#info' ).attr 'class', 'error'
+ setTimeout fDelayed, 500
# Fetch Action Invoker user-specific parameters
fFetchActionParams = ( div, name ) ->
@@ -119,8 +126,10 @@ fOnLoad = () ->
fAppendActionParam name for name in arrParams
.fail ( err ) ->
console.log err
- $( '#info' ).text 'Error fetching action invoker params'
- $( '#info' ).attr 'class', 'error'
+ fDelayed = () ->
+ $( '#info' ).text 'Error fetching action invoker params'
+ $( '#info' ).attr 'class', 'error'
+ setTimeout fDelayed, 500
$( '#select_actions' ).on 'change', () ->
opt = $ 'option:selected', this
@@ -201,26 +210,27 @@ fOnLoad = () ->
id: $( '#input_id' ).val()
event: $( '#select_event option:selected' ).val()
event_params: encryptedParams.cipher
- conditions: {} #TODO Add conditions!
+ conditions: [] #TODO Add conditions!
actions: acts
action_params: ap
obj.payload = JSON.stringify obj.payload
$.post( '/usercommand', obj )
.done ( data ) ->
- console.log 'success'
$( '#info' ).text data.message
$( '#info' ).attr 'class', 'success'
.fail ( err ) ->
- if err.responseText is ''
- msg = 'No Response from Server!'
- else
- try
- oErr = JSON.parse err.responseText
- msg = oErr.message
- $( '#info' ).text 'Error in upload: ' + msg
- $( '#info' ).attr 'class', 'error'
- if err.status is 401
- window.location.href = 'forge?page=forge_rule'
+ fDelayed = () ->
+ if err.responseText is ''
+ msg = 'No Response from Server!'
+ else
+ try
+ oErr = JSON.parse err.responseText
+ msg = oErr.message
+ $( '#info' ).text 'Error in upload: ' + msg
+ $( '#info' ).attr 'class', 'error'
+ if err.status is 401
+ window.location.href = 'forge?page=forge_rule'
+ setTimeout fDelayed, 500
catch err
alert err.message
diff --git a/webpages/handlers/js/admin.js b/webpages/handlers/js/admin.js
index 8d7b0aa..bb5fcec 100644
--- a/webpages/handlers/js/admin.js
+++ b/webpages/handlers/js/admin.js
@@ -14,14 +14,18 @@
$('#info').text(data.message);
return $('#info').attr('class', 'success');
}).fail(function(err) {
- if (err.responseText === '') {
- err.responseText = 'No Response from Server!';
- }
- $('#info').text('Error: ' + err.responseText);
- $('#info').attr('class', 'error');
- if (err.status === 401) {
- return window.location.href = 'admin';
- }
+ var fDelayed;
+ fDelayed = function() {
+ if (err.responseText === '') {
+ err.responseText = 'No Response from Server!';
+ }
+ $('#info').text('Error: ' + err.responseText);
+ $('#info').attr('class', 'error');
+ if (err.status === 401) {
+ return window.location.href = 'admin';
+ }
+ };
+ return setTimeout(fDelayed, 500);
});
});
};
diff --git a/webpages/handlers/js/edit_rules.js b/webpages/handlers/js/edit_rules.js
new file mode 100644
index 0000000..b535ea4
--- /dev/null
+++ b/webpages/handlers/js/edit_rules.js
@@ -0,0 +1,86 @@
+// Generated by CoffeeScript 1.7.1
+(function() {
+ var fOnLoad;
+
+ fOnLoad = function() {
+ var fErrHandler, fFetchRules, fUpdateRuleList;
+ document.title = 'Edit Rules';
+ $('#pagetitle').text("{{{user.username}}}, edit your Rules!");
+ fErrHandler = function(errMsg) {
+ return function(err) {
+ var fDelayed;
+ fDelayed = function() {
+ var msg, oErr;
+ if (err.responseText === '') {
+ msg = 'No Response from Server!';
+ } else {
+ try {
+ oErr = JSON.parse(err.responseText);
+ msg = oErr.message;
+ } catch (_error) {}
+ }
+ $('#info').text(errMsg + msg);
+ return $('#info').attr('class', 'error');
+ };
+ return setTimeout(fDelayed, 500);
+ };
+ };
+ fFetchRules = function() {
+ return $.post('/usercommand', {
+ command: 'get_rules'
+ }).done(fUpdateRuleList).fail(fErrHandler('Did not retrieve rules! '));
+ };
+ fUpdateRuleList = function(data) {
+ var img, imgTwo, inp, ruleName, tr, _i, _len, _ref, _results;
+ $('#tableRules tr').remove();
+ _ref = data.message;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ ruleName = _ref[_i];
+ tr = $(' | ');
+ img = $(' ').attr('class', 'del').attr('src', 'red_cross_small.png');
+ imgTwo = $(' ').attr('class', 'log').attr('src', 'logicon.png');
+ inp = $('').text(ruleName);
+ tr.append($(' ').append(img));
+ tr.append($(' | ').append(imgTwo));
+ tr.append($(' | ').append(inp));
+ _results.push($('#tableRules').append(tr));
+ }
+ return _results;
+ };
+ fFetchRules();
+ $('#tableRules').on('click', 'img.del', function() {
+ var data, ruleName;
+ ruleName = $('div', $(this).closest('tr')).text();
+ if (confirm("Do you really want to delete the rule '" + ruleName + "'?")) {
+ data = {
+ command: 'delete_rule',
+ payload: {
+ id: ruleName
+ }
+ };
+ data.payload = JSON.stringify(data.payload);
+ return $.post('/usercommand', data).done(fFetchRules).fail(fErrHandler('Could not delete rule! '));
+ }
+ });
+ return $('#tableRules').on('click', 'img.log', function() {
+ var data, ruleName;
+ ruleName = $('div', $(this).closest('tr')).text();
+ data = {
+ command: 'get_rule_log',
+ payload: {
+ id: ruleName
+ }
+ };
+ data.payload = JSON.stringify(data.payload);
+ return $.post('/usercommand', data).done(function(data) {
+ var log;
+ log = data.message.replace(new RegExp("\n", 'g'), " ");
+ return $('#log_col').html("" + ruleName + " Log:" + log);
+ }).fail(fErrHandler('Could not get rule log! '));
+ });
+ };
+
+ window.addEventListener('load', fOnLoad, true);
+
+}).call(this);
diff --git a/webpages/handlers/js/forge_action_invoker.js b/webpages/handlers/js/forge_action_invoker.js
index 0ff2b84..d691c54 100644
--- a/webpages/handlers/js/forge_action_invoker.js
+++ b/webpages/handlers/js/forge_action_invoker.js
@@ -80,20 +80,24 @@
$('#info').text(data.message);
return $('#info').attr('class', 'success');
}).fail(function(err) {
- var msg, oErr;
- if (err.responseText === '') {
- msg = 'No Response from Server!';
- } else {
- try {
- oErr = JSON.parse(err.responseText);
- msg = oErr.message;
- } catch (_error) {}
- }
- $('#info').text('Action Invoker not stored! ' + msg);
- $('#info').attr('class', 'error');
- if (err.status === 401) {
- return window.location.href = 'forge?page=forge_action_invoker';
- }
+ var fDelayed;
+ fDelayed = function() {
+ var msg, oErr;
+ if (err.responseText === '') {
+ msg = 'No Response from Server!';
+ } else {
+ try {
+ oErr = JSON.parse(err.responseText);
+ msg = oErr.message;
+ } catch (_error) {}
+ }
+ $('#info').text('Action Invoker not stored! ' + msg);
+ $('#info').attr('class', 'error');
+ if (err.status === 401) {
+ return window.location.href = 'forge?page=forge_action_invoker';
+ }
+ };
+ return setTimeout(fDelayed, 500);
});
}
});
diff --git a/webpages/handlers/js/forge_event.js b/webpages/handlers/js/forge_event.js
index 4951d18..7f6670c 100644
--- a/webpages/handlers/js/forge_event.js
+++ b/webpages/handlers/js/forge_event.js
@@ -21,14 +21,18 @@
$('#info').text(data.message);
return $('#info').attr('class', 'success');
}).fail(function(err) {
- if (err.responseText === '') {
- err.responseText = 'No Response from Server!';
- }
- $('#info').text('Error in upload: ' + err.responseText);
- $('#info').attr('class', 'error');
- if (err.status === 401) {
- return window.location.href = 'forge?page=forge_event';
- }
+ var fDelayed;
+ fDelayed = function() {
+ if (err.responseText === '') {
+ err.responseText = 'No Response from Server!';
+ }
+ $('#info').text('Error in upload: ' + err.responseText);
+ $('#info').attr('class', 'error');
+ if (err.status === 401) {
+ return window.location.href = 'forge?page=forge_event';
+ }
+ };
+ return setTimeout(fDelayed, 500);
});
} catch (_error) {
err = _error;
diff --git a/webpages/handlers/js/forge_event_poller.js b/webpages/handlers/js/forge_event_poller.js
index 28e3262..fb8c640 100644
--- a/webpages/handlers/js/forge_event_poller.js
+++ b/webpages/handlers/js/forge_event_poller.js
@@ -80,20 +80,24 @@
$('#info').text(data.message);
return $('#info').attr('class', 'success');
}).fail(function(err) {
- var msg, oErr;
- if (err.responseText === '') {
- msg = 'No Response from Server!';
- } else {
- try {
- oErr = JSON.parse(err.responseText);
- msg = oErr.message;
- } catch (_error) {}
- }
- $('#info').text('Event Poller not stored! ' + msg);
- $('#info').attr('class', 'error');
- if (err.status === 401) {
- return window.location.href = 'forge?page=forge_event_poller';
- }
+ var fDelayed;
+ fDelayed = function() {
+ var msg, oErr;
+ if (err.responseText === '') {
+ msg = 'No Response from Server!';
+ } else {
+ try {
+ oErr = JSON.parse(err.responseText);
+ msg = oErr.message;
+ } catch (_error) {}
+ }
+ $('#info').text('Event Poller not stored! ' + msg);
+ $('#info').attr('class', 'error');
+ if (err.status === 401) {
+ return window.location.href = 'forge?page=forge_event_poller';
+ }
+ };
+ return setTimeout(fDelayed, 500);
});
}
});
diff --git a/webpages/handlers/js/forge_rule.js b/webpages/handlers/js/forge_rule.js
index 3fed0f6..0658d62 100644
--- a/webpages/handlers/js/forge_rule.js
+++ b/webpages/handlers/js/forge_rule.js
@@ -20,44 +20,50 @@
$('#pagetitle').text('{{{user.username}}}, forge your rule!');
fFetchEventParams = function(name) {
var arr, obj;
- arr = name.split(' -> ');
- obj = {
- command: 'get_event_poller_params',
- payload: {
- id: arr[0]
- }
- };
- obj.payload = JSON.stringify(obj.payload);
- return $.post('/usercommand', obj).done(function(data) {
- var arrParams, fAppendParam, table, _i, _len, _results;
- if (data.message) {
- arrParams = JSON.parse(data.message);
- $('#event_poller_params table').remove();
- if (arrParams.length > 0) {
- table = $('');
- $('#event_poller_params').append(table);
- fAppendParam = function(name) {
- var inp, tr;
- tr = $('');
- tr.append($('| ').css('width', '20px'));
- tr.append($(' | ').attr('class', 'key').text(name));
- inp = $('').attr('type', 'password').attr('id', "" + name);
- tr.append($(' | ').text(' :').append(inp));
- return table.append(tr);
- };
- _results = [];
- for (_i = 0, _len = arrParams.length; _i < _len; _i++) {
- name = arrParams[_i];
- _results.push(fAppendParam(name));
- }
- return _results;
+ if (name) {
+ arr = name.split(' -> ');
+ obj = {
+ command: 'get_event_poller_params',
+ payload: {
+ id: arr[0]
}
- }
- }).fail(function(err) {
- console.log(err);
- $('#info').text('Error fetching event poller params');
- return $('#info').attr('class', 'error');
- });
+ };
+ obj.payload = JSON.stringify(obj.payload);
+ return $.post('/usercommand', obj).done(function(data) {
+ var arrParams, fAppendParam, table, _i, _len, _results;
+ if (data.message) {
+ arrParams = JSON.parse(data.message);
+ $('#event_poller_params table').remove();
+ if (arrParams.length > 0) {
+ table = $('');
+ $('#event_poller_params').append(table);
+ fAppendParam = function(name) {
+ var inp, tr;
+ tr = $('');
+ tr.append($('| ').css('width', '20px'));
+ tr.append($(' | ').attr('class', 'key').text(name));
+ inp = $('').attr('type', 'password').attr('id', "" + name);
+ tr.append($(' | ').text(' :').append(inp));
+ return table.append(tr);
+ };
+ _results = [];
+ for (_i = 0, _len = arrParams.length; _i < _len; _i++) {
+ name = arrParams[_i];
+ _results.push(fAppendParam(name));
+ }
+ return _results;
+ }
+ }
+ }).fail(function(err) {
+ var fDelayed;
+ fDelayed = function() {
+ console.log(err);
+ $('#info').text('Error fetching event poller params');
+ return $('#info').attr('class', 'error');
+ };
+ return setTimeout(fDelayed, 500);
+ });
+ }
};
obj = {
command: 'get_event_pollers'
@@ -89,9 +95,13 @@
}
return fFetchEventParams($('#select_event option:selected').text());
}).fail(function(err) {
- console.log(err);
- $('#info').text('Error fetching event poller');
- return $('#info').attr('class', 'error');
+ var fDelayed;
+ fDelayed = function() {
+ console.log(err);
+ $('#info').text('Error fetching event poller');
+ return $('#info').attr('class', 'error');
+ };
+ return setTimeout(fDelayed, 500);
});
$('#select_event').change(function() {
return fFetchEventParams($(this).val());
@@ -130,9 +140,13 @@
}
return _results;
}).fail(function(err) {
+ var fDelayed;
console.log(err);
- $('#info').text('Error fetching event poller');
- return $('#info').attr('class', 'error');
+ fDelayed = function() {
+ $('#info').text('Error fetching event poller');
+ return $('#info').attr('class', 'error');
+ };
+ return setTimeout(fDelayed, 500);
});
fFetchActionParams = function(div, name) {
obj = {
@@ -166,9 +180,13 @@
}
}
}).fail(function(err) {
+ var fDelayed;
console.log(err);
- $('#info').text('Error fetching action invoker params');
- return $('#info').attr('class', 'error');
+ fDelayed = function() {
+ $('#info').text('Error fetching action invoker params');
+ return $('#info').attr('class', 'error');
+ };
+ return setTimeout(fDelayed, 500);
});
};
$('#select_actions').on('change', function() {
@@ -258,31 +276,34 @@
id: $('#input_id').val(),
event: $('#select_event option:selected').val(),
event_params: encryptedParams.cipher,
- conditions: {},
+ conditions: [],
actions: acts,
action_params: ap
}
};
obj.payload = JSON.stringify(obj.payload);
return $.post('/usercommand', obj).done(function(data) {
- console.log('success');
$('#info').text(data.message);
return $('#info').attr('class', 'success');
}).fail(function(err) {
- var msg, oErr;
- if (err.responseText === '') {
- msg = 'No Response from Server!';
- } else {
- try {
- oErr = JSON.parse(err.responseText);
- msg = oErr.message;
- } catch (_error) {}
- }
- $('#info').text('Error in upload: ' + msg);
- $('#info').attr('class', 'error');
- if (err.status === 401) {
- return window.location.href = 'forge?page=forge_rule';
- }
+ var fDelayed;
+ fDelayed = function() {
+ var msg, oErr;
+ if (err.responseText === '') {
+ msg = 'No Response from Server!';
+ } else {
+ try {
+ oErr = JSON.parse(err.responseText);
+ msg = oErr.message;
+ } catch (_error) {}
+ }
+ $('#info').text('Error in upload: ' + msg);
+ $('#info').attr('class', 'error');
+ if (err.status === 401) {
+ return window.location.href = 'forge?page=forge_rule';
+ }
+ };
+ return setTimeout(fDelayed, 500);
});
} catch (_error) {
err = _error;
diff --git a/webpages/handlers/templates/edit_rules.html b/webpages/handlers/templates/edit_rules.html
new file mode 100644
index 0000000..57b4f93
--- /dev/null
+++ b/webpages/handlers/templates/edit_rules.html
@@ -0,0 +1,12 @@
+
+
+
+ Active Rules:
+
+ |
+ |
+
+
+ |
+
+
\ No newline at end of file
diff --git a/webpages/handlers/templates/forge_action_invoker.html b/webpages/handlers/templates/forge_action_invoker.html
index e59caba..a7ab17f 100644
--- a/webpages/handlers/templates/forge_action_invoker.html
+++ b/webpages/handlers/templates/forge_action_invoker.html
@@ -21,7 +21,7 @@ Action Invoker Name:
# - company: The ProBidner company of the binder
# - context: The ProBinder context (the binder ID)
#
-exports.createBinderEntry = ( args ) ->
+exports.createBinderEntry = ( evt ) ->
url = 'https://probinder.com/service/27/save'
credentials =
@@ -29,9 +29,9 @@ exports.createBinderEntry = ( args ) ->
password: params.password
data =
- companyId: args.company
- context: args.context
- text: args.content
+ companyId: evt.company
+ context: evt.context
+ text: evt.content
needle.post url, data, credentials, ( err, resp, body ) ->
if err
diff --git a/webpages/handlers/templates/menubar.html b/webpages/handlers/templates/menubar.html
index e4eedd7..303d8dd 100644
--- a/webpages/handlers/templates/menubar.html
+++ b/webpages/handlers/templates/menubar.html
@@ -14,9 +14,6 @@
menubar.append(link);
};
- fCreateLink( 'invoke event',
- fRedirect( 'forge?page=forge_event' )
- );
fCreateLink( 'forge event poller',
fRedirect( 'forge?page=forge_event_poller' )
);
@@ -26,6 +23,12 @@
fCreateLink( 'forge rule',
fRedirect( 'forge?page=forge_rule' )
);
+ fCreateLink( 'invoke event',
+ fRedirect( 'forge?page=forge_event' )
+ );
+ fCreateLink( 'edit rules',
+ fRedirect( 'forge?page=edit_rules' )
+ );
fCreateLink( 'admin', fRedirect( 'admin' ) );
fCreateLink( 'logout', function() {
diff --git a/webpages/public/cross.jpg b/webpages/public/cross.jpg
deleted file mode 100644
index 71b77c2..0000000
Binary files a/webpages/public/cross.jpg and /dev/null differ
diff --git a/webpages/public/logicon.png b/webpages/public/logicon.png
new file mode 100644
index 0000000..4443890
Binary files /dev/null and b/webpages/public/logicon.png differ
diff --git a/webpages/public/style.css b/webpages/public/style.css
index 27be15c..2ca745d 100644
--- a/webpages/public/style.css
+++ b/webpages/public/style.css
@@ -114,6 +114,14 @@ input[type=text]:focus {
margin-left: 10px;
}
+#tableRules tr {
+ margin-bottom: 10px;
+}
+#log_col {
+ padding-left: 20px;
+ border-left: double #666;
+}
+
.underlined {
padding-left: 10px;
font-style: italic;
| | | | |