System fully managable over web based UI, event intervals added, mapping from events to actions added. Let's get it tested

This commit is contained in:
Dominic Bosch 2014-04-19 22:35:05 +02:00
parent 0e8ce1233c
commit 2e66a24409
22 changed files with 488 additions and 338 deletions

View file

@ -240,11 +240,11 @@ storeRule = ( user, oPayload, callback ) =>
oParams = oPayload.action_params
for id, params of oParams
db.actionInvokers.storeUserParams id, user.username, JSON.stringify params
oParams = oPayload.action_functions
oFuncArgs = oPayload.action_functions
# if action function arguments were send, store them
for id, params of oParams
for id, args of oFuncArgs
arr = id.split ' -> '
db.actionInvokers.storeUserArguments user.username, rule.id, arr[ 0 ], arr[ 1 ], JSON.stringify params
db.actionInvokers.storeUserArguments user.username, rule.id, arr[ 0 ], arr[ 1 ], JSON.stringify args
# Initialize the rule log
db.resetLog user.username, rule.id

View file

@ -141,15 +141,17 @@ fTryToLoadModule = ( userId, ruleId, modId, src, dbMod, params, cb ) =>
if dbMod
oFuncArgs = {}
for func of oFuncParams
dbMod.getUserArguments userId, ruleId, modId, func, ( err, obj ) =>
fRegisterArguments = ( fName ) =>
( err, obj ) =>
if obj
try
oFuncArgs[ func ] = JSON.parse encryption.decrypt obj
@log.info "DM | Found and attached user-specific arguments to #{ userId }, #{ ruleId }, #{ modId }"
oFuncArgs[ fName ] = JSON.parse obj
@log.info "DM | Found and attached user-specific arguments to #{ userId }, #{ ruleId }, #{ modId }: #{ obj }"
catch err
@log.warn "DM | Error during parsing of user-specific arguments for #{ userId }, #{ ruleId }, #{ modId }"
@log.warn err
for func of oFuncParams
dbMod.getUserArguments userId, ruleId, modId, func, fRegisterArguments func
cb
answ: answ
module: sandbox.exports

View file

@ -160,7 +160,7 @@ updateActionModules = ( updatedRuleId ) =>
else
@log.error "EN | Compilation of code failed! #{ userName },
#{ oMyRule.rule.id }, #{ moduleName }: #{ result.answ.message }"
oMyRule.actions[moduleName] = result.module
oMyRule.actions[moduleName] = result
else
@log.warn "EN | #{ moduleName } not found for #{ oMyRule.rule.id }!"
@ -209,7 +209,16 @@ processEvent = ( evt ) =>
try
numExecutingFunctions++
@log.info "EN | #{ funcName } executes..."
node[funcName] evt.payload
arrArgs = []
if node.funcArgs[ funcName ]
for oArg in node.funcArgs[ funcName ]
if oArg.jsselector
arrArgs.push jsonQuery( evt.payload, oArg.value ).nodes()[ 0 ]
else
arrArgs.push oArg.value
else
@log.warn "EN | Weird! arguments not loaded for function '#{ funcName }'!"
node.module[ funcName ].apply null, arrArgs
@log.info "EN | #{ funcName } finished execution"
catch err
@log.info "EN | ERROR IN ACTION INVOKER: " + err.message

View file

@ -93,33 +93,40 @@ fLoadModule = ( msg ) ->
if not listUserModules[msg.user]
listUserModules[msg.user] = {}
iv = msg.rule.event_interval * 60 * 1000
ts = new Date()
# We open up a new object for the rule it
listUserModules[msg.user][msg.rule.id] =
id: msg.rule.event
pollfunc: arrName[1]
event_interval: iv
event_interval: msg.rule.event_interval * 60 * 1000
module: result.module
logger: result.logger
timestamp: ts
log.info "EP | New event module '#{ arrName[0] }' loaded for user #{ msg.user },
in rule #{ msg.rule.id }, polling every #{ msg.rule.event_interval } minutes"
setTimeout fCheckAndRun( msg.user, msg.rule.id ), iv
in rule #{ msg.rule.id }, starting at #{ ts.toISOString() }
and polling every #{ msg.rule.event_interval } minutes"
fCheckAndRun( msg.user, msg.rule.id, ts )()
if msg.event is 'new' or
not listUserModules[msg.user] or
not listUserModules[msg.user][msg.rule.id]
fAnonymous()
fCheckAndRun = ( userId, ruleId ) ->
fCheckAndRun = ( userId, ruleId, timestamp ) ->
() ->
log.info "EP | Check and run user #{ userId }, rule #{ ruleId }"
if isRunning and
listUserModules[userId] and
listUserModules[userId][ruleId]
oRule = listUserModules[userId][ruleId]
fCallFunction userId, ruleId, oRule
setTimeout fCheckAndRun( userId, ruleId ), oRule.event_interval
# If there was a rule update we only continue the latest setTimeout execution
if listUserModules[userId][ruleId].timestamp is timestamp
oRule = listUserModules[userId][ruleId]
fCallFunction userId, ruleId, oRule
setTimeout fCheckAndRun( userId, ruleId, timestamp ), oRule.event_interval
else
log.info "EP | We found a newer polling interval and discontinue this one which
was created at #{ timestamp.toISOString() }"
# We have to register the poll function in belows anonymous function
# because we're fast iterating through the listUserModules and references will
@ -129,7 +136,7 @@ fCallFunction = ( userId, ruleId, oRule ) ->
oRule.module[oRule.pollfunc] ( obj ) ->
db.pushEvent
event: oRule.id
eventid: "polled #{ oRule.id } #{ userId }_#{ ( new Date ).toISOString() }"
eventid: "polled #{ oRule.id } #{ userId }_#{ ( new Date() ).toISOString() }"
payload: obj
catch err
log.info "EP | ERROR in module when polled: #{ oRule.id } #{ userId }: #{err.message}"

View file

@ -43,7 +43,7 @@ exports = module.exports = ( args ) =>
indexEvent = ( event, body, resp ) ->
try
obj = JSON.parse body
timestamp = ( new Date ).toISOString()
timestamp = ( new Date() ).toISOString()
rand = ( Math.floor Math.random() * 10e9 ).toString( 16 ).toUpperCase()
obj.event = event
obj.eventid = "#{ obj.event }_#{ timestamp }_#{ rand }"

View file

@ -349,8 +349,6 @@ class IndexedModules
@log.info "DB | (IdxedMods) #{ @setname }.getAllModuleUserArguments( #{ userId }, #{ ruleId }, #{ mId } )"
@db.smembers "#{ @setname }:#{ userId }:#{ ruleId }:#{ mId }:functions", ( err, obj ) =>
sem = obj.length
console.log 'getAllModuleUserArguments'
console.log obj
oAnswer = {}
for func in obj
fRegisterFunction = ( func ) =>
@ -388,7 +386,7 @@ Appends a log entry.
###
exports.appendLog = ( userId, ruleId, moduleId, message ) =>
@db.append "#{ userId }:#{ ruleId }:log",
"[#{ ( new Date ).toISOString() }] {#{ moduleId }} #{ message }\n"
"[#{ ( new Date() ).toISOString() }] {#{ moduleId }} #{ message }\n"
###
Retrieves a log entry.

View file

@ -77,7 +77,7 @@ exports.handleEvent = ( req, resp ) ->
resp.send 400, 'Badly formed event!'
# If required event properties are present we process the event #
if obj and obj.event and not err
timestamp = ( new Date ).toISOString()
timestamp = ( new Date() ).toISOString()
rand = ( Math.floor Math.random() * 10e9 ).toString( 16 ).toUpperCase()
obj.eventid = "#{ obj.event }_#{ timestamp }_#{ rand }"
answ =

View file

@ -1,2 +0,0 @@
exports.printUserParamToLog = ( evt ) ->
log params.password

View file

@ -0,0 +1,31 @@
###
Import.io allows to capture data from the web
required module params:
- apikey
- queryGuid
###
params.apikey = "Cc8AX35d4B89ozzmn5bpm7k70HRon5rrfUxZvOwkVRj31/oBGHzVfQSRp5mEvlOgxyh7xi+tFSL66iAFo1W/sQ=="
params.userGuid = "d19f0d08-bf73-4115-90a8-ac045ad4f225"
params.queryGuid = "caff10dc-3bf8-402e-b1b8-c799a77c3e8c"
exports.queryData = ( pushEvent ) ->
debug params.apikey
debug params.queryGuid
debug params.userGuid
io = new importio params.userGuid, params.apikey, "query.import.io"
io.connect ( connected ) ->
if not connected
log "ERROR: Unable to connect"
else
log "Connected!"
data = []
io.query "input": "input": "query", "connectorGuids": [ params.queryGuid ], ( finished, msg ) ->
if msg.type is "MESSAGE"
log "Adding #{ msg.data.results.length } results"
data = data.concat msg.data.results
if finished
log "Done"
log JSON.stringify data

View file

@ -311,7 +311,7 @@ Components Manager
storeRule = (function(_this) {
return function(user, oPayload, callback) {
var arr, epModId, id, oParams, params, rule, strRule;
var args, arr, epModId, id, oFuncArgs, oParams, params, rule, strRule;
rule = {
id: oPayload.id,
event: oPayload.event,
@ -332,11 +332,11 @@ Components Manager
params = oParams[id];
db.actionInvokers.storeUserParams(id, user.username, JSON.stringify(params));
}
oParams = oPayload.action_functions;
for (id in oParams) {
params = oParams[id];
oFuncArgs = oPayload.action_functions;
for (id in oFuncArgs) {
args = oFuncArgs[id];
arr = id.split(' -> ');
db.actionInvokers.storeUserArguments(user.username, rule.id, arr[0], arr[1], JSON.stringify(params));
db.actionInvokers.storeUserArguments(user.username, rule.id, arr[0], arr[1], JSON.stringify(args));
}
db.resetLog(user.username, rule.id);
db.appendLog(user.username, rule.id, "INIT", "Rule '" + rule.id + "' initialized");

View file

@ -120,7 +120,7 @@ Dynamic Modules
fTryToLoadModule = (function(_this) {
return function(userId, ruleId, modId, src, dbMod, params, cb) {
var answ, err, fName, func, logFunc, msg, oFuncArgs, oFuncParams, sandbox, _ref;
var answ, err, fName, fRegisterArguments, func, logFunc, msg, oFuncArgs, oFuncParams, sandbox, _ref;
if (!params) {
params = {};
}
@ -162,19 +162,22 @@ Dynamic Modules
}
if (dbMod) {
oFuncArgs = {};
for (func in oFuncParams) {
dbMod.getUserArguments(userId, ruleId, modId, func, function(err, obj) {
fRegisterArguments = function(fName) {
return function(err, obj) {
if (obj) {
try {
oFuncArgs[func] = JSON.parse(encryption.decrypt(obj));
return _this.log.info("DM | Found and attached user-specific arguments to " + userId + ", " + ruleId + ", " + modId);
oFuncArgs[fName] = JSON.parse(obj);
return _this.log.info("DM | Found and attached user-specific arguments to " + userId + ", " + ruleId + ", " + modId + ": " + obj);
} catch (_error) {
err = _error;
_this.log.warn("DM | Error during parsing of user-specific arguments for " + userId + ", " + ruleId + ", " + modId);
return _this.log.warn(err);
}
}
});
};
};
for (func in oFuncParams) {
dbMod.getUserArguments(userId, ruleId, modId, func, fRegisterArguments(func));
}
}
return cb({

View file

@ -172,7 +172,7 @@ Engine
} else {
_this.log.error("EN | Compilation of code failed! " + userName + ", " + oMyRule.rule.id + ", " + moduleName + ": " + result.answ.message);
}
return oMyRule.actions[moduleName] = result.module;
return oMyRule.actions[moduleName] = result;
});
} else {
return _this.log.warn("EN | " + moduleName + " not found for " + oMyRule.rule.id + "!");
@ -253,7 +253,7 @@ Engine
return function(evt) {
var action, arr, fSearchAndInvokeAction, oMyRule, oUser, ruleName, userName, _results;
fSearchAndInvokeAction = function(node, arrPath, funcName, evt, depth) {
var err;
var arrArgs, err, oArg, _i, _len, _ref;
if (!node) {
_this.log.error("EN | Didn't find property in user rule list: " + arrPath.join(', ') + " at depth " + depth);
return;
@ -262,7 +262,21 @@ Engine
try {
numExecutingFunctions++;
_this.log.info("EN | " + funcName + " executes...");
node[funcName](evt.payload);
arrArgs = [];
if (node.funcArgs[funcName]) {
_ref = node.funcArgs[funcName];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
oArg = _ref[_i];
if (oArg.jsselector) {
arrArgs.push(jsonQuery(evt.payload, oArg.value).nodes()[0]);
} else {
arrArgs.push(oArg.value);
}
}
} else {
_this.log.warn("EN | Weird! arguments not loaded for function '" + funcName + "'!");
}
node.module[funcName].apply(null, arrArgs);
_this.log.info("EN | " + funcName + " finished execution");
} catch (_error) {
err = _error;

View file

@ -84,23 +84,24 @@ Dynamic Modules
return log.warn("EP | Strange... no module retrieved: " + arrName[0]);
} else {
return dynmod.compileString(obj.data, msg.user, msg.rule.id, arrName[0], obj.lang, db.eventPollers, function(result) {
var iv;
var ts;
if (!result.answ === 200) {
log.error("EP | Compilation of code failed! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]);
}
if (!listUserModules[msg.user]) {
listUserModules[msg.user] = {};
}
iv = msg.rule.event_interval * 60 * 1000;
ts = new Date();
listUserModules[msg.user][msg.rule.id] = {
id: msg.rule.event,
pollfunc: arrName[1],
event_interval: iv,
event_interval: msg.rule.event_interval * 60 * 1000,
module: result.module,
logger: result.logger
logger: result.logger,
timestamp: ts
};
log.info("EP | New event module '" + arrName[0] + "' loaded for user " + msg.user + ", in rule " + msg.rule.id + ", polling every " + msg.rule.event_interval + " minutes");
return setTimeout(fCheckAndRun(msg.user, msg.rule.id), iv);
log.info("EP | New event module '" + arrName[0] + "' loaded for user " + msg.user + ", in rule " + msg.rule.id + ", starting at " + (ts.toISOString()) + " and polling every " + msg.rule.event_interval + " minutes");
return fCheckAndRun(msg.user, msg.rule.id, ts)();
});
}
});
@ -110,14 +111,18 @@ Dynamic Modules
}
};
fCheckAndRun = function(userId, ruleId) {
fCheckAndRun = function(userId, ruleId, timestamp) {
return function() {
var oRule;
log.info("EP | Check and run user " + userId + ", rule " + ruleId);
if (isRunning && listUserModules[userId] && listUserModules[userId][ruleId]) {
oRule = listUserModules[userId][ruleId];
fCallFunction(userId, ruleId, oRule);
return setTimeout(fCheckAndRun(userId, ruleId), oRule.event_interval);
if (listUserModules[userId][ruleId].timestamp === timestamp) {
oRule = listUserModules[userId][ruleId];
fCallFunction(userId, ruleId, oRule);
return setTimeout(fCheckAndRun(userId, ruleId, timestamp), oRule.event_interval);
} else {
return log.info("EP | We found a newer polling interval and discontinue this one which was created at " + (timestamp.toISOString()));
}
}
};
};
@ -128,7 +133,7 @@ Dynamic Modules
return oRule.module[oRule.pollfunc](function(obj) {
return db.pushEvent({
event: oRule.id,
eventid: "polled " + oRule.id + " " + userId + "_" + ((new Date).toISOString()),
eventid: "polled " + oRule.id + " " + userId + "_" + ((new Date()).toISOString()),
payload: obj
});
});

View file

@ -46,7 +46,7 @@ HTTP Listener
var err, obj, rand, timestamp;
try {
obj = JSON.parse(body);
timestamp = (new Date).toISOString();
timestamp = (new Date()).toISOString();
rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase();
obj.event = event;
obj.eventid = "" + obj.event + "_" + timestamp + "_" + rand;

View file

@ -445,8 +445,6 @@ Persistence
return function(err, obj) {
var fRegisterFunction, func, oAnswer, sem, _i, _len, _results;
sem = obj.length;
console.log('getAllModuleUserArguments');
console.log(obj);
oAnswer = {};
_results = [];
for (_i = 0, _len = obj.length; _i < _len; _i++) {
@ -509,7 +507,7 @@ Persistence
exports.appendLog = (function(_this) {
return function(userId, ruleId, moduleId, message) {
return _this.db.append("" + userId + ":" + ruleId + ":log", "[" + ((new Date).toISOString()) + "] {" + moduleId + "} " + message + "\n");
return _this.db.append("" + userId + ":" + ruleId + ":log", "[" + ((new Date()).toISOString()) + "] {" + moduleId + "} " + message + "\n");
};
})(this);

View file

@ -85,7 +85,7 @@ Request Handler
resp.send(400, 'Badly formed event!');
}
if (obj && obj.event && !err) {
timestamp = (new Date).toISOString();
timestamp = (new Date()).toISOString();
rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase();
obj.eventid = "" + obj.event + "_" + timestamp + "_" + rand;
answ = {

View file

@ -80,18 +80,30 @@
"ruleOne": {
"id": "ruleReal",
"event": "test_1",
"event_interval": 1,
"conditions": [".more:val(\"really nested\")"],
"actions": ["aiOne -> printToLog"]
"actions": ["aiOne -> printToLog"],
"action_functions": {
"aiOne -> printToLog": [
{
"argument": "evt",
"value": "*",
"jsselector": true
}
]
}
},
"ruleTwo": {
"id": "ruleRealTwo",
"event": "test_2",
"event_interval": 1,
"conditions": [],
"actions": ["aiTwo -> otherEvent"]
},
"ruleThree": {
"id": "ruleRealThree",
"event": "epOne -> newMail",
"event_interval": 1,
"conditions": [],
"actions": ["aiThree -> printUserParamToLog"]
}

View file

@ -35,6 +35,9 @@ cm.addRuleListener engine.internalEvent
db = require path.join '..', 'js', 'persistence'
db opts
encryption = require path.join '..', 'js', 'encryption'
encryption opts
oUser = objects.users.userOne
oRuleOne = objects.rules.ruleOne
oRuleTwo = objects.rules.ruleTwo
@ -196,10 +199,12 @@ exports.ruleForge =
db.actionInvokers.storeModule oUser.username, oAiThree
pw = 'This password should come out cleartext'
userparams = JSON.stringify password: pw
oEncrypted = cryptico.encrypt userparams, strPublicKey
oEncrypted = cryptico.encrypt pw, strPublicKey
userparams = JSON.stringify password:
shielded: false
value: oEncrypted.cipher
db.actionInvokers.storeUserParams oAiThree.id, oUser.username, oEncrypted.cipher
db.actionInvokers.storeUserParams oAiThree.id, oUser.username, userparams
request =
command: 'forge_rule'
@ -230,7 +235,7 @@ exports.ruleForge =
test.strictEqual 200, answ.code, "Deleting Rule returned #{ answ.code }: #{ answ.message }"
setTimeout test.done, 200
setTimeout fWaitAgain, 200
setTimeout fWaitAgain, 500
setTimeout fWaitForPersistence, 200

View file

@ -42,35 +42,7 @@ fOnLoad = () ->
editor.setShowPrintMargin false
# editor.session.setUseSoftTabs false
# Fetch Event Poller user-specific parameters
fFetchEventParams = ( name ) ->
$( '#event_poller_params *' ).remove()
if name
arr = name.split ' -> '
obj =
command: 'get_event_poller_params'
payload: JSON.stringify
id: arr[ 0 ]
$.post( '/usercommand', obj )
.done ( data ) ->
if data.message
oParams = JSON.parse data.message
$( '#event_poller_params' ).html '<br><b>Required Parameters:</b>'
table = $ '<table>'
$( '#event_poller_params' ).append table
fAppendParam = ( name, shielded ) ->
tr = $( '<tr>' )
tr.append $( '<td>' ).css 'width', '20px'
tr.append $( '<td>' ).attr( 'class', 'key' ).text name
inp = $( '<input>' )
if shielded
inp.attr( 'type', 'password' )
tr.append $( '<td>' ).text( ' : ' ).append inp
table.append tr
fAppendParam name, shielded for name, shielded of oParams
.fail fFailedRequest 'Error fetching event poller params'
# Init Event Pollers
# EVENT
$.post( '/usercommand', command: 'get_event_pollers' )
.done ( data ) ->
try
@ -89,12 +61,13 @@ fOnLoad = () ->
.fail fFailedRequest 'Error fetching event poller'
$( '#select_event' ).change () ->
if $( this ).val() is ''
evtFunc = $( this ).val()
if evtFunc is ''
$( '#input_interval' ).html ''
else
fPlaceAndPaintInterval()
$( '#input_event' ).val $( this ).val()
fFetchEventParams $( this ).val()
$( '#input_event' ).val evtFunc
fFetchEventParams evtFunc
$( '#input_event' ).change () ->
$( '#select_event' ).val ''
@ -105,8 +78,54 @@ fOnLoad = () ->
else
fPlaceAndPaintInterval()
fFetchEventParams = ( name ) ->
$( '#event_poller_params *' ).remove()
if name
arr = name.split ' -> '
obj =
command: 'get_event_poller_params'
payload: JSON.stringify
id: arr[ 0 ]
$.post( '/usercommand', obj )
.done fAddEventParams arr[ 0 ]
.fail fFailedRequest 'Error fetching event poller params'
# Init Action Invoker
fAddEventParams = ( id ) ->
( data ) ->
if data.message
oParams = JSON.parse data.message
$( '#event_poller_params' ).html '<br><b>Required Parameters:</b>'
table = $ '<table>'
$( '#event_poller_params' ).append table
fAppendParam = ( name, shielded ) ->
tr = $( '<tr>' )
tr.append $( '<td>' ).css 'width', '20px'
tr.append $( '<td>' ).attr( 'class', 'key' ).text name
inp = $( '<input>' )
if shielded
inp.attr( 'type', 'password' )
tr.append $( '<td>' ).text( ' : ' ).append inp
table.append tr
fAppendParam name, shielded for name, shielded of oParams
fFillEventParams id
fFillEventParams = ( moduleId ) ->
obj =
command: 'get_event_poller_user_params'
payload: JSON.stringify
id: moduleId
$.post( '/usercommand', obj )
.done ( data ) ->
oParams = JSON.parse data.message
for param, oParam of oParams
par = $( "#event_poller_params tr" ).filter () ->
$( 'td.key', this ).text() is param
$( 'input', par ).val oParam.value
$( 'input', par ).attr 'unchanged', 'true'
$( 'input', par ).change () ->
$( this ).attr 'unchanged', 'false'
# ACTIONS
obj =
command: 'get_action_invokers'
$.post( '/usercommand', obj )
@ -119,11 +138,37 @@ fOnLoad = () ->
return
fAppendActions = ( module, actions ) ->
for act in actions
if $( "#action_params div:contains(#{ module } -> #{ act })" ).length is 0
arrEls = $( "#action_params div" ).filter () ->
$( this ).text() is "#{ module } -> #{ act }"
# It could have been loaded async before through the rules ito the action params
if arrEls.length is 0
$( '#select_actions' ).append $( '<option>' ).text module + ' -> ' + act
fAppendActions module, actions for module, actions of oAis
.fail fFailedRequest 'Error fetching event poller'
fAddSelectedAction = ( name ) ->
arrName = name.split ' -> '
arrEls = $( "#action_params div.modName" ).map( () ->
$( this ).text()
).get()
table = $( '#selected_actions' )
tr = $( '<tr>' ).appendTo table
img = $( '<img>' ).attr 'src', 'red_cross_small.png'
tr.append $( '<td>' ).css( 'width', '20px' ).append img
tr.append $( '<td>' ).attr( 'class', 'title').text name
td = $( '<td>' ).attr( 'class', 'funcMappings').appendTo tr
fFetchActionFunctionArgs td, arrName
if arrName[ 0 ] not in arrEls
div = $( '<div>' ).appendTo $( '#action_params' )
subdiv = $( '<div> ').appendTo div
subdiv.append $( '<div>' )
.attr( 'class', 'modName underlined' ).text arrName[ 0 ]
fFetchActionParams div, arrName[ 0 ]
$( "#select_actions option" ).each () ->
if $( this ).text() is name
$( this ).remove()
fFillActionFunction arrName[ 0 ]
fFetchActionParams = ( div, modName ) ->
obj =
command: 'get_action_invoker_params'
@ -149,7 +194,7 @@ fOnLoad = () ->
fAppendActionParam name, sh for name, sh of oParams
.fail fFailedRequest 'Error fetching action invoker params'
fFetchActionFunctionParams = ( tag, arrName ) ->
fFetchActionFunctionArgs = ( tag, arrName ) ->
obj =
command: 'get_action_invoker_function_arguments'
payload: JSON.stringify
@ -174,25 +219,44 @@ fOnLoad = () ->
.attr 'title', 'js-select expression to be resolved on event?'
.fail fFailedRequest 'Error fetching action invoker function params'
fAddSelectedAction = ( name ) ->
arrName = name.split ' -> '
arrEls = $( "#action_params div.modName" ).map( () ->
$( this ).text()
).get()
table = $( '#selected_actions' )
tr = $( '<tr>' ).appendTo table
img = $( '<img>' ).attr 'src', 'red_cross_small.png'
tr.append $( '<td>' ).css( 'width', '20px' ).append img
tr.append $( '<td>' ).attr( 'class', 'title').text name
td = $( '<td>' ).attr( 'class', 'funcMappings').appendTo tr
fFetchActionFunctionParams td, arrName
if arrName[ 0 ] not in arrEls
div = $( '<div>' ).appendTo $( '#action_params' )
subdiv = $( '<div> ').appendTo div
subdiv.append $( '<div>' )
.attr( 'class', 'modName underlined' ).text arrName[ 0 ]
fFetchActionParams div, arrName[ 0 ]
$( "#select_actions option:contains(#{ name })" ).remove()
fFillActionFunction = ( name ) ->
obj =
command: 'get_action_invoker_user_params'
payload: JSON.stringify
id: name
$.post( '/usercommand', obj )
.done fAddActionUserParams name
obj.command = 'get_action_invoker_user_arguments'
obj.payload = JSON.stringify
ruleId: $( '#input_id' ).val()
moduleId: name
$.post( '/usercommand', obj )
.done fAddActionUserArgs name
fAddActionUserParams = ( name ) ->
( data ) ->
oParams = JSON.parse data.message
domMod = $( "#action_params div" ).filter () ->
$( 'div.modName', this ).text() is name
for param, oParam of oParams
par = $( "tr", domMod ).filter () ->
$( 'td.key', this ).text() is param
$( 'input', par ).val oParam.value
$( 'input', par ).attr 'unchanged', 'true'
$( 'input', par ).change () ->
$( this ).attr 'unchanged', 'false'
fAddActionUserArgs = ( name ) ->
( data ) ->
for key, arrFuncs of data.message
par = $( "#selected_actions tr" ).filter () ->
$( 'td.title', this ).text() is "#{ name } -> #{ key }"
for oFunc in JSON.parse arrFuncs
tr = $( "tr", par ).filter () ->
$( '.funcarg', this ).text() is "#{ oFunc.argument }"
$( "input[type=text]", tr ).val oFunc.value
$( "input[type=checkbox]", tr ).prop 'checked', oFunc.jsselector
$( '#select_actions' ).on 'change', () ->
opt = $ 'option:selected', this
@ -217,6 +281,8 @@ fOnLoad = () ->
$( this ).closest( 'tr' ).remove()
# SUBMIT
$( '#but_submit' ).click () ->
window.scrollTo 0, 0
$( '#info' ).text ''
@ -240,11 +306,12 @@ fOnLoad = () ->
shielded = $( 'input', this ).attr( 'type' ) is 'password'
ep[ key ] =
shielded: shielded
if $( 'input', this ).attr( 'unchanged' ) is 'true'
ep[ key ].value = val
else
if not shielded or $( 'input', this ).attr( 'unchanged' ) isnt 'true'
encryptedParam = cryptico.encrypt val, strPublicKey
ep[ key ].value = encryptedParam.cipher
ep[ key ].value = encryptedParam.cipher
else
ep[ key ].value = val
if $( '#selected_actions tr' ).length is 0
throw new Error 'Please select at least one action or create one!'
@ -262,11 +329,12 @@ fOnLoad = () ->
throw new Error "'#{ key }' missing for '#{ modName }'"
params[ key ] =
shielded: shielded
if $( 'input', this ).attr( 'unchanged' ) is 'true'
params[ key ].value = val
else
if not shielded or $( 'input', this ).attr( 'unchanged' ) isnt 'true'
encryptedParam = cryptico.encrypt val, strPublicKey
params[ key ].value = encryptedParam.cipher
params[ key ].value = encryptedParam.cipher
else
params[ key ].value = val
ap[ modName ] = params
acts = []
actParams = {}
@ -286,7 +354,7 @@ fOnLoad = () ->
actParams[ actionName ].push
argument: $( 'div.funcarg', this ).text()
value: $( 'input[type=text]', this ).val()
regexp: $( 'input[type=checkbox]', this ).is( ':checked' )
jsselector: $( 'input[type=checkbox]', this ).is( ':checked' )
try
conds = JSON.parse editor.getValue()
@ -379,19 +447,7 @@ fOnLoad = () ->
if $( '#select_event' ).val() isnt ''
fFetchEventParams oRule.event
fPlaceAndPaintInterval()
obj =
command: 'get_event_poller_user_params'
payload: JSON.stringify
id: oRule.event.split( ' -> ' )[ 0 ]
$.post( '/usercommand', obj )
.done ( data ) ->
oParams = JSON.parse data.message
for param, oParam of oParams
par = $( "#event_poller_params tr:contains(#{ param })" ).parent()
$( 'input', par ).val oParam.value
$( 'input', par ).attr 'unchanged', 'true'
$( 'input', par ).change () ->
$( this ).attr 'unchanged', 'false'
$( '#input_event' ).val oRule.event
$( '#event_interval' ).val oRule.event_interval
@ -399,47 +455,9 @@ fOnLoad = () ->
editor.setValue JSON.stringify oRule.conditions
# Actions
oActions = {}
for action in oRule.actions
fAddSelectedAction action
arrName = action.split ' -> '
if not oActions[ arrName[ 0 ] ]
oActions[ arrName[ 0 ] ] = []
oActions[ arrName[ 0 ] ].push arrName[ 1 ]
fAddActionModuleParams = ( name ) ->
( data ) ->
oParams = JSON.parse data.message
domMod = $( "#action_params div.modName:contains(#{ name })" ).parent()
for param, oParam of oParams
par = $( "td.key:contains(#{ param })", domMod ).parent()
$( 'input', par ).val oParam.value
$( 'input', par ).attr 'unchanged', 'true'
$( 'input', par ).change () ->
$( this ).attr 'unchanged', 'false'
fAddActionModuleArgs = ( name ) ->
( data ) ->
for key, arrFuncs of data.message
par = $( "#selected_actions td.title:contains(#{ name } -> #{ key })" ).parent()
for oFunc in JSON.parse arrFuncs
tr = $( ".funcarg:contains(#{ oFunc.argument })", par ).parent().parent()
$( "input[type=text]", tr ).val oFunc.value
$( "input[type=checkbox]", tr ).prop 'checked', oFunc.regexp
for mod, arrMod of oActions
obj =
command: 'get_action_invoker_user_params'
payload: JSON.stringify
id: mod
$.post( '/usercommand', obj )
.done fAddActionModuleParams mod
obj.command = 'get_action_invoker_user_arguments'
obj.payload = JSON.stringify
ruleId: oRule.id
moduleId: mod
$.post( '/usercommand', obj )
.done fAddActionModuleArgs mod
fAddSelectedAction action
.fail ( err ) ->
if err.responseText is ''

View file

@ -48,53 +48,13 @@
});
fOnLoad = function() {
var editor, fAddSelectedAction, fFetchActionFunctionParams, fFetchActionParams, fFetchEventParams, obj;
var editor, fAddActionUserArgs, fAddActionUserParams, fAddEventParams, fAddSelectedAction, fFetchActionFunctionArgs, fFetchActionParams, fFetchEventParams, fFillActionFunction, fFillEventParams, obj;
document.title = 'Rule Forge!';
$('#pagetitle').text('{{{user.username}}}, forge your ECA Rule!');
editor = ace.edit("editor_conditions");
editor.setTheme("ace/theme/monokai");
editor.getSession().setMode("ace/mode/json");
editor.setShowPrintMargin(false);
fFetchEventParams = function(name) {
var arr, obj;
$('#event_poller_params *').remove();
if (name) {
arr = name.split(' -> ');
obj = {
command: 'get_event_poller_params',
payload: JSON.stringify({
id: arr[0]
})
};
return $.post('/usercommand', obj).done(function(data) {
var fAppendParam, shielded, table, _results;
if (data.message) {
oParams = JSON.parse(data.message);
$('#event_poller_params').html('<br><b>Required Parameters:</b>');
table = $('<table>');
$('#event_poller_params').append(table);
fAppendParam = function(name, shielded) {
var inp, tr;
tr = $('<tr>');
tr.append($('<td>').css('width', '20px'));
tr.append($('<td>').attr('class', 'key').text(name));
inp = $('<input>');
if (shielded) {
inp.attr('type', 'password');
}
tr.append($('<td>').text(' : ').append(inp));
return table.append(tr);
};
_results = [];
for (name in oParams) {
shielded = oParams[name];
_results.push(fAppendParam(name, shielded));
}
return _results;
}
}).fail(fFailedRequest('Error fetching event poller params'));
}
};
$.post('/usercommand', {
command: 'get_event_pollers'
}).done(function(data) {
@ -126,13 +86,15 @@
return fFetchEventParams($('#select_event option:selected').text());
}).fail(fFailedRequest('Error fetching event poller'));
$('#select_event').change(function() {
if ($(this).val() === '') {
var evtFunc;
evtFunc = $(this).val();
if (evtFunc === '') {
$('#input_interval').html('');
} else {
fPlaceAndPaintInterval();
}
$('#input_event').val($(this).val());
return fFetchEventParams($(this).val());
$('#input_event').val(evtFunc);
return fFetchEventParams(evtFunc);
});
$('#input_event').change(function() {
$('#select_event').val('');
@ -144,6 +106,74 @@
return fPlaceAndPaintInterval();
}
});
fFetchEventParams = function(name) {
var arr, obj;
$('#event_poller_params *').remove();
if (name) {
arr = name.split(' -> ');
obj = {
command: 'get_event_poller_params',
payload: JSON.stringify({
id: arr[0]
})
};
return $.post('/usercommand', obj).done(fAddEventParams(arr[0])).fail(fFailedRequest('Error fetching event poller params'));
}
};
fAddEventParams = function(id) {
return function(data) {
var fAppendParam, name, shielded, table;
if (data.message) {
oParams = JSON.parse(data.message);
$('#event_poller_params').html('<br><b>Required Parameters:</b>');
table = $('<table>');
$('#event_poller_params').append(table);
fAppendParam = function(name, shielded) {
var inp, tr;
tr = $('<tr>');
tr.append($('<td>').css('width', '20px'));
tr.append($('<td>').attr('class', 'key').text(name));
inp = $('<input>');
if (shielded) {
inp.attr('type', 'password');
}
tr.append($('<td>').text(' : ').append(inp));
return table.append(tr);
};
for (name in oParams) {
shielded = oParams[name];
fAppendParam(name, shielded);
}
return fFillEventParams(id);
}
};
};
fFillEventParams = function(moduleId) {
var obj;
obj = {
command: 'get_event_poller_user_params',
payload: JSON.stringify({
id: moduleId
})
};
return $.post('/usercommand', obj).done(function(data) {
var oParam, par, _results;
oParams = JSON.parse(data.message);
_results = [];
for (param in oParams) {
oParam = oParams[param];
par = $("#event_poller_params tr").filter(function() {
return $('td.key', this).text() === param;
});
$('input', par).val(oParam.value);
$('input', par).attr('unchanged', 'true');
_results.push($('input', par).change(function() {
return $(this).attr('unchanged', 'false');
}));
}
return _results;
});
};
obj = {
command: 'get_action_invokers'
};
@ -157,11 +187,14 @@
return;
}
fAppendActions = function(module, actions) {
var act, _j, _len1, _results;
var act, arrEls, _j, _len1, _results;
_results = [];
for (_j = 0, _len1 = actions.length; _j < _len1; _j++) {
act = actions[_j];
if ($("#action_params div:contains(" + module + " -> " + act + ")").length === 0) {
arrEls = $("#action_params div").filter(function() {
return $(this).text() === ("" + module + " -> " + act);
});
if (arrEls.length === 0) {
_results.push($('#select_actions').append($('<option>').text(module + ' -> ' + act)));
} else {
_results.push(void 0);
@ -176,6 +209,32 @@
}
return _results;
}).fail(fFailedRequest('Error fetching event poller'));
fAddSelectedAction = function(name) {
var arrEls, arrName, div, img, subdiv, table, td, tr, _ref;
arrName = name.split(' -> ');
arrEls = $("#action_params div.modName").map(function() {
return $(this).text();
}).get();
table = $('#selected_actions');
tr = $('<tr>').appendTo(table);
img = $('<img>').attr('src', 'red_cross_small.png');
tr.append($('<td>').css('width', '20px').append(img));
tr.append($('<td>').attr('class', 'title').text(name));
td = $('<td>').attr('class', 'funcMappings').appendTo(tr);
fFetchActionFunctionArgs(td, arrName);
if (_ref = arrName[0], __indexOf.call(arrEls, _ref) < 0) {
div = $('<div>').appendTo($('#action_params'));
subdiv = $('<div> ').appendTo(div);
subdiv.append($('<div>')).attr('class', 'modName underlined').text(arrName[0]);
fFetchActionParams(div, arrName[0]);
}
$("#select_actions option").each(function() {
if ($(this).text() === name) {
return $(this).remove();
}
});
return fFillActionFunction(arrName[0]);
};
fFetchActionParams = function(div, modName) {
obj = {
command: 'get_action_invoker_params',
@ -212,7 +271,7 @@
}
}).fail(fFailedRequest('Error fetching action invoker params'));
};
fFetchActionFunctionParams = function(tag, arrName) {
fFetchActionFunctionArgs = function(tag, arrName) {
obj = {
command: 'get_action_invoker_function_arguments',
payload: JSON.stringify({
@ -245,26 +304,70 @@
}
}).fail(fFailedRequest('Error fetching action invoker function params'));
};
fAddSelectedAction = function(name) {
var arrEls, arrName, div, img, subdiv, table, td, tr, _ref;
arrName = name.split(' -> ');
arrEls = $("#action_params div.modName").map(function() {
return $(this).text();
}).get();
table = $('#selected_actions');
tr = $('<tr>').appendTo(table);
img = $('<img>').attr('src', 'red_cross_small.png');
tr.append($('<td>').css('width', '20px').append(img));
tr.append($('<td>').attr('class', 'title').text(name));
td = $('<td>').attr('class', 'funcMappings').appendTo(tr);
fFetchActionFunctionParams(td, arrName);
if (_ref = arrName[0], __indexOf.call(arrEls, _ref) < 0) {
div = $('<div>').appendTo($('#action_params'));
subdiv = $('<div> ').appendTo(div);
subdiv.append($('<div>')).attr('class', 'modName underlined').text(arrName[0]);
fFetchActionParams(div, arrName[0]);
}
return $("#select_actions option:contains(" + name + ")").remove();
fFillActionFunction = function(name) {
obj = {
command: 'get_action_invoker_user_params',
payload: JSON.stringify({
id: name
})
};
$.post('/usercommand', obj).done(fAddActionUserParams(name));
obj.command = 'get_action_invoker_user_arguments';
obj.payload = JSON.stringify({
ruleId: $('#input_id').val(),
moduleId: name
});
return $.post('/usercommand', obj).done(fAddActionUserArgs(name));
};
fAddActionUserParams = function(name) {
return function(data) {
var domMod, oParam, par, _results;
oParams = JSON.parse(data.message);
domMod = $("#action_params div").filter(function() {
return $('div.modName', this).text() === name;
});
_results = [];
for (param in oParams) {
oParam = oParams[param];
par = $("tr", domMod).filter(function() {
return $('td.key', this).text() === param;
});
$('input', par).val(oParam.value);
$('input', par).attr('unchanged', 'true');
_results.push($('input', par).change(function() {
return $(this).attr('unchanged', 'false');
}));
}
return _results;
};
};
fAddActionUserArgs = function(name) {
return function(data) {
var arrFuncs, key, oFunc, par, tr, _ref, _results;
_ref = data.message;
_results = [];
for (key in _ref) {
arrFuncs = _ref[key];
par = $("#selected_actions tr").filter(function() {
return $('td.title', this).text() === ("" + name + " -> " + key);
});
_results.push((function() {
var _j, _len1, _ref1, _results1;
_ref1 = JSON.parse(arrFuncs);
_results1 = [];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
oFunc = _ref1[_j];
tr = $("tr", par).filter(function() {
return $('.funcarg', this).text() === ("" + oFunc.argument);
});
$("input[type=text]", tr).val(oFunc.value);
_results1.push($("input[type=checkbox]", tr).prop('checked', oFunc.jsselector));
}
return _results1;
})());
}
return _results;
};
};
$('#select_actions').on('change', function() {
var opt;
@ -320,11 +423,11 @@
ep[key] = {
shielded: shielded
};
if ($('input', this).attr('unchanged') === 'true') {
return ep[key].value = val;
} else {
if (!shielded || $('input', this).attr('unchanged') !== 'true') {
encryptedParam = cryptico.encrypt(val, strPublicKey);
return ep[key].value = encryptedParam.cipher;
} else {
return ep[key].value = val;
}
});
if ($('#selected_actions tr').length === 0) {
@ -347,11 +450,11 @@
params[key] = {
shielded: shielded
};
if ($('input', this).attr('unchanged') === 'true') {
return params[key].value = val;
} else {
if (!shielded || $('input', this).attr('unchanged') !== 'true') {
encryptedParam = cryptico.encrypt(val, strPublicKey);
return params[key].value = encryptedParam.cipher;
} else {
return params[key].value = val;
}
});
return ap[modName] = params;
@ -368,7 +471,7 @@
return actParams[actionName].push({
argument: $('div.funcarg', this).text(),
value: $('input[type=text]', this).val(),
regexp: $('input[type=checkbox]', this).is(':checked')
jsselector: $('input[type=checkbox]', this).is(':checked')
});
});
});
@ -461,7 +564,7 @@
})
};
return $.post('/usercommand', obj).done(function(data) {
var action, arrMod, arrName, fAddActionModuleArgs, fAddActionModuleParams, mod, oActions, oRule, _j, _len1, _ref, _results;
var action, arrName, oRule, _j, _len1, _ref, _results;
oRule = JSON.parse(data.message);
if (oRule) {
$('#input_id').val(oRule.id);
@ -469,96 +572,16 @@
if ($('#select_event').val() !== '') {
fFetchEventParams(oRule.event);
fPlaceAndPaintInterval();
obj = {
command: 'get_event_poller_user_params',
payload: JSON.stringify({
id: oRule.event.split(' -> ')[0]
})
};
$.post('/usercommand', obj).done(function(data) {
var oParam, par;
oParams = JSON.parse(data.message);
for (param in oParams) {
oParam = oParams[param];
par = $("#event_poller_params tr:contains(" + param + ")").parent();
$('input', par).val(oParam.value);
$('input', par).attr('unchanged', 'true');
}
return $('input', par).change(function() {
return $(this).attr('unchanged', 'false');
});
});
}
$('#input_event').val(oRule.event);
$('#event_interval').val(oRule.event_interval);
editor.setValue(JSON.stringify(oRule.conditions));
oActions = {};
_ref = oRule.actions;
_results = [];
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
action = _ref[_j];
fAddSelectedAction(action);
arrName = action.split(' -> ');
if (!oActions[arrName[0]]) {
oActions[arrName[0]] = [];
}
oActions[arrName[0]].push(arrName[1]);
}
fAddActionModuleParams = function(name) {
return function(data) {
var domMod, oParam, par;
oParams = JSON.parse(data.message);
domMod = $("#action_params div.modName:contains(" + name + ")").parent();
for (param in oParams) {
oParam = oParams[param];
par = $("td.key:contains(" + param + ")", domMod).parent();
$('input', par).val(oParam.value);
$('input', par).attr('unchanged', 'true');
}
return $('input', par).change(function() {
return $(this).attr('unchanged', 'false');
});
};
};
fAddActionModuleArgs = function(name) {
return function(data) {
var arrFuncs, key, oFunc, par, tr, _ref1, _results;
_ref1 = data.message;
_results = [];
for (key in _ref1) {
arrFuncs = _ref1[key];
par = $("#selected_actions td.title:contains(" + name + " -> " + key + ")").parent();
_results.push((function() {
var _k, _len2, _ref2, _results1;
_ref2 = JSON.parse(arrFuncs);
_results1 = [];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
oFunc = _ref2[_k];
tr = $(".funcarg:contains(" + oFunc.argument + ")", par).parent().parent();
$("input[type=text]", tr).val(oFunc.value);
_results1.push($("input[type=checkbox]", tr).prop('checked', oFunc.regexp));
}
return _results1;
})());
}
return _results;
};
};
_results = [];
for (mod in oActions) {
arrMod = oActions[mod];
obj = {
command: 'get_action_invoker_user_params',
payload: JSON.stringify({
id: mod
})
};
$.post('/usercommand', obj).done(fAddActionModuleParams(mod));
obj.command = 'get_action_invoker_user_arguments';
obj.payload = JSON.stringify({
ruleId: oRule.id,
moduleId: mod
});
_results.push($.post('/usercommand', obj).done(fAddActionModuleArgs(mod)));
_results.push(fAddSelectedAction(action));
}
return _results;
}

View file

@ -18,14 +18,40 @@ exports.newMail = ( pushEvent ) ->
# Syntax: needle.request method, url, data, [options], callback
#
needle.request 'get', url, null, null, ( err, resp, body ) ->
log 'Poll function executed'
if err
log 'Error in EmailYak EM newMail: ' + err.message
else
if resp.statusCode is 200
for mail in body.Emails
pushEvent
subject: mail.Subject
content: mail.TextBody
if body.Emails.length > 0
log JSON.stringify body.Emails[0]
log 'Poll function executed'
pushEvent mail for mail in body.Emails
###
This will emit events of the form:
( Refer to http://docs.emailyak.com/get-new-email.html for more information. )
{
"EmailID": "xquukd5z",
"Received": "2014-04-19T11:27:11",
"ToAddress": "test@mscliveweb.simpleyak.com",
"ParsedData": [
{
"Data": "Best Regards\nTest User",
"Part": 0,
"Type": "Email"
}
],
"FromName": "Test User",
"ToAddressList": "test@mscliveweb.simpleyak.com",
"FromAddress": "test.address@provider.com",
"HtmlBody": "Best Regards\nTest User",
"CcAddressList": "",
"TextBody": "Best Regards\nTest User",
"Subject": "test subject"
}
###
</script>
<script id="template_action_invoker" type="text/template">
###
@ -72,6 +98,7 @@ callService = ( args ) ->
if not args.callback
args.callback = standardCallback 'call'
url = urlService + args.service + '/' + args.method
log 'call service executed: ' + url
needle.request 'post', url, args.data, credentials, args.callback
@ -116,7 +143,7 @@ exports.makeFileEntry = ( fromService, fromId, toCompany, toContext ) ->
Calls the content get service with the content id and the service id provided.
@param {Object} args the object containing the service id and the content id,
success and error callback methods
success and error callback methods
@param {String} args.serviceid the service id that is able to process this content
@param {String} args.contentid the content id
@param {function} [args.callback] receives the needle answer from the "call" function

View file

@ -6,7 +6,7 @@
<div id="event_poller_params"></div>
<br>
<h2>CONDITIONS</h2>
Refer to <a target="_blank" href="https://github.com/harthur/js-select#selectors">js-select selectors</a> for valid selectors!
Refer to <a target="_blank" href="https://github.com/harthur/js-select#selectors">js-select selectors</a> for valid selectors! ( only the first matching element will be returned )
<table>
<tr><td>
<div id="editor_conditions">