mirror of
https://github.com/Hopiu/webapi-eca.git
synced 2026-03-16 22:10:31 +00:00
User-parameter support implemented, system seems to run smoothly
This commit is contained in:
parent
c71bf520a4
commit
418d5441fe
29 changed files with 1053 additions and 452 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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).
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
})());
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
63
webpages/handlers/coffee/edit_rules.coffee
Normal file
63
webpages/handlers/coffee/edit_rules.coffee
Normal file
|
|
@ -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 = $ '<tr>'
|
||||
img = $( '<img>' ).attr( 'class', 'del' ).attr 'src', 'red_cross_small.png'
|
||||
imgTwo = $( '<img>' ).attr( 'class', 'log' ).attr 'src', 'logicon.png'
|
||||
inp = $( '<div>' ).text ruleName
|
||||
tr.append( $( '<td>' ).append img )
|
||||
tr.append( $( '<td>' ).append imgTwo )
|
||||
tr.append( $( '<td>' ).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'), "<br>"
|
||||
$( '#log_col' ).html "<h3>#{ ruleName } Log:</h3>#{ log }"
|
||||
.fail fErrHandler 'Could not get rule log! '
|
||||
|
||||
window.addEventListener 'load', fOnLoad, true
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = $ '<table>'
|
||||
$( '#event_poller_params' ).append table
|
||||
fAppendParam = ( name ) ->
|
||||
tr = $( '<tr>' )
|
||||
tr.append $( '<td>' ).css 'width', '20px'
|
||||
tr.append $( '<td>' ).attr( 'class', 'key' ).text name
|
||||
inp = $( '<input>' ).attr( 'type', 'password' ).attr 'id', "#{ name }"
|
||||
tr.append $( '<td>' ).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 = $ '<table>'
|
||||
$( '#event_poller_params' ).append table
|
||||
fAppendParam = ( name ) ->
|
||||
tr = $( '<tr>' )
|
||||
tr.append $( '<td>' ).css 'width', '20px'
|
||||
tr.append $( '<td>' ).attr( 'class', 'key' ).text name
|
||||
inp = $( '<input>' ).attr( 'type', 'password' ).attr 'id', "#{ name }"
|
||||
tr.append $( '<td>' ).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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
86
webpages/handlers/js/edit_rules.js
Normal file
86
webpages/handlers/js/edit_rules.js
Normal file
|
|
@ -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 = $('<tr>');
|
||||
img = $('<img>').attr('class', 'del').attr('src', 'red_cross_small.png');
|
||||
imgTwo = $('<img>').attr('class', 'log').attr('src', 'logicon.png');
|
||||
inp = $('<div>').text(ruleName);
|
||||
tr.append($('<td>').append(img));
|
||||
tr.append($('<td>').append(imgTwo));
|
||||
tr.append($('<td>').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'), "<br>");
|
||||
return $('#log_col').html("<h3>" + ruleName + " Log:</h3>" + log);
|
||||
}).fail(fErrHandler('Could not get rule log! '));
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener('load', fOnLoad, true);
|
||||
|
||||
}).call(this);
|
||||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 = $('<table>');
|
||||
$('#event_poller_params').append(table);
|
||||
fAppendParam = function(name) {
|
||||
var inp, tr;
|
||||
tr = $('<tr>');
|
||||
tr.append($('<td>').css('width', '20px'));
|
||||
tr.append($('<td>').attr('class', 'key').text(name));
|
||||
inp = $('<input>').attr('type', 'password').attr('id', "" + name);
|
||||
tr.append($('<td>').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 = $('<table>');
|
||||
$('#event_poller_params').append(table);
|
||||
fAppendParam = function(name) {
|
||||
var inp, tr;
|
||||
tr = $('<tr>');
|
||||
tr.append($('<td>').css('width', '20px'));
|
||||
tr.append($('<td>').attr('class', 'key').text(name));
|
||||
inp = $('<input>').attr('type', 'password').attr('id', "" + name);
|
||||
tr.append($('<td>').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;
|
||||
|
|
|
|||
12
webpages/handlers/templates/edit_rules.html
Normal file
12
webpages/handlers/templates/edit_rules.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<h3>Active Rules:</h3>
|
||||
<table id="tableRules"></table>
|
||||
</td>
|
||||
<td width="50px"></td>
|
||||
<td valign="top" id="log_col">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
@ -21,7 +21,7 @@ Action Invoker Name: <input id="input_id" type="text" />
|
|||
# - 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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 496 B |
BIN
webpages/public/logicon.png
Normal file
BIN
webpages/public/logicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 443 B |
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue