From 18b36b84ac384aa3f30387d938362f91beab1b20 Mon Sep 17 00:00:00 2001 From: Dominic Bosch Date: Wed, 16 Apr 2014 17:42:56 +0200 Subject: [PATCH] We are dirty again, replaced all indents with tabs, tried to fix all the lil things showing up as we test rule upload --- coffee/components-manager.coffee | 486 ++++---- coffee/config.coffee | 66 +- coffee/dynamic-modules.coffee | 207 ++-- coffee/engine.coffee | 237 ++-- coffee/event-poller.coffee | 191 +-- coffee/http-listener.coffee | 126 +- coffee/logging.coffee | 108 +- coffee/persistence.coffee | 756 ++++++------ coffee/request-handler.coffee | 298 ++--- coffee/webapi-eca.coffee | 203 ++-- config/system.json | 3 + examples/action-invokers/probinder.coffee | 66 +- examples/runscript.coffee | 26 +- examples/runscript.js | 45 +- js/components-manager.js | 10 +- js/config.js | 12 +- js/dynamic-modules.js | 171 +-- js/engine.js | 177 +-- js/event-poller.js | 67 +- js/http-listener.js | 47 +- js/persistence.js | 46 +- js/request-handler.js | 40 +- js/sandbox.js | 42 + js/webapi-eca.js | 1 + package.json | 1 + testing/files/testObjects.json | 34 +- testing/test_components-manager.coffee | 275 +++-- testing/test_config.coffee | 60 +- testing/test_dynamic-modules.coffee | 106 +- testing/test_engine.coffee | 206 ++-- testing/test_logging.coffee | 150 +-- testing/test_persistence.coffee | 1032 ++++++++--------- testing/test_request-handler.coffee | 344 +++--- testing/test_webapi-eca.coffee | 200 ++-- webpages/handlers/coffee/admin.coffee | 36 +- webpages/handlers/coffee/edit_modules.coffee | 196 ++-- webpages/handlers/coffee/edit_rules.coffee | 194 ++-- .../coffee/forge_action_invoker.coffee | 172 +-- webpages/handlers/coffee/forge_event.coffee | 66 +- .../handlers/coffee/forge_event_poller.coffee | 172 +-- webpages/handlers/coffee/forge_rule.coffee | 552 +++++---- webpages/handlers/coffee/login.coffee | 30 +- webpages/handlers/js/forge_rule.js | 66 +- .../templates/forge_action_invoker.html | 2 +- webpages/handlers/templates/forge_rule.html | 8 +- 45 files changed, 3771 insertions(+), 3562 deletions(-) create mode 100644 js/sandbox.js diff --git a/coffee/components-manager.coffee b/coffee/components-manager.coffee index 20e1f7b..8bed044 100644 --- a/coffee/components-manager.coffee +++ b/coffee/components-manager.coffee @@ -31,10 +31,10 @@ Initializes the Components Manager and constructs a new Event Emitter. @param {Object} args ### exports = module.exports = ( args ) => - @log = args.logger - db args - dynmod args - module.exports + @log = args.logger + db args + dynmod args + module.exports ### @@ -45,35 +45,35 @@ Add an event handler (eh) that listens for rules. ### exports.addRuleListener = ( eh ) => - eventEmitter.addListener 'rule', eh + eventEmitter.addListener 'rule', eh - # Fetch all active rules per user - db.getAllActivatedRuleIdsPerUser ( err, objUsers ) -> + # Fetch all active rules per user + db.getAllActivatedRuleIdsPerUser ( err, objUsers ) -> - # Go through all rules of each user - fGoThroughUsers = ( user, rules ) -> + # Go through all rules of each user + fGoThroughUsers = ( user, rules ) -> - # Fetch the rules object for each rule in each user - fFetchRule = ( userName ) -> - ( rule ) -> - db.getRule rule, ( err, strRule ) => - try - oRule = JSON.parse strRule - db.resetLog userName, oRule.id - db.appendLog userName, oRule.id, "INIT", "Rule '#{ oRule.id }' initialized" + # Fetch the rules object for each rule in each user + fFetchRule = ( userName ) -> + ( rule ) -> + db.getRule rule, ( err, strRule ) => + try + oRule = JSON.parse strRule + db.resetLog userName, oRule.id + db.appendLog userName, oRule.id, "INIT", "Rule '#{ oRule.id }' initialized" - eventEmitter.emit 'rule', - event: 'init' - user: userName - rule: oRule - catch err - @log.warn "CM | There's an invalid rule in the system: #{ strRule }" + eventEmitter.emit 'rule', + event: 'init' + user: userName + rule: oRule + catch err + @log.warn "CM | There's an invalid rule in the system: #{ strRule }" - # Go through all rules for each user - fFetchRule( user ) rule for rule in rules - - # Go through each user - fGoThroughUsers user, rules for user, rules of objUsers + # Go through all rules for each user + fFetchRule( user ) rule for rule in rules + + # Go through each user + fGoThroughUsers user, rules for user, rules of objUsers ### Processes a user request coming through the request-handler. @@ -81,30 +81,30 @@ Processes a user request coming through the request-handler. - `user` is the user object as it comes from the DB. - `oReq` is the request object that contains: - - `command` as a string - - `payload` an optional stringified JSON object + - `command` as a string + - `payload` an optional stringified JSON object The callback function `callback( obj )` will receive an object containing the HTTP response code and a corresponding message. @public processRequest ( *user, oReq, callback* ) ### exports.processRequest = ( user, oReq, callback ) -> - if not oReq.payload - oReq.payload = '{}' - try - dat = JSON.parse oReq.payload - catch err - return callback - code: 404 - message: 'You had a strange payload in your request!' - if commandFunctions[oReq.command] + if not oReq.payload + oReq.payload = '{}' + try + dat = JSON.parse oReq.payload + catch err + return callback + code: 404 + message: 'You had a strange payload in your request!' + if commandFunctions[oReq.command] - # If the command function was registered we invoke it - commandFunctions[oReq.command] user, dat, callback - else - callback - code: 404 - message: 'What do you want from me?' + # If the command function was registered we invoke it + commandFunctions[oReq.command] user, dat, callback + else + callback + code: 404 + message: 'What do you want from me?' ### Checks whether all required parameters are present in the payload. @@ -114,13 +114,13 @@ Checks whether all required parameters are present in the payload. @param {Object} oPayload ### hasRequiredParams = ( arrParams, oPayload ) -> - answ = - code: 400 - message: "Your request didn't contain all necessary fields! Requires: #{ arrParams.join() }" - return answ for param in arrParams when not oPayload[param] - answ.code = 200 - answ.message = 'All required properties found' - answ + answ = + code: 400 + message: "Your request didn't contain all necessary fields! Requires: #{ arrParams.join() }" + return answ for param in arrParams when not oPayload[param] + answ.code = 200 + answ.message = 'All required properties found' + answ ### Fetches all available modules and return them together with the available functions. @@ -132,211 +132,225 @@ Fetches all available modules and return them together with the available functi @param {function} callback ### getModules = ( user, oPayload, dbMod, callback ) -> - dbMod.getAvailableModuleIds user.username, ( err, arrNames ) -> - oRes = {} - answReq = () -> - callback - code: 200 - message: JSON.stringify oRes - sem = arrNames.length - if sem is 0 - answReq() - else - fGetFunctions = ( id ) => - dbMod.getModule id, ( err, oModule ) => - if oModule - oRes[id] = JSON.parse oModule.functions - if --sem is 0 - answReq() - fGetFunctions id for id in arrNames + dbMod.getAvailableModuleIds user.username, ( err, arrNames ) -> + oRes = {} + answReq = () -> + callback + code: 200 + message: JSON.stringify oRes + sem = arrNames.length + if sem is 0 + answReq() + else + fGetFunctions = ( id ) => + dbMod.getModule id, ( err, oModule ) => + if oModule + oRes[id] = JSON.parse oModule.functions + if --sem is 0 + answReq() + fGetFunctions id for id in arrNames getModuleParams = ( user, oPayload, dbMod, callback ) -> - answ = hasRequiredParams [ 'id' ], oPayload - if answ.code isnt 200 - callback answ - else - dbMod.getModuleParams oPayload.id, ( err, oPayload ) -> - answ.message = oPayload - callback answ + answ = hasRequiredParams [ 'id' ], oPayload + if answ.code isnt 200 + callback answ + else + dbMod.getModuleParams oPayload.id, ( err, oPayload ) -> + answ.message = oPayload + callback answ forgeModule = ( user, oPayload, dbMod, callback ) => - answ = hasRequiredParams [ 'id', 'params', 'lang', 'data' ], oPayload - if answ.code isnt 200 - callback answ - else - i = 0 - dbMod.getModule oPayload.id, ( err, mod ) => - if mod - answ.code = 409 - answ.message = 'Module name already existing: ' + oPayload.id - callback answ - else - src = oPayload.data - 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 = - " Module #{ oPayload.id } successfully stored! Found following function(s): #{ funcs }" - oPayload.functions = JSON.stringify funcs - oPayload.functionParameters = JSON.stringify cm.funcParams - dbMod.storeModule user.username, oPayload - if oPayload.public is 'true' - dbMod.publish oPayload.id - callback answ + answ = hasRequiredParams [ 'id', 'params', 'lang', 'data' ], oPayload + if answ.code isnt 200 + callback answ + else + i = 0 + dbMod.getModule oPayload.id, ( err, mod ) => + if mod + answ.code = 409 + answ.message = 'Module name already existing: ' + oPayload.id + callback answ + else + src = oPayload.data + dynmod.compileString src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, ( cm ) => + console.log 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 = + " Module #{ oPayload.id } successfully stored! Found following function(s): #{ funcs }" + oPayload.functions = JSON.stringify funcs + oPayload.functionArgs = JSON.stringify cm.funcParams + dbMod.storeModule user.username, oPayload + if oPayload.public is 'true' + dbMod.publish oPayload.id + callback answ commandFunctions = - get_public_key: ( user, oPayload, callback ) -> - callback - code: 200 - message: dynmod.getPublicKey() + get_public_key: ( user, oPayload, callback ) -> + callback + code: 200 + message: dynmod.getPublicKey() # EVENT POLLERS # ------------- - get_event_pollers: ( user, oPayload, callback ) -> - getModules user, oPayload, db.eventPollers, callback - - get_full_event_poller: ( user, oPayload, callback ) -> - db.eventPollers.getModule oPayload.id, ( err, obj ) -> - callback - code: 200 - message: JSON.stringify obj - - get_event_poller_params: ( user, oPayload, callback ) -> - getModuleParams user, oPayload, db.eventPollers, callback + get_event_pollers: ( user, oPayload, callback ) -> + getModules user, oPayload, db.eventPollers, callback + + get_full_event_poller: ( user, oPayload, callback ) -> + db.eventPollers.getModule oPayload.id, ( err, obj ) -> + callback + code: 200 + message: JSON.stringify obj + + get_event_poller_params: ( user, oPayload, callback ) -> + getModuleParams user, oPayload, db.eventPollers, callback - forge_event_poller: ( user, oPayload, callback ) -> - forgeModule user, oPayload, db.eventPollers, callback + forge_event_poller: ( user, oPayload, callback ) -> + forgeModule user, oPayload, db.eventPollers, callback - delete_event_poller: ( user, oPayload, callback ) -> - answ = hasRequiredParams [ 'id' ], oPayload - if answ.code isnt 200 - callback answ - else - db.eventPollers.deleteModule oPayload.id - callback - code: 200 - message: 'OK!' + delete_event_poller: ( user, oPayload, callback ) -> + answ = hasRequiredParams [ 'id' ], oPayload + if answ.code isnt 200 + callback answ + else + db.eventPollers.deleteModule oPayload.id + callback + code: 200 + message: 'OK!' # ACTION INVOKERS # --------------- - get_action_invokers: ( user, oPayload, callback ) -> - getModules user, oPayload, db.actionInvokers, callback - - get_full_action_invoker: ( user, oPayload, callback ) -> - answ = hasRequiredParams [ 'id' ], oPayload - if answ.code isnt 200 - callback answ - else - db.actionInvokers.getModule oPayload.id, ( err, obj ) -> - callback - code: 200 - message: JSON.stringify obj + get_action_invokers: ( user, oPayload, callback ) -> + getModules user, oPayload, db.actionInvokers, callback + + get_full_action_invoker: ( user, oPayload, callback ) -> + answ = hasRequiredParams [ 'id' ], oPayload + if answ.code isnt 200 + callback answ + else + db.actionInvokers.getModule oPayload.id, ( err, obj ) -> + callback + code: 200 + message: JSON.stringify obj - get_action_invoker_params: ( user, oPayload, callback ) -> - getModuleParams user, oPayload, db.actionInvokers, callback + get_action_invoker_params: ( user, oPayload, callback ) -> + getModuleParams user, oPayload, db.actionInvokers, callback - get_action_invoker_function_params: ( user, oPayload, callback ) -> - answ = hasRequiredParams [ 'id' ], oPayload - if answ.code isnt 200 - callback answ - else - db.actionInvokers.getModuleField oPayload.id, 'functionParameters', ( err, obj ) -> - callback - code: 200 - message: obj - - forge_action_invoker: ( user, oPayload, callback ) -> - forgeModule user, oPayload, db.actionInvokers, callback + get_action_invoker_function_params: ( user, oPayload, callback ) -> + answ = hasRequiredParams [ 'id' ], oPayload + if answ.code isnt 200 + callback answ + else + db.actionInvokers.getModuleField oPayload.id, 'functionArgs', ( err, obj ) -> + callback + code: 200 + message: obj + + forge_action_invoker: ( user, oPayload, callback ) -> + forgeModule user, oPayload, db.actionInvokers, callback - delete_action_invoker: ( user, oPayload, callback ) -> - answ = hasRequiredParams [ 'id' ], oPayload - if answ.code isnt 200 - callback answ - else - db.actionInvokers.deleteModule oPayload.id - callback - code: 200 - message: 'OK!' + delete_action_invoker: ( user, oPayload, callback ) -> + answ = hasRequiredParams [ 'id' ], oPayload + if answ.code isnt 200 + callback answ + else + db.actionInvokers.deleteModule oPayload.id + callback + code: 200 + message: 'OK!' # RULES # ----- - get_rules: ( user, oPayload, callback ) -> - db.getUserLinkedRules user.username, ( err, obj ) -> - callback - code: 200 - message: obj + get_rules: ( user, oPayload, callback ) -> + 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 + 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 - # A rule needs to be in following format: - - # - id - # - event - # - conditions - # - actions - forge_rule: ( user, oPayload, callback ) -> - answ = hasRequiredParams [ 'id', 'event', 'conditions', 'actions' ], oPayload - if answ.code isnt 200 - callback answ - else - db.getRule oPayload.id, ( err, oExisting ) -> - if oExisting isnt null - answ = - code: 409 - message: 'Rule name already existing!' - else - rule = - id: oPayload.id - event: oPayload.event - conditions: oPayload.conditions - actions: oPayload.actions - strRule = JSON.stringify rule - db.storeRule rule.id, strRule - db.linkRule rule.id, user.username - db.activateRule rule.id, user.username - if oPayload.event_params - epModId = rule.event.split( ' -> ' )[0] - db.eventPollers.storeUserParams epModId, user.username, oPayload.event_params - oParams = oPayload.action_params - db.actionInvokers.storeUserParams id, user.username, JSON.stringify params for id, params of oParams - oParams = oPayload.action_functions - for id, params of oParams - arr = id.split ' -> ' - db.actionInvokers.storeUserArguments arr[ 0 ], arr[ 1 ], user.username, JSON.stringify params - db.resetLog user.username, rule.id - db.appendLog user.username, rule.id, "INIT", "Rule '#{ rule.id }' initialized" - eventEmitter.emit 'rule', - event: 'new' - user: user.username - rule: rule - answ = - code: 200 - message: "Rule '#{ rule.id }' stored and activated!" - callback answ + # A rule needs to be in following format: + + # - id + # - event + # - conditions + # - actions + forge_rule: ( user, oPayload, callback ) -> + answ = hasRequiredParams [ 'id', 'event', 'conditions', 'actions' ], oPayload + if answ.code isnt 200 + callback answ + else + db.getRule oPayload.id, ( err, oExisting ) -> + if oExisting isnt null + answ = + code: 409 + message: 'Rule name already existing!' + else + # This is how a rule is stored in the database + rule = + id: oPayload.id + event: oPayload.event + event_interval: oPayload.event_interval + conditions: oPayload.conditions + actions: oPayload.actions + strRule = JSON.stringify rule + # store the rule + db.storeRule rule.id, strRule + # link the rule to the user + db.linkRule rule.id, user.username + # activate the rule + db.activateRule rule.id, user.username + # if event module parameters were send, store them + if oPayload.event_params + epModId = rule.event.split( ' -> ' )[0] + db.eventPollers.storeUserParams epModId, user.username, oPayload.event_params + + # if action module params were send, store them + oParams = oPayload.action_params + db.actionInvokers.storeUserParams id, user.username, JSON.stringify params for id, params of oParams + oParams = oPayload.action_functions + # if action function arguments were send, store them + for id, params of oParams + arr = id.split ' -> ' + db.actionInvokers.storeUserArguments arr[ 0 ], arr[ 1 ], user.username, JSON.stringify params + + # Initialize the rule log + db.resetLog user.username, rule.id + db.appendLog user.username, rule.id, "INIT", "Rule '#{ rule.id }' initialized" + + # Inform everbody about the new rule + eventEmitter.emit 'rule', + event: 'new' + user: user.username + rule: rule + answ = + code: 200 + message: "Rule '#{ rule.id }' stored and activated!" + callback answ - 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!' + 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!' diff --git a/coffee/config.coffee b/coffee/config.coffee index 2f4461a..f5d8c25 100644 --- a/coffee/config.coffee +++ b/coffee/config.coffee @@ -24,14 +24,14 @@ be generated) and configPath for a custom configuration file path. @param {Object} args ### exports = module.exports = ( args ) => - args = args ? {} - if args.nolog - @nolog = true - if args.configPath - loadConfigFile args.configPath - else - loadConfigFile path.join 'config', 'system.json' - module.exports + args = args ? {} + if args.nolog + @nolog = true + if args.configPath + loadConfigFile args.configPath + else + loadConfigFile path.join 'config', 'system.json' + module.exports ### Tries to load a configuration file from the path relative to this module's parent folder. @@ -41,26 +41,26 @@ Reads the config file synchronously from the file system and try to parse it. @param {String} configPath ### loadConfigFile = ( configPath ) => - @config = null - confProperties = [ - 'log' - 'http-port' - 'db-port' - ] - try - @config = JSON.parse fs.readFileSync path.resolve __dirname, '..', configPath - @isReady = true - for prop in confProperties - if !@config[prop] - @isReady = false - if not @isReady and not @nolog - console.error "Missing property in config file, requires:\n" + - " - #{ confProperties.join "\n - " }" - catch e - @isReady = false - if not @nolog - console.error "Failed loading config file: #{ e.message }" - + @config = null + confProperties = [ + 'log' + 'http-port' + 'db-port' + ] + try + @config = JSON.parse fs.readFileSync path.resolve __dirname, '..', configPath + @isReady = true + for prop in confProperties + if !@config[prop] + @isReady = false + if not @isReady and not @nolog + console.error "Missing property in config file, requires:\n" + + " - #{ confProperties.join "\n - " }" + catch e + @isReady = false + if not @nolog + console.error "Failed loading config file: #{ e.message }" + ### Fetch a property from the configuration @@ -68,7 +68,7 @@ Fetch a property from the configuration @private fetchProp( *prop* ) @param {String} prop ### -fetchProp = ( prop ) => @config?[prop] +exports.fetchProp = ( prop ) => @config?[prop] ### ***Returns*** true if the config file is ready, else false @@ -82,25 +82,25 @@ exports.isReady = => @isReady @public getHttpPort() ### -exports.getHttpPort = -> fetchProp 'http-port' +exports.getHttpPort = -> exports.fetchProp 'http-port' ### ***Returns*** the DB port* @public getDBPort() ### -exports.getDbPort = -> fetchProp 'db-port' +exports.getDbPort = -> exports.fetchProp 'db-port' ### ***Returns*** the log conf object @public getLogConf() ### -exports.getLogConf = -> fetchProp 'log' +exports.getLogConf = -> exports.fetchProp 'log' ### ***Returns*** the crypto key @public getCryptoKey() ### -exports.getKeygenPassphrase = -> fetchProp 'keygen-passphrase' +exports.getKeygenPassphrase = -> exports.fetchProp 'keygen-passphrase' diff --git a/coffee/dynamic-modules.coffee b/coffee/dynamic-modules.coffee index 09c4222..dd74b1b 100644 --- a/coffee/dynamic-modules.coffee +++ b/coffee/dynamic-modules.coffee @@ -18,10 +18,13 @@ needle = require 'needle' request = require 'request' # - External Modules: [coffee-script](http://coffeescript.org/), -# [cryptico](https://github.com/wwwtyro/cryptico) +# [cryptico](https://github.com/wwwtyro/cryptico), +# [crypto-js](https://www.npmjs.org/package/crypto-js) and +# [import-io](https://www.npmjs.org/package/import-io) cs = require 'coffee-script' cryptico = require 'my-cryptico' cryptoJS = require 'crypto-js' +importio = require( 'import-io' ).client @@ -33,34 +36,33 @@ Initializes the dynamic module handler. @param {Object} args ### 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 "DM | Public Key generated: #{ @strPublicKey }" + @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 "DM | Public Key generated: #{ @strPublicKey }" - module.exports + module.exports exports.getPublicKey = () => - @strPublicKey + @strPublicKey logFunction = ( uId, rId, mId ) -> - ( msg ) -> - db.appendLog uId, rId, mId, msg + ( msg ) -> + db.appendLog uId, rId, mId, msg regexpComments = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; getFunctionParamNames = ( fName, func, oFuncs ) -> - fnStr = func.toString().replace regexpComments, '' - result = fnStr.slice( fnStr.indexOf( '(' ) + 1, fnStr.indexOf( ')' ) ).match /([^\s,]+)/g - if not result - result = [] - oFuncs[fName] = result - + fnStr = func.toString().replace regexpComments, '' + result = fnStr.slice( fnStr.indexOf( '(' ) + 1, fnStr.indexOf( ')' ) ).match /([^\s,]+)/g + if not result + result = [] + oFuncs[fName] = result ### Try to run a JS module from a string, together with the @@ -74,86 +76,101 @@ compile it first into JS. @param {String} lang ### exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) => - answ = - code: 200 - message: 'Successfully compiled' + if lang is 'CoffeeScript' + try + @log.info "DM | Compiling module '#{ modId }' for user '#{ userId }'" + src = cs.compile src + catch err + cb + code: 400 + message: 'Compilation of CoffeeScript failed at line ' + + err.location.first_line + return - if lang is 'CoffeeScript' - try - src = cs.compile src - catch err - answ.code = 400 - answ.message = 'Compilation of CoffeeScript failed at line ' + - err.location.first_line - - 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 }" - @log.warn err - params = {} - else - params = {} + @log.info "DM | Trying to fetch user specific module '#{ modId }' paramters for user '#{ userId }'" + # dbMod is only attached if the module really gets loaded and needs to fetch user information from the database + if dbMod + dbMod.getUserParams modId, userId, ( err, obj ) => + try + oDecrypted = cryptico.decrypt obj, @oPrivateRSAkey + obj = JSON.parse oDecrypted.plaintext + @log.warn "DM | Loaded user defined params for #{ userId }, #{ ruleId }, #{ modId }" + catch err + @log.warn "DM | Error during parsing of user defined params for #{ userId }, #{ ruleId }, #{ modId }" + @log.warn err + fTryToLoadModule userId, ruleId, modId, src, dbMod, obj, cb + else + fTryToLoadModule userId, ruleId, modId, src, dbMod, null, cb - logFunc = logFunction userId, ruleId, modId - sandbox = - id: userId + '.' + modId + '.vm' - params: params - needle: needle - request: request - cryptoJS: cryptoJS - log: logFunc - debug: console.log - exports: {} +fTryToLoadModule = ( userId, ruleId, modId, src, dbMod, params, cb ) => + if not params + params = {} - #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 - msg = err.message - if not msg - msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number' - answ.message = 'Loading Module failed: ' + msg - oFuncParams = {} - for fName, func of sandbox.exports - getFunctionParamNames fName, func, oFuncParams + answ = + code: 200 + message: 'Successfully compiled' - if dbMod - oFuncArgs = {} - console.log 'oFuncParams' - console.log oFuncParams + @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 + # 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" + params: params + needle: needle + importio: importio + request: request + cryptoJS: cryptoJS + log: logFunc + debug: console.log + exports: {} - for func of oFuncParams - console.log 'fetching ' + func - console.log typeof func - dbMod.getUserArguments modId, func, userId, ( err, obj ) => - console.log err, obj - try - oDecrypted = cryptico.decrypt obj, @oPrivateRSAkey - oFuncArgs[ func ] = JSON.parse oDecrypted.plaintext - catch err - @log.warn "DM | Error during parsing of user defined params for #{ userId }, #{ ruleId }, #{ modId }" - @log.warn err - cb - answ: answ - module: sandbox.exports - funcParams: oFuncParams - funcArgs: oFuncArgs - logger: sandbox.log + #TODO child_process to run module! + #Define max runtime per function call 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 + # Finally the module is run in a + 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 + msg = err.message + if not msg + msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number' + answ.message = 'Loading Module failed: ' + msg - if dbMod - dbMod.getUserParams modId, userId, ( err, obj ) -> - fTryToLoad obj - else - fTryToLoad null + @log.info "DM | Module '#{ modId }' ran successfully for user '#{ userId }' in rule '#{ ruleId }'" + oFuncParams = {} + oFuncArgs = {} + for fName, func of sandbox.exports + getFunctionParamNames fName, func, oFuncParams + if dbMod + oFuncArgs = {} + console.log 'oFuncParams' + console.log oFuncParams + + for func of oFuncParams + console.log 'fetching ' + func + console.log typeof func + dbMod.getUserArguments modId, func, userId, ( err, obj ) => + console.log err, obj + try + oDecrypted = cryptico.decrypt obj, @oPrivateRSAkey + oFuncArgs[ func ] = JSON.parse oDecrypted.plaintext + catch err + @log.warn "DM | Error during parsing of user defined params for #{ userId }, #{ ruleId }, #{ modId }" + @log.warn err + + console.log 'answering compile request string' + console.log cb + + cb + answ: answ + module: sandbox.exports + funcParams: oFuncParams + funcArgs: oFuncArgs + logger: sandbox.log diff --git a/coffee/engine.coffee b/coffee/engine.coffee index 48514bc..fb305fe 100644 --- a/coffee/engine.coffee +++ b/coffee/engine.coffee @@ -23,21 +23,21 @@ 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 + "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 ### #TODO how often do we allow rules to be processed? @@ -55,12 +55,12 @@ Initializes the Engine and starts polling the event queue for new events. @param {Object} args ### exports = module.exports = ( args ) => - if not isRunning - @log = args.logger - db args - dynmod args - setTimeout exports.startEngine, 10 # Very important, this forks a token for the poll task - module.exports + if not isRunning + @log = args.logger + db args + dynmod args + setTimeout exports.startEngine, 10 # Very important, this forks a token for the poll task + module.exports ### @@ -72,13 +72,13 @@ modules are loaded correctly #TODO we should change this to functions returning true or false rather than returning #the whole list exports.getListUserRules = () -> - listUserRules + listUserRules # We need this so we can shut it down after the module unit tests exports.startEngine = () -> - if not isRunning - isRunning = true - pollQueue() + if not isRunning + isRunning = true + pollQueue() ### An event associated to rules happened and is captured here. Such events @@ -88,23 +88,23 @@ are basically CRUD on rules. @param {Object} evt ### exports.internalEvent = ( evt ) => - if not listUserRules[evt.user] and evt.event isnt 'del' - listUserRules[evt.user] = {} + if not listUserRules[evt.user] and evt.event isnt 'del' + listUserRules[evt.user] = {} - oUser = listUserRules[evt.user] - oRule = evt.rule - if evt.event is 'new' or ( evt.event is 'init' and not oUser[oRule.id] ) - oUser[oRule.id] = - rule: oRule - actions: {} - updateActionModules oRule.id + oUser = listUserRules[evt.user] + oRule = evt.rule + 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[evt.ruleId] + if evt.event is 'del' and oUser + 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] + # 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] @@ -115,65 +115,67 @@ invoker modules are loaded, updated or deleted. @private updateActionModules ( *updatedRuleId* ) @param {Object} updatedRuleId ### -updateActionModules = ( updatedRuleId ) -> - - # Remove all action invoker modules that are not required anymore - fRemoveNotRequired = ( oUser ) -> +updateActionModules = ( updatedRuleId ) => + + # Remove all action invoker modules that are not required anymore + fRemoveNotRequired = ( oUser ) -> - # Check whether the action is still existing in the rule - fRequired = ( actionName ) -> - 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 + # Check whether the action is still existing in the rule + fRequired = ( actionName ) -> + 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 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 + # 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 + fRemoveNotRequired oUser for name, oUser of listUserRules - # Add action invoker modules that are not yet loaded - fAddRequired = ( userName, oUser ) -> + # Add action invoker modules that are not yet loaded + fAddRequired = ( userName, oUser ) => - # Check whether the action is existing in a rule and load if not - fCheckRules = ( oMyRule ) -> + # Check whether the action is existing in a rule and load if not + 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 oMyRule.actions[moduleName] or oMyRule.rule.id is updatedRuleId - db.actionInvokers.getModule moduleName, ( err, obj ) -> - # 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 + # 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 oMyRule.actions[moduleName] or oMyRule.rule.id is updatedRuleId + db.actionInvokers.getModule moduleName, ( err, obj ) => + if obj + # 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 + else + @log.warn 'EN | #{ moduleName } not found for #{ oMyRule.rule.id }!' - fAddIfNewOrNotExisting action for action in oMyRule.rule.actions + fAddIfNewOrNotExisting action for action in oMyRule.rule.actions - # Go thorugh all rules and check whether the action is still required - fCheckRules oRl for nmRl, oRl of oUser + # 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 + # load all required modules for all users + fAddRequired userName, oUser for userName, oUser of listUserRules -semaphore = 0 +numExecutingFunctions = 1 pollQueue = () -> - if isRunning - db.popEvent ( err, obj ) -> - if not err and obj - processEvent obj - semaphore-- - setTimeout pollQueue, 20 * semaphore #FIXME right wayx to adapt to load? + if isRunning + db.popEvent ( err, obj ) -> + if not err and obj + processEvent obj + setTimeout pollQueue, 20 * numExecutingFunctions #FIXME right way to adapt to load? ### Checks whether all conditions of the rule are met by the event. @@ -183,13 +185,12 @@ 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 + 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 -semaphore = 0 ### Handles retrieved events. @@ -197,30 +198,32 @@ Handles retrieved events. @param {Object} evt ### processEvent = ( evt ) => - fSearchAndInvokeAction = ( node, arrPath, funcName, 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 - semaphore++ - node[funcName] evt.payload - catch err - @log.info "EN | ERROR IN ACTION INVOKER: " + err.message - node.logger err.message - if semaphore-- % 100 is 0 - @log.warn "EN | The system is producing too many tokens! Currently: #{ semaphore }" - else - fSearchAndInvokeAction node[arrPath[depth]], arrPath, funcName, evt, depth + 1 + fSearchAndInvokeAction = ( node, arrPath, funcName, 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 + numExecutingFunctions++ + @log.info "EN | #{ funcName } executes..." + node[funcName] evt.payload + @log.info "EN | #{ funcName } finished execution" + catch err + @log.info "EN | ERROR IN ACTION INVOKER: " + err.message + node.logger err.message + if numExecutingFunctions-- % 100 is 0 + @log.warn "EN | The system is producing too many tokens! Currently: #{ numExecutingFunctions }" + else + fSearchAndInvokeAction node[arrPath[depth]], arrPath, funcName, evt, depth + 1 - @log.info 'EN | processing event: ' + evt.event + '(' + evt.eventid + ')' - for userName, oUser of listUserRules - 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 - for action in oMyRule.rule.actions - arr = action.split ' -> ' - fSearchAndInvokeAction listUserRules, [ userName, ruleName, 'actions', arr[0]], arr[1], evt, 0 + @log.info 'EN | processing event: ' + evt.event + '(' + evt.eventid + ')' + for userName, oUser of listUserRules + 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 + for action in oMyRule.rule.actions + arr = action.split ' -> ' + fSearchAndInvokeAction listUserRules, [ userName, ruleName, 'actions', arr[0]], arr[1], evt, 0 exports.shutDown = () -> - isRunning = false \ No newline at end of file + isRunning = false \ No newline at end of file diff --git a/coffee/event-poller.coffee b/coffee/event-poller.coffee index 93840a5..c8d0def 100644 --- a/coffee/event-poller.coffee +++ b/coffee/event-poller.coffee @@ -16,13 +16,13 @@ dynmod = require './dynamic-modules' # If we do not receive all required arguments we shut down immediately if process.argv.length < 8 - console.error 'Not all arguments have been passed!' - process.exit() + console.error 'Not all arguments have been passed!' + process.exit() # Fetch all the command line arguments to the process to init the logger logconf = - mode: process.argv[ 2 ] - nolog: process.argv[ 6 ] + mode: process.argv[ 2 ] + nolog: process.argv[ 6 ] logconf[ 'io-level' ] = process.argv[ 3 ] logconf[ 'file-level' ] = process.argv[ 4 ] logconf[ 'file-path' ] = process.argv[ 5 ] @@ -32,8 +32,8 @@ log.info 'EP | Event Poller starts up' # Initialize required modules (should be in cache already) db logger: log dynmod - logger: log - keygen: process.argv[ 7 ] + logger: log + keygen: process.argv[ 7 ] # Initialize module local variables and listUserModules = {} @@ -42,102 +42,111 @@ isRunning = true # Register disconnect action. Since no standalone mode is intended # the event poller will shut down process.on 'disconnect', () -> - log.info 'EP | Shutting down Event Poller' - isRunning = false - # very important so the process doesnt linger on when the paren process is killed - process.exit() + log.info 'EP | Shutting down Event Poller' + isRunning = false + # very important so the process doesnt linger on when the paren process is killed + process.exit() # If the process receives a message it is concerning the rules process.on 'message', ( msg ) -> - # Let's split the event string to find module and function in an array + # Let's split the event string to find module and function in an array - # A initialization notification or a new rule - if msg.event is 'new' or msg.event is 'init' - fLoadModule msg - # We fetch the module also if the rule was updated + # A initialization notification or a new rule + if msg.event is 'new' or msg.event is 'init' + fLoadModule msg + # We fetch the module also if the rule was updated - # A rule was deleted - if msg.event is 'del' - delete listUserModules[msg.user][msg.ruleId] - if JSON.stringify( listUserModules[msg.user] ) is "{}" - delete listUserModules[msg.user] + # A rule was deleted + if msg.event is 'del' + delete listUserModules[msg.user][msg.ruleId] + if JSON.stringify( listUserModules[msg.user] ) is "{}" + delete listUserModules[msg.user] # Loads a module if required fLoadModule = ( msg ) -> - arrName = msg.rule.event.split ' -> ' - fAnonymous = () -> - db.eventPollers.getModule arrName[ 0 ], ( err, obj ) -> - if not obj - log.warn "EP | Strange... no module retrieved: #{ arrName[0] }" - else - # we compile the module and pass: - dynmod.compileString obj.data, # code - msg.user, # userId - msg.rule.id, # ruleId - arrName[0], # moduleId - obj.lang, # script language - db.eventPollers, # the DB interface - ( result ) -> - if not result.answ is 200 - log.error "EP | Compilation of code failed! #{ msg.user }, - #{ msg.rule.id }, #{ arrName[0] }" + arrName = msg.rule.event.split ' -> ' + fAnonymous = () -> + db.eventPollers.getModule arrName[ 0 ], ( err, obj ) -> + if not obj + log.warn "EP | Strange... no module retrieved: #{ arrName[0] }" + else + # we compile the module and pass: + dynmod.compileString obj.data, # code + msg.user, # userId + msg.rule.id, # ruleId + arrName[0], # moduleId + obj.lang, # script language + db.eventPollers, # the DB interface + ( result ) -> + if not result.answ is 200 + log.error "EP | Compilation of code failed! #{ msg.user }, + #{ msg.rule.id }, #{ arrName[0] }" - # If user is not yet stored, we open a new object - if not listUserModules[msg.user] - listUserModules[msg.user] = {} - - # We open up a new object for the rule it - listUserModules[msg.user][msg.rule.id] = - id: msg.rule.event - pollfunc: arrName[1] - module: result.module - logger: result.logger + # If user is not yet stored, we open a new object + if not listUserModules[msg.user] + listUserModules[msg.user] = {} + + iv = msg.rule.interval * 60 * 1000 + # We open up a new object for the rule it + listUserModules[msg.user][msg.rule.id] = + id: msg.rule.event + pollfunc: arrName[1] + interval: iv + module: result.module + logger: result.logger - log.info "EP | New event module loaded! #{ msg.user }, - #{ msg.rule.id }, #{ arrName[0] }" + log.info "EP | New event module '#{ arrName[0] }' loaded for user #{ msg.user }, + in rule #{ msg.rule.id }, polling every #{ iv } minutes" + setTimeout fCheckAndRun( msg.user, msg.rule.id ), iv - if msg.event is 'new' or - not listUserModules[msg.user] or - not listUserModules[msg.user][msg.rule.id] - fAnonymous() + if msg.event is 'new' or + not listUserModules[msg.user] or + not listUserModules[msg.user][msg.rule.id] + fAnonymous() + +fCheckAndRun = ( userId, ruleId ) -> + () -> + if isRunning and + listUserModules[userId] and + listUserModules[userId][ruleId] + oRule = listUserModules[userId][ruleId] + fCallFunction userId, ruleId, oRule + setTimeout fCheckAndRun( userId, ruleId ), oRule.interval + +# We have to register the poll function in belows anonymous function +# because we're fast iterating through the listUserModules and references will +# eventually not be what they are expected to be +fCallFunction = ( userId, ruleId, oRule ) -> + try + oRule.module[oRule.pollfunc] ( obj ) -> + db.pushEvent + event: oRule.id + eventid: "polled #{ oRule.id } #{ userId }_#{ ( new Date ).toISOString() }" + payload: obj + catch err + log.info "EP | ERROR in module when polled: #{ oRule.id } #{ userId }: #{err.message}" + oRule.logger err.message +# ### +# This function will loop infinitely every 10 seconds until isRunning is set to false + +# @private pollLoop() +# ### +# pollLoop = () -> +# # We only loop if we're running +# if isRunning + +# # Go through all users +# for userName, oRules of listUserModules + +# # Go through each of the users modules +# for ruleName, myRule of oRules + +# # Call the event poller module function +# fCallFunction myRule, ruleName, userName + +# setTimeout pollLoop, 10000 -### -This function will loop infinitely every 10 seconds until isRunning is set to false - -@private pollLoop() -### -pollLoop = () -> - # We only loop if we're running - if isRunning - - # Go through all users - for userName, oRules of listUserModules - - # Go through each of the users modules - for ruleName, myRule of oRules - - # # This is the to be polled function - # fPoll = myRule.module[myRule.pollfunc] - - # We have to register the poll function in belows anonymous function - # because we're fast iterating through the listUserModules and references will - # eventually not be what they are expected to be - fCallFunction = ( oRule, ruleId, userId ) -> - try - oRule.module[oRule.pollfunc] ( obj ) -> - db.pushEvent - event: oRule.id - eventid: "polled #{ oRule.id } #{ userId }_#{ ( new Date ).toISOString() }" - payload: obj - catch err - log.info "EP | ERROR in module when polled: #{ oRule.id } #{ userId }: #{err.message}" - oRule.logger err.message - - fCallFunction myRule, ruleName, userName - setTimeout pollLoop, 10000 - - -# Finally if everything initialized we start polling for new events -pollLoop() \ No newline at end of file +# # Finally if everything initialized we start polling for new events +# pollLoop() \ No newline at end of file diff --git a/coffee/http-listener.coffee b/coffee/http-listener.coffee index 4d91451..dcac45a 100644 --- a/coffee/http-listener.coffee +++ b/coffee/http-listener.coffee @@ -33,11 +33,37 @@ Initializes the HTTP listener and its request handler. @param {Object} args ### exports = module.exports = ( args ) => - @log = args.logger - @shutDownSystem = args[ 'shutdown-function' ] - requestHandler args - initRouting args[ 'http-port' ] - module.exports + @log = args.logger + @arrWebhooks = args.webhooks + @shutDownSystem = args[ 'shutdown-function' ] + requestHandler args + initRouting args[ 'http-port' ] + module.exports + +indexEvent = ( event, body, resp ) -> + try + obj = JSON.parse body + timestamp = ( new Date ).toISOString() + rand = ( Math.floor Math.random() * 10e9 ).toString( 16 ).toUpperCase() + obj.event = event + obj.eventid = "#{ obj.event }_#{ timestamp }_#{ rand }" + db.pushEvent obj + resp.send 200, "Thank you for the event: #{ obj.eventid }" + catch err + resp.send 400, 'Badly formed event!' + +# Activate a webhook. the body will be JSON parsed, the name of the webhook will +# be the event name given to the event object, a timestamp will be added +activateWebHook = ( app, name ) => + @log.info "HL | Webhook activated for #{ name }" + app.post "/webhooks/#{ name }", ( req, resp ) -> + console.log 'something is coming through' + body = '' + req.on 'data', ( data ) -> + body += data + + req.on 'end', -> + indexEvent name, body, resp ### Initializes the request routing and starts listening on the given port. @@ -46,58 +72,60 @@ Initializes the request routing and starts listening on the given port. @private initRouting( *fShutDown* ) ### initRouting = ( port ) => - # Add cookie support for session handling. - app.use express.cookieParser() - #TODO The session secret approach needs to be fixed! - sess_sec = "149u*y8C:@kmN/520Gt\\v'+KFBnQ!\\r<>5X/xRI`sT - addr = server.address() - if addr.port isnt port - @shutDownSystem() - server.on 'error', ( err ) => - ### - Error handling of the express port listener requires special attention, - thus we have to catch the error, which is issued if the port is already in use. - ### - switch err.errno - when 'EADDRINUSE' - @log.error err, 'HL | http-port already in use, shutting down!' - when 'EACCES' - @log.error err, 'HL | http-port not accessible, shutting down!' - else - @log.error err, 'HL | Error in server, shutting down!' - @shutDownSystem() + server.on 'listening', () => + addr = server.address() + if addr.port isnt port + @shutDownSystem() + server.on 'error', ( err ) => + ### + Error handling of the express port listener requires special attention, + thus we have to catch the error, which is issued if the port is already in use. + ### + switch err.errno + when 'EADDRINUSE' + @log.error err, 'HL | http-port already in use, shutting down!' + when 'EACCES' + @log.error err, 'HL | http-port not accessible, shutting down!' + else + @log.error err, 'HL | Error in server, shutting down!' + @shutDownSystem() # diff --git a/coffee/logging.coffee b/coffee/logging.coffee index 8abf6f0..04c8d35 100644 --- a/coffee/logging.coffee +++ b/coffee/logging.coffee @@ -25,61 +25,61 @@ Returns a bunyan logger according to the given arguments. @param {Object} args ### exports.getLogger = ( args ) => - emptylog = - trace: () -> - debug: () -> - info: () -> - warn: () -> - error: () -> - fatal: () -> - # `args` holds the configuration settings for the logging, see either CLI arguments - # in [webapi-eca](webapi-eca.html) or the configuration parameters in [config](config.html). - args = args ? {} - # We need to check for string 'true' also since the cliArgs passed to - # the event-poller will be strings - if args.nolog is true or args.nolog is 'true' - # if the user doesn't want to have a log at all (e.g. during tests), it can be omitted with - # the nolog flag - emptylog - else - try - opt = - name: "webapi-eca" - # if we are in development mode, we also add information about where the call came from - # this should be turned off in productive mode since it slows down the logging. - if args['mode'] is 'development' - opt.src = true - # if there's a custom path defined for the log, we adopt the setting. - if args['file-path'] - @logPath = path.resolve args['file-path'] - else - @logPath = path.resolve __dirname, '..', 'logs', 'server.log' + emptylog = + trace: () -> + debug: () -> + info: () -> + warn: () -> + error: () -> + fatal: () -> + # `args` holds the configuration settings for the logging, see either CLI arguments + # in [webapi-eca](webapi-eca.html) or the configuration parameters in [config](config.html). + args = args ? {} + # We need to check for string 'true' also since the cliArgs passed to + # the event-poller will be strings + if args.nolog is true or args.nolog is 'true' + # if the user doesn't want to have a log at all (e.g. during tests), it can be omitted with + # the nolog flag + emptylog + else + try + opt = + name: "webapi-eca" + # if we are in development mode, we also add information about where the call came from + # this should be turned off in productive mode since it slows down the logging. + if args['mode'] is 'development' + opt.src = true + # if there's a custom path defined for the log, we adopt the setting. + if args['file-path'] + @logPath = path.resolve args['file-path'] + else + @logPath = path.resolve __dirname, '..', 'logs', 'server.log' - # We try to write a temp file in the same folder to check if the log can be written - try - fs.writeFileSync @logPath + '.temp', 'temp' - fs.unlinkSync @logPath + '.temp' - catch e - console.error "Log folder '#{ @logPath }' is not writable" - return emptylog + # We try to write a temp file in the same folder to check if the log can be written + try + fs.writeFileSync @logPath + '.temp', 'temp' + fs.unlinkSync @logPath + '.temp' + catch e + console.error "Log folder '#{ @logPath }' is not writable" + return emptylog - # We attach two streams, one for the I/O and one for the log file. - # The log levels are defined per stream according to the CLI args or the configuration. - opt.streams = [ - { - level: args['io-level'] - stream: process.stdout - }, - { - level: args['file-level'] - path: @logPath - } - ] - # Finally we create the bunyan logger and return it - bunyan.createLogger opt + # We attach two streams, one for the I/O and one for the log file. + # The log levels are defined per stream according to the CLI args or the configuration. + opt.streams = [ + { + level: args['io-level'] + stream: process.stdout + }, + { + level: args['file-level'] + path: @logPath + } + ] + # Finally we create the bunyan logger and return it + bunyan.createLogger opt - # If something goes wrong we print the error and return an empty logger. - catch e - console.error e - emptylog + # If something goes wrong we print the error and return an empty logger. + catch e + console.error e + emptylog diff --git a/coffee/persistence.coffee b/coffee/persistence.coffee index 2efef24..7460e0e 100644 --- a/coffee/persistence.coffee +++ b/coffee/persistence.coffee @@ -34,32 +34,34 @@ Initializes the DB connection with the given `db-port` property in the `args` ob @param {Object} args ### exports = module.exports = ( args ) => - if not @db - #TODO we need to have a secure concept here, private keys per user - #FIXME get rid of crpto - if not args[ 'db-port' ] - args[ 'db-port' ] = 6379 - @log = args.logger - exports.eventPollers = new IndexedModules 'event-poller', @log - exports.actionInvokers = new IndexedModules 'action-invoker', @log - exports.initPort args[ 'db-port' ] + if not @db + #TODO we need to have a secure concept here, private keys per user + #FIXME get rid of crpto + if not args[ 'db-port' ] + args[ 'db-port' ] = 6379 + @log = args.logger + exports.eventPollers = new IndexedModules 'event-poller', @log + exports.actionInvokers = new IndexedModules 'action-invoker', @log + exports.initPort args[ 'db-port' ] exports.getLogger = () => - @log + @log exports.initPort = ( port ) => - @connRefused = false - @db?.quit() - @db = redis.createClient port, - 'localhost', { connect_timeout: 2000 } - # Eventually we try to connect to the wrong port, redis will emit an error that we - # need to catch and take into account when answering the isConnected function call - @db.on 'error', ( err ) => - if err.message.indexOf( 'ECONNREFUSED' ) > -1 - @connRefused = true - @log.error err, 'DB | Wrong port?' - exports.eventPollers.setDB @db - exports.actionInvokers.setDB @db + @connRefused = false + @db?.quit() + @db = redis.createClient port, + 'localhost', { connect_timeout: 2000 } + # Eventually we try to connect to the wrong port, redis will emit an error that we + # need to catch and take into account when answering the isConnected function call + @db.on 'error', ( err ) => + if err.message.indexOf( 'ECONNREFUSED' ) > -1 + @connRefused = true + @log.warn 'DB | Wrong port?' + else + @log.error err + exports.eventPollers.setDB @db + exports.actionInvokers.setDB @db ### Checks whether the db is connected and passes either an error on failure after @@ -69,26 +71,26 @@ ten attempts within five seconds, or nothing on success to the callback(err). @param {function} cb ### exports.isConnected = ( cb ) => - if not @db - cb new Error 'DB | DB initialization did not occur or failed miserably!' - else - if @db.connected - cb() - else - numAttempts = 0 - fCheckConnection = => - if @connRefused - @db?.quit() - cb new Error 'DB | Connection refused! Wrong port?' - else - if @db.connected - @log.info 'DB | Successfully connected to DB!' - cb() - else if numAttempts++ < 10 - setTimeout fCheckConnection, 100 - else - cb new Error 'DB | Connection to DB failed!' - setTimeout fCheckConnection, 100 + if not @db + cb new Error 'DB | DB initialization did not occur or failed miserably!' + else + if @db.connected + cb() + else + numAttempts = 0 + fCheckConnection = => + if @connRefused + @db?.quit() + cb new Error 'DB | Connection refused! Wrong port?' + else + if @db.connected + @log.info 'DB | Successfully connected to DB!' + cb() + else if numAttempts++ < 10 + setTimeout fCheckConnection, 100 + else + cb new Error 'DB | Connection to DB failed!' + setTimeout fCheckConnection, 100 ### @@ -98,11 +100,11 @@ Abstracts logging for simple action replies from the DB. @param {String} action ### replyHandler = ( action ) => - ( err, reply ) => - if err - @log.warn err, "during '#{ action }'" - else - @log.info "DB | #{ action }: #{ reply }" + ( err, reply ) => + if err + @log.warn err, "during '#{ action }'" + else + @log.info "DB | #{ action }: #{ reply }" ### @@ -112,11 +114,11 @@ Push an event into the event queue. @param {Object} oEvent ### exports.pushEvent = ( oEvent ) => - if oEvent - @log.info "DB | Event pushed into the queue: '#{ oEvent.eventid }'" - @db.rpush 'event_queue', JSON.stringify oEvent - else - @log.warn 'DB | Why would you give me an empty event...' + if oEvent + @log.info "DB | Event pushed into the queue: '#{ oEvent.eventid }'" + @db.rpush 'event_queue', JSON.stringify oEvent + else + @log.warn 'DB | Why would you give me an empty event...' ### @@ -126,10 +128,10 @@ Pop an event from the event queue and pass it to cb(err, obj). @param {function} cb ### exports.popEvent = ( cb ) => - makeObj = ( pcb ) -> - ( err, obj ) -> - pcb err, JSON.parse obj - @db.lpop 'event_queue', makeObj cb + makeObj = ( pcb ) -> + ( err, obj ) -> + pcb err, JSON.parse obj + @db.lpop 'event_queue', makeObj cb ### @@ -138,7 +140,7 @@ Purge the event queue. @public purgeEventQueue() ### exports.purgeEventQueue = () => - @db.del 'event_queue', replyHandler 'purging event queue' + @db.del 'event_queue', replyHandler 'purging event queue' ### @@ -148,202 +150,202 @@ data objects via the provided function and returns the results to cb(err, obj). @private getSetRecords( *set, fSingle, cb* ) @param {String} set the set name how it is stored in the DB @param {function} fSingle a function to retrieve a single data element - per set entry + per set entry @param {function} cb the callback(err, obj) function that receives all - the retrieved data or an error + the retrieved data or an error ### getSetRecords = ( set, fSingle, cb ) => - @log.info "DB | Fetching set records: '#{ set }'" - # Fetch all members of the set - @db.smembers set, ( err, arrReply ) => - if err - # If an error happens we return it to the callback function - @log.warn err, "DB | fetching '#{ set }'" - cb err - else if arrReply.length == 0 - # If the set was empty we return null to the callback - cb() - else - # We need to fetch all the entries from the set and use a semaphore - # since the fetching from the DB will happen asynchronously - semaphore = arrReply.length - objReplies = {} - setTimeout -> - # We use a timeout function to cancel the operation - # in case the DB does not respond - if semaphore > 0 - cb new Error "Timeout fetching '#{ set }'" - , 2000 - fCallback = ( prop ) => - # The callback function is required to preprocess the result before - # handing it to the callback. This especially includes decrementing - # the semaphore - ( err, data ) => - --semaphore - if err - @log.warn err, "DB | fetching single element: '#{ prop }'" - else if not data - # There was no data behind the key - @log.warn new Error "Empty key in DB: '#{ prop }'" - else - # We found a valid record and add it to the reply object - objReplies[ prop ] = data - if semaphore == 0 - # If all fetch calls returned we finally pass the result - # to the callback - cb null, objReplies - # Since we retrieved an array of keys, we now execute the fSingle function - # on each of them, to retrieve the ata behind the key. Our fCallback function - # is used to preprocess the answer to determine correct execution - fSingle reply, fCallback reply for reply in arrReply + @log.info "DB | Fetching set records: '#{ set }'" + # Fetch all members of the set + @db.smembers set, ( err, arrReply ) => + if err + # If an error happens we return it to the callback function + @log.warn err, "DB | fetching '#{ set }'" + cb err + else if arrReply.length == 0 + # If the set was empty we return null to the callback + cb() + else + # We need to fetch all the entries from the set and use a semaphore + # since the fetching from the DB will happen asynchronously + semaphore = arrReply.length + objReplies = {} + setTimeout -> + # We use a timeout function to cancel the operation + # in case the DB does not respond + if semaphore > 0 + cb new Error "Timeout fetching '#{ set }'" + , 2000 + fCallback = ( prop ) => + # The callback function is required to preprocess the result before + # handing it to the callback. This especially includes decrementing + # the semaphore + ( err, data ) => + --semaphore + if err + @log.warn err, "DB | fetching single element: '#{ prop }'" + else if not data + # There was no data behind the key + @log.warn new Error "Empty key in DB: '#{ prop }'" + else + # We found a valid record and add it to the reply object + objReplies[ prop ] = data + if semaphore == 0 + # If all fetch calls returned we finally pass the result + # to the callback + cb null, objReplies + # Since we retrieved an array of keys, we now execute the fSingle function + # on each of them, to retrieve the ata behind the key. Our fCallback function + # is used to preprocess the answer to determine correct execution + fSingle reply, fCallback reply for reply in arrReply class IndexedModules - constructor: ( @setname, @log ) -> - @log.info "DB | (IdxedMods) Instantiated indexed modules for '#{ @setname }'" + constructor: ( @setname, @log ) -> + @log.info "DB | (IdxedMods) Instantiated indexed modules for '#{ @setname }'" - setDB: ( @db ) -> - @log.info "DB | (IdxedMods) Registered new DB connection for '#{ @setname }'" + setDB: ( @db ) -> + @log.info "DB | (IdxedMods) Registered new DB connection for '#{ @setname }'" - ### - Stores a module and links it to the user. - - @private storeModule( *userId, oModule* ) - @param {String} userId - @param {object} oModule - ### - storeModule: ( userId, oModule ) => - @log.info "DB | (IdxedMods) #{ @setname }.storeModule( #{ userId }, oModule )" - @db.sadd "#{ @setname }s", oModule.id, - replyHandler "sadd '#{ oModule.id }' to '#{ @setname }'" - @db.hmset "#{ @setname }:#{ oModule.id }", oModule, - replyHandler "hmset properties in hash '#{ @setname }:#{ oModule.id }'" - @linkModule oModule.id, userId + ### + Stores a module and links it to the user. + + @private storeModule( *userId, oModule* ) + @param {String} userId + @param {object} oModule + ### + storeModule: ( userId, oModule ) => + @log.info "DB | (IdxedMods) #{ @setname }.storeModule( #{ userId }, oModule )" + @db.sadd "#{ @setname }s", oModule.id, + replyHandler "sadd '#{ oModule.id }' to '#{ @setname }'" + @db.hmset "#{ @setname }:#{ oModule.id }", oModule, + replyHandler "hmset properties in hash '#{ @setname }:#{ oModule.id }'" + @linkModule oModule.id, userId - #TODO add testing - linkModule: ( mId, userId ) => - @log.info "DB | (IdxedMods) #{ @setname }.linkModule( #{ mId }, #{ userId } )" - @db.sadd "#{ @setname }:#{ mId }:users", userId, - replyHandler "sadd #{ userId } to '#{ @setname }:#{ mId }:users'" - @db.sadd "user:#{ userId }:#{ @setname }s", mId, - replyHandler "sadd #{ mId } to 'user:#{ userId }:#{ @setname }s'" + #TODO add testing + linkModule: ( mId, userId ) => + @log.info "DB | (IdxedMods) #{ @setname }.linkModule( #{ mId }, #{ userId } )" + @db.sadd "#{ @setname }:#{ mId }:users", userId, + replyHandler "sadd #{ userId } to '#{ @setname }:#{ mId }:users'" + @db.sadd "user:#{ userId }:#{ @setname }s", mId, + replyHandler "sadd #{ mId } to 'user:#{ userId }:#{ @setname }s'" - #TODO add testing - unlinkModule: ( mId, userId ) => - @log.info "DB | (IdxedMods) #{ @setname }.unlinkModule( #{ mId }, #{ userId } )" - @db.srem "#{ @setname }:#{ mId }:users", userId, - replyHandler "srem #{ userId } from '#{ @setname }:#{ mId }:users'" - @db.srem "user:#{ userId }:#{ @setname }s", mId, - replyHandler "srem #{ mId } from 'user:#{ userId }:#{ @setname }s'" + #TODO add testing + unlinkModule: ( mId, userId ) => + @log.info "DB | (IdxedMods) #{ @setname }.unlinkModule( #{ mId }, #{ userId } )" + @db.srem "#{ @setname }:#{ mId }:users", userId, + replyHandler "srem #{ userId } from '#{ @setname }:#{ mId }:users'" + @db.srem "user:#{ userId }:#{ @setname }s", mId, + replyHandler "srem #{ mId } from 'user:#{ userId }:#{ @setname }s'" - #TODO add testing - publish: ( mId ) => - @log.info "DB | (IdxedMods) #{ @setname }.publish( #{ mId } )" - @db.sadd "public-#{ @setname }s", mId, - replyHandler "sadd '#{ mId }' to 'public-#{ @setname }s'" + #TODO add testing + publish: ( mId ) => + @log.info "DB | (IdxedMods) #{ @setname }.publish( #{ mId } )" + @db.sadd "public-#{ @setname }s", mId, + replyHandler "sadd '#{ mId }' to 'public-#{ @setname }s'" - #TODO add testing - unpublish: ( mId ) => - @log.info "DB | (IdxedMods) #{ @setname }.unpublish( #{ mId } )" - @db.srem "public-#{ @setname }s", mId, - replyHandler "srem '#{ mId }' from 'public-#{ @setname }s'" + #TODO add testing + unpublish: ( mId ) => + @log.info "DB | (IdxedMods) #{ @setname }.unpublish( #{ mId } )" + @db.srem "public-#{ @setname }s", mId, + replyHandler "srem '#{ mId }' from 'public-#{ @setname }s'" - getModule: ( mId, cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getModule( #{ mId } )" - @db.hgetall "#{ @setname }:#{ mId }", cb + getModule: ( mId, cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getModule( #{ mId } )" + @db.hgetall "#{ @setname }:#{ mId }", cb - getModuleField: ( mId, field, cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getModule( #{ mId } )" - @db.hget "#{ @setname }:#{ mId }", field, cb + getModuleField: ( mId, field, cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getModule( #{ mId } )" + @db.hget "#{ @setname }:#{ mId }", field, cb - #TODO add testing - getModuleParams: ( mId, cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getModuleParams( #{ mId } )" - @db.hget "#{ @setname }:#{ mId }", "params", cb + #TODO add testing + getModuleParams: ( mId, cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getModuleParams( #{ mId } )" + @db.hget "#{ @setname }:#{ mId }", "params", cb - #TODO add testing - getAvailableModuleIds: ( userId, cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getPublicModuleIds( #{ userId } )" - @db.sunion "public-#{ @setname }s", "user:#{ userId }:#{ @setname }s", cb + #TODO add testing + getAvailableModuleIds: ( userId, cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getPublicModuleIds( #{ userId } )" + @db.sunion "public-#{ @setname }s", "user:#{ userId }:#{ @setname }s", cb - getModuleIds: ( cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getModuleIds()" - @db.smembers "#{ @setname }s", cb + getModuleIds: ( cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getModuleIds()" + @db.smembers "#{ @setname }s", cb - getModules: ( cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getModules()" - getSetRecords "#{ @setname }s", @getModule, cb + getModules: ( cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getModules()" + getSetRecords "#{ @setname }s", @getModule, cb - deleteModule: ( mId ) => - @log.info "DB | (IdxedMods) #{ @setname }.deleteModule( #{ mId } )" - @db.srem "#{ @setname }s", mId, - replyHandler "srem '#{ mId }' from #{ @setname }s" - @db.del "#{ @setname }:#{ mId }", - replyHandler "del of '#{ @setname }:#{ mId }'" - @unpublish mId - @db.smembers "#{ @setname }:#{ mId }:users", ( err, obj ) => - @unlinkModule mId, userId for userId in obj - @deleteUserParams mId, userId for userId in obj - @deleteUserArguments mId, userId for userId in obj + deleteModule: ( mId ) => + @log.info "DB | (IdxedMods) #{ @setname }.deleteModule( #{ mId } )" + @db.srem "#{ @setname }s", mId, + replyHandler "srem '#{ mId }' from #{ @setname }s" + @db.del "#{ @setname }:#{ mId }", + replyHandler "del of '#{ @setname }:#{ mId }'" + @unpublish mId + @db.smembers "#{ @setname }:#{ mId }:users", ( err, obj ) => + @unlinkModule mId, userId for userId in obj + @deleteUserParams mId, userId for userId in obj + @deleteUserArguments mId, userId for userId in obj - ### - Stores user params for a module. They are expected to be RSA encrypted with helps of - the provided cryptico JS library and will only be decrypted right before the module is loaded! - - @private storeUserParams( *mId, userId, encData* ) - @param {String} mId - @param {String} userId - @param {object} encData - ### - storeUserParams: ( mId, userId, encData ) => - @log.info "DB | (IdxedMods) #{ @setname }.storeUserParams( #{ mId }, #{ userId }, encData )" - @db.sadd "#{ @setname }-params", "#{ mId }:#{ userId }", - replyHandler "sadd '#{ mId }:#{ userId }' to '#{ @setname }-params'" - @db.set "#{ @setname }-params:#{ mId }:#{ userId }", encData, - replyHandler "set user params in '#{ @setname }-params:#{ mId }:#{ userId }'" + ### + Stores user params for a module. They are expected to be RSA encrypted with helps of + the provided cryptico JS library and will only be decrypted right before the module is loaded! + + @private storeUserParams( *mId, userId, encData* ) + @param {String} mId + @param {String} userId + @param {object} encData + ### + storeUserParams: ( mId, userId, encData ) => + @log.info "DB | (IdxedMods) #{ @setname }.storeUserParams( #{ mId }, #{ userId }, encData )" + @db.sadd "#{ @setname }-params", "#{ mId }:#{ userId }", + replyHandler "sadd '#{ mId }:#{ userId }' to '#{ @setname }-params'" + @db.set "#{ @setname }-params:#{ mId }:#{ userId }", encData, + replyHandler "set user params in '#{ @setname }-params:#{ mId }:#{ userId }'" - getUserParams: ( mId, userId, cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getUserParams( #{ mId }, #{ userId } )" - @db.get "#{ @setname }-params:#{ mId }:#{ userId }", cb + getUserParams: ( mId, userId, cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getUserParams( #{ mId }, #{ userId } )" + @db.get "#{ @setname }-params:#{ mId }:#{ userId }", cb - getUserParamsIds: ( cb ) => - @log.info "DB | (IdxedMods) #{ @setname }.getUserParamsIds()" - @db.smembers "#{ @setname }-params", cb + getUserParamsIds: ( cb ) => + @log.info "DB | (IdxedMods) #{ @setname }.getUserParamsIds()" + @db.smembers "#{ @setname }-params", cb - deleteUserParams: ( mId, userId ) => - @log.info "DB | (IdxedMods) #{ @setname }.deleteUserParams(#{ mId }, #{ userId } )" - @db.srem "#{ @setname }-params", "#{ mId }:#{ userId }", - replyHandler "srem '#{ mId }:#{ userId }' from '#{ @setname }-params'" - @db.del "#{ @setname }-params:#{ mId }:#{ userId }", - replyHandler "del '#{ @setname }-params:#{ mId }:#{ userId }'" + deleteUserParams: ( mId, userId ) => + @log.info "DB | (IdxedMods) #{ @setname }.deleteUserParams(#{ mId }, #{ userId } )" + @db.srem "#{ @setname }-params", "#{ mId }:#{ userId }", + replyHandler "srem '#{ mId }:#{ userId }' from '#{ @setname }-params'" + @db.del "#{ @setname }-params:#{ mId }:#{ userId }", + replyHandler "del '#{ @setname }-params:#{ mId }:#{ userId }'" - ### - Stores user arguments for a function within a module. They are expected to be RSA encrypted with helps of - the provided cryptico JS library and will only be decrypted right before the module is loaded! - - @private storeUserArguments( *mId, userId, encData* ) - @param {String} mId - @param {String} userId - @param {object} encData - ### - storeUserArguments: ( mId, funcId, userId, encData ) => - @log.info "DB | (IdxedMods) #{ @setname }.storeUserArguments( #{ mId }, #{ funcId }, #{ userId }, encData )" - @db.sadd "#{ @setname }:#{ mId }:#{ userId }:functions", funcId, - replyHandler "sadd '#{ funcId }' to '#{ @setname }:#{ mId }:#{ userId }:functions'" - @db.set "#{ @setname }:#{ mId }:#{ userId }:function:#{ funcId }", encData, - replyHandler "set user params in '#{ @setname }:#{ mId }:#{ userId }:function:#{ func }'" + ### + Stores user arguments for a function within a module. They are expected to be RSA encrypted with helps of + the provided cryptico JS library and will only be decrypted right before the module is loaded! + + @private storeUserArguments( *mId, userId, encData* ) + @param {String} mId + @param {String} userId + @param {object} encData + ### + storeUserArguments: ( mId, funcId, userId, encData ) => + @log.info "DB | (IdxedMods) #{ @setname }.storeUserArguments( #{ mId }, #{ funcId }, #{ userId }, encData )" + @db.sadd "#{ @setname }:#{ mId }:#{ userId }:functions", funcId, + replyHandler "sadd '#{ funcId }' to '#{ @setname }:#{ mId }:#{ userId }:functions'" + @db.set "#{ @setname }:#{ mId }:#{ userId }:function:#{ funcId }", encData, + replyHandler "set user params in '#{ @setname }:#{ mId }:#{ userId }:function:#{ func }'" - getUserArguments: ( mId, funcId, userId, cb ) => - console.log 'calling ffunct' - @log.info "DB | (IdxedMods) #{ @setname }.getUserArguments( #{ mId }, #{ funcId }, #{ userId } )" - @db.get "#{ @setname }:#{ mId }:#{ userId }:function:#{ funcId }", cb + getUserArguments: ( mId, funcId, userId, cb ) => + console.log 'calling ffunct' + @log.info "DB | (IdxedMods) #{ @setname }.getUserArguments( #{ mId }, #{ funcId }, #{ userId } )" + @db.get "#{ @setname }:#{ mId }:#{ userId }:function:#{ funcId }", cb - deleteUserArguments: ( mId, userId ) => - @log.info "DB | (IdxedMods) #{ @setname }.deleteUserArguments(#{ mId }, #{ userId } )" - @db.smembers "#{ @setname }:#{ mId }:#{ userId }:functions", ( err, obj ) => - for func in obj - @db.del "#{ @setname }:#{ mId }:#{ userId }:function:#{ func }", - replyHandler "del '#{ @setname }:#{ mId }:#{ userId }:function:#{ func }'" + deleteUserArguments: ( mId, userId ) => + @log.info "DB | (IdxedMods) #{ @setname }.deleteUserArguments(#{ mId }, #{ userId } )" + @db.smembers "#{ @setname }:#{ mId }:#{ userId }:functions", ( err, obj ) => + for func in obj + @db.del "#{ @setname }:#{ mId }:#{ userId }:function:#{ func }", + replyHandler "del '#{ @setname }:#{ mId }:#{ userId }:function:#{ func }'" ### @@ -360,8 +362,8 @@ Appends a log entry. @param {String} message ### exports.appendLog = ( userId, ruleId, moduleId, message ) => - @db.append "#{ userId }:#{ ruleId }:log", - "[#{ ( new Date ).toISOString() }] {#{ moduleId }} #{ message }\n" + @db.append "#{ userId }:#{ ruleId }:log", + "[#{ ( new Date ).toISOString() }] {#{ moduleId }} #{ message }\n" ### Retrieves a log entry. @@ -372,7 +374,7 @@ Retrieves a log entry. @param {function} cb ### exports.getLog = ( userId, ruleId, cb ) => - @db.get "#{ userId }:#{ ruleId }:log", cb + @db.get "#{ userId }:#{ ruleId }:log", cb ### Resets a log entry. @@ -382,8 +384,8 @@ Resets a log entry. @param {String} ruleId ### exports.resetLog = ( userId, ruleId ) => - @db.del "#{ userId }:#{ ruleId }:log", - replyHandler "del '#{ userId }:#{ ruleId }:log'" + @db.del "#{ userId }:#{ ruleId }:log", + replyHandler "del '#{ userId }:#{ ruleId }:log'" ### Query the DB for a rule and pass it to cb(err, obj). @@ -393,8 +395,8 @@ Query the DB for a rule and pass it to cb(err, obj). @param {function} cb ### exports.getRule = ( ruleId, cb ) => - @log.info "DB | get: 'rule:#{ ruleId }'" - @db.get "rule:#{ ruleId }", cb + @log.info "DB | get: 'rule:#{ ruleId }'" + @db.get "rule:#{ ruleId }", cb ### Fetch all rules and pass them to cb(err, obj). @@ -403,8 +405,8 @@ Fetch all rules and pass them to cb(err, obj). @param {function} cb ### exports.getRules = ( cb ) => - @log.info "DB | Fetching all Rules: getSetRecords 'rules'" - getSetRecords 'rules', exports.getRule, cb + @log.info "DB | Fetching all Rules: getSetRecords 'rules'" + getSetRecords 'rules', exports.getRule, cb ### Fetch all rule IDs and hand it to cb(err, obj). @@ -413,8 +415,8 @@ Fetch all rule IDs and hand it to cb(err, obj). @param {function} cb ### exports.getRuleIds = ( cb ) => - @log.info "DB | Fetching all Rule IDs: 'rules'" - @db.smembers 'rules', cb + @log.info "DB | Fetching all Rule IDs: 'rules'" + @db.smembers 'rules', cb ### Store a string representation of a rule in the DB. @@ -424,11 +426,11 @@ Store a string representation of a rule in the DB. @param {String} data ### exports.storeRule = ( ruleId, data ) => - @log.info "DB | storeRule: '#{ ruleId }'" - @db.sadd 'rules', "#{ ruleId }", - replyHandler "sadd rules: '#{ ruleId }'" - @db.set "rule:#{ ruleId }", data, - replyHandler "set 'rule:#{ ruleId }': data" + @log.info "DB | storeRule: '#{ ruleId }'" + @db.sadd 'rules', "#{ ruleId }", + replyHandler "sadd rules: '#{ ruleId }'" + @db.set "rule:#{ ruleId }", data, + replyHandler "set 'rule:#{ ruleId }': data" ### Delete a string representation of a rule. @@ -438,26 +440,26 @@ Delete a string representation of a rule. @param {String} userId ### exports.deleteRule = ( ruleId ) => - @log.info "DB | deleteRule: '#{ ruleId }'" - @db.srem "rules", ruleId, replyHandler "srem 'rules': '#{ ruleId }'" - @db.del "rule:#{ ruleId }", replyHandler "del: 'rule:#{ ruleId }'" + @log.info "DB | deleteRule: '#{ ruleId }'" + @db.srem "rules", ruleId, replyHandler "srem 'rules': '#{ ruleId }'" + @db.del "rule:#{ ruleId }", replyHandler "del: 'rule:#{ ruleId }'" - # We also need to delete all references in linked and active users - @db.smembers "rule:#{ ruleId }:users", ( err, obj ) => - delLinkedUserRule = ( userId ) => - exports.resetLog userId, ruleId - @db.srem "user:#{ userId }:rules", ruleId, - replyHandler "srem 'user:#{ userId }:rules': '#{ ruleId }'" - delLinkedUserRule id for id in obj - @db.del "rule:#{ ruleId }:users", replyHandler "del 'rule:#{ ruleId }:users'" + # We also need to delete all references in linked and active users + @db.smembers "rule:#{ ruleId }:users", ( err, obj ) => + delLinkedUserRule = ( userId ) => + exports.resetLog userId, ruleId + @db.srem "user:#{ userId }:rules", ruleId, + replyHandler "srem 'user:#{ userId }:rules': '#{ ruleId }'" + delLinkedUserRule id for id in obj + @db.del "rule:#{ ruleId }:users", replyHandler "del 'rule:#{ ruleId }:users'" - @db.smembers "rule:#{ ruleId }:active-users", ( err, obj ) => - delActiveUserRule = ( userId ) => - @db.srem "user:#{ userId }:active-rules", ruleId, - replyHandler "srem 'user:#{ userId }:active-rules': '#{ ruleId }'" - delActiveUserRule id for id in obj - @db.del "rule:#{ ruleId }:active-users", - replyHandler "del 'rule:#{ ruleId }:active-users'" + @db.smembers "rule:#{ ruleId }:active-users", ( err, obj ) => + delActiveUserRule = ( userId ) => + @db.srem "user:#{ userId }:active-rules", ruleId, + replyHandler "srem 'user:#{ userId }:active-rules': '#{ ruleId }'" + delActiveUserRule id for id in obj + @db.del "rule:#{ ruleId }:active-users", + replyHandler "del 'rule:#{ ruleId }:active-users'" ### Associate a rule to a user. @@ -467,11 +469,11 @@ Associate a rule to a user. @param {String} userId ### exports.linkRule = ( ruleId, userId ) => - @log.info "DB | linkRule: '#{ ruleId }' to user '#{ userId }'" - @db.sadd "rule:#{ ruleId }:users", userId, - replyHandler "sadd 'rule:#{ ruleId }:users': '#{ userId }'" - @db.sadd "user:#{ userId }:rules", ruleId, - replyHandler "sadd 'user:#{ userId }:rules': '#{ ruleId }'" + @log.info "DB | linkRule: '#{ ruleId }' to user '#{ userId }'" + @db.sadd "rule:#{ ruleId }:users", userId, + replyHandler "sadd 'rule:#{ ruleId }:users': '#{ userId }'" + @db.sadd "user:#{ userId }:rules", ruleId, + replyHandler "sadd 'user:#{ userId }:rules': '#{ ruleId }'" ### Get rules linked to a user and hand it to cb(err, obj). @@ -481,8 +483,8 @@ Get rules linked to a user and hand it to cb(err, obj). @param {function} cb ### exports.getUserLinkedRules = ( userId, cb ) => - @log.info "DB | getUserLinkedRules: 'user:#{ userId }:rules'" - @db.smembers "user:#{ userId }:rules", cb + @log.info "DB | getUserLinkedRules: 'user:#{ userId }:rules'" + @db.smembers "user:#{ userId }:rules", cb ### Get users linked to a rule and hand it to cb(err, obj). @@ -492,8 +494,8 @@ Get users linked to a rule and hand it to cb(err, obj). @param {function} cb ### exports.getRuleLinkedUsers = ( ruleId, cb ) => - @log.info "DB | getRuleLinkedUsers: 'rule:#{ ruleId }:users'" - @db.smembers "rule:#{ ruleId }:users", cb + @log.info "DB | getRuleLinkedUsers: 'rule:#{ ruleId }:users'" + @db.smembers "rule:#{ ruleId }:users", cb ### Delete an association of a rule to a user. @@ -503,11 +505,11 @@ Delete an association of a rule to a user. @param {String} userId ### exports.unlinkRule = ( ruleId, userId ) => - @log.info "DB | unlinkRule: '#{ ruleId }:#{ userId }'" - @db.srem "rule:#{ ruleId }:users", userId, - replyHandler "srem 'rule:#{ ruleId }:users': '#{ userId }'" - @db.srem "user:#{ userId }:rules", ruleId, - replyHandler "srem 'user:#{ userId }:rules': '#{ ruleId }'" + @log.info "DB | unlinkRule: '#{ ruleId }:#{ userId }'" + @db.srem "rule:#{ ruleId }:users", userId, + replyHandler "srem 'rule:#{ ruleId }:users': '#{ userId }'" + @db.srem "user:#{ userId }:rules", ruleId, + replyHandler "srem 'user:#{ userId }:rules': '#{ ruleId }'" ### Activate a rule. @@ -517,11 +519,11 @@ Activate a rule. @param {String} userId ### exports.activateRule = ( ruleId, userId ) => - @log.info "DB | activateRule: '#{ ruleId }' for '#{ userId }'" - @db.sadd "rule:#{ ruleId }:active-users", userId, - replyHandler "sadd 'rule:#{ ruleId }:active-users': '#{ userId }'" - @db.sadd "user:#{ userId }:active-rules", ruleId, - replyHandler "sadd 'user:#{ userId }:active-rules': '#{ ruleId }'" + @log.info "DB | activateRule: '#{ ruleId }' for '#{ userId }'" + @db.sadd "rule:#{ ruleId }:active-users", userId, + replyHandler "sadd 'rule:#{ ruleId }:active-users': '#{ userId }'" + @db.sadd "user:#{ userId }:active-rules", ruleId, + replyHandler "sadd 'user:#{ userId }:active-rules': '#{ ruleId }'" ### Get rules activated for a user and hand it to cb(err, obj). @@ -531,8 +533,8 @@ Get rules activated for a user and hand it to cb(err, obj). @param {function} cb ### exports.getUserActivatedRules = ( userId, cb ) => - @log.info "DB | getUserActivatedRules: smembers 'user:#{ userId }:active-rules'" - @db.smembers "user:#{ userId }:active-rules", cb + @log.info "DB | getUserActivatedRules: smembers 'user:#{ userId }:active-rules'" + @db.smembers "user:#{ userId }:active-rules", cb ### Get users activated for a rule and hand it to cb(err, obj). @@ -542,8 +544,8 @@ Get users activated for a rule and hand it to cb(err, obj). @param {function} cb ### exports.getRuleActivatedUsers = ( ruleId, cb ) => - @log.info "DB | getRuleActivatedUsers: smembers 'rule:#{ ruleId }:active-users'" - @db.smembers "rule:#{ ruleId }:active-users", cb + @log.info "DB | getRuleActivatedUsers: smembers 'rule:#{ ruleId }:active-users'" + @db.smembers "rule:#{ ruleId }:active-users", cb ### Deactivate a rule. @@ -553,11 +555,11 @@ Deactivate a rule. @param {String} userId ### exports.deactivateRule = ( ruleId, userId ) => - @log.info "DB | deactivateRule: '#{ ruleId }' for '#{ userId }'" - @db.srem "rule:#{ ruleId }:active-users", userId, - replyHandler "srem 'rule:#{ ruleId }:active-users': '#{ userId }'" - @db.srem "user:#{ userId }:active-rules", ruleId, - replyHandler "srem 'user:#{ userId }:active-rules' '#{ ruleId }'" + @log.info "DB | deactivateRule: '#{ ruleId }' for '#{ userId }'" + @db.srem "rule:#{ ruleId }:active-users", userId, + replyHandler "srem 'rule:#{ ruleId }:active-users': '#{ userId }'" + @db.srem "user:#{ userId }:active-rules", ruleId, + replyHandler "srem 'user:#{ userId }:active-rules' '#{ ruleId }'" ### Fetch all active ruleIds and pass them to cb(err, obj). @@ -566,20 +568,20 @@ Fetch all active ruleIds and pass them to cb(err, obj). @param {function} cb ### exports.getAllActivatedRuleIdsPerUser = ( cb ) => - @log.info "DB | Fetching all active rules" - @db.smembers 'users', ( err, obj ) => - result = {} - if obj.length is 0 - cb null, result - else - semaphore = obj.length - fFetchActiveUserRules = ( userId ) => - @db.smembers "user:#{ user }:active-rules", ( err, obj ) => - if obj.length > 0 - result[userId] = obj - if --semaphore is 0 - cb null, result - fFetchActiveUserRules user for user in obj + @log.info "DB | Fetching all active rules" + @db.smembers 'users', ( err, obj ) => + result = {} + if obj.length is 0 + cb null, result + else + semaphore = obj.length + fFetchActiveUserRules = ( userId ) => + @db.smembers "user:#{ user }:active-rules", ( err, obj ) => + if obj.length > 0 + result[userId] = obj + if --semaphore is 0 + cb null, result + fFetchActiveUserRules user for user in obj ### @@ -594,15 +596,15 @@ The password should be hashed before it is passed to this function. @param {Object} objUser ### exports.storeUser = ( objUser ) => - @log.info "DB | storeUser: '#{ objUser.username }'" - if objUser and objUser.username and objUser.password - @db.sadd 'users', objUser.username, - replyHandler "storing user key '#{ objUser.username }'" - objUser.password = objUser.password - @db.hmset "user:#{ objUser.username }", objUser, - replyHandler "storing user properties '#{ objUser.username }'" - else - @log.warn new Error 'DB | username or password was missing' + @log.info "DB | storeUser: '#{ objUser.username }'" + if objUser and objUser.username and objUser.password + @db.sadd 'users', objUser.username, + replyHandler "storing user key '#{ objUser.username }'" + objUser.password = objUser.password + @db.hmset "user:#{ objUser.username }", objUser, + replyHandler "storing user properties '#{ objUser.username }'" + else + @log.warn new Error 'DB | username or password was missing' ### Fetch all user IDs and pass them to cb(err, obj). @@ -611,9 +613,9 @@ Fetch all user IDs and pass them to cb(err, obj). @param {function} cb ### exports.getUserIds = ( cb ) => - @log.info "DB | getUserIds" - @db.smembers "users", cb - + @log.info "DB | getUserIds" + @db.smembers "users", cb + ### Fetch a user by id and pass it to cb(err, obj). @@ -622,9 +624,9 @@ Fetch a user by id and pass it to cb(err, obj). @param {function} cb ### exports.getUser = ( userId, cb ) => - @log.info "DB | getUser: '#{ userId }'" - @db.hgetall "user:#{ userId }", cb - + @log.info "DB | getUser: '#{ userId }'" + @db.hgetall "user:#{ userId }", cb + ### Deletes a user and all his associated linked and active rules. @@ -632,36 +634,36 @@ Deletes a user and all his associated linked and active rules. @param {String} userId ### exports.deleteUser = ( userId ) => - @log.info "DB | deleteUser: '#{ userId }'" - @db.srem "users", userId, replyHandler "Deleting user key '#{ userId }'" - @db.del "user:#{ userId }", replyHandler "Deleting user '#{ userId }'" + @log.info "DB | deleteUser: '#{ userId }'" + @db.srem "users", userId, replyHandler "Deleting user key '#{ userId }'" + @db.del "user:#{ userId }", replyHandler "Deleting user '#{ userId }'" - # We also need to delete all linked rules - @db.smembers "user:#{ userId }:rules", ( err, obj ) => - delLinkedRuleUser = ( ruleId ) => - @db.srem "rule:#{ ruleId }:users", userId, - replyHandler "Deleting user key '#{ userId }' in linked rule '#{ ruleId }'" - delLinkedRuleUser id for id in obj - @db.del "user:#{ userId }:rules", - replyHandler "Deleting user '#{ userId }' rules" + # We also need to delete all linked rules + @db.smembers "user:#{ userId }:rules", ( err, obj ) => + delLinkedRuleUser = ( ruleId ) => + @db.srem "rule:#{ ruleId }:users", userId, + replyHandler "Deleting user key '#{ userId }' in linked rule '#{ ruleId }'" + delLinkedRuleUser id for id in obj + @db.del "user:#{ userId }:rules", + replyHandler "Deleting user '#{ userId }' rules" - # We also need to delete all active rules - @db.smembers "user:#{ userId }:active-rules", ( err, obj ) => - delActivatedRuleUser = ( ruleId ) => - @db.srem "rule:#{ ruleId }:active-users", userId, - replyHandler "Deleting user key '#{ userId }' in active rule '#{ ruleId }'" - delActivatedRuleUser id for id in obj - @db.del "user:#{ userId }:active-rules", - replyHandler "Deleting user '#{ userId }' rules" + # We also need to delete all active rules + @db.smembers "user:#{ userId }:active-rules", ( err, obj ) => + delActivatedRuleUser = ( ruleId ) => + @db.srem "rule:#{ ruleId }:active-users", userId, + replyHandler "Deleting user key '#{ userId }' in active rule '#{ ruleId }'" + delActivatedRuleUser id for id in obj + @db.del "user:#{ userId }:active-rules", + replyHandler "Deleting user '#{ userId }' rules" - # We also need to delete all associated roles - @db.smembers "user:#{ userId }:roles", ( err, obj ) => - delRoleUser = ( roleId ) => - @db.srem "role:#{ roleId }:users", userId, - replyHandler "Deleting user key '#{ userId }' in role '#{ roleId }'" - delRoleUser id for id in obj - @db.del "user:#{ userId }:roles", - replyHandler "Deleting user '#{ userId }' roles" + # We also need to delete all associated roles + @db.smembers "user:#{ userId }:roles", ( err, obj ) => + delRoleUser = ( roleId ) => + @db.srem "role:#{ roleId }:users", userId, + replyHandler "Deleting user key '#{ userId }' in role '#{ roleId }'" + delRoleUser id for id in obj + @db.del "user:#{ userId }:roles", + replyHandler "Deleting user '#{ userId }' roles" ### Checks the credentials and on success returns the user object to the @@ -675,20 +677,20 @@ because we only store hashes of passwords for security6 reasons. @param {function} cb ### exports.loginUser = ( userId, password, cb ) => - @log.info "DB | User '#{ userId }' tries to log in" - fCheck = ( pw ) => - ( err, obj ) => - if err - cb err, null - else if obj and obj.password - if pw is obj.password - @log.info "DB | User '#{ obj.username }' logged in!" - cb null, obj - else - cb (new Error 'Wrong credentials!'), null - else - cb (new Error 'User not found!'), null - @db.hgetall "user:#{ userId }", fCheck password + @log.info "DB | User '#{ userId }' tries to log in" + fCheck = ( pw ) => + ( err, obj ) => + if err + cb err, null + else if obj and obj.password + if pw is obj.password + @log.info "DB | User '#{ obj.username }' logged in!" + cb null, obj + else + cb (new Error 'Wrong credentials!'), null + else + cb (new Error 'User not found!'), null + @db.hgetall "user:#{ userId }", fCheck password #TODO implement functions required for user sessions? @@ -705,12 +707,12 @@ Associate a role with a user. @param {String} role ### exports.storeUserRole = ( userId, role ) => - @log.info "DB | storeUserRole: '#{ userId }:#{ role }'" - @db.sadd 'roles', role, replyHandler "adding role '#{ role }' to role index set" - @db.sadd "user:#{ userId }:roles", role, - replyHandler "adding role '#{ role }' to user '#{ userId }'" - @db.sadd "role:#{ role }:users", userId, - replyHandler "adding user '#{ userId }' to role '#{ role }'" + @log.info "DB | storeUserRole: '#{ userId }:#{ role }'" + @db.sadd 'roles', role, replyHandler "adding role '#{ role }' to role index set" + @db.sadd "user:#{ userId }:roles", role, + replyHandler "adding role '#{ role }' to user '#{ userId }'" + @db.sadd "role:#{ role }:users", userId, + replyHandler "adding user '#{ userId }' to role '#{ role }'" ### Fetch all roles of a user and pass them to cb(err, obj). @@ -720,9 +722,9 @@ Fetch all roles of a user and pass them to cb(err, obj). @param {function} cb ### exports.getUserRoles = ( userId, cb ) => - @log.info "DB | getUserRoles: '#{ userId }'" - @db.smembers "user:#{ userId }:roles", cb - + @log.info "DB | getUserRoles: '#{ userId }'" + @db.smembers "user:#{ userId }:roles", cb + ### Fetch all users of a role and pass them to cb(err, obj). @@ -731,8 +733,8 @@ Fetch all users of a role and pass them to cb(err, obj). @param {function} cb ### exports.getRoleUsers = ( role, cb ) => - @log.info "DB | getRoleUsers: '#{ role }'" - @db.smembers "role:#{ role }:users", cb + @log.info "DB | getRoleUsers: '#{ role }'" + @db.smembers "role:#{ role }:users", cb ### Remove a role from a user. @@ -742,11 +744,11 @@ Remove a role from a user. @param {String} userId ### exports.removeUserRole = ( userId, role ) => - @log.info "DB | removeRoleFromUser: role '#{ role }', user '#{ userId }'" - @db.srem "user:#{ userId }:roles", role, - replyHandler "Removing role '#{ role }' from user '#{ userId }'" - @db.srem "role:#{ role }:users", userId, - replyHandler "Removing user '#{ userId }' from role '#{ role }'" + @log.info "DB | removeRoleFromUser: role '#{ role }', user '#{ userId }'" + @db.srem "user:#{ userId }:roles", role, + replyHandler "Removing role '#{ role }' from user '#{ userId }'" + @db.srem "role:#{ role }:users", userId, + replyHandler "Removing user '#{ userId }' from role '#{ role }'" ### @@ -755,5 +757,5 @@ Shuts down the db link. @public shutDown() ### exports.shutDown = () => - @db?.quit() - # @db?.end() + @db?.quit() + # @db?.end() diff --git a/coffee/request-handler.coffee b/coffee/request-handler.coffee index 7bbc6bb..552f75e 100644 --- a/coffee/request-handler.coffee +++ b/coffee/request-handler.coffee @@ -25,32 +25,32 @@ qs = require 'querystring' # [crypto-js](https://github.com/evanvosberg/crypto-js) mustache = require 'mustache' crypto = require 'crypto-js' - + # Prepare the user command handlers which are invoked via HTTP requests. dirHandlers = path.resolve __dirname, '..', 'webpages', 'handlers' exports = module.exports = ( args ) => - @log = args.logger + @log = args.logger - # Register the request service - @userRequestHandler = args[ 'request-service' ] + # Register the request service + @userRequestHandler = args[ 'request-service' ] - # Register the shutdown handler to the admin command. - @objAdminCmds = - shutdown: ( obj, cb ) -> - data = - code: 200 - message: 'Shutting down... BYE!' - setTimeout args[ 'shutdown-function' ], 500 - cb null, data - db args + # Register the shutdown handler to the admin command. + @objAdminCmds = + shutdown: ( obj, cb ) -> + data = + code: 200 + message: 'Shutting down... BYE!' + setTimeout args[ 'shutdown-function' ], 500 + cb null, data + db args - # Load the standard users from the user config file - users = JSON.parse fs.readFileSync path.resolve __dirname, '..', 'config', 'users.json' - fStoreUser = ( username, oUser ) -> - oUser.username = username - db.storeUser oUser - fStoreUser user, oUser for user, oUser of users - module.exports + # Load the standard users from the user config file + users = JSON.parse fs.readFileSync path.resolve __dirname, '..', 'config', 'users.json' + fStoreUser = ( username, oUser ) -> + oUser.username = username + db.storeUser oUser + fStoreUser user, oUser for user, oUser of users + module.exports ### @@ -65,32 +65,32 @@ objects.* @public handleEvent( *req, resp* ) ### exports.handleEvent = ( req, resp ) -> - body = '' - req.on 'data', ( data ) -> - body += data + body = '' + req.on 'data', ( data ) -> + body += data - req.on 'end', -> - #if req.session and req.session.user - try - obj = JSON.parse body - console.log 'got foreign event!' - console.log obj - catch err - resp.send 400, 'Badly formed event!' - # If required event properties are present we process the event # - if obj and obj.event and not err - timestamp = ( new Date ).toISOString() - rand = ( Math.floor Math.random() * 10e9 ).toString( 16 ).toUpperCase() - obj.eventid = "#{ obj.event }_#{ timestamp }_#{ rand }" - answ = - code: 200 - message: "Thank you for the event: #{ obj.eventid }" - resp.send answ.code, answ - db.pushEvent obj - else - resp.send 400, 'Your event was missing important parameters!' - # else - # resp.send 401, 'Please login!' + req.on 'end', -> + #if req.session and req.session.user + try + obj = JSON.parse body + console.log 'got foreign event!' + console.log obj + catch err + resp.send 400, 'Badly formed event!' + # If required event properties are present we process the event # + if obj and obj.event and not err + timestamp = ( new Date ).toISOString() + rand = ( Math.floor Math.random() * 10e9 ).toString( 16 ).toUpperCase() + obj.eventid = "#{ obj.event }_#{ timestamp }_#{ rand }" + answ = + code: 200 + message: "Thank you for the event: #{ obj.eventid }" + resp.send answ.code, answ + db.pushEvent obj + else + resp.send 400, 'Your event was missing important parameters!' + # else + # resp.send 401, 'Please login!' @@ -105,21 +105,21 @@ objects.* @public handleLogin( *req, resp* ) ### exports.handleLogin = ( req, resp ) => - body = '' - req.on 'data', ( data ) -> body += data - req.on 'end', => - obj = JSON.parse body - db.loginUser obj.username, obj.password, ( err, usr ) => - if err - # Tapping on fingers, at least in log... - @log.warn "RH | AUTH-UH-OH ( #{ obj.username } ): #{ err.message }" - else - # no error, so we can associate the user object from the DB to the session - req.session.user = usr - if req.session.user - resp.send 'OK!' - else - resp.send 401, 'NO!' + body = '' + req.on 'data', ( data ) -> body += data + req.on 'end', => + obj = JSON.parse body + db.loginUser obj.username, obj.password, ( err, usr ) => + if err + # Tapping on fingers, at least in log... + @log.warn "RH | AUTH-UH-OH ( #{ obj.username } ): #{ err.message }" + else + # no error, so we can associate the user object from the DB to the session + req.session.user = usr + if req.session.user + resp.send 'OK!' + else + resp.send 401, 'NO!' ### A post request retrieved on this handler causes the user object to be @@ -133,9 +133,9 @@ objects.* @public handleLogout( *req, resp* ) ### exports.handleLogout = ( req, resp ) -> - if req.session - req.session.user = null - resp.send 'Bye!' + if req.session + req.session.user = null + resp.send 'Bye!' ### @@ -145,7 +145,7 @@ Resolves the path to a handler webpage. @param {String} name ### getHandlerPath = ( name ) -> - path.join dirHandlers, name + '.html' + path.join dirHandlers, name + '.html' ### Fetches a template. @@ -154,9 +154,9 @@ Fetches a template. @param {String} name ### getTemplate = ( name ) -> - pth = path.join dirHandlers, 'templates', name + '.html' - fs.readFileSync pth, 'utf8' - + pth = path.join dirHandlers, 'templates', name + '.html' + fs.readFileSync pth, 'utf8' + ### Fetches a script. @@ -164,9 +164,9 @@ Fetches a script. @param {String} name ### getScript = ( name ) -> - pth = path.join dirHandlers, 'js', name + '.js' - fs.readFileSync pth, 'utf8' - + pth = path.join dirHandlers, 'js', name + '.js' + fs.readFileSync pth, 'utf8' + ### Fetches remote scripts snippets. @@ -174,9 +174,9 @@ Fetches remote scripts snippets. @param {String} name ### getRemoteScripts = ( name ) -> - pth = path.join dirHandlers, 'remote-scripts', name + '.html' - fs.readFileSync pth, 'utf8' - + pth = path.join dirHandlers, 'remote-scripts', name + '.html' + fs.readFileSync pth, 'utf8' + ### Renders a page, with helps of mustache, depending on the user session and returns it. @@ -186,46 +186,46 @@ Renders a page, with helps of mustache, depending on the user session and return @param {Object} msg ### renderPage = ( name, req, resp, msg ) -> - # Grab the skeleton - pathSkel = path.join dirHandlers, 'skeleton.html' - skeleton = fs.readFileSync pathSkel, 'utf8' - code = 200 - data = - message: msg - user: req.session.user + # Grab the skeleton + pathSkel = path.join dirHandlers, 'skeleton.html' + skeleton = fs.readFileSync pathSkel, 'utf8' + code = 200 + data = + message: msg + user: req.session.user - # Try to grab the script belonging to this page. But don't bother if it's not existing - try - script = getScript name - # Try to grab the remote scripts belonging to this page. But don't bother if it's not existing - try - remote_scripts = getRemoteScripts name + # Try to grab the script belonging to this page. But don't bother if it's not existing + try + script = getScript name + # Try to grab the remote scripts belonging to this page. But don't bother if it's not existing + try + remote_scripts = getRemoteScripts name - # Now try to find the page the user requested. - try - content = getTemplate name - catch err - # If the page doesn't exist we return the error page, load the error script into it - # and render the error page with some additional data - content = getTemplate 'error' - script = getScript 'error' - code = 404 - data.message = 'Invalid Page!' + # Now try to find the page the user requested. + try + content = getTemplate name + catch err + # If the page doesn't exist we return the error page, load the error script into it + # and render the error page with some additional data + content = getTemplate 'error' + script = getScript 'error' + code = 404 + data.message = 'Invalid Page!' - if req.session.user - menubar = getTemplate 'menubar' + if req.session.user + menubar = getTemplate 'menubar' - pageElements = - content: content - script: script - remote_scripts: remote_scripts - menubar: menubar + pageElements = + content: content + script: script + remote_scripts: remote_scripts + menubar: menubar - # First we render the page by including all page elements into the skeleton - page = mustache.render skeleton, pageElements + # First we render the page by including all page elements into the skeleton + page = mustache.render skeleton, pageElements - # Then we complete the rendering by adding the data, and send the result to the user - resp.send code, mustache.render page, data + # Then we complete the rendering by adding the data, and send the result to the user + resp.send code, mustache.render page, data ### Present the desired forge page to the user. @@ -238,10 +238,10 @@ objects.* @public handleForge( *req, resp* ) ### exports.handleForge = ( req, resp ) -> - page = req.query.page - if not req.session.user - page = 'login' - renderPage page, req, resp + page = req.query.page + if not req.session.user + page = 'login' + renderPage page, req, resp ### Handles the user command requests. @@ -254,18 +254,18 @@ objects.* @public handleUser( *req, resp* ) ### exports.handleUserCommand = ( req, resp ) => - if req.session and req.session.user - body = '' - #Append data to body while receiving fragments - req.on 'data', ( data ) -> - body += data - req.on 'end', => - obj = qs.parse body - # Let the user request handler service answer the request - @userRequestHandler req.session.user, obj, ( obj ) -> - resp.send obj.code, obj - else - resp.send 401, 'Login first!' + if req.session and req.session.user + body = '' + #Append data to body while receiving fragments + req.on 'data', ( data ) -> + body += data + req.on 'end', => + obj = qs.parse body + # Let the user request handler service answer the request + @userRequestHandler req.session.user, obj, ( obj ) -> + resp.send obj.code, obj + else + resp.send 401, 'Login first!' ### @@ -279,15 +279,15 @@ objects.* @public handleForge( *req, resp* ) ### exports.handleAdmin = ( req, resp ) -> - if not req.session.user - page = 'login' - #TODO isAdmin should come from the db role - else if req.session.user.isAdmin isnt "true" - page = 'login' - msg = 'You need to be admin!' - else - page = 'admin' - renderPage page, req, resp, msg + if not req.session.user + page = 'login' + #TODO isAdmin should come from the db role + else if req.session.user.isAdmin isnt "true" + page = 'login' + msg = 'You need to be admin!' + else + page = 'admin' + renderPage page, req, resp, msg ### Handles the admin command requests. @@ -300,20 +300,20 @@ objects.* @public handleAdminCommand( *req, resp* ) ### exports.handleAdminCommand = ( req, resp ) => - if req.session and - req.session.user and - req.session.user.isAdmin is "true" - body = '' - req.on 'data', ( data ) -> - body += data - req.on 'end', => - obj = qs.parse body - @log.info 'RH | Received admin request: ' + obj.command - if obj.command and @objAdminCmds[obj.command] - @objAdminCmds[obj.command] obj, ( err, obj ) -> - resp.send obj.code, obj - else - resp.send 404, 'Command unknown!' - else - resp.send 401, 'You need to be logged in as admin!' - + if req.session and + req.session.user and + req.session.user.isAdmin is "true" + body = '' + req.on 'data', ( data ) -> + body += data + req.on 'end', => + obj = qs.parse body + @log.info 'RH | Received admin request: ' + obj.command + if obj.command and @objAdminCmds[obj.command] + @objAdminCmds[obj.command] obj, ( err, obj ) -> + resp.send obj.code, obj + else + resp.send 404, 'Command unknown!' + else + resp.send 401, 'You need to be logged in as admin!' + diff --git a/coffee/webapi-eca.coffee b/coffee/webapi-eca.coffee index e9fbccd..9f6a3f3 100644 --- a/coffee/webapi-eca.coffee +++ b/coffee/webapi-eca.coffee @@ -51,69 +51,69 @@ Let's prepare the optimist CLI optional arguments `[opt]`: usage = 'This runs your webapi-based ECA engine' opt = # `-h`, `--help`: Display the help - 'h': - alias : 'help', - describe: 'Display this' + 'h': + alias : 'help', + describe: 'Display this' # `-c`, `--config-path`: Specify a path to a custom configuration file, other than "config/config.json" - 'c': - alias : 'config-path', - describe: 'Specify a path to a custom configuration file, other than "config/config.json"' + 'c': + alias : 'config-path', + describe: 'Specify a path to a custom configuration file, other than "config/config.json"' # `-w`, `--http-port`: Specify a HTTP port for the web server - 'w': - alias : 'http-port', - describe: 'Specify a HTTP port for the web server' + 'w': + alias : 'http-port', + describe: 'Specify a HTTP port for the web server' # `-d`, `--db-port`: Specify a port for the redis DB - 'd': - alias : 'db-port', - describe: 'Specify a port for the redis DB' + 'd': + alias : 'db-port', + describe: 'Specify a port for the redis DB' # `-m`, `--log-mode`: Specify a log mode: [development|productive] - 'm': - alias : 'log-mode', - describe: 'Specify a log mode: [development|productive]' + 'm': + alias : 'log-mode', + describe: 'Specify a log mode: [development|productive]' # `-i`, `--log-io-level`: Specify the log level for the I/O. in development expensive origin # lookups are made and added to the log entries - 'i': - alias : 'log-io-level', - describe: 'Specify the log level for the I/O' + 'i': + alias : 'log-io-level', + describe: 'Specify the log level for the I/O' # `-f`, `--log-file-level`: Specify the log level for the log file - 'f': - alias : 'log-file-level', - describe: 'Specify the log level for the log file' + 'f': + alias : 'log-file-level', + describe: 'Specify the log level for the log file' # `-p`, `--log-file-path`: Specify the path to the log file within the "logs" folder - 'p': - alias : 'log-file-path', - describe: 'Specify the path to the log file within the "logs" folder' + 'p': + alias : 'log-file-path', + describe: 'Specify the path to the log file within the "logs" folder' # `-n`, `--nolog`: Set this true if no output shall be generated - 'n': - alias : 'nolog', - describe: 'Set this if no output shall be generated' + 'n': + alias : 'nolog', + describe: 'Set this if no output shall be generated' # now fetch the CLI arguments and exit if the help has been called. argv = optimist.usage( usage ).options( opt ).argv if argv.help - console.log optimist.help() - process.exit() + console.log optimist.help() + process.exit() conf argv.c # > Check whether the config file is ready, which is required to start the server. if !conf.isReady() - console.error 'FAIL: Config file not ready! Shutting down...' - process.exit() + console.error 'FAIL: Config file not ready! Shutting down...' + process.exit() logconf = conf.getLogConf() if argv.m - logconf[ 'mode' ] = argv.m + logconf[ 'mode' ] = argv.m if argv.i - logconf[ 'io-level' ] = argv.i + logconf[ 'io-level' ] = argv.i if argv.f - logconf[ 'file-level' ] = argv.f + logconf[ 'file-level' ] = argv.f if argv.p - logconf[ 'file-path' ] = argv.p + logconf[ 'file-path' ] = argv.p if argv.n - logconf[ 'nolog' ] = true + logconf[ 'nolog' ] = true try - fs.unlinkSync path.resolve __dirname, '..', 'logs', logconf[ 'file-path' ] + fs.unlinkSync path.resolve __dirname, '..', 'logs', logconf[ 'file-path' ] @log = logger.getLogger logconf @log.info 'RS | STARTING SERVER' @@ -124,80 +124,81 @@ This function is invoked right after the module is loaded and starts the server. ### init = => - args = - logger: @log - logconf: logconf - # > Fetch the `http-port` argument - args[ 'http-port' ] = parseInt argv.w || conf.getHttpPort() - args[ 'db-port' ] = parseInt argv.d || conf.getDbPort() + args = + logger: @log + logconf: logconf + # > Fetch the `http-port` argument + args[ 'http-port' ] = parseInt argv.w || conf.getHttpPort() + args[ 'db-port' ] = parseInt argv.d || conf.getDbPort() - #FIXME this has to come from user input for security reasons: - args[ 'keygen' ] = conf.getKeygenPassphrase() - - @log.info 'RS | Initialzing DB' - db args - # > We only proceed with the initialization if the DB is ready - #TODO eventually we shouldn't let each module load its own persistence - #module, but hand this one through them via the args... - db.isConnected ( err ) => - if err - @log.error 'RS | No DB connection, shutting down system!' - shutDown() + #FIXME this has to come from user input for security reasons: + args[ 'keygen' ] = conf.getKeygenPassphrase() + args[ 'webhooks' ] = conf.fetchProp 'webhooks' + + @log.info 'RS | Initialzing DB' + db args + # > We only proceed with the initialization if the DB is ready + #TODO eventually we shouldn't let each module load its own persistence + #module, but hand this one through them via the args... + db.isConnected ( err ) => + if err + @log.error 'RS | No DB connection, shutting down system!' + shutDown() - else - # > Initialize all required modules with the args object. - @log.info 'RS | Initialzing engine' - #TODO We could in the future make the engine a child process as well - engine args - - # Start the event poller. The module manager will emit events for it - @log.info 'RS | Forking a child process for the event poller' - # Grab all required log config fields - - cliArgs = [ - # - the log mode: [development|productive], in development expensive origin - # lookups are made and added to the log entries - args.logconf[ 'mode' ] - # - the I/O log level, refer to logging.coffee for the different levels - args.logconf[ 'io-level' ] - # - the file log level, refer to logging.coffee for the different levels - args.logconf[ 'file-level' ] - # - the optional path to the log file - args.logconf[ 'file-path' ] - # - whether a log file shall be written at all [true|false] - args.logconf[ 'nolog' ] - # - The keygen phrase, this has to be handled differently in the future! - args[ 'keygen' ] - ] - poller = cp.fork path.resolve( __dirname, nameEP ), cliArgs + else + # > Initialize all required modules with the args object. + @log.info 'RS | Initialzing engine' + #TODO We could in the future make the engine a child process as well + engine args + + # Start the event poller. The module manager will emit events for it + @log.info 'RS | Forking a child process for the event poller' + # Grab all required log config fields + + cliArgs = [ + # - the log mode: [development|productive], in development expensive origin + # lookups are made and added to the log entries + args.logconf[ 'mode' ] + # - the I/O log level, refer to logging.coffee for the different levels + args.logconf[ 'io-level' ] + # - the file log level, refer to logging.coffee for the different levels + args.logconf[ 'file-level' ] + # - the optional path to the log file + args.logconf[ 'file-path' ] + # - whether a log file shall be written at all [true|false] + args.logconf[ 'nolog' ] + # - The keygen phrase, this has to be handled differently in the future! + args[ 'keygen' ] + ] + poller = cp.fork path.resolve( __dirname, nameEP ), cliArgs - # after the engine and the event poller have been initialized we can - # initialize the module manager and register event listener functions - # from engine and event poller - @log.info 'RS | Initialzing module manager' - cm args - cm.addRuleListener engine.internalEvent - cm.addRuleListener ( evt ) -> poller.send evt + # after the engine and the event poller have been initialized we can + # initialize the module manager and register event listener functions + # from engine and event poller + @log.info 'RS | Initialzing module manager' + cm args + cm.addRuleListener engine.internalEvent + cm.addRuleListener ( evt ) -> poller.send evt - @log.info 'RS | Initialzing http listener' - # The request handler passes certain requests to the module manager - args[ 'request-service' ] = cm.processRequest - # We give the HTTP listener the ability to shutdown the whole system - args[ 'shutdown-function' ] = shutDown - http args - + @log.info 'RS | Initialzing http listener' + # The request handler passes certain requests to the module manager + args[ 'request-service' ] = cm.processRequest + # We give the HTTP listener the ability to shutdown the whole system + args[ 'shutdown-function' ] = shutDown + http args + ### Shuts down the server. @private shutDown() ### shutDown = () => - @log.warn 'RS | Received shut down command!' - db?.shutDown() - engine.shutDown() - # We need to call process.exit() since the express server in the http-listener - # can't be stopped gracefully. Why would you stop this system anyways!?? - process.exit() + @log.warn 'RS | Received shut down command!' + db?.shutDown() + engine.shutDown() + # We need to call process.exit() since the express server in the http-listener + # can't be stopped gracefully. Why would you stop this system anyways!?? + process.exit() ### ## Process Commands diff --git a/config/system.json b/config/system.json index c75a3a9..fc5282f 100644 --- a/config/system.json +++ b/config/system.json @@ -8,5 +8,8 @@ "file-level": "info", "file-path": "logs/server.log" }, + "webhooks": [ + "github" + ], "keygen-passphrase": "[TODO this has to come from prompt when server is started!]" } \ No newline at end of file diff --git a/examples/action-invokers/probinder.coffee b/examples/action-invokers/probinder.coffee index 06c9446..4a83d80 100644 --- a/examples/action-invokers/probinder.coffee +++ b/examples/action-invokers/probinder.coffee @@ -1,3 +1,5 @@ + + ### ProBinder ACTION INVOKER ------------------------ @@ -6,8 +8,6 @@ Global variables This module requires user-specific parameters: - username - password -- companyId: company where to post the binder entries -- contextId: context where to post the binder entries ### urlService = 'https://probinder.com/service/' credentials = @@ -44,50 +44,45 @@ callService = ( args ) -> if not args.callback args.callback = standardCallback 'call' url = urlService + args.service + '/' + args.method - needlereq 'post', url, args.data, credentials, args.callback + needle.request 'post', url, args.data, credentials, args.callback ### Does everything to post something in a binder -@param {Object} args the object containing the content -@param {String} args.content the content to be posted +@param {String} companyId the comany associated to the binder +@param {String} contextId the binder id +@param {String} content the content to be posted ### -exports.newContent = ( args ) -> - if not args.callback - args.callback = standardCallback 'newContent' +exports.newContent = ( companyId, contextId, content ) -> + if arguments[ 4 ] + callback = arguments[ 4 ] + else + callback = standardCallback 'newContent' callService service: '27' method: 'save' data: - companyId: params.companyId - context: params.contextId - text: args.content - callback: args.callback + companyId: companyId + context: contextId + text: content + callback: callback ### -Does everything to post a file info in a binder tabe +Does everything to post a file info in a binder tab -@param {Object} args the object containing the content -@param {String} args.service the content service -@param {String} args.id the content id +@param {String} fromService the content service which grabs the content +@param {String} fromId the content id from which the information is grabbed ### -exports.makeFileEntry = ( args ) -> - if not args.callback - args.callback = standardCallback 'makeFileEntry' +exports.makeFileEntry = ( fromService, fromId, toCompany, toContext ) -> getContent - serviceid: args.service - contentid: args.id + serviceid: fromService + contentid: fromId callback: ( err, resp, body ) -> - callService - service: '27' - method: 'save' - data: - companyId: params.companyId - context: params.contextId - text: "New file (#{ body.title }) in tab \"#{ body.context[0].name }\", - find it here!'" - callback: args.callback + content = "New file (#{ body.title }) in tab \"#{ body.context[0].name }\", + find it here!'" + exports.newContent toCompanyId, toContextId, content, standardCallback 'makeFileEntry' + ### Calls the content get service with the content id and the service id provided. @@ -112,15 +107,12 @@ getContent = ( args ) -> ### Sets the content as read. -@param {Object} args the object containing the content -@param {String} args.content the content to be posted +@param {Object} id the content id to be set to read. ### -exports.setRead = ( args ) -> - if not args.callback - args.callback = standardCallback 'setRead' +exports.setRead = ( id ) -> callService service: '2' method: 'setread' data: - id: args.id - callback: args.callback \ No newline at end of file + id: id + callback: standardCallback 'setRead' diff --git a/examples/runscript.coffee b/examples/runscript.coffee index daaff56..a8478df 100644 --- a/examples/runscript.coffee +++ b/examples/runscript.coffee @@ -18,26 +18,7 @@ cs = require 'coffee-script' needle = require 'needle' crypto = require 'crypto-js' request = require 'request' - -issueApiCall = ( method, url, data, options, cb ) -> - try - needle.request method, url, data, options, ( err, resp, body ) => - try - cb err, resp, body - catch err - console.log 'Error during needle request! ' + err.message - catch err - console.log 'Error before needle request! ' + err.message - -issueRequest = ( options, cb ) -> - try - request options, ( err, resp, body ) => - try - cb err, resp, body - catch err - console.log 'Error during request! ' + err.message - catch err - console.log 'Error before request! ' + err.message +importio = require( 'import-io' ).client params = JSON.parse fs.readFileSync 'params.json', 'utf8' code = fs.readFileSync process.argv[ 2 ], 'utf8' @@ -46,9 +27,10 @@ src = cs.compile code sandbox = id: 'test.vm' params: params.userparams - needlereq: issueApiCall - request: issueRequest + needle: needle + request: request cryptoJS: crypto + importio: importio log: console.log debug: console.log exports: {} diff --git a/examples/runscript.js b/examples/runscript.js index aaa559f..8271233 100644 --- a/examples/runscript.js +++ b/examples/runscript.js @@ -9,7 +9,7 @@ compilation and running of module code */ (function() { - var code, crypto, cs, fs, issueApiCall, issueRequest, needle, params, request, sandbox, src, vm; + var code, crypto, cs, fs, importio, needle, params, request, sandbox, src, vm; if (!process.argv[2]) { console.log('Please provide a path to a coffee file'); @@ -28,43 +28,7 @@ compilation and running of module code request = require('request'); - issueApiCall = function(method, url, data, options, cb) { - var err; - try { - return needle.request(method, url, data, options, (function(_this) { - return function(err, resp, body) { - try { - return cb(err, resp, body); - } catch (_error) { - err = _error; - return console.log('Error during needle request! ' + err.message); - } - }; - })(this)); - } catch (_error) { - err = _error; - return console.log('Error before needle request! ' + err.message); - } - }; - - issueRequest = function(options, cb) { - var err; - try { - return request(options, (function(_this) { - return function(err, resp, body) { - try { - return cb(err, resp, body); - } catch (_error) { - err = _error; - return console.log('Error during request! ' + err.message); - } - }; - })(this)); - } catch (_error) { - err = _error; - return console.log('Error before request! ' + err.message); - } - }; + importio = require('import-io').client; params = JSON.parse(fs.readFileSync('params.json', 'utf8')); @@ -75,9 +39,10 @@ compilation and running of module code sandbox = { id: 'test.vm', params: params.userparams, - needlereq: issueApiCall, - request: issueRequest, + needle: needle, + request: request, cryptoJS: crypto, + importio: importio, log: console.log, debug: console.log, exports: {} diff --git a/js/components-manager.js b/js/components-manager.js index 667a3a8..e092e30 100644 --- a/js/components-manager.js +++ b/js/components-manager.js @@ -103,8 +103,8 @@ Components Manager - `user` is the user object as it comes from the DB. - `oReq` is the request object that contains: - - `command` as a string - - `payload` an optional stringified JSON object + - `command` as a string + - `payload` an optional stringified JSON object The callback function `callback( obj )` will receive an object containing the HTTP response code and a corresponding message. @@ -239,6 +239,7 @@ Components Manager src = oPayload.data; return dynmod.compileString(src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, function(cm) { var funcs, id, name, _ref; + console.log(cm); answ = cm.answ; if (answ.code === 200) { funcs = []; @@ -250,7 +251,7 @@ Components Manager _this.log.info("CM | Storing new module with functions " + (funcs.join(', '))); answ.message = " Module " + oPayload.id + " successfully stored! Found following function(s): " + funcs; oPayload.functions = JSON.stringify(funcs); - oPayload.functionParameters = JSON.stringify(cm.funcParams); + oPayload.functionArgs = JSON.stringify(cm.funcParams); dbMod.storeModule(user.username, oPayload); if (oPayload["public"] === 'true') { dbMod.publish(oPayload.id); @@ -327,7 +328,7 @@ Components Manager if (answ.code !== 200) { return callback(answ); } else { - return db.actionInvokers.getModuleField(oPayload.id, 'functionParameters', function(err, obj) { + return db.actionInvokers.getModuleField(oPayload.id, 'functionArgs', function(err, obj) { return callback({ code: 200, message: obj @@ -390,6 +391,7 @@ Components Manager rule = { id: oPayload.id, event: oPayload.event, + event_interval: oPayload.event_interval, conditions: oPayload.conditions, actions: oPayload.actions }; diff --git a/js/config.js b/js/config.js index e984a2e..38f1dbd 100644 --- a/js/config.js +++ b/js/config.js @@ -8,7 +8,7 @@ Configuration */ (function() { - var exports, fetchProp, fs, loadConfigFile, path; + var exports, fs, loadConfigFile, path; fs = require('fs'); @@ -85,7 +85,7 @@ Configuration @param {String} prop */ - fetchProp = (function(_this) { + exports.fetchProp = (function(_this) { return function(prop) { var _ref; return (_ref = _this.config) != null ? _ref[prop] : void 0; @@ -113,7 +113,7 @@ Configuration */ exports.getHttpPort = function() { - return fetchProp('http-port'); + return exports.fetchProp('http-port'); }; @@ -124,7 +124,7 @@ Configuration */ exports.getDbPort = function() { - return fetchProp('db-port'); + return exports.fetchProp('db-port'); }; @@ -135,7 +135,7 @@ Configuration */ exports.getLogConf = function() { - return fetchProp('log'); + return exports.fetchProp('log'); }; @@ -146,7 +146,7 @@ Configuration */ exports.getKeygenPassphrase = function() { - return fetchProp('keygen-passphrase'); + return exports.fetchProp('keygen-passphrase'); }; }).call(this); diff --git a/js/dynamic-modules.js b/js/dynamic-modules.js index 49833b6..8695dbc 100644 --- a/js/dynamic-modules.js +++ b/js/dynamic-modules.js @@ -9,7 +9,7 @@ Dynamic Modules */ (function() { - var cryptico, cryptoJS, cs, db, exports, getFunctionParamNames, logFunction, needle, regexpComments, request, vm; + var cryptico, cryptoJS, cs, db, exports, fTryToLoadModule, getFunctionParamNames, importio, logFunction, needle, regexpComments, request, vm; db = require('./persistence'); @@ -25,6 +25,8 @@ Dynamic Modules cryptoJS = require('crypto-js'); + importio = require('import-io').client; + /* Module call @@ -89,99 +91,114 @@ Dynamic Modules exports.compileString = (function(_this) { return function(src, userId, ruleId, modId, lang, dbMod, cb) { - var answ, err, fTryToLoad; - answ = { - code: 200, - message: 'Successfully compiled' - }; + var err; if (lang === 'CoffeeScript') { try { + _this.log.info("DM | Compiling module '" + modId + "' for user '" + userId + "'"); src = cs.compile(src); } catch (_error) { err = _error; - answ.code = 400; - answ.message = 'Compilation of CoffeeScript failed at line ' + err.location.first_line; + cb({ + code: 400, + message: 'Compilation of CoffeeScript failed at line ' + err.location.first_line + }); + return; } } - fTryToLoad = function(params) { - var fName, func, logFunc, msg, oDecrypted, oFuncArgs, oFuncParams, sandbox, _ref; - if (params) { + _this.log.info("DM | Trying to fetch user specific module '" + modId + "' paramters for user '" + userId + "'"); + if (dbMod) { + return dbMod.getUserParams(modId, userId, function(err, obj) { + var oDecrypted; try { - oDecrypted = cryptico.decrypt(params, _this.oPrivateRSAkey); - params = JSON.parse(oDecrypted.plaintext); + oDecrypted = cryptico.decrypt(obj, _this.oPrivateRSAkey); + obj = JSON.parse(oDecrypted.plaintext); + _this.log.warn("DM | Loaded user defined params for " + userId + ", " + ruleId + ", " + modId); } catch (_error) { err = _error; _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + ruleId + ", " + modId); _this.log.warn(err); - params = {}; } - } else { - params = {}; - } - logFunc = logFunction(userId, ruleId, modId); - sandbox = { - id: userId + '.' + modId + '.vm', - params: params, - needle: needle, - request: request, - cryptoJS: cryptoJS, - log: logFunc, - debug: console.log, - exports: {} - }; - try { - vm.runInNewContext(src, sandbox, sandbox.id); - } catch (_error) { - err = _error; - answ.code = 400; - msg = err.message; - if (!msg) { - msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number'; - } - answ.message = 'Loading Module failed: ' + msg; - } - oFuncParams = {}; - _ref = sandbox.exports; - for (fName in _ref) { - func = _ref[fName]; - getFunctionParamNames(fName, func, oFuncParams); - } - if (dbMod) { - oFuncArgs = {}; - console.log('oFuncParams'); - console.log(oFuncParams); - for (func in oFuncParams) { - console.log('fetching ' + func); - console.log(typeof func); - dbMod.getUserArguments(modId, func, userId, function(err, obj) { - console.log(err, obj); - try { - oDecrypted = cryptico.decrypt(obj, _this.oPrivateRSAkey); - return oFuncArgs[func] = JSON.parse(oDecrypted.plaintext); - } catch (_error) { - err = _error; - _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + ruleId + ", " + modId); - return _this.log.warn(err); - } - }); - } - } - return cb({ - answ: answ, - module: sandbox.exports, - funcParams: oFuncParams, - funcArgs: oFuncArgs, - logger: sandbox.log - }); - }; - if (dbMod) { - return dbMod.getUserParams(modId, userId, function(err, obj) { - return fTryToLoad(obj); + return fTryToLoadModule(userId, ruleId, modId, src, dbMod, obj, cb); }); } else { - return fTryToLoad(null); + return fTryToLoadModule(userId, ruleId, modId, src, dbMod, null, cb); } }; })(this); + fTryToLoadModule = (function(_this) { + return function(userId, ruleId, modId, src, dbMod, params, cb) { + var answ, err, fName, func, logFunc, msg, oFuncArgs, oFuncParams, sandbox, _ref; + if (!params) { + params = {}; + answ = { + code: 200, + message: 'Successfully compiled' + }; + } + _this.log.info("DM | Running module '" + modId + "' for user '" + userId + "'"); + logFunc = logFunction(userId, ruleId, modId); + sandbox = { + id: "" + userId + "." + ruleId + "." + modId + ".vm", + params: params, + needle: needle, + importio: importio, + request: request, + cryptoJS: cryptoJS, + log: logFunc, + debug: console.log, + exports: {} + }; + try { + vm.runInNewContext(src, sandbox, sandbox.id); + } catch (_error) { + err = _error; + answ.code = 400; + msg = err.message; + if (!msg) { + msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number'; + } + answ.message = 'Loading Module failed: ' + msg; + } + _this.log.info("DM | Module '" + modId + "' ran successfully for user '" + userId + "' in rule '" + ruleId + "'"); + oFuncParams = {}; + oFuncArgs = {}; + _ref = sandbox.exports; + for (fName in _ref) { + func = _ref[fName]; + getFunctionParamNames(fName, func, oFuncParams); + } + if (dbMod) { + oFuncArgs = {}; + console.log('oFuncParams'); + console.log(oFuncParams); + for (func in oFuncParams) { + console.log('fetching ' + func); + console.log(typeof func); + dbMod.getUserArguments(modId, func, userId, function(err, obj) { + var oDecrypted; + console.log(err, obj); + try { + oDecrypted = cryptico.decrypt(obj, _this.oPrivateRSAkey); + return oFuncArgs[func] = JSON.parse(oDecrypted.plaintext); + } catch (_error) { + err = _error; + _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + ruleId + ", " + modId); + return _this.log.warn(err); + } + }); + } + } + console.log('answering compile request string'); + console.log(cb); + return cb({ + answ: answ, + module: sandbox.exports, + funcParams: oFuncParams, + funcArgs: oFuncArgs, + logger: sandbox.log + }); + }; + })(this); + }).call(this); diff --git a/js/engine.js b/js/engine.js index 9430c60..22bcd52 100644 --- a/js/engine.js +++ b/js/engine.js @@ -10,7 +10,7 @@ Engine */ (function() { - var db, dynmod, exports, isRunning, jsonQuery, listUserRules, pollQueue, processEvent, semaphore, updateActionModules, validConditions; + var db, dynmod, exports, isRunning, jsonQuery, listUserRules, numExecutingFunctions, pollQueue, processEvent, updateActionModules, validConditions; db = require('./persistence'); @@ -23,21 +23,21 @@ Engine 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 + "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 = {}; @@ -126,87 +126,92 @@ Engine @param {Object} updatedRuleId */ - updateActionModules = function(updatedRuleId) { - var fAddRequired, fRemoveNotRequired, name, oUser, userName, _results; - fRemoveNotRequired = function(oUser) { - var action, fRequired, _results; - fRequired = function(actionName) { - 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[updatedRuleId].rule.actions) { - if (!fRequired(action)) { - _results.push(delete oUser[updatedRuleId].actions[action]); - } else { - _results.push(void 0); - } - } - return _results; - }; - for (name in listUserRules) { - oUser = listUserRules[name]; - fRemoveNotRequired(oUser); - } - fAddRequired = function(userName, oUser) { - 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 (!oMyRule.actions[moduleName] || oMyRule.rule.id === updatedRuleId) { - return db.actionInvokers.getModule(moduleName, function(err, obj) { - 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; - }); - }); + updateActionModules = (function(_this) { + return function(updatedRuleId) { + var fAddRequired, fRemoveNotRequired, name, oUser, userName, _results; + fRemoveNotRequired = function(oUser) { + var action, fRequired, _results; + fRequired = function(actionName) { + 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; }; - _ref = oMyRule.rule.actions; _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - action = _ref[_i]; - _results.push(fAddIfNewOrNotExisting(action)); + for (action in oUser[updatedRuleId].rule.actions) { + if (!fRequired(action)) { + _results.push(delete oUser[updatedRuleId].actions[action]); + } else { + _results.push(void 0); + } + } + return _results; + }; + for (name in listUserRules) { + oUser = listUserRules[name]; + fRemoveNotRequired(oUser); + } + fAddRequired = function(userName, oUser) { + 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 (!oMyRule.actions[moduleName] || oMyRule.rule.id === updatedRuleId) { + return db.actionInvokers.getModule(moduleName, function(err, obj) { + if (obj) { + 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; + }); + } else { + return _this.log.warn('EN | #{ moduleName } not found for #{ oMyRule.rule.id }!'); + } + }); + } + }; + _ref = oMyRule.rule.actions; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + action = _ref[_i]; + _results.push(fAddIfNewOrNotExisting(action)); + } + return _results; + }; + _results = []; + for (nmRl in oUser) { + oRl = oUser[nmRl]; + _results.push(fCheckRules(oRl)); } return _results; }; _results = []; - for (nmRl in oUser) { - oRl = oUser[nmRl]; - _results.push(fCheckRules(oRl)); + for (userName in listUserRules) { + oUser = listUserRules[userName]; + _results.push(fAddRequired(userName, oUser)); } return _results; }; - _results = []; - for (userName in listUserRules) { - oUser = listUserRules[userName]; - _results.push(fAddRequired(userName, oUser)); - } - return _results; - }; + })(this); - semaphore = 0; + numExecutingFunctions = 1; pollQueue = function() { if (isRunning) { db.popEvent(function(err, obj) { if (!err && obj) { - processEvent(obj); + return processEvent(obj); } - return semaphore--; }); - return setTimeout(pollQueue, 20 * semaphore); + return setTimeout(pollQueue, 20 * numExecutingFunctions); } }; @@ -234,8 +239,6 @@ Engine return true; }; - semaphore = 0; - /* Handles retrieved events. @@ -250,20 +253,22 @@ Engine fSearchAndInvokeAction = function(node, arrPath, funcName, evt, depth) { var err; if (!node) { - this.log.error("EN | Didn't find property in user rule list: " + arrPath.join(', ' + " at depth " + depth)); + _this.log.error("EN | Didn't find property in user rule list: " + arrPath.join(', ' + " at depth " + depth)); return; } if (depth === arrPath.length) { try { - semaphore++; + numExecutingFunctions++; + _this.log.info("EN | " + funcName + " executes..."); node[funcName](evt.payload); + _this.log.info("EN | " + funcName + " finished execution"); } catch (_error) { err = _error; - this.log.info("EN | ERROR IN ACTION INVOKER: " + err.message); + _this.log.info("EN | ERROR IN ACTION INVOKER: " + err.message); node.logger(err.message); } - if (semaphore-- % 100 === 0) { - return this.log.warn("EN | The system is producing too many tokens! Currently: " + semaphore); + if (numExecutingFunctions-- % 100 === 0) { + return _this.log.warn("EN | The system is producing too many tokens! Currently: " + numExecutingFunctions); } } else { return fSearchAndInvokeAction(node[arrPath[depth]], arrPath, funcName, evt, depth + 1); diff --git a/js/event-poller.js b/js/event-poller.js index 1954c93..f73ce2f 100644 --- a/js/event-poller.js +++ b/js/event-poller.js @@ -9,7 +9,7 @@ Dynamic Modules */ (function() { - var db, dynmod, fLoadModule, isRunning, listUserModules, log, logconf, logger, pollLoop; + var db, dynmod, fCallFunction, fCheckAndRun, fLoadModule, isRunning, listUserModules, log, logconf, logger; logger = require('./logging'); @@ -77,19 +77,23 @@ Dynamic Modules return log.warn("EP | Strange... no module retrieved: " + arrName[0]); } else { return dynmod.compileString(obj.data, msg.user, msg.rule.id, arrName[0], obj.lang, db.eventPollers, function(result) { + var iv; if (!result.answ === 200) { log.error("EP | Compilation of code failed! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]); } if (!listUserModules[msg.user]) { listUserModules[msg.user] = {}; } + iv = msg.rule.interval * 60 * 1000; listUserModules[msg.user][msg.rule.id] = { id: msg.rule.event, pollfunc: arrName[1], + interval: iv, module: result.module, logger: result.logger }; - return log.info("EP | New event module loaded! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]); + log.info("EP | New event module '" + arrName[0] + "' loaded for user " + msg.user + ", in rule " + msg.rule.id + ", polling every " + iv + " minutes"); + return setTimeout(fCheckAndRun(msg.user, msg.rule.id), iv); }); } }); @@ -99,43 +103,32 @@ Dynamic Modules } }; - - /* - This function will loop infinitely every 10 seconds until isRunning is set to false - - @private pollLoop() - */ - - pollLoop = function() { - var fCallFunction, myRule, oRules, ruleName, userName; - if (isRunning) { - for (userName in listUserModules) { - oRules = listUserModules[userName]; - for (ruleName in oRules) { - myRule = oRules[ruleName]; - fCallFunction = function(oRule, ruleId, userId) { - var err; - try { - return oRule.module[oRule.pollfunc](function(obj) { - return db.pushEvent({ - event: oRule.id, - eventid: "polled " + oRule.id + " " + userId + "_" + ((new Date).toISOString()), - payload: obj - }); - }); - } catch (_error) { - err = _error; - log.info("EP | ERROR in module when polled: " + oRule.id + " " + userId + ": " + err.message); - return oRule.logger(err.message); - } - }; - fCallFunction(myRule, ruleName, userName); - } + fCheckAndRun = function(userId, ruleId) { + return function() { + var oRule; + if (isRunning && listUserModules[userId] && listUserModules[userId][ruleId]) { + oRule = listUserModules[userId][ruleId]; + fCallFunction(userId, ruleId, oRule); + return setTimeout(fCheckAndRun(userId, ruleId), oRule.interval); } - return setTimeout(pollLoop, 10000); + }; + }; + + fCallFunction = function(userId, ruleId, oRule) { + var err; + try { + return oRule.module[oRule.pollfunc](function(obj) { + return db.pushEvent({ + event: oRule.id, + eventid: "polled " + oRule.id + " " + userId + "_" + ((new Date).toISOString()), + payload: obj + }); + }); + } catch (_error) { + err = _error; + log.info("EP | ERROR in module when polled: " + oRule.id + " " + userId + ": " + err.message); + return oRule.logger(err.message); } }; - pollLoop(); - }).call(this); diff --git a/js/http-listener.js b/js/http-listener.js index aa686b2..d00eed5 100644 --- a/js/http-listener.js +++ b/js/http-listener.js @@ -10,7 +10,7 @@ HTTP Listener */ (function() { - var app, exports, express, initRouting, path, qs, requestHandler; + var activateWebHook, app, exports, express, indexEvent, initRouting, path, qs, requestHandler; requestHandler = require('./request-handler'); @@ -34,6 +34,7 @@ HTTP Listener exports = module.exports = (function(_this) { return function(args) { _this.log = args.logger; + _this.arrWebhooks = args.webhooks; _this.shutDownSystem = args['shutdown-function']; requestHandler(args); initRouting(args['http-port']); @@ -41,6 +42,39 @@ HTTP Listener }; })(this); + indexEvent = function(event, body, resp) { + var err, obj, rand, timestamp; + try { + obj = JSON.parse(body); + timestamp = (new Date).toISOString(); + rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase(); + obj.event = event; + obj.eventid = "" + obj.event + "_" + timestamp + "_" + rand; + db.pushEvent(obj); + return resp.send(200, "Thank you for the event: " + obj.eventid); + } catch (_error) { + err = _error; + return resp.send(400, 'Badly formed event!'); + } + }; + + activateWebHook = (function(_this) { + return function(app, name) { + _this.log.info("HL | Webhook activated for " + name); + return app.post("/webhooks/" + name, function(req, resp) { + var body; + console.log('something is coming through'); + body = ''; + req.on('data', function(data) { + return body += data; + }); + return req.on('end', function() { + return indexEvent(name, body, resp); + }); + }); + }; + })(this); + /* Initializes the request routing and starts listening on the given port. @@ -51,7 +85,7 @@ HTTP Listener initRouting = (function(_this) { return function(port) { - var server, sess_sec; + var hookName, server, sess_sec, _i, _len, _ref; app.use(express.cookieParser()); sess_sec = "149u*y8C:@kmN/520Gt\\v'+KFBnQ!\\r<>5X/xRI`sT -1) { _this.connRefused = true; - return _this.log.error(err, 'DB | Wrong port?'); + return _this.log.warn('DB | Wrong port?'); + } else { + return _this.log.error(err); } }); exports.eventPollers.setDB(_this.db); @@ -200,9 +202,9 @@ Persistence @private getSetRecords( *set, fSingle, cb* ) @param {String} set the set name how it is stored in the DB @param {function} fSingle a function to retrieve a single data element - per set entry + per set entry @param {function} cb the callback(err, obj) function that receives all - the retrieved data or an error + the retrieved data or an error */ getSetRecords = (function(_this) { @@ -282,11 +284,11 @@ Persistence /* - Stores a module and links it to the user. - - @private storeModule( *userId, oModule* ) - @param {String} userId - @param {object} oModule + Stores a module and links it to the user. + + @private storeModule( *userId, oModule* ) + @param {String} userId + @param {object} oModule */ IndexedModules.prototype.storeModule = function(userId, oModule) { @@ -376,13 +378,13 @@ Persistence /* - Stores user params for a module. They are expected to be RSA encrypted with helps of - the provided cryptico JS library and will only be decrypted right before the module is loaded! - - @private storeUserParams( *mId, userId, encData* ) - @param {String} mId - @param {String} userId - @param {object} encData + Stores user params for a module. They are expected to be RSA encrypted with helps of + the provided cryptico JS library and will only be decrypted right before the module is loaded! + + @private storeUserParams( *mId, userId, encData* ) + @param {String} mId + @param {String} userId + @param {object} encData */ IndexedModules.prototype.storeUserParams = function(mId, userId, encData) { @@ -409,13 +411,13 @@ Persistence /* - Stores user arguments for a function within a module. They are expected to be RSA encrypted with helps of - the provided cryptico JS library and will only be decrypted right before the module is loaded! - - @private storeUserArguments( *mId, userId, encData* ) - @param {String} mId - @param {String} userId - @param {object} encData + Stores user arguments for a function within a module. They are expected to be RSA encrypted with helps of + the provided cryptico JS library and will only be decrypted right before the module is loaded! + + @private storeUserArguments( *mId, userId, encData* ) + @param {String} mId + @param {String} userId + @param {object} encData */ IndexedModules.prototype.storeUserArguments = function(mId, funcId, userId, encData) { diff --git a/js/request-handler.js b/js/request-handler.js index 4011f31..207858c 100644 --- a/js/request-handler.js +++ b/js/request-handler.js @@ -78,28 +78,26 @@ Request Handler }); return req.on('end', function() { var answ, err, obj, rand, timestamp; - if (req.session && req.session.user) { - try { - obj = JSON.parse(body); - } catch (_error) { - err = _error; - resp.send(400, 'Badly formed event!'); - } - if (obj && obj.event && !err) { - timestamp = (new Date).toISOString(); - rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase(); - obj.eventid = "" + obj.event + "_" + timestamp + "_" + rand; - answ = { - code: 200, - message: "Thank you for the event: " + obj.eventid - }; - resp.send(answ.code, answ); - return db.pushEvent(obj); - } else { - return resp.send(400, 'Your event was missing important parameters!'); - } + try { + obj = JSON.parse(body); + console.log('got foreign event!'); + console.log(obj); + } catch (_error) { + err = _error; + resp.send(400, 'Badly formed event!'); + } + if (obj && obj.event && !err) { + timestamp = (new Date).toISOString(); + rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase(); + obj.eventid = "" + obj.event + "_" + timestamp + "_" + rand; + answ = { + code: 200, + message: "Thank you for the event: " + obj.eventid + }; + resp.send(answ.code, answ); + return db.pushEvent(obj); } else { - return resp.send(401, 'Please login!'); + return resp.send(400, 'Your event was missing important parameters!'); } }); }; diff --git a/js/sandbox.js b/js/sandbox.js new file mode 100644 index 0000000..bb91592 --- /dev/null +++ b/js/sandbox.js @@ -0,0 +1,42 @@ +// Generated by CoffeeScript 1.7.1 +(function() { + var app, express, fHandleEvent, fHandleEventGet; + + express = require('express'); + + app = express(); + + app.post('/event', fHandleEvent); + + app.get('/event', fHandleEventGet); + + app.listen(8111); + + fHandleEvent = function(req, resp) { + var body; + console.log('received something with POST!'); + body = ''; + req.on('data', function(data) { + return body += data; + }); + req.on('end', function() { + var err, obj; + console.log('got foreign event!'); + console.log(body); + try { + obj = JSON.parse(body); + return console.log('successfully parsed'); + } catch (_error) { + err = _error; + return console.log(err); + } + }); + return resp.send(200, 'Cheers!'); + }; + + fHandleEventGet = function(req, resp) { + console.log('received something with GET!'); + return resp.send(200, 'Cheers!'); + }; + +}).call(this); diff --git a/js/webapi-eca.js b/js/webapi-eca.js index 86d72c9..e02cb30 100644 --- a/js/webapi-eca.js +++ b/js/webapi-eca.js @@ -146,6 +146,7 @@ WebAPI-ECA Engine args['http-port'] = parseInt(argv.w || conf.getHttpPort()); args['db-port'] = parseInt(argv.d || conf.getDbPort()); args['keygen'] = conf.getKeygenPassphrase(); + args['webhooks'] = conf.fetchProp('webhooks'); _this.log.info('RS | Initialzing DB'); db(args); return db.isConnected(function(err) { diff --git a/package.json b/package.json index f349554..8c6d253 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "crypto-js": "3.1.2", "express": "3.4.8", "groc": "0.6.1", + "import-io": "1.0.x", "js-select": "0.6.0", "mustache": "0.8.1", "needle": "0.6.3", diff --git a/testing/files/testObjects.json b/testing/files/testObjects.json index 22be358..14b9915 100644 --- a/testing/files/testObjects.json +++ b/testing/files/testObjects.json @@ -35,15 +35,17 @@ "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\"]" + "functions":"[\"otherEvent\"]", + "functionArgs":"{\"otherEvent\":[\"evt\"]}" }, "aiThree": { "id":"aiThree", "lang":"CoffeeScript", - "data":"exports.printUserParamToLog = ( evt ) ->\n\tlog params.password", + "data":"exports.printUserParamToLog = ( evt ) ->\n\tdebug 'wow'n\tlog 'wow'\n\tlog params.password", "public":"false", "params":"[\"password\"]", - "functions":"[\"printUserParamToLog\"]" + "functions":"[\"printUserParamToLog\"]", + "functionArgs":"{\"printUserParamToLog\":[\"evt\"]}" } }, "userparams": { @@ -76,36 +78,18 @@ }, "rules": { "ruleOne": { - "id": "ruleOne_id", - "event": "custom-test-1", - "conditions": [], - "actions": [] - }, - "ruleTwo": { - "id": "ruleTwo_id", - "event": "custom-test-2", - "conditions": [], - "actions": [] - }, - "ruleThree": { - "id": "ruleThree_id", - "event": "custom-test-3", - "conditions": [], - "actions": [] - }, - "ruleReal": { "id": "ruleReal", - "event": "epOne -> newMail", + "event": "test_1", "conditions": [".more:val(\"really nested\")"], "actions": ["aiOne -> printToLog"] }, - "ruleRealTwo": { + "ruleTwo": { "id": "ruleRealTwo", - "event": "epOne -> newMail", + "event": "test_2", "conditions": [], "actions": ["aiTwo -> otherEvent"] }, - "ruleRealThree": { + "ruleThree": { "id": "ruleRealThree", "event": "epOne -> newMail", "conditions": [], diff --git a/testing/test_components-manager.coffee b/testing/test_components-manager.coffee index 3769888..836993f 100644 --- a/testing/test_components-manager.coffee +++ b/testing/test_components-manager.coffee @@ -1,24 +1,36 @@ 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' - try - objects = JSON.parse data - catch err - console.log 'Error parsing standard objects file: ' + err.message + data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' + try + objects = JSON.parse data + catch err + console.log 'Error parsing standard objects file: ' + err.message catch err - console.log 'Error fetching standard objects file: ' + err.message + console.log 'Error fetching standard objects file: ' + err.message logger = require path.join '..', 'js', 'logging' -log = logger.getLogger - nolog: true +log = logger.getLogger() + # nolog: true opts = - logger: log + logger: log + +engine = require path.join '..', 'js', 'engine' +engine opts cm = require path.join '..', 'js', 'components-manager' cm opts +cm.addRuleListener engine.internalEvent + db = require path.join '..', 'js', 'persistence' db opts @@ -29,139 +41,182 @@ oRuleThree = objects.rules.ruleThree oEpOne = objects.eps.epOne oEpTwo = objects.eps.epTwo oAiTwo = objects.ais.aiTwo +oAiThree = objects.ais.aiThree exports.tearDown = ( cb ) -> - db.deleteRule oRuleOne.id - db.deleteRule oRuleTwo.id - db.deleteRule oRuleThree.id - setTimeout cb, 100 + db.deleteRule oRuleOne.id + db.deleteRule oRuleTwo.id + db.deleteRule oRuleThree.id + setTimeout cb, 100 exports.requestProcessing = - testEmptyPayload: ( test ) => - test.expect 1 + testEmptyPayload: ( test ) => + test.expect 1 - request = - command: 'get_event_pollers' + request = + command: 'get_event_pollers' - cm.processRequest oUser, request, ( answ ) => - test.strictEqual 200, answ.code, 'Empty payload did not return 200' - test.done() + cm.processRequest oUser, request, ( answ ) => + test.strictEqual 200, answ.code, 'Empty payload did not return 200' + test.done() - testCorruptPayload: ( test ) => - test.expect 1 + testCorruptPayload: ( test ) => + test.expect 1 - request = - command: 'get_event_pollers' - payload: 'no-json' + request = + command: 'get_event_pollers' + payload: 'no-json' - cm.processRequest oUser, request, ( answ ) => - test.strictEqual 404, answ.code, 'Corrupt payload did not return 404' - test.done() + cm.processRequest oUser, request, ( answ ) => + test.strictEqual 404, answ.code, 'Corrupt payload did not return 404' + test.done() exports.testListener = ( test ) => - test.expect 3 + test.expect 3 - strRuleOne = JSON.stringify oRuleOne - strRuleTwo = JSON.stringify oRuleTwo - strRuleThree = JSON.stringify oRuleThree + strRuleOne = JSON.stringify oRuleOne + strRuleTwo = JSON.stringify oRuleTwo + strRuleThree = JSON.stringify oRuleThree - db.storeUser oUser - db.storeRule oRuleOne.id, strRuleOne - db.linkRule oRuleOne.id, oUser.username - db.activateRule oRuleOne.id, oUser.username - - db.storeRule oRuleTwo.id, strRuleTwo - db.linkRule oRuleTwo.id, oUser.username - db.activateRule oRuleTwo.id, oUser.username + db.storeUser oUser + db.storeRule oRuleOne.id, strRuleOne + db.linkRule oRuleOne.id, oUser.username + db.activateRule oRuleOne.id, oUser.username + + db.storeRule oRuleTwo.id, strRuleTwo + db.linkRule oRuleTwo.id, oUser.username + db.activateRule oRuleTwo.id, oUser.username - request = - command: 'forge_rule' - payload: strRuleThree + request = + command: 'forge_rule' + payload: strRuleThree - cm.addRuleListener ( evt ) => - strEvt = JSON.stringify evt.rule - if evt.event is 'init' - if strEvt is strRuleOne or strEvt is strRuleTwo - test.ok true, 'Dummy true to fill expected tests!' + cm.addRuleListener ( evt ) => + strEvt = JSON.stringify evt.rule + if evt.event is 'init' + if strEvt is strRuleOne or strEvt is strRuleTwo + test.ok true, 'Dummy true to fill expected tests!' - if strEvt is strRuleThree - test.ok false, 'Init Rule found test rule number two??' + if strEvt is strRuleThree + test.ok false, 'Init Rule found test rule number two??' - if evt.event is 'new' - if strEvt is strRuleOne or strEvt is strRuleTwo - test.ok false, 'New Rule got test rule number one??' + if evt.event is 'new' + if strEvt is strRuleOne or strEvt is strRuleTwo + test.ok false, 'New Rule got test rule number one??' - if strEvt is strRuleThree - test.ok true, 'Dummy true to fill expected tests!' + if strEvt is strRuleThree + test.ok true, 'Dummy true to fill expected tests!' - fWaitForInit = -> - cm.processRequest oUser, request, ( answ ) => - if answ.code isnt 200 - test.ok false, 'testListener failed: ' + answ.message - test.done() - setTimeout test.done, 500 + fWaitForInit = -> + cm.processRequest oUser, request, ( answ ) => + if answ.code isnt 200 + test.ok false, 'testListener failed: ' + answ.message + test.done() + setTimeout test.done, 500 - setTimeout fWaitForInit, 200 + setTimeout fWaitForInit, 200 exports.moduleHandling = - tearDown: ( cb ) -> - db.eventPollers.deleteModule oEpOne.id - db.eventPollers.deleteModule oEpTwo.id - db.actionInvokers.deleteModule oAiTwo.id - setTimeout cb, 100 + tearDown: ( cb ) -> + db.eventPollers.deleteModule oEpOne.id + db.eventPollers.deleteModule oEpTwo.id + db.actionInvokers.deleteModule oAiTwo.id + setTimeout cb, 100 - testGetModules: ( test ) -> - test.expect 2 + testGetModules: ( test ) -> + test.expect 2 - db.eventPollers.storeModule oUser.username, oEpOne - db.eventPollers.storeModule oUser.username, oEpTwo - request = - command: 'get_event_pollers' + db.eventPollers.storeModule oUser.username, oEpOne + db.eventPollers.storeModule oUser.username, oEpTwo + request = + command: 'get_event_pollers' - cm.processRequest oUser, request, ( answ ) => - test.strictEqual 200, answ.code, 'GetModules failed...' - oExpected = {} - oExpected[oEpOne.id] = JSON.parse oEpOne.functions - oExpected[oEpTwo.id] = JSON.parse oEpTwo.functions - test.deepEqual oExpected, JSON.parse(answ.message), - 'GetModules retrieved modules is not what we expected' - test.done() + cm.processRequest oUser, request, ( answ ) => + test.strictEqual 200, answ.code, 'GetModules failed...' + oExpected = {} + oExpected[oEpOne.id] = JSON.parse oEpOne.functions + oExpected[oEpTwo.id] = JSON.parse oEpTwo.functions + test.deepEqual oExpected, JSON.parse(answ.message), + 'GetModules retrieved modules is not what we expected' + test.done() - testGetModuleParams: ( test ) -> - test.expect 2 + testGetModuleParams: ( test ) -> + test.expect 2 - db.eventPollers.storeModule oUser.username, oEpOne + db.eventPollers.storeModule oUser.username, oEpOne - request = - command: 'get_event_poller_params' - payload: - id: oEpOne.id - request.payload = JSON.stringify request.payload - cm.processRequest oUser, request, ( answ ) => - test.strictEqual 200, answ.code, - 'Required Module Parameters did not return 200' - test.strictEqual oEpOne.params, answ.message, - 'Required Module Parameters did not match' - test.done() + request = + command: 'get_event_poller_params' + payload: + id: oEpOne.id + request.payload = JSON.stringify request.payload + cm.processRequest oUser, request, ( answ ) => + test.strictEqual 200, answ.code, + 'Required Module Parameters did not return 200' + test.strictEqual oEpOne.params, answ.message, + 'Required Module Parameters did not match' + test.done() - testForgeModule: ( test ) -> - test.expect 2 + testForgeModule: ( test ) -> + test.expect 2 - oTmp = {} - for key, val of oAiTwo - oTmp[key] = val if key isnt 'functions' and key isnt 'functionParameters' + oTmp = {} + for key, val of oAiTwo + oTmp[key] = val if key isnt 'functions' and key isnt 'functionParameters' - request = - command: 'forge_action_invoker' - payload: JSON.stringify oTmp + request = + command: 'forge_action_invoker' + payload: JSON.stringify oTmp - cm.processRequest oUser, request, ( answ ) => - test.strictEqual 200, answ.code, 'Forging Module did not return 200' + cm.processRequest oUser, request, ( answ ) => + test.strictEqual 200, answ.code, 'Forging Module did not return 200' + + db.actionInvokers.getModule oAiTwo.id, ( err, obj ) -> + test.deepEqual obj, oAiTwo, 'Forged Module is not what we expected' + test.done() + + +exports.testForgeRule = ( test ) -> + test.expect 1 + + db.storeUser oUser + db.actionInvokers.storeModule oUser.username, oAiThree + + pw = 'This password should come out cleartext' + userparams = JSON.stringify password: pw + oEncrypted = cryptico.encrypt userparams, strPublicKey + + db.actionInvokers.storeUserParams oAiThree.id, oUser.username, oEncrypted.cipher + + request = + command: 'forge_rule' + payload: JSON.stringify oRuleThree + + cm.processRequest oUser, request, ( answ ) => + test.strictEqual 200, answ.code, "Forging Rule returned #{ answ.code }: #{ answ.message }" + + fWaitForPersistence = () -> + evt = objects.events.eventReal + evt.eventid = 'event_testid' + db.pushEvent evt + console.log 'pushed' + + fWaitAgain = () -> + console.log 'waited' + db.getLog oUser.username, oRuleThree.id, ( err, data ) -> + console.log data + try + logged = data.split( '] ' )[1] + logged = logged.split( "\n" )[0] + test.strictEqual logged, "{#{ oAiThree.id }} " + pw, 'Did not log the right thing' + catch e + test.ok false, 'Parsing log failed' + + setTimeout test.done, 200 + + setTimeout fWaitAgain, 200 + + setTimeout fWaitForPersistence, 200 - db.actionInvokers.getModule oAiTwo.id, ( err, obj ) -> - console.log obj - console.log oAiTwo - test.deepEqual obj, oAiTwo, 'Forged Module is not what we expected' - test.done() diff --git a/testing/test_config.coffee b/testing/test_config.coffee index 5535ca7..feb1eed 100644 --- a/testing/test_config.coffee +++ b/testing/test_config.coffee @@ -1,43 +1,43 @@ path = require 'path' logger = require path.join '..', 'js', 'logging' log = logger.getLogger - nolog: true + nolog: true conf = require path.join '..', 'js', 'config' conf - logger: log + logger: log exports.testRequire = ( test ) -> - test.expect 1 - test.ok conf.isReady(), 'File does not exist!' - test.done() + test.expect 1 + test.ok conf.isReady(), 'File does not exist!' + test.done() exports.testParameters = ( test ) -> - reqProp = [ - 'mode' - 'io-level' - 'file-level' - ] - test.expect 3 + reqProp.length - test.ok conf.getHttpPort(), 'HTTP port does not exist!' - test.ok conf.getDbPort(), 'DB port does not exist!' - logconf = conf.getLogConf() - test.ok logconf, 'Log config does not exist!' - for prop in reqProp - test.ok logconf[prop], "Log conf property #{ prop } does not exist!" - test.done() + reqProp = [ + 'mode' + 'io-level' + 'file-level' + ] + test.expect 3 + reqProp.length + test.ok conf.getHttpPort(), 'HTTP port does not exist!' + test.ok conf.getDbPort(), 'DB port does not exist!' + logconf = conf.getLogConf() + test.ok logconf, 'Log config does not exist!' + for prop in reqProp + test.ok logconf[prop], "Log conf property #{ prop } does not exist!" + test.done() exports.testDifferentConfigFile = ( test ) -> - test.expect 1 - conf - # nolog: true - configPath: path.join 'testing', 'files', 'jsonTestConfig.json' - test.ok conf.isReady(), 'Different path not loaded!' - test.done() + test.expect 1 + conf + # nolog: true + configPath: path.join 'testing', 'files', 'jsonTestConfig.json' + test.ok conf.isReady(), 'Different path not loaded!' + test.done() exports.testNoConfigFile = ( test ) -> - test.expect 1 - conf - nolog: true - configPath: 'wrongpath.file' - test.strictEqual conf.isReady(), false, 'Wrong path still loaded!' - test.done() + test.expect 1 + conf + nolog: true + configPath: 'wrongpath.file' + test.strictEqual conf.isReady(), false, 'Wrong path still loaded!' + test.done() diff --git a/testing/test_dynamic-modules.coffee b/testing/test_dynamic-modules.coffee index 59259a6..875e420 100644 --- a/testing/test_dynamic-modules.coffee +++ b/testing/test_dynamic-modules.coffee @@ -8,20 +8,20 @@ oPrivateRSAkey = cryptico.generateRSAKey passPhrase, numBits strPublicKey = cryptico.publicKeyString oPrivateRSAkey try - data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' - try - objects = JSON.parse data - catch err - console.log 'Error parsing standard objects file: ' + err.message + data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' + try + objects = JSON.parse data + catch err + console.log 'Error parsing standard objects file: ' + err.message catch err - console.log 'Error fetching standard objects file: ' + err.message + console.log 'Error fetching standard objects file: ' + err.message logger = require path.join '..', 'js', 'logging' log = logger.getLogger - nolog: true + nolog: true opts = - logger: log - keygen: passPhrase + logger: log + keygen: passPhrase db = require path.join '..', 'js', 'persistence' db opts @@ -33,78 +33,30 @@ dm = require path.join '..', 'js', 'dynamic-modules' dm opts oUser = objects.users.userOne -oRuleReal = objects.rules.ruleRealThree +oRule = objects.rules.ruleThree oAi = objects.ais.aiThree exports.tearDown = ( cb ) -> - db.storeUser oUser - db.deleteRule oRuleReal.id - db.actionInvokers.deleteModule oAi.id - setTimeout cb, 200 + db.storeUser oUser + db.deleteRule oRule.id + db.actionInvokers.deleteModule oAi.id + setTimeout cb, 200 exports.testCompile = ( test ) -> - test.expect 5 + test.expect 5 - 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" - - 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] - logged = logged.split( "\n" )[0] - test.strictEqual logged, "{#{ oAi.id }} " + pw, '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 - engine.shutDown() - setTimeout test.done, 200 - - setTimeout fWaitAgain, 200 - - setTimeout fWaitForPersistence, 200 + 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" + 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 diff --git a/testing/test_engine.coffee b/testing/test_engine.coffee index e51aa3d..cfaf15e 100644 --- a/testing/test_engine.coffee +++ b/testing/test_engine.coffee @@ -2,19 +2,19 @@ fs = require 'fs' path = require 'path' try - data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' - try - objects = JSON.parse data - catch err - console.log 'Error parsing standard objects file: ' + err.message + data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' + try + objects = JSON.parse data + catch err + console.log 'Error parsing standard objects file: ' + err.message catch err - console.log 'Error fetching standard objects file: ' + err.message + console.log 'Error fetching standard objects file: ' + err.message logger = require path.join '..', 'js', 'logging' log = logger.getLogger - nolog: true + nolog: true opts = - logger: log + logger: log engine = require path.join '..', 'js', 'engine' engine opts @@ -25,93 +25,93 @@ db opts listRules = engine.getListUserRules() oUser = objects.users.userOne -oRuleReal = objects.rules.ruleReal -oRuleRealTwo = objects.rules.ruleRealTwo +oRuleOne = objects.rules.ruleOne +oRuleTwo = objects.rules.ruleTwo oAiOne = objects.ais.aiOne oAiTwo = objects.ais.aiTwo exports.setUp = ( cb ) -> - engine.startEngine() - cb() - + engine.startEngine() + cb() + exports.tearDown = ( cb ) -> - db.deleteRule oRuleReal.id - db.actionInvokers.deleteModule oAiOne.id - db.actionInvokers.deleteModule oAiTwo.id - # TODO if user is deleted all his modules should be unlinked and deleted - db.deleteUser oUser.username + db.deleteRule oRuleOne.id + db.actionInvokers.deleteModule oAiOne.id + db.actionInvokers.deleteModule oAiTwo.id + # TODO if user is deleted all his modules should be unlinked and deleted + db.deleteUser oUser.username - engine.internalEvent - event: 'del' - user: oUser.username - rule: oRuleReal + engine.internalEvent + event: 'del' + user: oUser.username + rule: oRuleOne - engine.internalEvent - event: 'del' - user: oUser.username - rule: oRuleRealTwo - engine.shutDown() + engine.internalEvent + event: 'del' + user: oUser.username + rule: oRuleTwo + engine.shutDown() - setTimeout cb, 200 + setTimeout cb, 200 exports.ruleEvents = - testInitAddDeleteMultiple: ( test ) -> - test.expect 2 + 2 * oRuleReal.actions.length + oRuleRealTwo.actions.length + testInitAddDeleteMultiple: ( test ) -> + test.expect 2 + 2 * oRuleOne.actions.length + oRuleTwo.actions.length - db.storeUser oUser - db.storeRule oRuleReal.id, JSON.stringify oRuleReal - db.linkRule oRuleReal.id, oUser.username - db.activateRule oRuleReal.id, oUser.username - db.actionInvokers.storeModule oUser.username, oAiOne - db.actionInvokers.storeModule oUser.username, oAiTwo + db.storeUser oUser + db.storeRule oRuleOne.id, JSON.stringify oRuleOne + db.linkRule oRuleOne.id, oUser.username + db.activateRule oRuleOne.id, oUser.username + db.actionInvokers.storeModule oUser.username, oAiOne + db.actionInvokers.storeModule oUser.username, oAiTwo - test.strictEqual listRules[oUser.username], undefined, 'Initial user object exists!?' + test.strictEqual listRules[oUser.username], undefined, 'Initial user object exists!?' - engine.internalEvent - event: 'new' - user: oUser.username - rule: oRuleReal + engine.internalEvent + event: 'new' + user: oUser.username + rule: oRuleOne - fWaitForPersistence = () -> + fWaitForPersistence = () -> - for act in oRuleReal.actions - mod = ( act.split ' -> ' )[0] - test.ok listRules[oUser.username][oRuleReal.id].actions[mod], 'Missing action!' - + for act in oRuleOne.actions + mod = ( act.split ' -> ' )[0] + test.ok listRules[oUser.username][oRuleOne.id].actions[mod], 'Missing action!' + - engine.internalEvent - event: 'new' - user: oUser.username - rule: oRuleRealTwo + engine.internalEvent + event: 'new' + user: oUser.username + rule: oRuleTwo - fWaitAgainForPersistence = () -> + fWaitAgainForPersistence = () -> - for act in oRuleRealTwo.actions - mod = ( act.split ' -> ' )[0] - test.ok listRules[oUser.username][oRuleRealTwo.id].actions[mod], 'Missing action!' - - engine.internalEvent - event: 'del' - user: oUser.username - rule: null - ruleId: oRuleRealTwo.id + for act in oRuleTwo.actions + mod = ( act.split ' -> ' )[0] + test.ok listRules[oUser.username][oRuleTwo.id].actions[mod], 'Missing action!' + + engine.internalEvent + event: 'del' + user: oUser.username + rule: null + ruleId: oRuleTwo.id - for act in oRuleReal.actions - mod = ( act.split ' -> ' )[0] - test.ok listRules[oUser.username][oRuleReal.id].actions[mod], 'Missing action!' - - engine.internalEvent - event: 'del' - user: oUser.username - rule: null - ruleId: oRuleReal.id + for act in oRuleOne.actions + mod = ( act.split ' -> ' )[0] + test.ok listRules[oUser.username][oRuleOne.id].actions[mod], 'Missing action!' + + engine.internalEvent + event: 'del' + user: oUser.username + rule: null + ruleId: oRuleOne.id - test.strictEqual listRules[oUser.username], undefined, 'Final user object exists!?' - test.done() + test.strictEqual listRules[oUser.username], undefined, 'Final user object exists!?' + test.done() - setTimeout fWaitAgainForPersistence, 200 + setTimeout fWaitAgainForPersistence, 200 - setTimeout fWaitForPersistence, 200 + setTimeout fWaitForPersistence, 200 # #TODO # testUpdate: ( test ) -> @@ -120,9 +120,9 @@ exports.ruleEvents = # test.done() # db.storeUser oUser -# db.storeRule oRuleReal.id, JSON.stringify oRuleReal -# db.linkRule oRuleReal.id, oUser.username -# db.activateRule oRuleReal.id, oUser.username +# db.storeRule oRuleOne.id, JSON.stringify oRuleOne +# db.linkRule oRuleOne.id, oUser.username +# db.activateRule oRuleOne.id, oUser.username # db.actionInvokers.storeModule oUser.username, oAiOne @@ -133,7 +133,7 @@ exports.ruleEvents = # engine.internalEvent # event: 'init' # user: oUser.username -# rule: oRuleReal +# rule: oRuleOne # fCheckRules = () -> # db.getAllActivatedRuleIdsPerUser ( err, obj ) -> @@ -143,35 +143,35 @@ exports.ruleEvents = # setTimeout fCheckRules, 500 exports.engine = - testMatchingEvent: ( 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, oAiOne + testMatchingEvent: ( test ) -> + test.expect 1 + db.storeUser oUser + db.storeRule oRuleOne.id, JSON.stringify oRuleOne + db.linkRule oRuleOne.id, oUser.username + db.activateRule oRuleOne.id, oUser.username + db.actionInvokers.storeModule oUser.username, oAiOne - engine.internalEvent - event: 'new' - user: oUser.username - rule: oRuleReal + engine.internalEvent + event: 'new' + user: oUser.username + rule: oRuleOne - fWaitForPersistence = () -> - evt = objects.events.eventReal - evt.eventid = 'event_testid' - db.pushEvent evt + fWaitForPersistence = () -> + evt = objects.events.eventReal + evt.eventid = 'event_testid' + db.pushEvent evt - fWaitAgain = () -> - db.getLog oUser.username, oRuleReal.id, ( err, data ) -> - try + fWaitAgain = () -> + db.getLog oUser.username, oRuleOne.id, ( err, data ) -> + try - logged = data.split( '] ' )[1] - logged = logged.split( "\n" )[0] - test.strictEqual logged, "{#{ oAiOne.id }} " + evt.payload.property, 'Did not log the right thing' - catch e - test.ok false, 'Parsing log failed' - test.done() + logged = data.split( '] ' )[1] + logged = logged.split( "\n" )[0] + test.strictEqual logged, "{#{ oAiOne.id }} " + evt.payload.property, 'Did not log the right thing' + catch e + test.ok false, 'Parsing log failed' + test.done() - setTimeout fWaitAgain, 200 + setTimeout fWaitAgain, 200 - setTimeout fWaitForPersistence, 200 + setTimeout fWaitForPersistence, 200 diff --git a/testing/test_logging.coffee b/testing/test_logging.coffee index f1c1507..ca04b17 100644 --- a/testing/test_logging.coffee +++ b/testing/test_logging.coffee @@ -4,97 +4,97 @@ stdPath = path.resolve __dirname, '..', 'logs', 'server.log' logger = require path.join '..', 'js', 'logging' getLog = ( strPath, cb ) -> - fWait = -> - # cb fs.readFileSync path, 'utf-8' - str = fs.readFileSync path.resolve( strPath ), 'utf-8' - arrStr = str.split "\n" - fConvertRow = ( row ) -> - try - JSON.parse row - arrStr[i] = fConvertRow row for row, i in arrStr - cb arrStr.slice 0, arrStr.length - 1 - setTimeout fWait, 100 + fWait = -> + # cb fs.readFileSync path, 'utf-8' + str = fs.readFileSync path.resolve( strPath ), 'utf-8' + arrStr = str.split "\n" + fConvertRow = ( row ) -> + try + JSON.parse row + arrStr[i] = fConvertRow row for row, i in arrStr + cb arrStr.slice 0, arrStr.length - 1 + setTimeout fWait, 100 exports.setUp = ( cb ) -> - try - fs.unlinkSync stdPath - cb() + try + fs.unlinkSync stdPath + cb() exports.testCreate = ( test ) -> - test.expect 2 - arrLogs = [ - 'TL | testInitIO - info' - 'TL | testInitIO - warn' - 'TL | testInitIO - error' - ] - args = {} - args[ 'io-level' ] = 'error' - log = logger.getLogger args - log.info arrLogs[0] - log.warn arrLogs[1] - log.error arrLogs[2] - test.ok fs.existsSync( stdPath ), 'Log file does not exist!' - getLog stdPath, ( arr ) -> - allCorrect = true - for o,i in arr - if o.msg is not arrLogs[i] - allCorrect = false - test.ok allCorrect, 'Log file does not contain the correct entries!' - test.done() + test.expect 2 + arrLogs = [ + 'TL | testInitIO - info' + 'TL | testInitIO - warn' + 'TL | testInitIO - error' + ] + args = {} + args[ 'io-level' ] = 'error' + log = logger.getLogger args + log.info arrLogs[0] + log.warn arrLogs[1] + log.error arrLogs[2] + test.ok fs.existsSync( stdPath ), 'Log file does not exist!' + getLog stdPath, ( arr ) -> + allCorrect = true + for o,i in arr + if o.msg is not arrLogs[i] + allCorrect = false + test.ok allCorrect, 'Log file does not contain the correct entries!' + test.done() exports.testNoLog = ( test ) -> - test.expect 1 + test.expect 1 - log = logger.getLogger - nolog: true - log.info 'TL | test 1' + log = logger.getLogger + nolog: true + log.info 'TL | test 1' - fWait = () -> - test.ok !fs.existsSync( stdPath ), 'Log file does still exist!' - test.done() + fWait = () -> + test.ok !fs.existsSync( stdPath ), 'Log file does still exist!' + test.done() - setTimeout fWait, 100 + setTimeout fWait, 100 exports.testCustomPath = ( test ) -> - test.expect 2 + test.expect 2 - strInfo = 'TL | custom path test 1' - strPath = 'testing/files/test.log' - args = {} - args[ 'file-path' ] = strPath - args[ 'io-level' ] = 'error' + strInfo = 'TL | custom path test 1' + strPath = 'testing/files/test.log' + args = {} + args[ 'file-path' ] = strPath + args[ 'io-level' ] = 'error' - log = logger.getLogger args - log.info strInfo + log = logger.getLogger args + log.info strInfo - fWait = () -> - test.ok fs.existsSync( strPath ), 'Custom log file does not exist!' - getLog strPath, ( arr ) -> - test.ok arr[0].msg is strInfo, 'Custom log file not correct!' - try - fs.unlinkSync strPath - test.done() + fWait = () -> + test.ok fs.existsSync( strPath ), 'Custom log file does not exist!' + getLog strPath, ( arr ) -> + test.ok arr[0].msg is strInfo, 'Custom log file not correct!' + try + fs.unlinkSync strPath + test.done() - setTimeout fWait, 100 + setTimeout fWait, 100 exports.testWrongPath = ( test ) -> - empty = [ - 'trace' - 'debug' - 'info' - 'warn' - 'error' - 'fatal' - ] - test.expect empty.length + empty = [ + 'trace' + 'debug' + 'info' + 'warn' + 'error' + 'fatal' + ] + test.expect empty.length - strInfo = 'TL | custom path test 1' - strPath = 'strange/path/to/test.log' - args = {} - args[ 'file-path' ] = strPath - args[ 'io-level' ] = 'error' - log = logger.getLogger args - test.ok prop in empty, "#{ prop } shouldn't be here" for prop of log - test.done() + strInfo = 'TL | custom path test 1' + strPath = 'strange/path/to/test.log' + args = {} + args[ 'file-path' ] = strPath + args[ 'io-level' ] = 'error' + log = logger.getLogger args + test.ok prop in empty, "#{ prop } shouldn't be here" for prop of log + test.done() - + diff --git a/testing/test_persistence.coffee b/testing/test_persistence.coffee index 7c8f578..bf11601 100644 --- a/testing/test_persistence.coffee +++ b/testing/test_persistence.coffee @@ -1,20 +1,20 @@ fs = require 'fs' path = require 'path' try - data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' - try - objects = JSON.parse data - catch err - console.log 'Error parsing standard objects file: ' + err.message + data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' + try + objects = JSON.parse data + catch err + console.log 'Error parsing standard objects file: ' + err.message catch err - console.log 'Error fetching standard objects file: ' + err.message + console.log 'Error fetching standard objects file: ' + err.message logger = require path.join '..', 'js', 'logging' log = logger.getLogger - nolog: true + nolog: true db = require path.join '..', 'js', 'persistence' opts = - logger: log + logger: log opts[ 'db-port' ] = 6379 db opts @@ -28,114 +28,114 @@ oRuleOne = objects.rules.ruleOne oRuleTwo = objects.rules.ruleTwo exports.tearDown = ( cb ) -> - db.deleteUser oUser.username - setTimeout cb, 100 + db.deleteUser oUser.username + setTimeout cb, 100 # ### # # Test AVAILABILITY # ### exports.Availability = - testRequire: ( test ) -> - test.expect 1 - test.ok db, 'DB interface loaded' - test.done() + testRequire: ( test ) -> + test.expect 1 + test.ok db, 'DB interface loaded' + test.done() - testConnect: ( test ) -> - test.expect 1 - db.isConnected ( err ) -> - test.ifError err, 'Connection failed!' - test.done() + testConnect: ( test ) -> + test.expect 1 + db.isConnected ( err ) -> + test.ifError err, 'Connection failed!' + test.done() - # We cannot test for no db-port, since node-redis then assumes standard port - testWrongDbPort: ( test ) -> - test.expect 1 - - db.initPort 13410 - db.isConnected ( err ) -> - test.ok err, 'Still connected!?' - db.initPort 6379 - test.done() + # We cannot test for no db-port, since node-redis then assumes standard port + testWrongDbPort: ( test ) -> + test.expect 1 + + db.initPort 13410 + db.isConnected ( err ) -> + test.ok err, 'Still connected!?' + db.initPort 6379 + test.done() - testPurgeQueue: ( test ) -> - test.expect 2 + testPurgeQueue: ( test ) -> + test.expect 2 - db.pushEvent oEvtOne - db.purgeEventQueue() - db.popEvent ( err, obj ) -> - test.ifError err, 'Error during pop after purging!' - test.strictEqual obj, null, 'There was an event in the queue!?' - test.done() + db.pushEvent oEvtOne + db.purgeEventQueue() + db.popEvent ( err, obj ) -> + test.ifError err, 'Error during pop after purging!' + test.strictEqual obj, null, 'There was an event in the queue!?' + test.done() ### # Test EVENT QUEUE ### exports.EventQueue = - testEmptyPopping: ( test ) -> - test.expect 2 - - db.purgeEventQueue() - db.popEvent ( err, obj ) -> - test.ifError err, - 'Error during pop after purging!' - test.strictEqual obj, null, - 'There was an event in the queue!?' - test.done() + testEmptyPopping: ( test ) -> + test.expect 2 + + db.purgeEventQueue() + db.popEvent ( err, obj ) -> + test.ifError err, + 'Error during pop after purging!' + test.strictEqual obj, null, + 'There was an event in the queue!?' + test.done() - testEmptyPushing: ( test ) -> - test.expect 2 + testEmptyPushing: ( test ) -> + test.expect 2 - db.pushEvent null - db.popEvent ( err, obj ) -> - test.ifError err, - 'Error during non-empty pushing!' - test.strictEqual obj, null, - 'There was an event in the queue!?' - - test.done() + db.pushEvent null + db.popEvent ( err, obj ) -> + test.ifError err, + 'Error during non-empty pushing!' + test.strictEqual obj, null, + 'There was an event in the queue!?' + + test.done() - testNonEmptyPopping: ( test ) -> - test.expect 3 + testNonEmptyPopping: ( test ) -> + test.expect 3 - db.pushEvent oEvtOne - db.popEvent ( err, obj ) -> - test.ifError err, - 'Error during non-empty popping!' - test.notStrictEqual obj, null, - 'There was no event in the queue!' - test.deepEqual oEvtOne, obj, - 'Wrong event in queue!' - - test.done() + db.pushEvent oEvtOne + db.popEvent ( err, obj ) -> + test.ifError err, + 'Error during non-empty popping!' + test.notStrictEqual obj, null, + 'There was no event in the queue!' + test.deepEqual oEvtOne, obj, + 'Wrong event in queue!' + + test.done() - testMultiplePushAndPops: ( test ) -> - test.expect 6 + testMultiplePushAndPops: ( test ) -> + test.expect 6 - semaphore = 2 - forkEnds = () -> - if --semaphore is 0 - - test.done() + semaphore = 2 + forkEnds = () -> + if --semaphore is 0 + + test.done() - db.pushEvent oEvtOne - db.pushEvent oEvtTwo - # eventually it would be wise to not care about the order of events - db.popEvent ( err, obj ) -> - test.ifError err, - 'Error during multiple push and pop!' - test.notStrictEqual obj, null, - 'There was no event in the queue!' - test.deepEqual oEvtOne, obj, - 'Wrong event in queue!' - forkEnds() - db.popEvent ( err, obj ) -> - test.ifError err, - 'Error during multiple push and pop!' - test.notStrictEqual obj, null, - 'There was no event in the queue!' - test.deepEqual oEvtTwo, obj, - 'Wrong event in queue!' - forkEnds() + db.pushEvent oEvtOne + db.pushEvent oEvtTwo + # eventually it would be wise to not care about the order of events + db.popEvent ( err, obj ) -> + test.ifError err, + 'Error during multiple push and pop!' + test.notStrictEqual obj, null, + 'There was no event in the queue!' + test.deepEqual oEvtOne, obj, + 'Wrong event in queue!' + forkEnds() + db.popEvent ( err, obj ) -> + test.ifError err, + 'Error during multiple push and pop!' + test.notStrictEqual obj, null, + 'There was no event in the queue!' + test.deepEqual oEvtTwo, obj, + 'Wrong event in queue!' + forkEnds() ### @@ -144,500 +144,500 @@ exports.EventQueue = ### exports.EventPoller = - tearDown: ( cb ) -> - # db.eventPollers.unlinkModule oEpOne.id, oUser.username - db.eventPollers.deleteModule oEpOne.id - # db.eventPollers.unlinkModule oEpTwo.id, oUser.username - db.eventPollers.deleteModule oEpTwo.id - cb() + tearDown: ( cb ) -> + # db.eventPollers.unlinkModule oEpOne.id, oUser.username + db.eventPollers.deleteModule oEpOne.id + # db.eventPollers.unlinkModule oEpTwo.id, oUser.username + db.eventPollers.deleteModule oEpTwo.id + cb() - testCreateAndRead: ( test ) -> - test.expect 3 - db.eventPollers.storeModule oUser.username, oEpOne - - # test that the ID shows up in the set - db.eventPollers.getModuleIds ( err , obj ) -> - test.ok oEpOne.id in obj, - 'Expected key not in event-pollers set' - - # the retrieved object really is the one we expected - db.eventPollers.getModule oEpOne.id, ( err , obj ) -> - test.deepEqual obj, oEpOne, - 'Retrieved Event Poller is not what we expected' - - # Ensure the event poller is in the list of all existing ones - db.eventPollers.getModules ( err , obj ) -> - test.deepEqual oEpOne, obj[oEpOne.id], - 'Event Poller ist not in result set' - test.done() - - testUpdate: ( test ) -> - test.expect 2 + testCreateAndRead: ( test ) -> + test.expect 3 + db.eventPollers.storeModule oUser.username, oEpOne + + # test that the ID shows up in the set + db.eventPollers.getModuleIds ( err , obj ) -> + test.ok oEpOne.id in obj, + 'Expected key not in event-pollers set' + + # the retrieved object really is the one we expected + db.eventPollers.getModule oEpOne.id, ( err , obj ) -> + test.deepEqual obj, oEpOne, + 'Retrieved Event Poller is not what we expected' + + # Ensure the event poller is in the list of all existing ones + db.eventPollers.getModules ( err , obj ) -> + test.deepEqual oEpOne, obj[oEpOne.id], + 'Event Poller ist not in result set' + test.done() + + testUpdate: ( test ) -> + test.expect 2 - oTmp = {} - oTmp[key] = val for key, val of oEpOne - oTmp.public = 'true' + oTmp = {} + oTmp[key] = val for key, val of oEpOne + oTmp.public = 'true' - # store an entry to start with - db.eventPollers.storeModule oUser.username, oEpOne - db.eventPollers.storeModule oUser.username, oTmp + # store an entry to start with + db.eventPollers.storeModule oUser.username, oEpOne + db.eventPollers.storeModule oUser.username, oTmp - # the retrieved object really is the one we expected - db.eventPollers.getModule oEpOne.id, ( err , obj ) -> - test.deepEqual obj, oTmp, - 'Retrieved Event Poller is not what we expected' - - # Ensure the event poller is in the list of all existing ones - db.eventPollers.getModules ( err , obj ) -> - test.deepEqual oTmp, obj[oEpOne.id], - 'Event Poller ist not in result set' - - test.done() + # the retrieved object really is the one we expected + db.eventPollers.getModule oEpOne.id, ( err , obj ) -> + test.deepEqual obj, oTmp, + 'Retrieved Event Poller is not what we expected' + + # Ensure the event poller is in the list of all existing ones + db.eventPollers.getModules ( err , obj ) -> + test.deepEqual oTmp, obj[oEpOne.id], + 'Event Poller ist not in result set' + + test.done() - testDelete: ( test ) -> - test.expect 2 + testDelete: ( test ) -> + test.expect 2 - # store an entry to start with - db.eventPollers.storeModule oUser.username, oEpOne + # store an entry to start with + db.eventPollers.storeModule oUser.username, oEpOne - # Ensure the event poller has been deleted - db.eventPollers.deleteModule oEpOne.id - db.eventPollers.getModule oEpOne.id, ( err , obj ) -> - test.strictEqual obj, null, - 'Event Poller still exists' - - # Ensure the ID has been removed from the set - db.eventPollers.getModuleIds ( err , obj ) -> - test.ok oEpOne.id not in obj, - 'Event Poller key still exists in set' - - test.done() - + # Ensure the event poller has been deleted + db.eventPollers.deleteModule oEpOne.id + db.eventPollers.getModule oEpOne.id, ( err , obj ) -> + test.strictEqual obj, null, + 'Event Poller still exists' + + # Ensure the ID has been removed from the set + db.eventPollers.getModuleIds ( err , obj ) -> + test.ok oEpOne.id not in obj, + 'Event Poller key still exists in set' + + test.done() + - testFetchSeveral: ( test ) -> - test.expect 3 - semaphore = 2 + testFetchSeveral: ( test ) -> + test.expect 3 + semaphore = 2 - fCheckInvoker = ( modname, mod ) -> - myTest = test - forkEnds = () -> - if --semaphore is 0 - - myTest.done() - ( err, obj ) -> - myTest.deepEqual mod, obj, - "Invoker #{ modname } does not equal the expected one" - forkEnds() + fCheckInvoker = ( modname, mod ) -> + myTest = test + forkEnds = () -> + if --semaphore is 0 + + myTest.done() + ( err, obj ) -> + myTest.deepEqual mod, obj, + "Invoker #{ modname } does not equal the expected one" + forkEnds() - db.eventPollers.storeModule oUser.username, oEpOne - db.eventPollers.storeModule oUser.username, oEpTwo - db.eventPollers.getModuleIds ( err, obj ) -> - test.ok oEpOne.id in obj and oEpTwo.id in obj, - 'Not all event poller Ids in set' - db.eventPollers.getModule oEpOne.id, fCheckInvoker oEpOne.id, oEpOne - db.eventPollers.getModule oEpTwo.id, fCheckInvoker oEpTwo.id, oEpTwo + db.eventPollers.storeModule oUser.username, oEpOne + db.eventPollers.storeModule oUser.username, oEpTwo + db.eventPollers.getModuleIds ( err, obj ) -> + test.ok oEpOne.id in obj and oEpTwo.id in obj, + 'Not all event poller Ids in set' + db.eventPollers.getModule oEpOne.id, fCheckInvoker oEpOne.id, oEpOne + db.eventPollers.getModule oEpTwo.id, fCheckInvoker oEpTwo.id, oEpTwo ### # Test EVENT POLLER PARAMS ### exports.EventPollerParams = - testCreateAndRead: ( test ) -> - test.expect 2 + testCreateAndRead: ( test ) -> + test.expect 2 - userId = 'tester1' - eventId = 'test-event-poller_1' - params = 'shouldn\'t this be an object?' + userId = 'tester1' + eventId = 'test-event-poller_1' + params = 'shouldn\'t this be an object?' - # store an entry to start with - db.eventPollers.storeUserParams eventId, userId, params - - # test that the ID shows up in the set - db.eventPollers.getUserParamsIds ( err, obj ) -> - test.ok eventId+':'+userId in obj, - 'Expected key not in event-params set' - - # the retrieved object really is the one we expected - db.eventPollers.getUserParams eventId, userId, ( err, obj ) -> - test.strictEqual obj, params, - 'Retrieved event params is not what we expected' - db.eventPollers.deleteUserParams eventId, userId - test.done() + # store an entry to start with + db.eventPollers.storeUserParams eventId, userId, params + + # test that the ID shows up in the set + db.eventPollers.getUserParamsIds ( err, obj ) -> + test.ok eventId+':'+userId in obj, + 'Expected key not in event-params set' + + # the retrieved object really is the one we expected + db.eventPollers.getUserParams eventId, userId, ( err, obj ) -> + test.strictEqual obj, params, + 'Retrieved event params is not what we expected' + db.eventPollers.deleteUserParams eventId, userId + test.done() - testUpdate: ( test ) -> - test.expect 1 + testUpdate: ( test ) -> + test.expect 1 - userId = 'tester1' - eventId = 'test-event-poller_1' - params = 'shouldn\'t this be an object?' - paramsNew = 'shouldn\'t this be a new object?' + userId = 'tester1' + eventId = 'test-event-poller_1' + params = 'shouldn\'t this be an object?' + paramsNew = 'shouldn\'t this be a new object?' - # store an entry to start with - db.eventPollers.storeUserParams eventId, userId, params - db.eventPollers.storeUserParams eventId, userId, paramsNew + # store an entry to start with + db.eventPollers.storeUserParams eventId, userId, params + db.eventPollers.storeUserParams eventId, userId, paramsNew - # the retrieved object really is the one we expected - db.eventPollers.getUserParams eventId, userId, ( err, obj ) -> - test.strictEqual obj, paramsNew, - 'Retrieved event params is not what we expected' - db.eventPollers.deleteUserParams eventId, userId - - test.done() + # the retrieved object really is the one we expected + db.eventPollers.getUserParams eventId, userId, ( err, obj ) -> + test.strictEqual obj, paramsNew, + 'Retrieved event params is not what we expected' + db.eventPollers.deleteUserParams eventId, userId + + test.done() - testDelete: ( test ) -> - test.expect 2 + testDelete: ( test ) -> + test.expect 2 - userId = 'tester1' - eventId = 'test-event-poller_1' - params = 'shouldn\'t this be an object?' + userId = 'tester1' + eventId = 'test-event-poller_1' + params = 'shouldn\'t this be an object?' - # store an entry to start with and delete it right away - db.eventPollers.storeUserParams eventId, userId, params - db.eventPollers.deleteUserParams eventId, userId - - # Ensure the event params have been deleted - db.eventPollers.getUserParams eventId, userId, ( err, obj ) -> - test.strictEqual obj, null, - 'Event params still exists' - # Ensure the ID has been removed from the set - db.eventPollers.getUserParamsIds ( err, obj ) -> - test.ok eventId+':'+userId not in obj, - 'Event Params key still exists in set' - - test.done() + # store an entry to start with and delete it right away + db.eventPollers.storeUserParams eventId, userId, params + db.eventPollers.deleteUserParams eventId, userId + + # Ensure the event params have been deleted + db.eventPollers.getUserParams eventId, userId, ( err, obj ) -> + test.strictEqual obj, null, + 'Event params still exists' + # Ensure the ID has been removed from the set + db.eventPollers.getUserParamsIds ( err, obj ) -> + test.ok eventId+':'+userId not in obj, + 'Event Params key still exists in set' + + test.done() ### # Test RULES ### exports.Rules = - tearDown: ( cb ) -> - db.deleteRule oRuleOne.id - cb() + tearDown: ( cb ) -> + db.deleteRule oRuleOne.id + cb() - testCreateAndRead: ( test ) -> - test.expect 3 + testCreateAndRead: ( test ) -> + test.expect 3 - # store an entry to start with - db.storeRule oRuleOne.id, JSON.stringify oRuleOne - - # test that the ID shows up in the set - db.getRuleIds ( err, obj ) -> - test.ok oRuleOne.id in obj, - 'Expected key not in rule key set' - - # the retrieved object really is the one we expected - db.getRule oRuleOne.id, ( err, obj ) -> - test.deepEqual JSON.parse(obj), oRuleOne, - 'Retrieved rule is not what we expected' + # store an entry to start with + db.storeRule oRuleOne.id, JSON.stringify oRuleOne + + # test that the ID shows up in the set + db.getRuleIds ( err, obj ) -> + test.ok oRuleOne.id in obj, + 'Expected key not in rule key set' + + # the retrieved object really is the one we expected + db.getRule oRuleOne.id, ( err, obj ) -> + test.deepEqual JSON.parse(obj), oRuleOne, + 'Retrieved rule is not what we expected' - # Ensure the rule is in the list of all existing ones - db.getRules ( err , obj ) -> - test.deepEqual oRuleOne, JSON.parse( obj[oRuleOne.id] ), - 'Rule not in result set' - - test.done() + # Ensure the rule is in the list of all existing ones + db.getRules ( err , obj ) -> + test.deepEqual oRuleOne, JSON.parse( obj[oRuleOne.id] ), + 'Rule not in result set' + + test.done() - testUpdate: ( test ) -> - test.expect 1 + testUpdate: ( test ) -> + test.expect 1 - # store an entry to start with - db.storeRule oRuleOne.id, JSON.stringify oRuleOne - db.storeRule oRuleOne.id, JSON.stringify oRuleTwo + # store an entry to start with + db.storeRule oRuleOne.id, JSON.stringify oRuleOne + db.storeRule oRuleOne.id, JSON.stringify oRuleTwo - # the retrieved object really is the one we expected - db.getRule oRuleOne.id, ( err, obj ) -> - test.deepEqual JSON.parse(obj), oRuleTwo, - 'Retrieved rule is not what we expected' - - test.done() + # the retrieved object really is the one we expected + db.getRule oRuleOne.id, ( err, obj ) -> + test.deepEqual JSON.parse(obj), oRuleTwo, + 'Retrieved rule is not what we expected' + + test.done() - testDelete: ( test ) -> - test.expect 2 + testDelete: ( test ) -> + test.expect 2 - # store an entry to start with and delete it right away - db.storeRule oRuleOne.id, JSON.stringify oRuleOne - db.deleteRule oRuleOne.id - - # Ensure the event params have been deleted - db.getRule oRuleOne.id, ( err, obj ) -> - test.strictEqual obj, null, - 'Rule still exists' + # store an entry to start with and delete it right away + db.storeRule oRuleOne.id, JSON.stringify oRuleOne + db.deleteRule oRuleOne.id + + # Ensure the event params have been deleted + db.getRule oRuleOne.id, ( err, obj ) -> + test.strictEqual obj, null, + 'Rule still exists' - # Ensure the ID has been removed from the set - db.getRuleIds ( err, obj ) -> - test.ok oRuleOne.id not in obj, - 'Rule key still exists in set' - - test.done() + # Ensure the ID has been removed from the set + db.getRuleIds ( err, obj ) -> + test.ok oRuleOne.id not in obj, + 'Rule key still exists in set' + + test.done() - testLink: ( test ) -> - test.expect 2 + testLink: ( test ) -> + test.expect 2 - # link a rule to the user - db.linkRule oRuleOne.id, oUser.username + # link a rule to the user + db.linkRule oRuleOne.id, oUser.username - # Ensure the user is linked to the rule - db.getRuleLinkedUsers oRuleOne.id, ( err, obj ) -> - test.ok oUser.username in obj, - "Rule not linked to user #{ oUser.username }" + # Ensure the user is linked to the rule + db.getRuleLinkedUsers oRuleOne.id, ( err, obj ) -> + test.ok oUser.username in obj, + "Rule not linked to user #{ oUser.username }" - # Ensure the rule is linked to the user - db.getUserLinkedRules oUser.username, ( err, obj ) -> - test.ok oRuleOne.id in obj, - "User not linked to rule #{ oRuleOne.id }" - - test.done() + # Ensure the rule is linked to the user + db.getUserLinkedRules oUser.username, ( err, obj ) -> + test.ok oRuleOne.id in obj, + "User not linked to rule #{ oRuleOne.id }" + + test.done() - testUnlink: ( test ) -> - test.expect 2 + testUnlink: ( test ) -> + test.expect 2 - # link and unlink immediately afterwards - db.linkRule oRuleOne.id, oUser.username - db.unlinkRule oRuleOne.id, oUser.username + # link and unlink immediately afterwards + db.linkRule oRuleOne.id, oUser.username + db.unlinkRule oRuleOne.id, oUser.username - # Ensure the user is linked to the rule - db.getRuleLinkedUsers oRuleOne.id, ( err, obj ) -> - test.ok oUser.username not in obj, - "Rule still linked to user #{ oUser.username }" + # Ensure the user is linked to the rule + db.getRuleLinkedUsers oRuleOne.id, ( err, obj ) -> + test.ok oUser.username not in obj, + "Rule still linked to user #{ oUser.username }" - # Ensure the rule is linked to the user - db.getUserLinkedRules oUser.username, ( err, obj ) -> - test.ok oRuleOne.id not in obj, - "User still linked to rule #{ oRuleOne.id }" - - test.done() + # Ensure the rule is linked to the user + db.getUserLinkedRules oUser.username, ( err, obj ) -> + test.ok oRuleOne.id not in obj, + "User still linked to rule #{ oRuleOne.id }" + + test.done() - testActivate: ( test ) -> - test.expect 4 + testActivate: ( test ) -> + test.expect 4 - usr = - username: "tester-1" - password: "tester-1" - db.storeUser usr - db.activateRule oRuleOne.id, oUser.username - # activate a rule for a user + usr = + username: "tester-1" + password: "tester-1" + db.storeUser usr + db.activateRule oRuleOne.id, oUser.username + # activate a rule for a user - # Ensure the user is activated to the rule - db.getRuleActivatedUsers oRuleOne.id, ( err, obj ) -> - test.ok oUser.username in obj, - "Rule not activated for user #{ oUser.username }" + # Ensure the user is activated to the rule + db.getRuleActivatedUsers oRuleOne.id, ( err, obj ) -> + test.ok oUser.username in obj, + "Rule not activated for user #{ oUser.username }" - # Ensure the rule is linked to the user - db.getUserActivatedRules oUser.username, ( err, obj ) -> - test.ok oRuleOne.id in obj, - "User not activated for rule #{ oRuleOne.id }" + # Ensure the rule is linked to the user + db.getUserActivatedRules oUser.username, ( err, obj ) -> + test.ok oRuleOne.id in obj, + "User not activated for rule #{ oRuleOne.id }" - # Ensure the rule is showing up in all active rules - db.getAllActivatedRuleIdsPerUser ( err, obj ) -> - test.notStrictEqual obj[oUser.username], undefined, - "User #{ oUser.username } not in activated rules set" - if obj[oUser.username] - test.ok oRuleOne.id in obj[oUser.username], - "Rule #{ oRuleOne.id } not in activated rules set" - # else - # test.ok true, - # "Dummy so we meet the expected num of tests" - - test.done() + # Ensure the rule is showing up in all active rules + db.getAllActivatedRuleIdsPerUser ( err, obj ) -> + test.notStrictEqual obj[oUser.username], undefined, + "User #{ oUser.username } not in activated rules set" + if obj[oUser.username] + test.ok oRuleOne.id in obj[oUser.username], + "Rule #{ oRuleOne.id } not in activated rules set" + # else + # test.ok true, + # "Dummy so we meet the expected num of tests" + + test.done() - testDeactivate: ( test ) -> - test.expect 3 + testDeactivate: ( test ) -> + test.expect 3 - # store an entry to start with and link it to te user - db.activateRule oRuleOne.id, oUser.username - db.deactivateRule oRuleOne.id, oUser.username + # store an entry to start with and link it to te user + db.activateRule oRuleOne.id, oUser.username + db.deactivateRule oRuleOne.id, oUser.username - # Ensure the user is linked to the rule - db.getRuleActivatedUsers oRuleOne.id, ( err, obj ) -> - test.ok oUser.username not in obj, - "Rule still activated for user #{ oUser.username }" + # Ensure the user is linked to the rule + db.getRuleActivatedUsers oRuleOne.id, ( err, obj ) -> + test.ok oUser.username not in obj, + "Rule still activated for user #{ oUser.username }" - # Ensure the rule is linked to the user - db.getUserActivatedRules oUser.username, ( err, obj ) -> - test.ok oRuleOne.id not in obj, - "User still activated for rule #{ oRuleOne.id }" + # Ensure the rule is linked to the user + db.getUserActivatedRules oUser.username, ( err, obj ) -> + test.ok oRuleOne.id not in obj, + "User still activated for rule #{ oRuleOne.id }" - # Ensure the rule is showing up in all active rules - db.getAllActivatedRuleIdsPerUser ( err, obj ) -> - if obj[oUser.username] - test.ok oRuleOne.id not in obj[oUser.username], - "Rule #{ oRuleOne.id } still in activated rules set" - else - test.ok true, - "We are fine since there are no entries for this user anymore" - - test.done() + # Ensure the rule is showing up in all active rules + db.getAllActivatedRuleIdsPerUser ( err, obj ) -> + if obj[oUser.username] + test.ok oRuleOne.id not in obj[oUser.username], + "Rule #{ oRuleOne.id } still in activated rules set" + else + test.ok true, + "We are fine since there are no entries for this user anymore" + + test.done() - testUnlinkAndDeactivateAfterDeletion: ( test ) -> - test.expect 2 + testUnlinkAndDeactivateAfterDeletion: ( test ) -> + test.expect 2 - # store an entry to start with and link it to te user - db.storeRule oRuleOne.id, JSON.stringify oRuleOne - db.linkRule oRuleOne.id, oUser.username - db.activateRule oRuleOne.id, oUser.username + # store an entry to start with and link it to te user + db.storeRule oRuleOne.id, JSON.stringify oRuleOne + db.linkRule oRuleOne.id, oUser.username + db.activateRule oRuleOne.id, oUser.username - # We need to wait here and there since these calls are asynchronous - fWaitForTest = () -> + # We need to wait here and there since these calls are asynchronous + fWaitForTest = () -> - # Ensure the user is unlinked to the rule - db.getUserLinkedRules oUser.username, ( err, obj ) -> - test.ok oRuleOne.id not in obj, - "Rule #{ oRuleOne.id } still linked to user #{ oUser.username }" + # Ensure the user is unlinked to the rule + db.getUserLinkedRules oUser.username, ( err, obj ) -> + test.ok oRuleOne.id not in obj, + "Rule #{ oRuleOne.id } still linked to user #{ oUser.username }" - # Ensure the rule is deactivated for the user - db.getUserActivatedRules oUser.username, ( err, obj ) -> - test.ok oRuleOne.id not in obj, - "Rule #{ oRuleOne.id } still activated for user #{ oUser.username }" - - test.done() + # Ensure the rule is deactivated for the user + db.getUserActivatedRules oUser.username, ( err, obj ) -> + test.ok oRuleOne.id not in obj, + "Rule #{ oRuleOne.id } still activated for user #{ oUser.username }" + + test.done() - fWaitForDeletion = () -> - db.deleteRule oRuleOne.id - setTimeout fWaitForTest, 500 + fWaitForDeletion = () -> + db.deleteRule oRuleOne.id + setTimeout fWaitForTest, 500 - setTimeout fWaitForDeletion, 100 + setTimeout fWaitForDeletion, 100 ### # Test USER ### exports.User = - testCreateInvalid: ( test ) -> - test.expect 4 - - oUserInvOne = - username: "tester-1-invalid" - oUserInvTwo = - password: "password" + testCreateInvalid: ( test ) -> + test.expect 4 + + oUserInvOne = + username: "tester-1-invalid" + oUserInvTwo = + password: "password" - # try to store invalid users, ensure they weren't - db.storeUser oUserInvOne - db.storeUser oUserInvTwo + # try to store invalid users, ensure they weren't + db.storeUser oUserInvOne + db.storeUser oUserInvTwo - db.getUser oUserInvOne.username, ( err, obj ) -> - test.strictEqual obj, null, - 'User One was stored!?' + db.getUser oUserInvOne.username, ( err, obj ) -> + test.strictEqual obj, null, + 'User One was stored!?' - db.getUser oUserInvTwo.username, ( err, obj ) -> - test.strictEqual obj, null, - 'User Two was stored!?' + db.getUser oUserInvTwo.username, ( err, obj ) -> + test.strictEqual obj, null, + 'User Two was stored!?' - db.getUserIds ( err, obj ) -> - test.ok oUserInvOne.username not in obj, - 'User key was stored!?' - test.ok oUserInvTwo.username not in obj, - 'User key was stored!?' - test.done() + db.getUserIds ( err, obj ) -> + test.ok oUserInvOne.username not in obj, + 'User key was stored!?' + test.ok oUserInvTwo.username not in obj, + 'User key was stored!?' + test.done() - testDelete: ( test ) -> - test.expect 2 + testDelete: ( test ) -> + test.expect 2 - # Store the user - db.storeUser oUser + # Store the user + db.storeUser oUser - db.getUser oUser.username, ( err, obj ) -> - test.deepEqual obj, oUser, - "User #{ oUser.username } is not what we expect!" + db.getUser oUser.username, ( err, obj ) -> + test.deepEqual obj, oUser, + "User #{ oUser.username } is not what we expect!" - db.getUserIds ( err, obj ) -> - test.ok oUser.username in obj, - 'User key was not stored!?' - - test.done() + db.getUserIds ( err, obj ) -> + test.ok oUser.username in obj, + 'User key was not stored!?' + + test.done() - testUpdate: ( test ) -> - test.expect 2 + testUpdate: ( test ) -> + test.expect 2 - # Store the user - db.storeUser oUser - oUser.password = "password-update" - db.storeUser oUser + # Store the user + db.storeUser oUser + oUser.password = "password-update" + db.storeUser oUser - db.getUser oUser.username, ( err, obj ) -> - test.deepEqual obj, oUser, - "User #{ oUser.username } is not what we expect!" + db.getUser oUser.username, ( err, obj ) -> + test.deepEqual obj, oUser, + "User #{ oUser.username } is not what we expect!" - db.getUserIds ( err, obj ) -> - test.ok oUser.username in obj, - 'User key was not stored!?' - test.done() + db.getUserIds ( err, obj ) -> + test.ok oUser.username in obj, + 'User key was not stored!?' + test.done() - testDelete: ( test ) -> - test.expect 2 + testDelete: ( test ) -> + test.expect 2 - # Wait until the user and his rules and roles are deleted - fWaitForDeletion = () -> - db.getUserIds ( err, obj ) -> - test.ok oUser.username not in obj, - 'User key still in set!' + # Wait until the user and his rules and roles are deleted + fWaitForDeletion = () -> + db.getUserIds ( err, obj ) -> + test.ok oUser.username not in obj, + 'User key still in set!' - db.getUser oUser.username, ( err, obj ) -> - test.strictEqual obj, null, - 'User key still exists!' - test.done() + db.getUser oUser.username, ( err, obj ) -> + test.strictEqual obj, null, + 'User key still exists!' + test.done() - # Store the user and make some links - db.storeUser oUser - db.deleteUser oUser.username - setTimeout fWaitForDeletion, 100 + # Store the user and make some links + db.storeUser oUser + db.deleteUser oUser.username + setTimeout fWaitForDeletion, 100 - testDeleteLinks: ( test ) -> - test.expect 4 + testDeleteLinks: ( test ) -> + test.expect 4 - # Wait until the user and his rules and roles are stored - fWaitForPersistence = () -> - db.deleteUser oUser.username - setTimeout fWaitForDeletion, 200 + # Wait until the user and his rules and roles are stored + fWaitForPersistence = () -> + db.deleteUser oUser.username + setTimeout fWaitForDeletion, 200 - # Wait until the user and his rules and roles are deleted - fWaitForDeletion = () -> - db.getRoleUsers 'tester', ( err, obj ) -> - test.ok oUser.username not in obj, - 'User key still in role tester!' + # Wait until the user and his rules and roles are deleted + fWaitForDeletion = () -> + db.getRoleUsers 'tester', ( err, obj ) -> + test.ok oUser.username not in obj, + 'User key still in role tester!' - db.getUserRoles oUser.username, ( err, obj ) -> - test.ok obj.length is 0, - 'User still associated to roles!' - - db.getUserLinkedRules oUser.username, ( err, obj ) -> - test.ok obj.length is 0, - 'User still associated to rules!' - db.getUserActivatedRules oUser.username, ( err, obj ) -> - test.ok obj.length is 0, - 'User still associated to activated rules!' - test.done() + db.getUserRoles oUser.username, ( err, obj ) -> + test.ok obj.length is 0, + 'User still associated to roles!' + + db.getUserLinkedRules oUser.username, ( err, obj ) -> + test.ok obj.length is 0, + 'User still associated to rules!' + db.getUserActivatedRules oUser.username, ( err, obj ) -> + test.ok obj.length is 0, + 'User still associated to activated rules!' + test.done() - # Store the user and make some links - db.storeUser oUser - db.linkRule 'rule-1', oUser.username - db.linkRule 'rule-2', oUser.username - db.linkRule 'rule-3', oUser.username - db.activateRule 'rule-1', oUser.username - db.storeUserRole oUser.username, 'tester' - - setTimeout fWaitForPersistence, 100 + # Store the user and make some links + db.storeUser oUser + db.linkRule 'rule-1', oUser.username + db.linkRule 'rule-2', oUser.username + db.linkRule 'rule-3', oUser.username + db.activateRule 'rule-1', oUser.username + db.storeUserRole oUser.username, 'tester' + + setTimeout fWaitForPersistence, 100 - testLogin: ( test ) -> - test.expect 3 + testLogin: ( test ) -> + test.expect 3 - # Store the user and make some links - db.storeUser oUser - db.loginUser oUser.username, oUser.password, ( err, obj ) -> - test.deepEqual obj, oUser, - 'User not logged in!' + # Store the user and make some links + db.storeUser oUser + db.loginUser oUser.username, oUser.password, ( err, obj ) -> + test.deepEqual obj, oUser, + 'User not logged in!' - db.loginUser 'dummyname', oUser.password, ( err, obj ) -> - test.strictEqual obj, null, - 'User logged in?!' + db.loginUser 'dummyname', oUser.password, ( err, obj ) -> + test.strictEqual obj, null, + 'User logged in?!' - db.loginUser oUser.username, 'wrongpass', ( err, obj ) -> - test.strictEqual obj, null, - 'User logged in?!' - - test.done() + db.loginUser oUser.username, 'wrongpass', ( err, obj ) -> + test.strictEqual obj, null, + 'User logged in?!' + + test.done() ### @@ -645,36 +645,36 @@ exports.User = ### exports.Roles = - testStore: ( test ) -> - test.expect 2 + testStore: ( test ) -> + test.expect 2 - db.storeUser oUser - db.storeUserRole oUser.username, 'tester' + db.storeUser oUser + db.storeUserRole oUser.username, 'tester' - db.getUserRoles oUser.username, ( err, obj ) -> - test.ok 'tester' in obj, - 'User role tester not stored!' + db.getUserRoles oUser.username, ( err, obj ) -> + test.ok 'tester' in obj, + 'User role tester not stored!' - db.getRoleUsers 'tester', ( err, obj ) -> - test.ok oUser.username in obj, - "User #{ oUser.username } not stored in role tester!" - - test.done() + db.getRoleUsers 'tester', ( err, obj ) -> + test.ok oUser.username in obj, + "User #{ oUser.username } not stored in role tester!" + + test.done() - testDelete: ( test ) -> - test.expect 2 + testDelete: ( test ) -> + test.expect 2 - db.storeUser oUser - db.storeUserRole oUser.username, 'tester' - db.removeUserRole oUser.username, 'tester' + db.storeUser oUser + db.storeUserRole oUser.username, 'tester' + db.removeUserRole oUser.username, 'tester' - db.getUserRoles oUser.username, ( err, obj ) -> - test.ok 'tester' not in obj, - 'User role tester not stored!' + db.getUserRoles oUser.username, ( err, obj ) -> + test.ok 'tester' not in obj, + 'User role tester not stored!' - db.getRoleUsers 'tester', ( err, obj ) -> - test.ok oUser.username not in obj, - "User #{ oUser.username } not stored in role tester!" - - test.done() - # store an entry to start with + db.getRoleUsers 'tester', ( err, obj ) -> + test.ok oUser.username not in obj, + "User #{ oUser.username } not stored in role tester!" + + test.done() + # store an entry to start with diff --git a/testing/test_request-handler.coffee b/testing/test_request-handler.coffee index 208e913..cc90744 100644 --- a/testing/test_request-handler.coffee +++ b/testing/test_request-handler.coffee @@ -6,241 +6,241 @@ cp = require 'child_process' try - data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' - try - objects = JSON.parse data - catch err - console.log 'Error parsing standard objects file: ' + err.message + data = fs.readFileSync path.resolve( 'testing', 'files', 'testObjects.json' ), 'utf8' + try + objects = JSON.parse data + catch err + console.log 'Error parsing standard objects file: ' + err.message catch err - console.log 'Error fetching standard objects file: ' + err.message + console.log 'Error fetching standard objects file: ' + err.message logger = require path.join '..', 'js', 'logging' log = logger.getLogger - nolog: true + nolog: true opts = - logger: log + logger: log opts[ 'db-port' ] = 6379 db = require path.join '..', 'js', 'persistence' db opts rh = require path.join '..', 'js', 'request-handler' opts[ 'request-service' ] = ( usr, obj, cb ) -> - test.ok false, 'testEvent should not cause a service request call' + test.ok false, 'testEvent should not cause a service request call' opts[ 'shutdown-function' ] = () -> - test.ok false, 'testEvent should not cause a system shutdown' + test.ok false, 'testEvent should not cause a system shutdown' rh opts createRequest = ( query, origUrl ) -> - req = new events.EventEmitter() - req.query = query - req.originalUrl = origUrl - req.session = {} - req + req = new events.EventEmitter() + req.query = query + req.originalUrl = origUrl + req.session = {} + req createLoggedInRequest = ( query, origUrl ) -> - req = createRequest query, origUrl - req.session = - user: objects.users.userOne - req + req = createRequest query, origUrl + req.session = + user: objects.users.userOne + req createAdminRequest = ( query, origUrl ) -> - req = createRequest() - req.session = - user: objects.users.userAdmin - req + req = createRequest() + req.session = + user: objects.users.userAdmin + req postRequestData = ( req, data ) -> - req.emit 'data', data - req.emit 'end' + req.emit 'data', data + req.emit 'end' # cb want's to get a response like { code, msg } createResponse = ( cb ) -> - resp = - send: ( code, msg ) -> - if msg - code = parseInt code - else - msg = code - code = 200 - cb code, msg + resp = + send: ( code, msg ) -> + if msg + code = parseInt code + else + msg = code + code = 200 + cb code, msg exports.session = - setUp: ( cb ) => - @oUsr = objects.users.userOne - db.storeUser @oUsr - cb() + setUp: ( cb ) => + @oUsr = objects.users.userOne + db.storeUser @oUsr + cb() - tearDown: ( cb ) => - db.deleteUser @oUsr.username - cb() + tearDown: ( cb ) => + db.deleteUser @oUsr.username + cb() - testLoginAndOut: ( test ) => - test.expect 6 + testLoginAndOut: ( test ) => + test.expect 6 - req = createRequest() - resp = createResponse ( code, msg ) => + req = createRequest() + resp = createResponse ( code, msg ) => - # Check Login - test.strictEqual code, 200, 'Login failed' - test.deepEqual req.session.user, @oUsr, 'Session user not what we expected' - req = createLoggedInRequest() - resp = createResponse ( code, msg ) => + # Check Login + test.strictEqual code, 200, 'Login failed' + test.deepEqual req.session.user, @oUsr, 'Session user not what we expected' + req = createLoggedInRequest() + resp = createResponse ( code, msg ) => - # Check Login again - test.strictEqual code, 200, 'Login again did nothing different' - test.deepEqual req.session.user, @oUsr, 'Session user not what we expected after relogin' - req = createRequest() - resp = createResponse ( code, msg ) -> + # Check Login again + test.strictEqual code, 200, 'Login again did nothing different' + test.deepEqual req.session.user, @oUsr, 'Session user not what we expected after relogin' + req = createRequest() + resp = createResponse ( code, msg ) -> - # Check logout - test.strictEqual code, 200, 'Logout failed' - test.strictEqual req.session.user, null, 'User not removed from session' - test.done() - rh.handleLogout req, resp # set the handler to listening - rh.handleLogin req, resp # set the handler to listening - postRequestData req, JSON.stringify @oUsr # emit the data post event + # Check logout + test.strictEqual code, 200, 'Logout failed' + test.strictEqual req.session.user, null, 'User not removed from session' + test.done() + rh.handleLogout req, resp # set the handler to listening + rh.handleLogin req, resp # set the handler to listening + postRequestData req, JSON.stringify @oUsr # emit the data post event - rh.handleLogin req, resp # set the handler to listening - postRequestData req, JSON.stringify @oUsr # emit the data post event + rh.handleLogin req, resp # set the handler to listening + postRequestData req, JSON.stringify @oUsr # emit the data post event - testWrongLogin: ( test ) => - test.expect 2 + testWrongLogin: ( test ) => + test.expect 2 - req = createRequest() - resp = createResponse ( code, msg ) => - test.strictEqual code, 401, 'Login did not fail?' - test.strictEqual req.session.user, undefined, 'User in session?' - test.done() + req = createRequest() + resp = createResponse ( code, msg ) => + test.strictEqual code, 401, 'Login did not fail?' + test.strictEqual req.session.user, undefined, 'User in session?' + test.done() - usr = - username: @oUsr.username - password: 'wrongpassword' - rh.handleLogin req, resp # set the handler to listening - postRequestData req, JSON.stringify usr # emit the data post event + usr = + username: @oUsr.username + password: 'wrongpassword' + rh.handleLogin req, resp # set the handler to listening + postRequestData req, JSON.stringify usr # emit the data post event exports.events = - setUp: ( cb ) -> - db.purgeEventQueue() - cb() + setUp: ( cb ) -> + db.purgeEventQueue() + cb() # This test seems to hang sometimes... maybe it's also happening somewhere else... - testCorrectEvent: ( test ) -> - test.expect 2 + testCorrectEvent: ( test ) -> + test.expect 2 - oEvt = objects.events.eventOne + oEvt = objects.events.eventOne - semaphore = 2 - fPopEvent = () -> - fCb = ( err, obj ) -> - oEvt.eventid = obj.eventid # because the event id is generated by the system - test.deepEqual obj, oEvt, 'Caught event is not what we expected' - if --semaphore is 0 - test.done() - db.popEvent fCb + semaphore = 2 + fPopEvent = () -> + fCb = ( err, obj ) -> + oEvt.eventid = obj.eventid # because the event id is generated by the system + test.deepEqual obj, oEvt, 'Caught event is not what we expected' + if --semaphore is 0 + test.done() + db.popEvent fCb - req = createLoggedInRequest() - resp = createResponse ( code, msg ) -> - test.strictEqual code, 200 - if --semaphore is 0 - test.done() + req = createLoggedInRequest() + resp = createResponse ( code, msg ) -> + test.strictEqual code, 200 + if --semaphore is 0 + test.done() - rh.handleEvent req, resp # set the handler to listening - postRequestData req, JSON.stringify oEvt # emit the data post event - setTimeout fPopEvent, 200 # try to fetch the db entry + rh.handleEvent req, resp # set the handler to listening + postRequestData req, JSON.stringify oEvt # emit the data post event + setTimeout fPopEvent, 200 # try to fetch the db entry - testIncorrectEvent: ( test ) -> - test.expect 2 + testIncorrectEvent: ( test ) -> + test.expect 2 - oEvt = - data: 'event misses event type property' + oEvt = + data: 'event misses event type property' - semaphore = 2 - fPopEvent = () -> - fCb = ( err, obj ) -> - test.deepEqual obj, null, 'We caught an event!?' - if --semaphore is 0 - test.done() - db.popEvent fCb + semaphore = 2 + fPopEvent = () -> + fCb = ( err, obj ) -> + test.deepEqual obj, null, 'We caught an event!?' + if --semaphore is 0 + test.done() + db.popEvent fCb - req = createLoggedInRequest() - resp = createResponse ( code, msg ) -> - test.strictEqual code, 400 - if --semaphore is 0 - test.done() + req = createLoggedInRequest() + resp = createResponse ( code, msg ) -> + test.strictEqual code, 400 + if --semaphore is 0 + test.done() - rh.handleEvent req, resp # set the handler to listening - postRequestData req, JSON.stringify oEvt # emit the data post event - setTimeout fPopEvent, 200 # try to fetch the db entry + rh.handleEvent req, resp # set the handler to listening + postRequestData req, JSON.stringify oEvt # emit the data post event + setTimeout fPopEvent, 200 # try to fetch the db entry exports.testLoginOrPage = ( test ) -> - test.expect 3 + test.expect 3 - req = createRequest() - req.query = - page: 'forge_event' - resp = createResponse ( code, msg ) -> - - # Ensure we have to login first - test.ok msg.indexOf( 'document.title = \'Login\'' ) > 0, 'Didn\'t get login page?' - req = createLoggedInRequest() - req.query = - page: 'forge_event' - resp = createResponse ( code, msg ) -> + req = createRequest() + req.query = + page: 'forge_event' + resp = createResponse ( code, msg ) -> + + # Ensure we have to login first + test.ok msg.indexOf( 'document.title = \'Login\'' ) > 0, 'Didn\'t get login page?' + req = createLoggedInRequest() + req.query = + page: 'forge_event' + resp = createResponse ( code, msg ) -> - # After being logged in we should get the expected page - test.ok msg.indexOf( 'document.title = \'Event Forge!\'' ) > 0, 'Didn\' get forge page?' - req = createLoggedInRequest() - req.query = - page: 'wrongpage' - resp = createResponse ( code, msg ) -> + # After being logged in we should get the expected page + test.ok msg.indexOf( 'document.title = \'Event Forge!\'' ) > 0, 'Didn\' get forge page?' + req = createLoggedInRequest() + req.query = + page: 'wrongpage' + resp = createResponse ( code, msg ) -> - # A wrong page request should give back an error page - test.ok msg.indexOf( 'document.title = \'Error!\'' ) > 0, 'Didn\' get forge page?' - test.done() + # A wrong page request should give back an error page + test.ok msg.indexOf( 'document.title = \'Error!\'' ) > 0, 'Didn\' get forge page?' + test.done() - rh.handleForge req, resp # set the handler to listening - rh.handleForge req, resp # set the handler to listening - rh.handleForge req, resp # set the handler to listening + rh.handleForge req, resp # set the handler to listening + rh.handleForge req, resp # set the handler to listening + rh.handleForge req, resp # set the handler to listening exports.testUserCommandsNoLogin = ( test ) -> - test.expect 1 + test.expect 1 - req = createRequest() - resp = createResponse ( code, msg ) -> - test.strictEqual code, 401, 'Login did not fail?' - test.done() - rh.handleUserCommand req, resp # set the handler to listening + req = createRequest() + resp = createResponse ( code, msg ) -> + test.strictEqual code, 401, 'Login did not fail?' + test.done() + rh.handleUserCommand req, resp # set the handler to listening exports.testUserCommands = ( test ) -> - test.expect 3 + test.expect 3 - oReqData = - command: 'get_something' - # store_action - # store_event - # store_rule - # get_eventmodules - # get_actionmodules + oReqData = + command: 'get_something' + # store_action + # store_event + # store_rule + # get_eventmodules + # get_actionmodules - oRespData = - code: 200 - some: 'very' - important: 'data' + oRespData = + code: 200 + some: 'very' + important: 'data' - args = - logger: log - args[ 'request-service' ] = ( usr, obj, cb ) -> - test.ok true, 'Yay we got the request!' - cb oRespData - rh args + args = + logger: log + args[ 'request-service' ] = ( usr, obj, cb ) -> + test.ok true, 'Yay we got the request!' + cb oRespData + rh args - req = createLoggedInRequest() - resp = createResponse ( code, msg ) -> - test.strictEqual code, 200, 'Service wasn\'t happy with our request' - test.deepEqual msg, oRespData, 'Service didn\'t return expected' - test.done() - rh.handleUserCommand req, resp # set the handler to listening - postRequestData req, JSON.stringify oReqData # emit the data post event - + req = createLoggedInRequest() + resp = createResponse ( code, msg ) -> + test.strictEqual code, 200, 'Service wasn\'t happy with our request' + test.deepEqual msg, oRespData, 'Service didn\'t return expected' + test.done() + rh.handleUserCommand req, resp # set the handler to listening + postRequestData req, JSON.stringify oReqData # emit the data post event + diff --git a/testing/test_webapi-eca.coffee b/testing/test_webapi-eca.coffee index 066b892..db96e25 100644 --- a/testing/test_webapi-eca.coffee +++ b/testing/test_webapi-eca.coffee @@ -6,125 +6,125 @@ path = require 'path' # TODO test wrong/invalid config file exports.testShutDown = ( test ) -> - test.expect 1 + test.expect 1 - isRunning = true - pth = path.resolve 'js', 'webapi-eca' - engine = cp.fork pth, [ '-n', '-w', '8640' ] # [ '-i' , 'warn' ] + isRunning = true + pth = path.resolve 'js', 'webapi-eca' + engine = cp.fork pth, [ '-n', '-w', '8640' ] # [ '-i' , 'warn' ] - engine.on 'error', ( err ) -> - console.log err - engine.on 'exit', ( code, signal ) -> - test.ok true, 'Engine stopped' - isRunning = false - test.done() - - fWaitForStartup = () -> - engine.send 'die' - setTimeout fWaitForDeath, 5000 - - # Garbage collect eventually still running process - fWaitForDeath = () -> - if isRunning - test.ok false, '"testShutDown" Engine didn\'t shut down!' - engine.kill() - setTimeout test.done, 100 + engine.on 'error', ( err ) -> + console.log err + engine.on 'exit', ( code, signal ) -> + test.ok true, 'Engine stopped' + isRunning = false + test.done() + + fWaitForStartup = () -> + engine.send 'die' + setTimeout fWaitForDeath, 5000 + + # Garbage collect eventually still running process + fWaitForDeath = () -> + if isRunning + test.ok false, '"testShutDown" Engine didn\'t shut down!' + engine.kill() + setTimeout test.done, 100 - setTimeout fWaitForStartup, 1000 + setTimeout fWaitForStartup, 1000 exports.testKill = ( test ) -> - test.expect 1 + test.expect 1 - pth = path.resolve 'js', 'webapi-eca' - engine = cp.fork pth, [ '-n', '-w', '8641' ] # [ '-i' , 'warn' ] - engine.on 'error', ( err ) -> - console.log err + pth = path.resolve 'js', 'webapi-eca' + engine = cp.fork pth, [ '-n', '-w', '8641' ] # [ '-i' , 'warn' ] + engine.on 'error', ( err ) -> + console.log err - fWaitForStartup = () -> - engine.kill() - setTimeout fWaitForDeath, 1000 - - # Garbage collect eventually still running process - fWaitForDeath = () -> - test.ok engine.killed, '"testKill" Engine didn\'t shut down!' - test.done() + fWaitForStartup = () -> + engine.kill() + setTimeout fWaitForDeath, 1000 + + # Garbage collect eventually still running process + fWaitForDeath = () -> + test.ok engine.killed, '"testKill" Engine didn\'t shut down!' + test.done() - setTimeout fWaitForStartup, 1000 + setTimeout fWaitForStartup, 1000 exports.testHttpPortAlreadyUsed = ( test ) => - test.expect 1 - isRunning = true - pth = path.resolve 'js', 'webapi-eca' - - # Strange! why can't we make these variables local without - # the tests failing in one of the next tests... - @engine_one = cp.fork pth, [ '-n', '-w', '8642' ] # [ '-i' , 'warn' ] - @engine_one.on 'error', ( err ) -> - console.log err + test.expect 1 + isRunning = true + pth = path.resolve 'js', 'webapi-eca' + + # Strange! why can't we make these variables local without + # the tests failing in one of the next tests... + @engine_one = cp.fork pth, [ '-n', '-w', '8642' ] # [ '-i' , 'warn' ] + @engine_one.on 'error', ( err ) -> + console.log err - fWaitForFirstStartup = () => - @engine_two = cp.fork pth, [ '-n', '-w', '8642' ] # [ '-i' , 'warn' ] - @engine_two.on 'error', ( err ) -> - console.log err + fWaitForFirstStartup = () => + @engine_two = cp.fork pth, [ '-n', '-w', '8642' ] # [ '-i' , 'warn' ] + @engine_two.on 'error', ( err ) -> + console.log err - @engine_two.on 'exit', ( code, signal ) -> - test.ok true, 'Engine stopped' - isRunning = false - test.done() - - setTimeout fWaitForDeath, 12000 - - # Garbage collect eventually still running process - fWaitForDeath = () => - if isRunning - test.ok false, '"testHttpPortAlreadyUsed" Engine didn\'t shut down!' - test.done() + @engine_two.on 'exit', ( code, signal ) -> + test.ok true, 'Engine stopped' + isRunning = false + test.done() + + setTimeout fWaitForDeath, 12000 + + # Garbage collect eventually still running process + fWaitForDeath = () => + if isRunning + test.ok false, '"testHttpPortAlreadyUsed" Engine didn\'t shut down!' + test.done() - @engine_one.kill() - @engine_two.kill() + @engine_one.kill() + @engine_two.kill() - setTimeout fWaitForFirstStartup, 1000 + setTimeout fWaitForFirstStartup, 1000 exports.testHttpPortInvalid = ( test ) -> - test.expect 1 - - isRunning = true - pth = path.resolve 'js', 'webapi-eca' - engine = cp.fork pth, [ '-n', '-w', '1' ] # [ '-i' , 'warn' ] - engine.on 'exit', ( code, signal ) -> - test.ok true, 'Engine stopped' - isRunning = false - test.done() - engine.on 'error', ( err ) -> - console.log err + test.expect 1 + + isRunning = true + pth = path.resolve 'js', 'webapi-eca' + engine = cp.fork pth, [ '-n', '-w', '1' ] # [ '-i' , 'warn' ] + engine.on 'exit', ( code, signal ) -> + test.ok true, 'Engine stopped' + isRunning = false + test.done() + engine.on 'error', ( err ) -> + console.log err - # Garbage collect eventually still running process - fWaitForDeath = () -> - if isRunning - test.ok false, '"testHttpPortInvalid" Engine didn\'t shut down!' - test.done() - # engine.kill() + # Garbage collect eventually still running process + fWaitForDeath = () -> + if isRunning + test.ok false, '"testHttpPortInvalid" Engine didn\'t shut down!' + test.done() + # engine.kill() - setTimeout fWaitForDeath, 12000 + setTimeout fWaitForDeath, 12000 exports.testDbPortInvalid = ( test ) -> - test.expect 1 - - isRunning = true - pth = path.resolve 'js', 'webapi-eca' - engine = cp.fork pth, [ '-n', '-d', '10'] # [ '-i' , 'warn' ] - engine.on 'error', ( err ) -> - console.log err - engine.on 'exit', ( code, signal ) -> - test.ok true, 'Engine stopped' - isRunning = false - test.done() + test.expect 1 + + isRunning = true + pth = path.resolve 'js', 'webapi-eca' + engine = cp.fork pth, [ '-n', '-d', '10'] # [ '-i' , 'warn' ] + engine.on 'error', ( err ) -> + console.log err + engine.on 'exit', ( code, signal ) -> + test.ok true, 'Engine stopped' + isRunning = false + test.done() - # Garbage collect eventually still running process - fWaitForDeath = () -> - engine.kill() - if isRunning - test.ok false, '"testHttpPortInvalid" Engine didn\'t shut down!' - test.done() + # Garbage collect eventually still running process + fWaitForDeath = () -> + engine.kill() + if isRunning + test.ok false, '"testHttpPortInvalid" Engine didn\'t shut down!' + test.done() - setTimeout fWaitForDeath, 12000 + setTimeout fWaitForDeath, 12000 diff --git a/webpages/handlers/coffee/admin.coffee b/webpages/handlers/coffee/admin.coffee index b2d33c4..a7d29b7 100644 --- a/webpages/handlers/coffee/admin.coffee +++ b/webpages/handlers/coffee/admin.coffee @@ -1,22 +1,22 @@ 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 ) -> - 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 + 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 ) -> + fDelayed = () -> + if err.responseText is '' + err.responseText = 'No Response from Server!' + $( '#info' ).text 'Error: ' + err.responseText + $( '#info' ).attr 'class', 'error' + if err.status is 401 + window.location.href = 'admin' + setTimeout fDelayed, 500 window.addEventListener 'load', fOnLoad, true diff --git a/webpages/handlers/coffee/edit_modules.coffee b/webpages/handlers/coffee/edit_modules.coffee index 62ede49..114843d 100644 --- a/webpages/handlers/coffee/edit_modules.coffee +++ b/webpages/handlers/coffee/edit_modules.coffee @@ -1,111 +1,111 @@ fOnLoad = () -> - document.title = 'Edit Modules' - $( '#pagetitle' ).text "{{{user.username}}}, edit your Modules!" + document.title = 'Edit Modules' + $( '#pagetitle' ).text "{{{user.username}}}, edit your Modules!" - moduleType = $( '#module_type' ).val() - $( '#module_type' ).change () -> - moduleType = $( this ).val() - console.log moduleType - fFetchModules() + moduleType = $( '#module_type' ).val() + $( '#module_type' ).change () -> + moduleType = $( this ).val() + console.log moduleType + fFetchModules() - editor = ace.edit "editor" - editor.setTheme "ace/theme/monokai" - editor.setReadOnly true - editor.setShowPrintMargin false + editor = ace.edit "editor" + editor.setTheme "ace/theme/monokai" + editor.setReadOnly true + editor.setShowPrintMargin false - fErrHandler = ( errMsg ) -> - ( err ) -> - if err.status is 401 - window.location.href = 'forge?page=edit_modules' - else - $( '#moduleName' ).html "

 

" - $( '#moduleLanguage' ).html " " - editor.setValue "" - 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 + fErrHandler = ( errMsg ) -> + ( err ) -> + if err.status is 401 + window.location.href = 'forge?page=edit_modules' + else + $( '#moduleName' ).html "

 

" + $( '#moduleLanguage' ).html " " + editor.setValue "" + 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 - fFetchModules = () -> - if moduleType is 'Event Poller' - cmd = 'get_event_pollers' - else - cmd = 'get_action_invokers' - $.post( '/usercommand', command: cmd ) - .done fUpdateModuleList - .fail fErrHandler 'Did not retrieve rules! ' + fFetchModules = () -> + if moduleType is 'Event Poller' + cmd = 'get_event_pollers' + else + cmd = 'get_action_invokers' + $.post( '/usercommand', command: cmd ) + .done fUpdateModuleList + .fail fErrHandler 'Did not retrieve rules! ' - fUpdateModuleList = ( data ) -> - $( '#tableModules tr' ).remove() - oMods = JSON.parse data.message - for modName of oMods - tr = $ '' - inp = $( '
' ).text modName - img = $( '' ).attr( 'class', 'del' ) - .attr( 'title', 'Delete Module' ).attr 'src', 'red_cross_small.png' - tr.append( $( '' ).append img ) - img = $( '' ).attr( 'class', 'log' ) - .attr( 'title', 'Edit Module' ).attr 'src', 'edit.png' - tr.append( $( '' ).append img ) - tr.append( $( '' ).append inp ) - $( '#tableModules' ).append tr + fUpdateModuleList = ( data ) -> + $( '#tableModules tr' ).remove() + oMods = JSON.parse data.message + for modName of oMods + tr = $ '' + inp = $( '
' ).text modName + img = $( '' ).attr( 'class', 'del' ) + .attr( 'title', 'Delete Module' ).attr 'src', 'red_cross_small.png' + tr.append( $( '' ).append img ) + img = $( '' ).attr( 'class', 'log' ) + .attr( 'title', 'Edit Module' ).attr 'src', 'edit.png' + tr.append( $( '' ).append img ) + tr.append( $( '' ).append inp ) + $( '#tableModules' ).append tr - fFetchModules() + fFetchModules() - $( '#tableModules' ).on 'click', 'img.del', () -> - modName = $( 'div', $( this ).closest( 'tr' )).text() - if confirm "Do you really want to delete the Module '#{ modName }'? - The module might still be active in some of your rules!" - $( '#moduleName' ).html "

 

" - $( '#moduleLanguage' ).html " " - editor.setValue "" - if moduleType is 'Event Poller' - cmd = 'delete_event_poller' - else - cmd = 'delete_action_invoker' - data = - command: cmd - payload: - id: modName - data.payload = JSON.stringify data.payload - $.post( '/usercommand', data ) - .done fFetchModules - .fail fErrHandler 'Could not delete module! ' + $( '#tableModules' ).on 'click', 'img.del', () -> + modName = $( 'div', $( this ).closest( 'tr' )).text() + if confirm "Do you really want to delete the Module '#{ modName }'? + The module might still be active in some of your rules!" + $( '#moduleName' ).html "

 

" + $( '#moduleLanguage' ).html " " + editor.setValue "" + if moduleType is 'Event Poller' + cmd = 'delete_event_poller' + else + cmd = 'delete_action_invoker' + data = + command: cmd + payload: + id: modName + data.payload = JSON.stringify data.payload + $.post( '/usercommand', data ) + .done fFetchModules + .fail fErrHandler 'Could not delete module! ' - $( '#tableModules' ).on 'click', 'img.log', () -> - modName = $( 'div', $( this ).closest( 'tr' )).text() - if moduleType is 'Event Poller' - cmd = 'get_full_event_poller' - else - cmd = 'get_full_action_invoker' - data = - command: cmd - payload: - id: modName - data.payload = JSON.stringify data.payload - $.post( '/usercommand', data ) - .done ( data ) -> - try - oMod = JSON.parse data.message - catch err - fErrHandler err.message - if oMod.lang is 'CoffeeScript' - editor.getSession().setMode "ace/mode/coffee" - else - editor.getSession().setMode "ace/mode/javascript" - editor.setValue oMod.data - editor.gotoLine 1, 1 - editor.scrollToRow 1 - $( '#moduleName' ).html "

#{ oMod.id }

" - $( '#moduleLanguage' ).html "#{ oMod.lang }" + $( '#tableModules' ).on 'click', 'img.log', () -> + modName = $( 'div', $( this ).closest( 'tr' )).text() + if moduleType is 'Event Poller' + cmd = 'get_full_event_poller' + else + cmd = 'get_full_action_invoker' + data = + command: cmd + payload: + id: modName + data.payload = JSON.stringify data.payload + $.post( '/usercommand', data ) + .done ( data ) -> + try + oMod = JSON.parse data.message + catch err + fErrHandler err.message + if oMod.lang is 'CoffeeScript' + editor.getSession().setMode "ace/mode/coffee" + else + editor.getSession().setMode "ace/mode/javascript" + editor.setValue oMod.data + editor.gotoLine 1, 1 + editor.scrollToRow 1 + $( '#moduleName' ).html "

#{ oMod.id }

" + $( '#moduleLanguage' ).html "#{ oMod.lang }" - .fail fErrHandler 'Could not get module! ' + .fail fErrHandler 'Could not get module! ' window.addEventListener 'load', fOnLoad, true diff --git a/webpages/handlers/coffee/edit_rules.coffee b/webpages/handlers/coffee/edit_rules.coffee index 3abf8f2..c220815 100644 --- a/webpages/handlers/coffee/edit_rules.coffee +++ b/webpages/handlers/coffee/edit_rules.coffee @@ -12,112 +12,112 @@ fOnLoad = () -> - document.title = 'Edit Rules' - $( '#pagetitle' ).text "{{{user.username}}}, edit your Rules!" + document.title = 'Edit Rules' + $( '#pagetitle' ).text "{{{user.username}}}, edit your Rules!" - fErrHandler = ( errMsg ) -> - ( err ) -> - if err.status is 401 - window.location.href = 'forge?page=edit_rules' - else - $( '#log_col' ).text "" - 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 + fErrHandler = ( errMsg ) -> + ( err ) -> + if err.status is 401 + window.location.href = 'forge?page=edit_rules' + else + $( '#log_col' ).text "" + 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! ' + fFetchRules = () -> + $.post( '/usercommand', command: 'get_rules' ) + .done fUpdateRuleList + .fail fErrHandler 'Did not retrieve rules! ' - fUpdateRuleList = ( data ) -> - $( '#tableRules tr' ).remove() - for ruleName in data.message - tr = $ '' - img = $( '' ).attr( 'class', 'del' ) - .attr( 'title', 'Delete Rule' ).attr 'src', 'red_cross_small.png' - tr.append( $( '' ).append img ) - img = $( '' ).attr( 'class', 'edit' ) - .attr( 'title', 'Edit Rule' ).attr 'src', 'edit.png' - tr.append( $( '' ).append img ) - img = $( '' ).attr( 'class', 'log' ) - .attr( 'title', 'Show Rule Log' ).attr 'src', 'logicon.png' - tr.append( $( '' ).append img ) - inp = $( '
' ).text ruleName - tr.append( $( '' ).append inp ) - $( '#tableRules' ).append tr + fUpdateRuleList = ( data ) -> + $( '#tableRules tr' ).remove() + for ruleName in data.message + tr = $ '' + img = $( '' ).attr( 'class', 'del' ) + .attr( 'title', 'Delete Rule' ).attr 'src', 'red_cross_small.png' + tr.append( $( '' ).append img ) + img = $( '' ).attr( 'class', 'edit' ) + .attr( 'title', 'Edit Rule' ).attr 'src', 'edit.png' + tr.append( $( '' ).append img ) + img = $( '' ).attr( 'class', 'log' ) + .attr( 'title', 'Show Rule Log' ).attr 'src', 'logicon.png' + tr.append( $( '' ).append img ) + inp = $( '
' ).text ruleName + tr.append( $( '' ).append inp ) + $( '#tableRules' ).append tr - fFetchRules() + fFetchRules() - $( '#tableRules' ).on 'click', 'img.del', () -> - ruleName = $( 'div', $( this ).closest( 'tr' )).text() - if confirm "Do you really want to delete the rule '#{ ruleName }'?" - $( '#log_col' ).text "" - 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.del', () -> + ruleName = $( 'div', $( this ).closest( 'tr' )).text() + if confirm "Do you really want to delete the rule '#{ ruleName }'?" + $( '#log_col' ).text "" + 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.edit', () -> - ruleName = $( 'div', $( this ).closest( 'tr' )).text() - window.location.href = 'forge?page=forge_rule&id=' + encodeURIComponent ruleName + $( '#tableRules' ).on 'click', 'img.edit', () -> + ruleName = $( 'div', $( this ).closest( 'tr' )).text() + window.location.href = 'forge?page=forge_rule&id=' + encodeURIComponent ruleName - $( '#tableRules' ).on 'click', 'img.log', () -> - ruleName = $( 'div', $( this ).closest( 'tr' )).text() - data = - command: 'get_rule_log' - payload: - id: ruleName - data.payload = JSON.stringify data.payload - $.post( '/usercommand', data ) - .done ( data ) -> - log = data.message.replace new RegExp("\n", 'g'), "
" - $( '#log_col' ).html "

#{ ruleName } Log:

#{ log }" - .fail fErrHandler 'Could not get rule log! ' + $( '#tableRules' ).on 'click', 'img.log', () -> + ruleName = $( 'div', $( this ).closest( 'tr' )).text() + data = + command: 'get_rule_log' + payload: + id: ruleName + data.payload = JSON.stringify data.payload + $.post( '/usercommand', data ) + .done ( data ) -> + log = data.message.replace new RegExp("\n", 'g'), "
" + $( '#log_col' ).html "

#{ ruleName } Log:

#{ log }" + .fail fErrHandler 'Could not get rule log! ' - # Add parameter list functionality - fChangeInputVisibility = () -> - $( '#tableParams tr' ).each ( id ) -> - if $( this ).is ':last-child' or $( this ).is ':only-child' - $( 'img', this ).hide() - $( 'input[type=checkbox]', this ).hide() - else - $( 'img', this ).show() - $( 'input[type=checkbox]', this ).show() + # Add parameter list functionality + fChangeInputVisibility = () -> + $( '#tableParams tr' ).each ( id ) -> + if $( this ).is ':last-child' or $( this ).is ':only-child' + $( 'img', this ).hide() + $( 'input[type=checkbox]', this ).hide() + else + $( 'img', this ).show() + $( 'input[type=checkbox]', this ).show() - $( '#tableParams' ).on 'click', 'img', () -> - par = $( this ).closest 'tr' - if not par.is ':last-child' - par.remove() - fChangeInputVisibility() + $( '#tableParams' ).on 'click', 'img', () -> + par = $( this ).closest 'tr' + if not par.is ':last-child' + par.remove() + fChangeInputVisibility() - $( '#tableParams' ).on 'keyup', 'input', ( e ) -> - code = e.keyCode or e.which - if code isnt 9 - par = $( this ).closest 'tr' - if par.is ':last-child' - tr = $ '' - img = $( '' ).attr( 'title', 'Remove?').attr 'src', 'red_cross_small.png' - cb = $( '' ).attr( 'type', 'checkbox' ).attr 'title', 'Password shielded input?' - inp = $( '' ).attr( 'type', 'text' ).attr 'class', 'textinput' - tr.append $( '' ).append img - tr.append $( '' ).append cb - tr.append $( '' ).append inp - par.parent().append tr - fChangeInputVisibility() - else if $( this ).val() is '' and not par.is ':only-child' - par.remove() + $( '#tableParams' ).on 'keyup', 'input', ( e ) -> + code = e.keyCode or e.which + if code isnt 9 + par = $( this ).closest 'tr' + if par.is ':last-child' + tr = $ '' + img = $( '' ).attr( 'title', 'Remove?').attr 'src', 'red_cross_small.png' + cb = $( '' ).attr( 'type', 'checkbox' ).attr 'title', 'Password shielded input?' + inp = $( '' ).attr( 'type', 'text' ).attr 'class', 'textinput' + tr.append $( '' ).append img + tr.append $( '' ).append cb + tr.append $( '' ).append inp + par.parent().append tr + fChangeInputVisibility() + else if $( this ).val() is '' and not par.is ':only-child' + par.remove() - fChangeInputVisibility() + fChangeInputVisibility() window.addEventListener 'load', fOnLoad, true diff --git a/webpages/handlers/coffee/forge_action_invoker.coffee b/webpages/handlers/coffee/forge_action_invoker.coffee index 80e9f8b..15c6a4a 100644 --- a/webpages/handlers/coffee/forge_action_invoker.coffee +++ b/webpages/handlers/coffee/forge_action_invoker.coffee @@ -1,95 +1,95 @@ fOnLoad = () -> - document.title = 'Forge Action Invoker' - $( '#pagetitle' ).text "{{{user.username}}}, forge your custom action invoker!" + document.title = 'Forge Action Invoker' + $( '#pagetitle' ).text "{{{user.username}}}, forge your custom action invoker!" - # Setup the ACE editor - editor = ace.edit "editor" - editor.setTheme "ace/theme/monokai" - editor.getSession().setMode "ace/mode/coffee" - editor.setShowPrintMargin false - editor.session.setUseSoftTabs false - - $( '#editor_mode' ).change ( el ) -> - if $( this ).val() is 'CoffeeScript' - editor.getSession().setMode "ace/mode/coffee" - else - editor.getSession().setMode "ace/mode/javascript" - - # Add parameter list functionality - fChangeInputVisibility = () -> - $( '#tableParams tr' ).each ( id ) -> - if $( this ).is ':last-child' or $( this ).is ':only-child' - $( 'img', this ).hide() - $( 'input[type=checkbox]', this ).hide() - else - $( 'img', this ).show() - $( 'input[type=checkbox]', this ).show() + # Setup the ACE editor + editor = ace.edit "editor" + editor.setTheme "ace/theme/monokai" + editor.getSession().setMode "ace/mode/coffee" + editor.setShowPrintMargin false + editor.session.setUseSoftTabs false + + $( '#editor_mode' ).change ( el ) -> + if $( this ).val() is 'CoffeeScript' + editor.getSession().setMode "ace/mode/coffee" + else + editor.getSession().setMode "ace/mode/javascript" + + # Add parameter list functionality + fChangeInputVisibility = () -> + $( '#tableParams tr' ).each ( id ) -> + if $( this ).is ':last-child' or $( this ).is ':only-child' + $( 'img', this ).hide() + $( 'input[type=checkbox]', this ).hide() + else + $( 'img', this ).show() + $( 'input[type=checkbox]', this ).show() - $( '#tableParams' ).on 'click', 'img', () -> - par = $( this ).closest 'tr' - if not par.is ':last-child' - par.remove() - fChangeInputVisibility() + $( '#tableParams' ).on 'click', 'img', () -> + par = $( this ).closest 'tr' + if not par.is ':last-child' + par.remove() + fChangeInputVisibility() - $( '#tableParams' ).on 'keyup', 'input', ( e ) -> - code = e.keyCode or e.which - if code isnt 9 - par = $( this ).closest( 'tr' ) - if par.is ':last-child' - tr = $ '' - img = $( '' ).attr( 'title', 'Remove?').attr 'src', 'red_cross_small.png' - cb = $( '' ).attr( 'type', 'checkbox' ).attr 'title', 'Password shielded input?' - inp = $( '' ).attr( 'type', 'text' ).attr 'class', 'textinput' - tr.append( $( '' ).append img ) - tr.append( $( '' ).append cb ) - tr.append( $( '' ).append inp ) - par.parent().append tr - fChangeInputVisibility() - else if $( this ).val() is '' and not par.is ':only-child' - par.remove() + $( '#tableParams' ).on 'keyup', 'input', ( e ) -> + code = e.keyCode or e.which + if code isnt 9 + par = $( this ).closest( 'tr' ) + if par.is ':last-child' + tr = $ '' + img = $( '' ).attr( 'title', 'Remove?').attr 'src', 'red_cross_small.png' + cb = $( '' ).attr( 'type', 'checkbox' ).attr 'title', 'Password shielded input?' + inp = $( '' ).attr( 'type', 'text' ).attr 'class', 'textinput' + tr.append( $( '' ).append img ) + tr.append( $( '' ).append cb ) + tr.append( $( '' ).append inp ) + par.parent().append tr + fChangeInputVisibility() + else if $( this ).val() is '' and not par.is ':only-child' + par.remove() - fChangeInputVisibility() + fChangeInputVisibility() - # Add submit button logic - $( '#but_submit' ).click () -> - if $( '#input_id' ).val() is '' - alert 'Please enter an action invoker name!' - else - listParams = {} - $( '#tableParams tr' ).each () -> - val = $( 'input.textinput', this ).val() - shld = $( 'input[type=checkbox]', this ).is ':checked' - if val isnt "" - listParams[val] = shld - true - obj = - command: 'forge_action_invoker' - payload: - id: $( '#input_id' ).val() - lang: $( '#editor_mode' ).val() - public: $( '#is_public' ).is ':checked' - data: editor.getValue() - params: JSON.stringify listParams - obj.payload = JSON.stringify obj.payload - window.scrollTo 0, 0 - $.post( '/usercommand', obj ) - .done ( data ) -> - $( '#info' ).text data.message - $( '#info' ).attr 'class', 'success' - .fail ( err ) -> - if err.status is 401 - window.location.href = 'forge?page=forge_action_invoker' - else - 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' - setTimeout fDelayed, 500 + # Add submit button logic + $( '#but_submit' ).click () -> + if $( '#input_id' ).val() is '' + alert 'Please enter an action invoker name!' + else + listParams = {} + $( '#tableParams tr' ).each () -> + val = $( 'input.textinput', this ).val() + shld = $( 'input[type=checkbox]', this ).is ':checked' + if val isnt "" + listParams[val] = shld + true + obj = + command: 'forge_action_invoker' + payload: + id: $( '#input_id' ).val() + lang: $( '#editor_mode' ).val() + public: $( '#is_public' ).is ':checked' + data: editor.getValue() + params: JSON.stringify listParams + obj.payload = JSON.stringify obj.payload + window.scrollTo 0, 0 + $.post( '/usercommand', obj ) + .done ( data ) -> + $( '#info' ).text data.message + $( '#info' ).attr 'class', 'success' + .fail ( err ) -> + if err.status is 401 + window.location.href = 'forge?page=forge_action_invoker' + else + 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' + setTimeout fDelayed, 500 window.addEventListener 'load', fOnLoad, true diff --git a/webpages/handlers/coffee/forge_event.coffee b/webpages/handlers/coffee/forge_event.coffee index 568ba3a..9230a82 100644 --- a/webpages/handlers/coffee/forge_event.coffee +++ b/webpages/handlers/coffee/forge_event.coffee @@ -1,38 +1,38 @@ fOnLoad = () -> - document.title = 'Event Forge!' - $( '#pagetitle' ).text 'Invoke your custom event!' + document.title = 'Event Forge!' + $( '#pagetitle' ).text 'Invoke your custom event!' - editor = ace.edit "editor" - editor.setTheme "ace/theme/monokai" - editor.getSession().setMode "ace/mode/json" - editor.setShowPrintMargin false - $( '#editor' ).css 'height', '400px' - $( '#editor' ).css 'width', '600px' - - $( '#but_submit' ).click () -> - try - val = editor.getValue() - JSON.parse val # try to parse, throw an error if JSON not valid - window.scrollTo 0, 0 - $.post( '/event', val ) - .done ( data ) -> - $( '#info' ).text data.message - $( '#info' ).attr 'class', 'success' - .fail ( err ) -> - if err.status is 401 - window.location.href = 'forge?page=forge_event' - else - fDelayed = () -> - if err.responseText is '' - err.responseText = 'No Response from Server!' - $( '#info' ).text 'Error in upload: ' + err.responseText - $( '#info' ).attr 'class', 'error' - setTimeout fDelayed, 500 - - catch err - $( '#info' ).text 'You have errors in your JSON object! ' + err - $( '#info' ).attr 'class', 'error' - + editor = ace.edit "editor" + editor.setTheme "ace/theme/monokai" + editor.getSession().setMode "ace/mode/json" + editor.setShowPrintMargin false + $( '#editor' ).css 'height', '400px' + $( '#editor' ).css 'width', '600px' + + $( '#but_submit' ).click () -> + try + val = editor.getValue() + JSON.parse val # try to parse, throw an error if JSON not valid + window.scrollTo 0, 0 + $.post( '/event', val ) + .done ( data ) -> + $( '#info' ).text data.message + $( '#info' ).attr 'class', 'success' + .fail ( err ) -> + if err.status is 401 + window.location.href = 'forge?page=forge_event' + else + fDelayed = () -> + if err.responseText is '' + err.responseText = 'No Response from Server!' + $( '#info' ).text 'Error in upload: ' + err.responseText + $( '#info' ).attr 'class', 'error' + setTimeout fDelayed, 500 + + catch err + $( '#info' ).text 'You have errors in your JSON object! ' + err + $( '#info' ).attr 'class', 'error' + window.addEventListener 'load', fOnLoad, true diff --git a/webpages/handlers/coffee/forge_event_poller.coffee b/webpages/handlers/coffee/forge_event_poller.coffee index 026f211..9827841 100644 --- a/webpages/handlers/coffee/forge_event_poller.coffee +++ b/webpages/handlers/coffee/forge_event_poller.coffee @@ -1,95 +1,95 @@ fOnLoad = () -> - document.title = 'Forge Event Poller' - $( '#pagetitle' ).text "{{{user.username}}}, forge your custom event poller!" + document.title = 'Forge Event Poller' + $( '#pagetitle' ).text "{{{user.username}}}, forge your custom event poller!" - # Setup the ACE editor - editor = ace.edit "editor" - editor.setTheme "ace/theme/monokai" - editor.getSession().setMode "ace/mode/coffee" - editor.setShowPrintMargin false - - $( '#editor_mode' ).change ( el ) -> - if $( this ).val() is 'CoffeeScript' - editor.getSession().setMode "ace/mode/coffee" - else - editor.getSession().setMode "ace/mode/javascript" - - # Add parameter list functionality - fChangeInputVisibility = () -> - $( '#tableParams tr' ).each ( id ) -> - if $( this ).is ':last-child' or $( this ).is ':only-child' - $( 'img', this ).hide() - $( 'input[type=checkbox]', this ).hide() - else - $( 'img', this ).show() - $( 'input[type=checkbox]', this ).show() + # Setup the ACE editor + editor = ace.edit "editor" + editor.setTheme "ace/theme/monokai" + editor.getSession().setMode "ace/mode/coffee" + editor.setShowPrintMargin false + + $( '#editor_mode' ).change ( el ) -> + if $( this ).val() is 'CoffeeScript' + editor.getSession().setMode "ace/mode/coffee" + else + editor.getSession().setMode "ace/mode/javascript" + + # Add parameter list functionality + fChangeInputVisibility = () -> + $( '#tableParams tr' ).each ( id ) -> + if $( this ).is ':last-child' or $( this ).is ':only-child' + $( 'img', this ).hide() + $( 'input[type=checkbox]', this ).hide() + else + $( 'img', this ).show() + $( 'input[type=checkbox]', this ).show() - $( '#tableParams' ).on 'click', 'img', () -> - par = $( this ).closest 'tr' - if not par.is ':last-child' - par.remove() - fChangeInputVisibility() + $( '#tableParams' ).on 'click', 'img', () -> + par = $( this ).closest 'tr' + if not par.is ':last-child' + par.remove() + fChangeInputVisibility() - $( '#tableParams' ).on 'keyup', 'input', ( e ) -> - code = e.keyCode or e.which - if code isnt 9 - par = $( this ).closest( 'tr' ) - if par.is ':last-child' - tr = $ '' - img = $( '' ).attr( 'title', 'Remove?').attr 'src', 'red_cross_small.png' - cb = $( '' ).attr( 'type', 'checkbox' ).attr 'title', 'Password shielded input?' - inp = $( '' ).attr( 'type', 'text' ).attr 'class', 'textinput' - tr.append( $( '' ).append img ) - tr.append( $( '' ).append cb ) - tr.append( $( '' ).append inp ) - tr.append $( '' ) - par.parent().append tr - fChangeInputVisibility() - else if $( this ).val() is '' and not par.is ':only-child' - par.remove() + $( '#tableParams' ).on 'keyup', 'input', ( e ) -> + code = e.keyCode or e.which + if code isnt 9 + par = $( this ).closest( 'tr' ) + if par.is ':last-child' + tr = $ '' + img = $( '' ).attr( 'title', 'Remove?').attr 'src', 'red_cross_small.png' + cb = $( '' ).attr( 'type', 'checkbox' ).attr 'title', 'Password shielded input?' + inp = $( '' ).attr( 'type', 'text' ).attr 'class', 'textinput' + tr.append( $( '' ).append img ) + tr.append( $( '' ).append cb ) + tr.append( $( '' ).append inp ) + tr.append $( '' ) + par.parent().append tr + fChangeInputVisibility() + else if $( this ).val() is '' and not par.is ':only-child' + par.remove() - fChangeInputVisibility() + fChangeInputVisibility() - # Add submit button logic - $( '#but_submit' ).click () -> - if $( '#input_id' ).val() is '' - alert 'Please enter an event poller name!' - else - listParams = {} - $( '#tableParams tr' ).each () -> - val = $( 'input.textinput', this ).val() - shld = $( 'input[type=checkbox]', this ).is ':checked' - if val isnt "" - listParams[val] = shld - true - obj = - command: 'forge_event_poller' - payload: - id: $( '#input_id' ).val() - lang: $( '#editor_mode' ).val() - public: $( '#is_public' ).is ':checked' - data: editor.getValue() - params: JSON.stringify listParams - obj.payload = JSON.stringify obj.payload - window.scrollTo 0, 0 - $.post( '/usercommand', obj ) - .done ( data ) -> - $( '#info' ).text data.message - $( '#info' ).attr 'class', 'success' - .fail ( err ) -> - if err.status is 401 - window.location.href = 'forge?page=forge_event_poller' - else - 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' - setTimeout fDelayed, 500 + # Add submit button logic + $( '#but_submit' ).click () -> + if $( '#input_id' ).val() is '' + alert 'Please enter an event poller name!' + else + listParams = {} + $( '#tableParams tr' ).each () -> + val = $( 'input.textinput', this ).val() + shld = $( 'input[type=checkbox]', this ).is ':checked' + if val isnt "" + listParams[val] = shld + true + obj = + command: 'forge_event_poller' + payload: + id: $( '#input_id' ).val() + lang: $( '#editor_mode' ).val() + public: $( '#is_public' ).is ':checked' + data: editor.getValue() + params: JSON.stringify listParams + obj.payload = JSON.stringify obj.payload + window.scrollTo 0, 0 + $.post( '/usercommand', obj ) + .done ( data ) -> + $( '#info' ).text data.message + $( '#info' ).attr 'class', 'success' + .fail ( err ) -> + if err.status is 401 + window.location.href = 'forge?page=forge_event_poller' + else + 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' + setTimeout fDelayed, 500 window.addEventListener 'load', fOnLoad, true diff --git a/webpages/handlers/coffee/forge_rule.coffee b/webpages/handlers/coffee/forge_rule.coffee index d3a555e..0493b4d 100644 --- a/webpages/handlers/coffee/forge_rule.coffee +++ b/webpages/handlers/coffee/forge_rule.coffee @@ -1,280 +1,332 @@ strPublicKey = '' +fPlaceAndPaintInterval = () -> + $( '#input_interval' ).html 'Interval: + + "days hours:minutes", default = 10 minutes' + fFailedRequest = ( msg ) -> - ( err ) -> - if err.status is 401 - window.location.href = 'forge?page=forge_rule' - else - $( '#info' ).text msg - $( '#info' ).attr 'class', 'error' + ( err ) -> + if err.status is 401 + window.location.href = 'forge?page=forge_rule' + else + $( '#info' ).text msg + $( '#info' ).attr 'class', 'error' $.post( '/usercommand', command: 'get_public_key' ) - .done ( data ) -> - strPublicKey = data.message - .fail ( err ) -> - if err.status is 401 - window.location.href = 'forge?page=forge_rule' - else - $( '#info' ).text 'Error fetching public key, unable to send user specific parameters securely' - $( '#info' ).attr 'class', 'error' + .done ( data ) -> + strPublicKey = data.message + .fail ( err ) -> + if err.status is 401 + window.location.href = 'forge?page=forge_rule' + else + $( '#info' ).text 'Error fetching public key, unable to send user specific parameters securely' + $( '#info' ).attr 'class', 'error' fOnLoad = () -> - document.title = 'Rule Forge!' - $( '#pagetitle' ).text '{{{user.username}}}, forge your ECA Rule!' + document.title = 'Rule Forge!' + $( '#pagetitle' ).text '{{{user.username}}}, forge your ECA Rule!' - editor = ace.edit "editor_conditions" - editor.setTheme "ace/theme/monokai" - editor.getSession().setMode "ace/mode/json" - editor.setShowPrintMargin false - # editor.session.setUseSoftTabs false + editor = ace.edit "editor_conditions" + editor.setTheme "ace/theme/monokai" + editor.getSession().setMode "ace/mode/json" + editor.setShowPrintMargin false + # editor.session.setUseSoftTabs false - # Fetch Event Poller user-specific parameters - fFetchEventParams = ( name ) -> - 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 - oParams = JSON.parse data.message - $( '#event_poller_params table' ).remove() - table = $ '' - $( '#event_poller_params' ).append table - fAppendParam = ( name, shielded ) -> - tr = $( '' ) - tr.append $( '
' ).css 'width', '20px' - tr.append $( '' ).attr( 'class', 'key' ).text name - inp = $( '' ).attr 'id', "#{ name }" - if shielded - inp.attr( 'type', 'password' ) - tr.append $( '' ).text( ' : ' ).append inp - table.append tr - fAppendParam name, shielded for name, shielded of oParams - .fail fFailedRequest 'Error fetching event poller params' + # Fetch Event Poller user-specific parameters + fFetchEventParams = ( name ) -> + $( '#event_poller_params *' ).remove() + 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 + oParams = JSON.parse data.message + $( '#event_poller_params' ).html '
Required Parameters:' + table = $ '' + $( '#event_poller_params' ).append table + fAppendParam = ( name, shielded ) -> + tr = $( '' ) + tr.append $( '
' ).css 'width', '20px' + tr.append $( '' ).attr( 'class', 'key' ).text name + inp = $( '' ).attr 'id', "#{ name }" + if shielded + inp.attr( 'type', 'password' ) + tr.append $( '' ).text( ' : ' ).append inp + table.append tr + fAppendParam name, shielded for name, shielded of oParams + .fail fFailedRequest 'Error fetching event poller params' - # Init Event Pollers - $.post( '/usercommand', command: 'get_event_pollers' ) - .done ( data ) -> - try - oEps = JSON.parse data.message - catch err - console.error 'ERROR: non-object received from server: ' + data.message - return - - fAppendEvents = ( id, events ) -> - fAppendEvent = ( evt ) -> - $( '#select_event' ).append $( '