diff --git a/coffee/components-manager.coffee b/coffee/components-manager.coffee index 6d1c260..d9e8d49 100644 --- a/coffee/components-manager.coffee +++ b/coffee/components-manager.coffee @@ -62,8 +62,11 @@ exports.addRuleListener = ( eh ) => try oRule = JSON.parse strRule db.resetLog userName, oRule.id - db.appendLog userName, oRule.id, "INIT", "Rule '#{ oRule.id }' initialized. - Interval set to #{ oRule.event_interval } minutes" + + eventInfo = '' + if oRule.event_start + eventInfo = "Starting at #{ new Date( oRule.event_start ) }, Interval set to #{ oRule.event_interval } minutes" + db.appendLog userName, oRule.id, "INIT", "Rule '#{ oRule.id }' initialized. #{ eventInfo }" eventEmitter.emit 'rule', event: 'init' @@ -187,13 +190,13 @@ getModuleUserArguments = ( user, oPayload, dbMod, callback ) -> answ.message = oPayload callback answ -forgeModule = ( user, oPayload, dbMod, callback ) => +forgeModule = ( user, oPayload, modType, dbMod, callback ) => answ = hasRequiredParams [ 'id', 'params', 'lang', 'data' ], oPayload if answ.code isnt 200 callback answ else if oPayload.overwrite - storeModule user, oPayload, dbMod, callback + storeModule user, oPayload, modType, dbMod, callback else dbMod.getModule user.username, oPayload.id, ( err, mod ) => if mod @@ -201,11 +204,11 @@ forgeModule = ( user, oPayload, dbMod, callback ) => answ.message = 'Module name already existing: ' + oPayload.id callback answ else - storeModule user, oPayload, dbMod, callback + storeModule user, oPayload, modType, dbMod, callback -storeModule = ( user, oPayload, dbMod, callback ) => +storeModule = ( user, oPayload, modType, dbMod, callback ) => src = oPayload.data - dynmod.compileString src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, ( cm ) => + dynmod.compileString src, user.username, id: 'dummyRule' , oPayload.id, oPayload.lang, modType, null, ( cm ) => answ = cm.answ if answ.code is 200 funcs = [] @@ -311,7 +314,7 @@ commandFunctions = message: obj forge_event_poller: ( user, oPayload, callback ) -> - forgeModule user, oPayload, db.eventPollers, callback + forgeModule user, oPayload, "eventpoller", db.eventPollers, callback delete_event_poller: ( user, oPayload, callback ) -> answ = hasRequiredParams [ 'id' ], oPayload @@ -358,7 +361,7 @@ commandFunctions = message: obj forge_action_invoker: ( user, oPayload, callback ) -> - forgeModule user, oPayload, db.actionInvokers, callback + forgeModule user, oPayload, "actioninvoker", db.actionInvokers, callback delete_action_invoker: ( user, oPayload, callback ) -> answ = hasRequiredParams [ 'id' ], oPayload diff --git a/coffee/dynamic-modules.coffee b/coffee/dynamic-modules.coffee index 1bca5ce..969b6dc 100644 --- a/coffee/dynamic-modules.coffee +++ b/coffee/dynamic-modules.coffee @@ -27,7 +27,6 @@ cryptoJS = require 'crypto-js' importio = require( 'import-io' ).client - ### Module call ----------- @@ -63,7 +62,7 @@ compile it first into JS. @param {Object} params @param {String} lang ### -exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) => +exports.compileString = ( src, userId, oRule, modId, lang, modType, dbMod, cb ) => if lang is 'CoffeeScript' try @log.info "DM | Compiling module '#{ modId }' for user '#{ userId }'" @@ -84,16 +83,30 @@ exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) => oParams = {} for name, oParam of JSON.parse obj oParams[ name ] = encryption.decrypt oParam.value - @log.info "DM | Loaded user defined params for #{ userId }, #{ ruleId }, #{ modId }" + @log.info "DM | Loaded user defined params for #{ userId }, #{ oRule.id }, #{ modId }" catch err - @log.warn "DM | Error during parsing of user defined params for #{ userId }, #{ ruleId }, #{ modId }" + @log.warn "DM | Error during parsing of user defined params for #{ userId }, #{ oRule.id }, #{ modId }" @log.warn err - fTryToLoadModule userId, ruleId, modId, src, dbMod, oParams, cb + fTryToLoadModule userId, oRule, modId, src, modType, dbMod, oParams, cb else - fTryToLoadModule userId, ruleId, modId, src, dbMod, null, cb + fTryToLoadModule userId, oRule, modId, src, modType, dbMod, null, cb -fTryToLoadModule = ( userId, ruleId, modId, src, dbMod, params, cb ) => +fPushEvent = ( userId, oRule, modType ) -> + ( obj ) -> + timestamp = ( new Date() ).toISOString() + rand = ( Math.floor Math.random() * 10e9 ).toString( 16 ).toUpperCase() + if modType is 'eventpoller' + db.pushEvent + event: oRule.event + '_created:' + oRule.timestamp + eventid: "#{ userId }_#{ oRule.event }_UTC|#{ timestamp }_#{ rand }" + payload: obj + + else + obj.eventid = "#{ userId }_#{ oRule.event }_UTC|#{ timestamp }_#{ rand }" + db.pushEvent obj + +fTryToLoadModule = ( userId, oRule, modId, src, modType, dbMod, params, cb ) => if not params params = {} @@ -103,10 +116,10 @@ fTryToLoadModule = ( userId, ruleId, modId, src, dbMod, params, cb ) => @log.info "DM | Running module '#{ modId }' for user '#{ userId }'" # The function used to provide logging mechanisms on a per rule basis - logFunc = logFunction userId, ruleId, modId + logFunc = logFunction userId, oRule.id, modId # The sandbox contains the objects that are accessible to the user. Eventually they need to be required from a vm themselves sandbox = - id: "#{ userId }.#{ ruleId }.#{ modId }.vm" + id: "#{ userId }.#{ oRule.id }.#{ modId }.vm" params: params needle: needle importio: importio @@ -115,6 +128,8 @@ fTryToLoadModule = ( userId, ruleId, modId, src, dbMod, params, cb ) => log: logFunc debug: console.log exports: {} + pushEvent: fPushEvent userId, oRule, modType + #TODO child_process to run module! #Define max runtime per function call as 10 seconds, after that the child will be killed @@ -132,7 +147,7 @@ fTryToLoadModule = ( userId, ruleId, modId, src, dbMod, params, cb ) => msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number' answ.message = 'Loading Module failed: ' + msg - @log.info "DM | Module '#{ modId }' ran successfully for user '#{ userId }' in rule '#{ ruleId }'" + @log.info "DM | Module '#{ modId }' ran successfully for user '#{ userId }' in rule '#{ oRule.id }'" oFuncParams = {} oFuncArgs = {} for fName, func of sandbox.exports @@ -146,12 +161,12 @@ fTryToLoadModule = ( userId, ruleId, modId, src, dbMod, params, cb ) => if obj try oFuncArgs[ fName ] = JSON.parse obj - @log.info "DM | Found and attached user-specific arguments to #{ userId }, #{ ruleId }, #{ modId }: #{ obj }" + @log.info "DM | Found and attached user-specific arguments to #{ userId }, #{ oRule.id }, #{ modId }: #{ obj }" catch err - @log.warn "DM | Error during parsing of user-specific arguments for #{ userId }, #{ ruleId }, #{ modId }" + @log.warn "DM | Error during parsing of user-specific arguments for #{ userId }, #{ oRule.id }, #{ modId }" @log.warn err for func of oFuncParams - dbMod.getUserArguments userId, ruleId, modId, func, fRegisterArguments func + dbMod.getUserArguments userId, oRule.id, modId, func, fRegisterArguments func cb answ: answ module: sandbox.exports diff --git a/coffee/engine.coffee b/coffee/engine.coffee index 062e0da..34e0dac 100644 --- a/coffee/engine.coffee +++ b/coffee/engine.coffee @@ -150,10 +150,11 @@ updateActionModules = ( updatedRuleId ) => # we compile the module and pass: dynmod.compileString obj.data, # code userName, # userId - oMyRule.rule.id, # ruleId + oMyRule.rule, # oRule moduleName, # moduleId obj.lang, # script language - db.actionInvokers, # the DB interface + "actioninvoker", # module type + db.actionInvokers, # the DB interface ( result ) => if result.answ.code is 200 @log.info "EN | Module '#{ moduleName }' successfully loaded for userName @@ -245,12 +246,13 @@ processEvent = ( evt ) => for oArg in node.funcArgs[ funcName ] arrSelectors = oArg.value.match /#\{(.*?)\}/g argument = oArg.value - for sel in arrSelectors - selector = sel.substring 2, sel.length - 1 - data = jsonQuery( evt.payload, selector ).nodes()[ 0 ] - argument = argument.replace sel, data - if oArg.value is sel - argument = data # if the user wants to pass an object, we allow him to do so + if arrSelectors + for sel in arrSelectors + selector = sel.substring 2, sel.length - 1 + data = jsonQuery( evt.payload, selector ).nodes()[ 0 ] + argument = argument.replace sel, data + if oArg.value is sel + argument = data # if the user wants to pass an object, we allow him to do so # if oArg.jsselector arrArgs.push argument #jsonQuery( evt.payload, oArg.value ).nodes()[ 0 ] # else diff --git a/coffee/event-poller.coffee b/coffee/event-poller.coffee index 18acf1d..c3294f5 100644 --- a/coffee/event-poller.coffee +++ b/coffee/event-poller.coffee @@ -82,9 +82,10 @@ fLoadModule = ( msg ) -> # we compile the module and pass: dynmod.compileString obj.data, # code msg.user, # userId - msg.rule.id, # ruleId + msg.rule, # oRule arrName[0], # moduleId obj.lang, # script language + "eventpoller", # the module type db.eventPollers, # the DB interface ( result ) -> if not result.answ is 200 @@ -105,7 +106,6 @@ fLoadModule = ( msg ) -> event_interval: msg.rule.event_interval * 60 * 1000 module: result.module logger: result.logger - oUser[msg.rule.id].module.pushEvent = fPushEvent msg.user, msg.rule.id, oUser[msg.rule.id] start = new Date msg.rule.event_start nd = new Date() @@ -133,12 +133,6 @@ fLoadModule = ( msg ) -> not listUserModules[msg.user][msg.rule.id] fAnonymous() -fPushEvent = ( userId, ruleId, oRule ) -> - ( obj ) -> - db.pushEvent - event: oRule.id + '_created:' + oRule.timestamp - eventid: "polled #{ oRule.id } #{ userId }_UTC|#{ ( new Date() ).toISOString() }" - payload: obj fCheckAndRun = ( userId, ruleId, timestamp ) -> () -> log.info "EP | Check and run user #{ userId }, rule #{ ruleId }" diff --git a/config/system.json b/config/system.json index a8a08ec..cf5bf8b 100644 --- a/config/system.json +++ b/config/system.json @@ -1,7 +1,7 @@ { "http-port": 8125, "db-port": 6379, - "db-select": 1, + "db-select": 0, "log": { "nolog": "false", "mode": "productive", diff --git a/examples/TODO b/examples/TODO new file mode 100644 index 0000000..ff2b13a --- /dev/null +++ b/examples/TODO @@ -0,0 +1,6 @@ +TODO's webservices + +Google: (OAuth) +https://developers.google.com/accounts/docs/OAuth2WebServer + +Github Webhook \ No newline at end of file diff --git a/examples/event-pollers/continuously.coffee b/examples/event-pollers/continuously.coffee index a264598..da209eb 100644 --- a/examples/event-pollers/continuously.coffee +++ b/examples/event-pollers/continuously.coffee @@ -2,5 +2,5 @@ # Pushes an event into the system each time the function is polled # exports.push = () -> - exports.pushEvent + pushEvent content: "This is an event that will be sent again and again every ten seconds" \ No newline at end of file diff --git a/examples/event-pollers/emailyak.coffee b/examples/event-pollers/emailyak.coffee index 521bd4e..b44250d 100644 --- a/examples/event-pollers/emailyak.coffee +++ b/examples/event-pollers/emailyak.coffee @@ -23,7 +23,7 @@ exports.newMail = () -> if resp.statusCode is 200 if body.Emails.length > 0 log "#{ body.Emails.length } mail events pushed into the system" - exports.pushEvent mail for mail in body.Emails + pushEvent mail for mail in body.Emails ### This will emit events of the form: diff --git a/examples/event-pollers/importio.coffee b/examples/event-pollers/importio.coffee index fe440ff..51ff6c3 100644 --- a/examples/event-pollers/importio.coffee +++ b/examples/event-pollers/importio.coffee @@ -49,7 +49,7 @@ queryService = ( inputParams ) -> data = data.concat msg.data.results if finished log JSON.stringify data - exports.pushEvent data + pushEvent data exports.meteoblueWeekData = ( idCity ) -> params = diff --git a/examples/event-pollers/neospeech.coffee b/examples/event-pollers/neospeech.coffee new file mode 100644 index 0000000..0356c39 --- /dev/null +++ b/examples/event-pollers/neospeech.coffee @@ -0,0 +1,111 @@ +# Neospeech +# +# Converts text to speech and issues an event into th system on completion +# +# Requires user-specific parameters: +# +# - emailaccount +# - accountid +# - loginkey +# - loginpassword + +arrVoices = [ + "TTS_KATE_DB" + "TTS_PAUL_DB" + "TTS_JULIE_DB" + "TTS_NEOBRIDGET_DB" + "TTS_NEOVIOLETA_DB" +] + +arrFormats = [ + "FORMAT_WAV" # (16bit linear PCM Wave) + "FORMAT_PCM" # (16bit linear PCM) + "FORMAT_MULAW" # (8bit Mu-law PCM) + "FORMAT_ALAW" # (8bit A-law PCM) + "FORMAT_ADPCM" # (4bit Dialogic ADPCM) + "FORMAT_OGG" # (Ogg Vorbis) + "FORMAT_8BITWAV" # (8bit unsigned linear PCM Wave) + "FORMAT_AWAV" # (8bit A-law PCM Wave) + "FORMAT_MUWAV" # (8bit Mu-law PCM Wave) +] + +# oResponseCodes = +# "0": "success" +# "-1": "invalid login" +# "-2": "account inactive" +# "-3": "account unauthorized" +# "-4": "invalid or inactive login key" +# "-5": "invalid conversion number lookup" +# "-6": "content size is too large (only for “Basic” subscribers)" +# "-7": "monthly allowance has been exceeded (only for “Basic” subscribers)" +# "-10": "invalid TTS Voice ID" +# "-11": "invalid TTS Output Format ID" +# "-12": "invalid REST request" +# "-13": "invalid or unavailable TTS Sample Rate" +# "1": "invalid SSML (not a valid XML document)" +# "2": "invalid SSML (SSML content must begin with a “speak” tag)" +# "3": "invalid SSML (“lexicon” tag is not supported)" + +parseAnswer = ( body ) -> + arrSelectors = body.match /(\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/g + oAnswer = {} + for sel in arrSelectors + arrSel = sel.split '=' + oAnswer[ arrSel[ 0 ] ] = arrSel[ 1 ].substring 1, arrSel[ 1 ].length - 1 + oAnswer + +# Function arguments: +# - text: the text to be translated into voice +# - idVoice: index of the voice used for conversion from the arrVoices array. +# - idAudioFormat: index of the voice used for conversion from the arrVoices array. +# - sampleRate: 8 or 16 kHz rate +exports.convertTextToSpeech = ( text, idVoice, idAudioFormat, sampleRate ) -> + idVoice = parseInt( idVoice ) || 0 + if idVoice > arrVoices.length - 1 or idVoice < 0 + idVoice = 0 + + idAudioFormat = parseInt( idAudioFormat ) || 0 + if idAudioFormat > arrFormats.length - 1 or idAudioFormat < 0 + idAudioFormat = 0 + + sampleRate = parseInt( sampleRate ) || 8 + if sampleRate isnt 8 or sampleRate isnt 16 + sampleRate = 8 + + oPost = + method: "ConvertSimple" + email: params.emailaccount + accountId: params.accountid + loginKey: params.loginkey + loginPassword: params.loginpassword + voice: arrVoices[ idVoice ] + outputFormat: arrFormats[ idAudioFormat ] + sampleRate: sampleRate + text: text + + needle.post "https://tts.neospeech.com/rest_1_1.php", oPost, ( err, resp, body ) -> + oAnsw = parseAnswer body + log 'Conversion order: ' + oAnsw.resultString + if oAnsw.resultCode is '0' + pollUntilDone oAnsw.resultCode, params.emailaccount, params.accountid + +pollUntilDone = ( conversionNumber, email, accountid ) -> + oPost = + method: "GetConversionStatus" + email: email + accountId: accountid + conversionNumber: conversionNumber + + needle.post "https://tts.neospeech.com/rest_1_1.php", oPost, ( err, resp, body ) -> + oAnsw = parseAnswer body + if oAnsw.resultCode is '0' + if oAnsw.statusCode is '4' or oAnsw.statusCode is '5' + pushEvent + event: "NeospeechConversionCompleted" + payload: + accountid: accountid + downloadUrl: oAnsw.downloadUrl + else + pollUntilDone conversionNumber, email, accountid + else + log 'Request failed: ' + oAnsw.resultString diff --git a/examples/event-pollers/probinder.coffee b/examples/event-pollers/probinder.coffee index 0fff979..4155712 100644 --- a/examples/event-pollers/probinder.coffee +++ b/examples/event-pollers/probinder.coffee @@ -53,7 +53,7 @@ exports.unreadContentInfo = () -> method: 'unreadcontent' callback: ( err, resp, body ) -> if not err and resp.statusCode is 200 - exports.pushEvent oEntry for oEntry in body + pushEvent oEntry for oEntry in body else log 'Error: ' + body.error.message @@ -67,7 +67,7 @@ exports.unreadContent = () -> contentServiceId: evt.serviceId callback: ( err, resp, body ) -> if not err and resp.statusCode is 200 - exports.pushEvent + pushEvent id: body.id content: body.text object: body diff --git a/examples/event-pollers/security.coffee b/examples/event-pollers/security.coffee new file mode 100644 index 0000000..cd33c67 --- /dev/null +++ b/examples/event-pollers/security.coffee @@ -0,0 +1,43 @@ +# +# Security EVENT POLLER +# --------------------- +# +# Informs about security breaches. +# +# Will emit events of the form: +# [ +# { +# "Title": "Adobe", +# "Name": "Adobe", +# "Domain": "adobe.com", +# "BreachDate": "2013-10-4", +# "AddedDate": "2013-12-4T00:12Z", +# "PwnCount": 152445165, +# "Description": "The big one. In October 2013, 153 million accounts were breached with each containing an internal ID, username, email, encrypted password and a password hint in plain text. The password cryptography was poorly done and many were quickly resolved back to plain text. The unencrypted hints also disclosed much about the passwords adding further to the risk that hundreds of millions of Adobe customers already faced.", +# "DataClasses": [ +# "Email addresses", +# "Password hints", +# "Passwords", +# "Usernames" +# ] +# }, +# [...] +# ] + +oAccountBreaches = {} +exports.breachedAccount = ( account ) -> + needle.get "https://haveibeenpwned.com/api/v2/breachedaccount/#{ account }", ( err, resp, body ) -> + for oBreach in body + myId = oBreach.Title + "_" + oBreach.AddedDate + if not oAccountBreaches[ myId ] + oAccountBreaches[ myId ] = oBreach + pushEvent oBreach + +oBreaches = {} +exports.newBreachedSite = () -> + needle.get 'https://haveibeenpwned.com/api/v2/breaches', ( err, resp, body ) -> + for oBreach in body + myId = oBreach.Title + "_" + oBreach.AddedDate + if not oBreaches[ myId ] + oBreaches[ myId ] = oBreach + pushEvent oBreach diff --git a/examples/event-pollers/system.coffee b/examples/event-pollers/system.coffee index 7f0e404..5dbf26c 100644 --- a/examples/event-pollers/system.coffee +++ b/examples/event-pollers/system.coffee @@ -11,6 +11,6 @@ This event is emitted if the system had a restart. exports.hasRestarted = () -> if not isRunning isRunning = true - exports.pushEvent + pushEvent content: "The system has been restarted at #{ ( new Date ).toISOString() }" diff --git a/examples/event-pollers/weather.coffee b/examples/event-pollers/weather.coffee index c7baec2..6ab0c42 100644 --- a/examples/event-pollers/weather.coffee +++ b/examples/event-pollers/weather.coffee @@ -25,7 +25,7 @@ exports.currentData = () -> if err or resp.statusCode isnt 200 log JSON.stringify body else - exports.pushEvent body + pushEvent body ### Emits one event per day if the temperature today raises above user defined threshold @@ -37,7 +37,7 @@ exports.temperatureOverThreshold = () -> else #If temperature is above threshold if body.main.temp_max - 272.15 > params.tempThreshold - exports.pushEvent + pushEvent threshold: params.tempThreshold measured: body.main.temp_max - 272.15 diff --git a/examples/runscript.coffee b/examples/runscript.coffee index c245cf2..52aba71 100644 --- a/examples/runscript.coffee +++ b/examples/runscript.coffee @@ -34,9 +34,8 @@ sandbox = log: console.log debug: console.log exports: {} - -sandbox.exports.pushEvent = ( obj ) -> - console.log obj + pushEvent: ( obj ) -> + console.log obj vm.runInNewContext src, sandbox, sandbox.id diff --git a/js/components-manager.js b/js/components-manager.js index 3cc3bd5..33aab8a 100644 --- a/js/components-manager.js +++ b/js/components-manager.js @@ -260,14 +260,14 @@ Components Manager }; forgeModule = (function(_this) { - return function(user, oPayload, dbMod, callback) { + return function(user, oPayload, modType, dbMod, callback) { var answ; answ = hasRequiredParams(['id', 'params', 'lang', 'data'], oPayload); if (answ.code !== 200) { return callback(answ); } else { if (oPayload.overwrite) { - return storeModule(user, oPayload, dbMod, callback); + return storeModule(user, oPayload, modType, dbMod, callback); } else { return dbMod.getModule(user.username, oPayload.id, function(err, mod) { if (mod) { @@ -275,7 +275,7 @@ Components Manager answ.message = 'Module name already existing: ' + oPayload.id; return callback(answ); } else { - return storeModule(user, oPayload, dbMod, callback); + return storeModule(user, oPayload, modType, dbMod, callback); } }); } @@ -284,10 +284,12 @@ Components Manager })(this); storeModule = (function(_this) { - return function(user, oPayload, dbMod, callback) { + return function(user, oPayload, modType, dbMod, callback) { var src; src = oPayload.data; - return dynmod.compileString(src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, function(cm) { + return dynmod.compileString(src, user.username, { + id: 'dummyRule' + }, oPayload.id, oPayload.lang, modType, null, function(cm) { var answ, funcs, id, name, _ref; answ = cm.answ; if (answ.code === 200) { @@ -407,7 +409,7 @@ Components Manager } }, forge_event_poller: function(user, oPayload, callback) { - return forgeModule(user, oPayload, db.eventPollers, callback); + return forgeModule(user, oPayload, "eventpoller", db.eventPollers, callback); }, delete_event_poller: function(user, oPayload, callback) { var answ; @@ -463,7 +465,7 @@ Components Manager } }, forge_action_invoker: function(user, oPayload, callback) { - return forgeModule(user, oPayload, db.actionInvokers, callback); + return forgeModule(user, oPayload, "actioninvoker", db.actionInvokers, callback); }, delete_action_invoker: function(user, oPayload, callback) { var answ; diff --git a/js/dynamic-modules.js b/js/dynamic-modules.js index 79cf400..71a6134 100644 --- a/js/dynamic-modules.js +++ b/js/dynamic-modules.js @@ -9,7 +9,7 @@ Dynamic Modules */ (function() { - var cryptoJS, cs, db, encryption, exports, fTryToLoadModule, getFunctionParamNames, importio, logFunction, needle, regexpComments, request, vm; + var cryptoJS, cs, db, encryption, exports, fPushEvent, fTryToLoadModule, getFunctionParamNames, importio, logFunction, needle, regexpComments, request, vm; db = require('./persistence'); @@ -76,7 +76,7 @@ Dynamic Modules */ exports.compileString = (function(_this) { - return function(src, userId, ruleId, modId, lang, dbMod, cb) { + return function(src, userId, oRule, modId, lang, modType, dbMod, cb) { var err; if (lang === 'CoffeeScript') { try { @@ -104,22 +104,40 @@ Dynamic Modules oParam = _ref[name]; oParams[name] = encryption.decrypt(oParam.value); } - _this.log.info("DM | Loaded user defined params for " + userId + ", " + ruleId + ", " + modId); + _this.log.info("DM | Loaded user defined params for " + userId + ", " + oRule.id + ", " + modId); } catch (_error) { err = _error; - _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + ruleId + ", " + modId); + _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + oRule.id + ", " + modId); _this.log.warn(err); } - return fTryToLoadModule(userId, ruleId, modId, src, dbMod, oParams, cb); + return fTryToLoadModule(userId, oRule, modId, src, modType, dbMod, oParams, cb); }); } else { - return fTryToLoadModule(userId, ruleId, modId, src, dbMod, null, cb); + return fTryToLoadModule(userId, oRule, modId, src, modType, dbMod, null, cb); } }; })(this); + fPushEvent = function(userId, oRule, modType) { + return function(obj) { + var rand, timestamp; + timestamp = (new Date()).toISOString(); + rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase(); + if (modType === 'eventpoller') { + return db.pushEvent({ + event: oRule.event + '_created:' + oRule.timestamp, + eventid: "" + userId + "_" + oRule.event + "_UTC|" + timestamp + "_" + rand, + payload: obj + }); + } else { + obj.eventid = "" + userId + "_" + oRule.event + "_UTC|" + timestamp + "_" + rand; + return db.pushEvent(obj); + } + }; + }; + fTryToLoadModule = (function(_this) { - return function(userId, ruleId, modId, src, dbMod, params, cb) { + return function(userId, oRule, modId, src, modType, dbMod, params, cb) { var answ, err, fName, fRegisterArguments, func, logFunc, msg, oFuncArgs, oFuncParams, sandbox, _ref; if (!params) { params = {}; @@ -129,9 +147,9 @@ Dynamic Modules message: 'Successfully compiled' }; _this.log.info("DM | Running module '" + modId + "' for user '" + userId + "'"); - logFunc = logFunction(userId, ruleId, modId); + logFunc = logFunction(userId, oRule.id, modId); sandbox = { - id: "" + userId + "." + ruleId + "." + modId + ".vm", + id: "" + userId + "." + oRule.id + "." + modId + ".vm", params: params, needle: needle, importio: importio, @@ -139,7 +157,8 @@ Dynamic Modules cryptoJS: cryptoJS, log: logFunc, debug: console.log, - exports: {} + exports: {}, + pushEvent: fPushEvent(userId, oRule, modType) }; try { vm.runInNewContext(src, sandbox, sandbox.id); @@ -152,7 +171,7 @@ Dynamic Modules } answ.message = 'Loading Module failed: ' + msg; } - _this.log.info("DM | Module '" + modId + "' ran successfully for user '" + userId + "' in rule '" + ruleId + "'"); + _this.log.info("DM | Module '" + modId + "' ran successfully for user '" + userId + "' in rule '" + oRule.id + "'"); oFuncParams = {}; oFuncArgs = {}; _ref = sandbox.exports; @@ -167,17 +186,17 @@ Dynamic Modules if (obj) { try { oFuncArgs[fName] = JSON.parse(obj); - return _this.log.info("DM | Found and attached user-specific arguments to " + userId + ", " + ruleId + ", " + modId + ": " + obj); + return _this.log.info("DM | Found and attached user-specific arguments to " + userId + ", " + oRule.id + ", " + modId + ": " + obj); } catch (_error) { err = _error; - _this.log.warn("DM | Error during parsing of user-specific arguments for " + userId + ", " + ruleId + ", " + modId); + _this.log.warn("DM | Error during parsing of user-specific arguments for " + userId + ", " + oRule.id + ", " + modId); return _this.log.warn(err); } } }; }; for (func in oFuncParams) { - dbMod.getUserArguments(userId, ruleId, modId, func, fRegisterArguments(func)); + dbMod.getUserArguments(userId, oRule.id, modId, func, fRegisterArguments(func)); } } return cb({ diff --git a/js/engine.js b/js/engine.js index a0c28bd..3d92316 100644 --- a/js/engine.js +++ b/js/engine.js @@ -168,7 +168,7 @@ Engine if (!oMyRule.actions[moduleName] || oMyRule.rule.id === updatedRuleId) { return db.actionInvokers.getModule(userName, moduleName, function(err, obj) { if (obj) { - return dynmod.compileString(obj.data, userName, oMyRule.rule.id, moduleName, obj.lang, db.actionInvokers, function(result) { + return dynmod.compileString(obj.data, userName, oMyRule.rule, moduleName, obj.lang, "actioninvoker", db.actionInvokers, function(result) { if (result.answ.code === 200) { _this.log.info("EN | Module '" + moduleName + "' successfully loaded for userName '" + userName + "' in rule '" + oMyRule.rule.id + "'"); } else { @@ -312,13 +312,15 @@ Engine oArg = _ref[_i]; arrSelectors = oArg.value.match(/#\{(.*?)\}/g); argument = oArg.value; - for (_j = 0, _len1 = arrSelectors.length; _j < _len1; _j++) { - sel = arrSelectors[_j]; - selector = sel.substring(2, sel.length - 1); - data = jsonQuery(evt.payload, selector).nodes()[0]; - argument = argument.replace(sel, data); - if (oArg.value === sel) { - argument = data; + if (arrSelectors) { + for (_j = 0, _len1 = arrSelectors.length; _j < _len1; _j++) { + sel = arrSelectors[_j]; + selector = sel.substring(2, sel.length - 1); + data = jsonQuery(evt.payload, selector).nodes()[0]; + argument = argument.replace(sel, data); + if (oArg.value === sel) { + argument = data; + } } } arrArgs.push(argument); diff --git a/js/event-poller.js b/js/event-poller.js index 5c6f452..e089b9e 100644 --- a/js/event-poller.js +++ b/js/event-poller.js @@ -9,7 +9,7 @@ Dynamic Modules */ (function() { - var db, dynmod, encryption, fCallFunction, fCheckAndRun, fLoadModule, fPushEvent, isRunning, listUserModules, log, logconf, logger, pollLoop; + var db, dynmod, encryption, fCallFunction, fCheckAndRun, fLoadModule, isRunning, listUserModules, log, logconf, logger, pollLoop; logger = require('./logging'); @@ -85,7 +85,7 @@ Dynamic Modules if (!obj) { 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) { + return dynmod.compileString(obj.data, msg.user, msg.rule, arrName[0], obj.lang, "eventpoller", db.eventPollers, function(result) { var nd, now, oUser, start; if (!result.answ === 200) { log.error("EP | Compilation of code failed! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]); @@ -103,7 +103,6 @@ Dynamic Modules module: result.module, logger: result.logger }; - oUser[msg.rule.id].module.pushEvent = fPushEvent(msg.user, msg.rule.id, oUser[msg.rule.id]); start = new Date(msg.rule.event_start); nd = new Date(); now = new Date(); @@ -129,16 +128,6 @@ Dynamic Modules } }; - fPushEvent = function(userId, ruleId, oRule) { - return function(obj) { - return db.pushEvent({ - event: oRule.id + '_created:' + oRule.timestamp, - eventid: "polled " + oRule.id + " " + userId + "_UTC|" + ((new Date()).toISOString()), - payload: obj - }); - }; - }; - fCheckAndRun = function(userId, ruleId, timestamp) { return function() { var oRule; diff --git a/testing/test_dynamic-modules.coffee b/testing/test_dynamic-modules.coffee index 8543fa8..1cf7bd4 100644 --- a/testing/test_dynamic-modules.coffee +++ b/testing/test_dynamic-modules.coffee @@ -51,14 +51,14 @@ exports.testCompile = ( test ) -> paramOne = 'First Test' code = "exports.testFunc = () ->\n\t'#{ paramOne }'" - dm.compileString code, 'userOne', 'ruleOne', 'moduleOne', 'CoffeeScript', null, ( result ) -> + dm.compileString code, 'userOne', 'ruleOne', 'moduleOne', 'CoffeeScript', 'eventpoller', null, ( result ) -> test.strictEqual 200, result.answ.code moduleOne = result.module test.strictEqual paramOne, moduleOne.testFunc(), "Other result expected" paramTwo = 'Second Test' code = "exports.testFunc = () ->\n\t'#{ paramTwo }'" - dm.compileString code, 'userOne', 'ruleOne', 'moduleOne', 'CoffeeScript', null, ( result ) -> + dm.compileString code, 'userOne', 'ruleOne', 'moduleOne', 'CoffeeScript', 'eventpoller', null, ( result ) -> test.strictEqual 200, result.answ.code moduleTwo = result.module test.strictEqual paramTwo, moduleTwo.testFunc(), "Other result expected"