diff --git a/coffee/components-manager.coffee b/coffee/components-manager.coffee index 5129aa5..420d991 100644 --- a/coffee/components-manager.coffee +++ b/coffee/components-manager.coffee @@ -69,19 +69,17 @@ exports.addRuleListener = ( eh ) => ### 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 The callback function `callback( obj )` will receive an object containing the HTTP response code and a corresponding message. @public processRequest ( *user, oReq, callback* ) -@param {Object} user -@param {Object} oReq -@param {function} callback ### - exports.processRequest = ( user, oReq, callback ) -> if not oReq.payload oReq.payload = '{}' @@ -92,12 +90,21 @@ exports.processRequest = ( user, oReq, 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?' +### +Checks whether all required parameters are present in the payload. + +@private hasRequiredParams ( *arrParams, oPayload* ) +@param {Array} arrParams +@param {Object} oPayload +### hasRequiredParams = ( arrParams, oPayload ) -> answ = code: 400 @@ -107,6 +114,15 @@ hasRequiredParams = ( arrParams, oPayload ) -> answ.message = 'All required properties found' answ +### +Fetches all available modules and return them together with the available functions. + +@private getModules ( *user, oPayload, dbMod, callback* ) +@param {Object} user +@param {Object} oPayload +@param {Object} dbMod +@param {function} callback +### getModules = ( user, oPayload, dbMod, callback ) -> dbMod.getAvailableModuleIds user.username, ( err, arrNames ) -> oRes = {} @@ -218,6 +234,7 @@ commandFunctions = message: 'OK!' # A rule needs to be in following format: + # - id # - event # - conditions diff --git a/coffee/dynamic-modules.coffee b/coffee/dynamic-modules.coffee index 0d09fd2..770ced8 100644 --- a/coffee/dynamic-modules.coffee +++ b/coffee/dynamic-modules.coffee @@ -41,13 +41,6 @@ exports = module.exports = ( args ) => @strPublicKey = cryptico.publicKeyString @oPrivateRSAkey @log.info "DM | Public Key generated: #{ @strPublicKey }" - # plainText = "Matt, I need you to help me with my Starcraft strategy." - # oEncrypted = cryptico.encrypt plainText, strPublicKey - - # console.log oEncrypted.cipher - # oDecrypted = cryptico.decrypt oEncrypted.cipher, oPrivateRSAkey - # console.log oDecrypted.plaintext - module.exports diff --git a/coffee/engine.coffee b/coffee/engine.coffee index 2009ea0..c250ccc 100644 --- a/coffee/engine.coffee +++ b/coffee/engine.coffee @@ -22,21 +22,22 @@ 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 ### listUserRules = {} isRunning = false @@ -61,10 +62,11 @@ exports = module.exports = ( args ) => ### This is a helper function for the unit tests so we can verify that action modules are loaded correctly -#TODO we should change this to functions returning true or false rather than returning -#the whole list + @public getListUserRules () ### +#TODO we should change this to functions returning true or false rather than returning +#the whole list exports.getListUserRules = () -> listUserRules diff --git a/coffee/http-listener.coffee b/coffee/http-listener.coffee index 1b53b6b..4d91451 100644 --- a/coffee/http-listener.coffee +++ b/coffee/http-listener.coffee @@ -100,16 +100,15 @@ initRouting = ( port ) => @shutDownSystem() -# ### +# # Shuts down the http listener. # There's no way to gracefully stop express from running, thus we # call process.exit() at the very end of our existance. # ... but process.exit cancels the unit tests ... # thus we do it in the main module and use a cli flag for the unit tests -# @public shutDown() -# ### +# # exports.shutDown = () => -# @log?.warn 'HL | Shutting down HTTP listener' +# log?.warn 'HL | Shutting down HTTP listener' # console.log 'exiting...' # process.exit() diff --git a/coffee/request-handler.coffee b/coffee/request-handler.coffee index 275a8f6..1f65253 100644 --- a/coffee/request-handler.coffee +++ b/coffee/request-handler.coffee @@ -277,7 +277,7 @@ objects.* exports.handleAdmin = ( req, resp ) -> if not req.session.user page = 'login' - # TODO isAdmin should come from the db role + #TODO isAdmin should come from the db role else if req.session.user.isAdmin isnt "true" page = 'login' msg = 'You need to be admin!' diff --git a/coffee/webapi-eca.coffee b/coffee/webapi-eca.coffee index 9b178de..153412c 100644 --- a/coffee/webapi-eca.coffee +++ b/coffee/webapi-eca.coffee @@ -70,7 +70,8 @@ opt = 'm': alias : 'log-mode', describe: 'Specify a log mode: [development|productive]' -# `-i`, `--log-io-level`: Specify the log level for the I/O +# `-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' @@ -151,17 +152,19 @@ init = => # 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] - 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: null else - args.logconf['nolog'] + # - 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: null else + args.logconf[ 'nolog' ] ] poller = cp.fork path.resolve( __dirname, nameEP ), cliArgs diff --git a/js/components-manager.js b/js/components-manager.js index 1bf7015..25d800f 100644 --- a/js/components-manager.js +++ b/js/components-manager.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Components Manager @@ -6,12 +7,10 @@ Components Manager > The components manager takes care of the dynamic JS modules and the rules. > Event Poller and Action Invoker modules are loaded as strings and stored in the database, > then compiled into node modules and rules and used in the engine and event poller. -*/ - + */ (function() { - var commandFunctions, db, dynmod, eventEmitter, events, exports, forgeModule, fs, getModuleParams, getModules, hasRequiredParams, path, - _this = this; + var commandFunctions, db, dynmod, eventEmitter, events, exports, forgeModule, fs, getModuleParams, getModules, hasRequiredParams, path; db = require('./persistence'); @@ -25,77 +24,81 @@ Components Manager eventEmitter = new events.EventEmitter(); + /* Module call ----------- Initializes the Components Manager and constructs a new Event Emitter. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + _this.log = args.logger; + db(args); + dynmod(args); + return module.exports; + }; + })(this); - exports = module.exports = function(args) { - _this.log = args.logger; - db(args); - dynmod(args); - return module.exports; - }; /* Add an event handler (eh) that listens for rules. @public addRuleListener ( *eh* ) @param {function} eh - */ + */ - - exports.addRuleListener = function(eh) { - eventEmitter.addListener('rule', eh); - return db.getAllActivatedRuleIdsPerUser(function(err, objUsers) { - var fGoThroughUsers, rules, user, _results; - fGoThroughUsers = function(user, rules) { - var fFetchRule, rule, _i, _len, _results; - fFetchRule = function(rule) { - var _this = this; - return db.getRule(rule, function(err, oRule) { - return eventEmitter.emit('rule', { - event: 'init', - user: user, - rule: JSON.parse(oRule) - }); - }); + exports.addRuleListener = (function(_this) { + return function(eh) { + eventEmitter.addListener('rule', eh); + return db.getAllActivatedRuleIdsPerUser(function(err, objUsers) { + var fGoThroughUsers, rules, user, _results; + fGoThroughUsers = function(user, rules) { + var fFetchRule, rule, _i, _len, _results; + fFetchRule = function(rule) { + return db.getRule(rule, (function(_this) { + return function(err, oRule) { + return eventEmitter.emit('rule', { + event: 'init', + user: user, + rule: JSON.parse(oRule) + }); + }; + })(this)); + }; + _results = []; + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + _results.push(fFetchRule(rule)); + } + return _results; }; _results = []; - for (_i = 0, _len = rules.length; _i < _len; _i++) { - rule = rules[_i]; - _results.push(fFetchRule(rule)); + for (user in objUsers) { + rules = objUsers[user]; + _results.push(fGoThroughUsers(user, rules)); } return _results; - }; - _results = []; - for (user in objUsers) { - rules = objUsers[user]; - _results.push(fGoThroughUsers(user, rules)); - } - return _results; - }); - }; + }); + }; + })(this); + /* 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 The callback function `callback( obj )` will receive an object containing the HTTP response code and a corresponding message. @public processRequest ( *user, oReq, callback* ) - @param {Object} user - @param {Object} oReq - @param {function} callback - */ - + */ exports.processRequest = function(user, oReq, callback) { var dat, err; @@ -121,6 +124,15 @@ Components Manager } }; + + /* + Checks whether all required parameters are present in the payload. + + @private hasRequiredParams ( *arrParams, oPayload* ) + @param {Array} arrParams + @param {Object} oPayload + */ + hasRequiredParams = function(arrParams, oPayload) { var answ, param, _i, _len; answ = { @@ -138,10 +150,20 @@ Components Manager return answ; }; + + /* + Fetches all available modules and return them together with the available functions. + + @private getModules ( *user, oPayload, dbMod, callback* ) + @param {Object} user + @param {Object} oPayload + @param {Object} dbMod + @param {function} callback + */ + getModules = function(user, oPayload, dbMod, callback) { return dbMod.getAvailableModuleIds(user.username, function(err, arrNames) { - var answReq, fGetFunctions, id, oRes, sem, _i, _len, _results, - _this = this; + var answReq, fGetFunctions, id, oRes, sem, _i, _len, _results; oRes = {}; answReq = function() { return callback({ @@ -153,16 +175,18 @@ Components Manager if (sem === 0) { return answReq(); } else { - fGetFunctions = function(id) { - return dbMod.getModule(id, function(err, oModule) { - if (oModule) { - oRes[id] = JSON.parse(oModule.functions); - } - if (--sem === 0) { - return answReq(); - } - }); - }; + fGetFunctions = (function(_this) { + return function(id) { + return dbMod.getModule(id, function(err, oModule) { + if (oModule) { + oRes[id] = JSON.parse(oModule.functions); + } + if (--sem === 0) { + return answReq(); + } + }); + }; + })(this); _results = []; for (_i = 0, _len = arrNames.length; _i < _len; _i++) { id = arrNames[_i]; @@ -186,44 +210,46 @@ Components Manager } }; - forgeModule = function(user, oPayload, dbMod, callback) { - var answ; - answ = hasRequiredParams(['id', 'params', 'lang', 'data'], oPayload); - if (answ.code !== 200) { - return callback(answ); - } else { - return dbMod.getModule(oPayload.id, function(err, mod) { - var src; - if (mod) { - answ.code = 409; - answ.message = 'Module name already existing: ' + oPayload.id; - return callback(answ); - } else { - src = oPayload.data; - return dynmod.compileString(src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, function(cm) { - var funcs, id, name, _ref; - answ = cm.answ; - if (answ.code === 200) { - funcs = []; - _ref = cm.module; - for (name in _ref) { - id = _ref[name]; - funcs.push(name); - } - _this.log.info("CM | Storing new module with functions " + (funcs.join())); - answ.message = "Event Poller module successfully stored! Found following function(s): " + funcs; - oPayload.functions = JSON.stringify(funcs); - dbMod.storeModule(user.username, oPayload); - if (oPayload["public"] === 'true') { - dbMod.publish(oPayload.id); - } - } + forgeModule = (function(_this) { + return function(user, oPayload, dbMod, callback) { + var answ; + answ = hasRequiredParams(['id', 'params', 'lang', 'data'], oPayload); + if (answ.code !== 200) { + return callback(answ); + } else { + return dbMod.getModule(oPayload.id, function(err, mod) { + var src; + if (mod) { + answ.code = 409; + answ.message = 'Module name already existing: ' + oPayload.id; return callback(answ); - }); - } - }); - } - }; + } else { + src = oPayload.data; + return dynmod.compileString(src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, function(cm) { + var funcs, id, name, _ref; + answ = cm.answ; + if (answ.code === 200) { + funcs = []; + _ref = cm.module; + for (name in _ref) { + id = _ref[name]; + funcs.push(name); + } + _this.log.info("CM | Storing new module with functions " + (funcs.join())); + answ.message = "Event Poller module successfully stored! Found following function(s): " + funcs; + oPayload.functions = JSON.stringify(funcs); + dbMod.storeModule(user.username, oPayload); + if (oPayload["public"] === 'true') { + dbMod.publish(oPayload.id); + } + } + return callback(answ); + }); + } + }); + } + }; + })(this); commandFunctions = { get_public_key: function(user, oPayload, callback) { diff --git a/js/config.js b/js/config.js index 4c48e7a..e984a2e 100644 --- a/js/config.js +++ b/js/config.js @@ -1,20 +1,20 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Configuration ============= > Loads the configuration file and acts as an interface to it. -*/ - + */ (function() { - var exports, fetchProp, fs, loadConfigFile, path, - _this = this; + var exports, fetchProp, fs, loadConfigFile, path; fs = require('fs'); path = require('path'); + /* Module call ----------- @@ -24,21 +24,23 @@ Configuration be generated) and configPath for a custom configuration file path. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + args = args != null ? args : {}; + if (args.nolog) { + _this.nolog = true; + } + if (args.configPath) { + loadConfigFile(args.configPath); + } else { + loadConfigFile(path.join('config', 'system.json')); + } + return module.exports; + }; + })(this); - exports = module.exports = function(args) { - args = args != null ? args : {}; - if (args.nolog) { - _this.nolog = true; - } - if (args.configPath) { - loadConfigFile(args.configPath); - } else { - loadConfigFile(path.join('config', 'system.json')); - } - return module.exports; - }; /* Tries to load a configuration file from the path relative to this module's parent folder. @@ -46,97 +48,102 @@ Configuration @private loadConfigFile @param {String} configPath - */ + */ - - loadConfigFile = function(configPath) { - var confProperties, e, prop, _i, _len; - _this.config = null; - confProperties = ['log', 'http-port', 'db-port']; - try { - _this.config = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', configPath))); - _this.isReady = true; - for (_i = 0, _len = confProperties.length; _i < _len; _i++) { - prop = confProperties[_i]; - if (!_this.config[prop]) { - _this.isReady = false; + loadConfigFile = (function(_this) { + return function(configPath) { + var confProperties, e, prop, _i, _len; + _this.config = null; + confProperties = ['log', 'http-port', 'db-port']; + try { + _this.config = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', configPath))); + _this.isReady = true; + for (_i = 0, _len = confProperties.length; _i < _len; _i++) { + prop = confProperties[_i]; + if (!_this.config[prop]) { + _this.isReady = false; + } + } + if (!_this.isReady && !_this.nolog) { + return console.error("Missing property in config file, requires:\n" + (" - " + (confProperties.join("\n - ")))); + } + } catch (_error) { + e = _error; + _this.isReady = false; + if (!_this.nolog) { + return console.error("Failed loading config file: " + e.message); } } - if (!_this.isReady && !_this.nolog) { - return console.error("Missing property in config file, requires:\n" + (" - " + (confProperties.join("\n - ")))); - } - } catch (_error) { - e = _error; - _this.isReady = false; - if (!_this.nolog) { - return console.error("Failed loading config file: " + e.message); - } - } - }; + }; + })(this); + /* Fetch a property from the configuration @private fetchProp( *prop* ) @param {String} prop - */ + */ + fetchProp = (function(_this) { + return function(prop) { + var _ref; + return (_ref = _this.config) != null ? _ref[prop] : void 0; + }; + })(this); - fetchProp = function(prop) { - var _ref; - return (_ref = _this.config) != null ? _ref[prop] : void 0; - }; /* ***Returns*** true if the config file is ready, else false @public isReady() - */ + */ + exports.isReady = (function(_this) { + return function() { + return _this.isReady; + }; + })(this); - exports.isReady = function() { - return _this.isReady; - }; /* ***Returns*** the HTTP port @public getHttpPort() - */ - + */ exports.getHttpPort = function() { return fetchProp('http-port'); }; + /* ***Returns*** the DB port* @public getDBPort() - */ - + */ exports.getDbPort = function() { return fetchProp('db-port'); }; + /* ***Returns*** the log conf object @public getLogConf() - */ - + */ exports.getLogConf = function() { return fetchProp('log'); }; + /* ***Returns*** the crypto key @public getCryptoKey() - */ - + */ exports.getKeygenPassphrase = function() { return fetchProp('keygen-passphrase'); diff --git a/js/dynamic-modules.js b/js/dynamic-modules.js index 3291020..543f47f 100644 --- a/js/dynamic-modules.js +++ b/js/dynamic-modules.js @@ -1,16 +1,15 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Dynamic Modules =============== > Compiles CoffeeScript modules and loads JS modules in a VM, together > with only a few allowed node.js modules. -*/ - + */ (function() { - var cryptico, cs, db, exports, issueApiCall, needle, vm, - _this = this; + var cryptico, cs, db, exports, issueApiCall, needle, vm; db = require('./persistence'); @@ -22,53 +21,60 @@ Dynamic Modules cryptico = require('my-cryptico'); + /* Module call ----------- Initializes the dynamic module handler. @param {Object} args - */ + */ - - exports = module.exports = function(args) { - var numBits, passPhrase; - _this.log = args.logger; - if (!_this.strPublicKey && args['keygen']) { - db(args); - passPhrase = args['keygen']; - numBits = 1024; - _this.oPrivateRSAkey = cryptico.generateRSAKey(passPhrase, numBits); - _this.strPublicKey = cryptico.publicKeyString(_this.oPrivateRSAkey); - _this.log.info("DM | Public Key generated: " + _this.strPublicKey); - } - return module.exports; - }; - - exports.getPublicKey = function() { - return _this.strPublicKey; - }; - - issueApiCall = function(method, url, credentials, cb) { - var err, func; - try { - if (method === 'get') { - func = needle.get; - } else { - func = needle.post; + exports = module.exports = (function(_this) { + return function(args) { + var numBits, passPhrase; + _this.log = args.logger; + if (!_this.strPublicKey && args['keygen']) { + db(args); + passPhrase = args['keygen']; + numBits = 1024; + _this.oPrivateRSAkey = cryptico.generateRSAKey(passPhrase, numBits); + _this.strPublicKey = cryptico.publicKeyString(_this.oPrivateRSAkey); + _this.log.info("DM | Public Key generated: " + _this.strPublicKey); } - return func(url, credentials, function(err, resp, body) { - if (!err) { - return cb(body); + return module.exports; + }; + })(this); + + exports.getPublicKey = (function(_this) { + return function() { + return _this.strPublicKey; + }; + })(this); + + issueApiCall = (function(_this) { + return function(method, url, credentials, cb) { + var err, func; + try { + if (method === 'get') { + func = needle.get; } else { - return cb(); + func = needle.post; } - }); - } catch (_error) { - err = _error; - return _this.log.info('DM | Error even before calling!'); - } - }; + return func(url, credentials, function(err, resp, body) { + if (!err) { + return cb(body); + } else { + return cb(); + } + }); + } catch (_error) { + err = _error; + return _this.log.info('DM | Error even before calling!'); + } + }; + })(this); + /* Try to run a JS module from a string, together with the @@ -80,71 +86,72 @@ Dynamic Modules @param {String} id @param {Object} params @param {String} lang - */ + */ - - exports.compileString = function(src, userId, ruleId, modId, lang, dbMod, cb) { - var answ, err, fTryToLoad, logFunction; - answ = { - code: 200, - message: 'Successfully compiled' - }; - if (lang === 'CoffeeScript') { - try { - src = cs.compile(src); - } catch (_error) { - err = _error; - answ.code = 400; - answ.message = 'Compilation of CoffeeScript failed at line ' + err.location.first_line; - } - } - logFunction = function(uId, rId, mId) { - return function(msg) { - return db.appendLog(uId, rId, mId, msg); + exports.compileString = (function(_this) { + return function(src, userId, ruleId, modId, lang, dbMod, cb) { + var answ, err, fTryToLoad, logFunction; + answ = { + code: 200, + message: 'Successfully compiled' }; - }; - db.resetLog(userId, ruleId); - fTryToLoad = function(params) { - var oDecrypted, sandbox; - if (params) { + if (lang === 'CoffeeScript') { try { - oDecrypted = cryptico.decrypt(params, _this.oPrivateRSAkey); - params = JSON.parse(oDecrypted.plaintext); + src = cs.compile(src); } catch (_error) { err = _error; - _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + ruleId + ", " + modId); + answ.code = 400; + answ.message = 'Compilation of CoffeeScript failed at line ' + err.location.first_line; + } + } + logFunction = function(uId, rId, mId) { + return function(msg) { + return db.appendLog(uId, rId, mId, msg); + }; + }; + db.resetLog(userId, ruleId); + fTryToLoad = function(params) { + var oDecrypted, sandbox; + if (params) { + try { + oDecrypted = cryptico.decrypt(params, _this.oPrivateRSAkey); + params = JSON.parse(oDecrypted.plaintext); + } catch (_error) { + err = _error; + _this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + ruleId + ", " + modId); + params = {}; + } + } else { params = {}; } - } else { - params = {}; - } - sandbox = { - id: userId + '.' + modId + '.vm', - params: params, - apicall: issueApiCall, - log: logFunction(userId, ruleId, modId), - exports: {} + sandbox = { + id: userId + '.' + modId + '.vm', + params: params, + apicall: issueApiCall, + log: logFunction(userId, ruleId, modId), + exports: {} + }; + try { + vm.runInNewContext(src, sandbox, sandbox.id); + } catch (_error) { + err = _error; + console.log(err); + answ.code = 400; + answ.message = 'Loading Module failed: ' + err.message; + } + return cb({ + answ: answ, + module: sandbox.exports + }); }; - try { - vm.runInNewContext(src, sandbox, sandbox.id); - } catch (_error) { - err = _error; - console.log(err); - answ.code = 400; - answ.message = 'Loading Module failed: ' + err.message; + if (dbMod) { + return dbMod.getUserParams(modId, userId, function(err, obj) { + return fTryToLoad(obj); + }); + } else { + return fTryToLoad(); } - return cb({ - answ: answ, - module: sandbox.exports - }); }; - if (dbMod) { - return dbMod.getUserParams(modId, userId, function(err, obj) { - return fTryToLoad(obj); - }); - } else { - return fTryToLoad(); - } - }; + })(this); }).call(this); diff --git a/js/engine.js b/js/engine.js index 94e82f9..ae7cea1 100644 --- a/js/engine.js +++ b/js/engine.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Engine @@ -6,12 +7,10 @@ Engine > The heart of the WebAPI ECA System. The engine loads action invoker modules > corresponding to active rules actions and invokes them if an appropriate event > is retrieved. -*/ - + */ (function() { - var db, dynmod, exports, isRunning, jsonQuery, listUserRules, pollQueue, processEvent, updateActionModules, validConditions, - _this = this; + var db, dynmod, exports, isRunning, jsonQuery, listUserRules, pollQueue, processEvent, updateActionModules, validConditions; db = require('./persistence'); @@ -19,94 +18,99 @@ Engine jsonQuery = require('js-select'); + /* This is ging to have a structure like: An object of users with their active rules and the required action modules - "user-1": - "rule-1": - "rule": oRule-1 - "actions": - "action-1": oAction-1 - "action-2": oAction-2 - "rule-2": - "rule": oRule-2 - "actions": - "action-1": oAction-1 - "user-2": - "rule-3": - "rule": oRule-3 - "actions": - "action-3": oAction-3 - */ - + + "user-1": + "rule-1": + "rule": oRule-1 + "actions": + "action-1": oAction-1 + "action-2": oAction-2 + "rule-2": + "rule": oRule-2 + "actions": + "action-1": oAction-1 + "user-2": + "rule-3": + "rule": oRule-3 + "actions": + "action-3": oAction-3 + */ listUserRules = {}; isRunning = false; + /* Module call ----------- Initializes the Engine and starts polling the event queue for new events. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + if (!isRunning) { + isRunning = true; + _this.log = args.logger; + db(args); + dynmod(args); + setTimeout(pollQueue, 10); + return module.exports; + } + }; + })(this); - exports = module.exports = function(args) { - if (!isRunning) { - isRunning = true; - _this.log = args.logger; - db(args); - dynmod(args); - setTimeout(pollQueue, 10); - return module.exports; - } - }; /* This is a helper function for the unit tests so we can verify that action modules are loaded correctly - #TODO we should change this to functions returning true or false rather than returning - #the whole list + @public getListUserRules () - */ - + */ exports.getListUserRules = function() { return listUserRules; }; + /* An event associated to rules happened and is captured here. Such events are basically CRUD on rules. @public internalEvent ( *evt* ) @param {Object} evt - */ + */ + exports.internalEvent = (function(_this) { + return function(evt) { + var oRule, oUser; + if (!listUserRules[evt.user] && evt.event !== 'del') { + listUserRules[evt.user] = {}; + } + oUser = listUserRules[evt.user]; + oRule = evt.rule; + if (evt.event === 'new' || (evt.event === 'init' && !oUser[oRule.id])) { + oUser[oRule.id] = { + rule: oRule, + actions: {} + }; + updateActionModules(oRule.id); + } + if (evt.event === 'del' && oUser) { + delete oUser[evt.ruleId]; + } + if (JSON.stringify(oUser) === "{}") { + return delete listUserRules[evt.user]; + } + }; + })(this); - exports.internalEvent = function(evt) { - var oRule, oUser; - if (!listUserRules[evt.user] && evt.event !== 'del') { - listUserRules[evt.user] = {}; - } - oUser = listUserRules[evt.user]; - oRule = evt.rule; - if (evt.event === 'new' || (evt.event === 'init' && !oUser[oRule.id])) { - oUser[oRule.id] = { - rule: oRule, - actions: {} - }; - updateActionModules(oRule.id); - } - if (evt.event === 'del' && oUser) { - delete oUser[evt.ruleId]; - } - if (JSON.stringify(oUser) === "{}") { - return delete listUserRules[evt.user]; - } - }; /* As soon as changes were made to the rule set we need to ensure that the aprropriate action @@ -114,8 +118,7 @@ Engine @private updateActionModules ( *updatedRuleId* ) @param {Object} updatedRuleId - */ - + */ updateActionModules = function(updatedRuleId) { var fAddRequired, fRemoveNotRequired, name, oUser, userName, _results; @@ -157,7 +160,7 @@ Engine 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); + this.log.error("EN | Compilation of code failed! " + userName + ", " + oMyRule.rule.id + ", " + moduleName); } return oMyRule.actions[moduleName] = result.module; }); @@ -198,14 +201,14 @@ Engine } }; + /* Checks whether all conditions of the rule are met by the event. @private validConditions ( *evt, rule* ) @param {Object} evt @param {Object} rule - */ - + */ validConditions = function(evt, rule) { var prop, _i, _len, _ref; @@ -222,64 +225,66 @@ Engine return true; }; + /* Handles retrieved events. @private processEvent ( *evt* ) @param {Object} evt - */ + */ - - processEvent = function(evt) { - var action, arr, fSearchAndInvokeAction, oMyRule, oUser, ruleName, userName, _results; - fSearchAndInvokeAction = function(node, arrPath, evt, depth) { - var err; - if (!node) { - this.log.error("EN | Didn't find property in user rule list: " + arrPath.join(', ' + " at depth " + depth)); - return; - } - if (depth === arrPath.length) { - try { - return node(evt.payload); - } catch (_error) { - err = _error; - return this.log.info("EN | ERROR IN ACTION INVOKER: " + err.message); + processEvent = (function(_this) { + return function(evt) { + var action, arr, fSearchAndInvokeAction, oMyRule, oUser, ruleName, userName, _results; + fSearchAndInvokeAction = function(node, arrPath, evt, depth) { + var err; + if (!node) { + this.log.error("EN | Didn't find property in user rule list: " + arrPath.join(', ' + " at depth " + depth)); + return; } - } else { - return fSearchAndInvokeAction(node[arrPath[depth]], arrPath, evt, depth + 1); - } - }; - _this.log.info('EN | processing event: ' + evt.event + '(' + evt.eventid + ')'); - _results = []; - for (userName in listUserRules) { - oUser = listUserRules[userName]; - _results.push((function() { - var _results1; - _results1 = []; - for (ruleName in oUser) { - oMyRule = oUser[ruleName]; - if (evt.event === oMyRule.rule.event && validConditions(evt, oMyRule.rule)) { - this.log.info('EN | EVENT FIRED: ' + evt.event + '(' + evt.eventid + ') for rule ' + ruleName); - _results1.push((function() { - var _i, _len, _ref, _results2; - _ref = oMyRule.rule.actions; - _results2 = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - action = _ref[_i]; - arr = action.split(' -> '); - _results2.push(fSearchAndInvokeAction(listUserRules, [userName, ruleName, 'actions', arr[0], arr[1]], evt, 0)); - } - return _results2; - })()); - } else { - _results1.push(void 0); + if (depth === arrPath.length) { + try { + return node(evt.payload); + } catch (_error) { + err = _error; + return this.log.info("EN | ERROR IN ACTION INVOKER: " + err.message); } + } else { + return fSearchAndInvokeAction(node[arrPath[depth]], arrPath, evt, depth + 1); } - return _results1; - }).call(_this)); - } - return _results; - }; + }; + _this.log.info('EN | processing event: ' + evt.event + '(' + evt.eventid + ')'); + _results = []; + for (userName in listUserRules) { + oUser = listUserRules[userName]; + _results.push((function() { + var _results1; + _results1 = []; + for (ruleName in oUser) { + oMyRule = oUser[ruleName]; + if (evt.event === oMyRule.rule.event && validConditions(evt, oMyRule.rule)) { + this.log.info('EN | EVENT FIRED: ' + evt.event + '(' + evt.eventid + ') for rule ' + ruleName); + _results1.push((function() { + var _i, _len, _ref, _results2; + _ref = oMyRule.rule.actions; + _results2 = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + action = _ref[_i]; + arr = action.split(' -> '); + _results2.push(fSearchAndInvokeAction(listUserRules, [userName, ruleName, 'actions', arr[0], arr[1]], evt, 0)); + } + return _results2; + })()); + } else { + _results1.push(void 0); + } + } + return _results1; + }).call(_this)); + } + return _results; + }; + })(this); exports.shutDown = function() { return isRunning = false; diff --git a/js/event-poller.js b/js/event-poller.js index 3922e1b..9b4121e 100644 --- a/js/event-poller.js +++ b/js/event-poller.js @@ -1,12 +1,12 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Dynamic Modules =============== > Compiles CoffeeScript modules and loads JS modules in a VM, together > with only a few allowed node.js modules. -*/ - + */ (function() { var db, dynmod, fLoadModule, isRunning, listUserModules, log, logconf, logger, pollLoop; @@ -77,7 +77,7 @@ Dynamic Modules } else { return dynmod.compileString(obj.data, msg.user, msg.rule.id, arrName[0], obj.lang, db.eventPollers, function(result) { if (!result.answ === 200) { - log.error("EP | Compilation of code failed! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]); + log.error("EP | Compilation of code failed! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]); } if (!listUserModules[msg.user]) { listUserModules[msg.user] = {}; @@ -87,7 +87,7 @@ Dynamic Modules pollfunc: arrName[1], module: result.module }; - return log.info("EP | New event module loaded! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]); + return log.info("EP | New event module loaded! " + msg.user + ", " + msg.rule.id + ", " + arrName[0]); }); } }); @@ -97,12 +97,12 @@ Dynamic Modules } }; + /* This function will loop infinitely every 10 seconds until isRunning is set to false @private pollLoop() - */ - + */ pollLoop = function() { var err, fPoll, fRegisterModuleReference, myRule, oRules, ruleName, userName; diff --git a/js/http-listener.js b/js/http-listener.js index ba133cc..aa686b2 100644 --- a/js/http-listener.js +++ b/js/http-listener.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* HTTP Listener @@ -6,12 +7,10 @@ HTTP Listener > Receives the HTTP requests to the server at the given port. The requests > (bound to a method) are then redirected to the appropriate handler which > takes care of the request. -*/ - + */ (function() { - var app, exports, express, initRouting, path, qs, requestHandler, - _this = this; + var app, exports, express, initRouting, path, qs, requestHandler; requestHandler = require('./request-handler'); @@ -23,73 +22,77 @@ HTTP Listener app = express(); + /* Module call ----------- Initializes the HTTP listener and its request handler. @param {Object} args - */ + */ + exports = module.exports = (function(_this) { + return function(args) { + _this.log = args.logger; + _this.shutDownSystem = args['shutdown-function']; + requestHandler(args); + initRouting(args['http-port']); + return module.exports; + }; + })(this); - exports = module.exports = function(args) { - _this.log = args.logger; - _this.shutDownSystem = args['shutdown-function']; - requestHandler(args); - initRouting(args['http-port']); - return module.exports; - }; /* Initializes the request routing and starts listening on the given port. @param {int} port @private initRouting( *fShutDown* ) - */ + */ + initRouting = (function(_this) { + return function(port) { + var server, sess_sec; + app.use(express.cookieParser()); + sess_sec = "149u*y8C:@kmN/520Gt\\v'+KFBnQ!\\r<>5X/xRI`sT 'action-invokers' and then stored in the db with the key 'action-invoker:' + ID > (e.g. action-invoker:probinder). > -*/ - + */ (function() { var IndexedModules, exports, getSetRecords, redis, replyHandler, - _this = this, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; redis = require('redis'); + /* Module call ----------- Initializes the DB connection with the given `db-port` property in the `args` object. @param {Object} args - */ + */ - - exports = module.exports = function(args) { - if (!_this.db) { - if (!args['db-port']) { - args['db-port'] = 6379; + exports = module.exports = (function(_this) { + return function(args) { + if (!_this.db) { + if (!args['db-port']) { + args['db-port'] = 6379; + } + _this.log = args.logger; + exports.eventPollers = new IndexedModules('event-poller', _this.log); + exports.actionInvokers = new IndexedModules('action-invoker', _this.log); + return exports.initPort(args['db-port']); } - _this.log = args.logger; - exports.eventPollers = new IndexedModules('event-poller', _this.log); - exports.actionInvokers = new IndexedModules('action-invoker', _this.log); - return exports.initPort(args['db-port']); - } - }; + }; + })(this); - exports.getLogger = function() { - return _this.log; - }; + exports.getLogger = (function(_this) { + return function() { + return _this.log; + }; + })(this); - exports.initPort = function(port) { - var _ref; - _this.connRefused = false; - if ((_ref = _this.db) != null) { - _ref.quit(); - } - _this.db = redis.createClient(port, 'localhost', { - connect_timeout: 2000 - }); - _this.db.on('error', function(err) { - if (err.message.indexOf('ECONNREFUSED') > -1) { - _this.connRefused = true; - return _this.log.error(err, 'DB | Wrong port?'); + exports.initPort = (function(_this) { + return function(port) { + var _ref; + _this.connRefused = false; + if ((_ref = _this.db) != null) { + _ref.quit(); } - }); - exports.eventPollers.setDB(_this.db); - return exports.actionInvokers.setDB(_this.db); - }; + _this.db = redis.createClient(port, 'localhost', { + connect_timeout: 2000 + }); + _this.db.on('error', function(err) { + if (err.message.indexOf('ECONNREFUSED') > -1) { + _this.connRefused = true; + return _this.log.error(err, 'DB | Wrong port?'); + } + }); + exports.eventPollers.setDB(_this.db); + return exports.actionInvokers.setDB(_this.db); + }; + })(this); + /* Checks whether the db is connected and passes either an error on failure after @@ -78,104 +84,114 @@ Persistence @public isConnected( *cb* ) @param {function} cb - */ + */ - - exports.isConnected = function(cb) { - var fCheckConnection, numAttempts; - if (!_this.db) { - return cb(new Error('DB | DB initialization did not occur or failed miserably!')); - } else { - if (_this.db.connected) { - return cb(); + exports.isConnected = (function(_this) { + return function(cb) { + var fCheckConnection, numAttempts; + if (!_this.db) { + return cb(new Error('DB | DB initialization did not occur or failed miserably!')); } else { - numAttempts = 0; - fCheckConnection = function() { - var _ref; - if (_this.connRefused) { - if ((_ref = _this.db) != null) { - _ref.quit(); - } - return cb(new Error('DB | Connection refused! Wrong port?')); - } else { - if (_this.db.connected) { - _this.log.info('DB | Successfully connected to DB!'); - return cb(); - } else if (numAttempts++ < 10) { - return setTimeout(fCheckConnection, 100); + if (_this.db.connected) { + return cb(); + } else { + numAttempts = 0; + fCheckConnection = function() { + var _ref; + if (_this.connRefused) { + if ((_ref = _this.db) != null) { + _ref.quit(); + } + return cb(new Error('DB | Connection refused! Wrong port?')); } else { - return cb(new Error('DB | Connection to DB failed!')); + if (_this.db.connected) { + _this.log.info('DB | Successfully connected to DB!'); + return cb(); + } else if (numAttempts++ < 10) { + return setTimeout(fCheckConnection, 100); + } else { + return cb(new Error('DB | Connection to DB failed!')); + } } - } - }; - return setTimeout(fCheckConnection, 100); + }; + return setTimeout(fCheckConnection, 100); + } } - } - }; + }; + })(this); + /* Abstracts logging for simple action replies from the DB. @private replyHandler( *action* ) @param {String} action - */ + */ - - replyHandler = function(action) { - return function(err, reply) { - if (err) { - return _this.log.warn(err, "during '" + action + "'"); - } else { - return _this.log.info("DB | " + action + ": " + reply); - } + replyHandler = (function(_this) { + return function(action) { + return function(err, reply) { + if (err) { + return _this.log.warn(err, "during '" + action + "'"); + } else { + return _this.log.info("DB | " + action + ": " + reply); + } + }; }; - }; + })(this); + /* Push an event into the event queue. @public pushEvent( *oEvent* ) @param {Object} oEvent - */ + */ + exports.pushEvent = (function(_this) { + return function(oEvent) { + if (oEvent) { + _this.log.info("DB | Event pushed into the queue: '" + oEvent.eventid + "'"); + return _this.db.rpush('event_queue', JSON.stringify(oEvent)); + } else { + return _this.log.warn('DB | Why would you give me an empty event...'); + } + }; + })(this); - exports.pushEvent = function(oEvent) { - if (oEvent) { - _this.log.info("DB | Event pushed into the queue: '" + oEvent.eventid + "'"); - return _this.db.rpush('event_queue', JSON.stringify(oEvent)); - } else { - return _this.log.warn('DB | Why would you give me an empty event...'); - } - }; /* Pop an event from the event queue and pass it to cb(err, obj). @public popEvent( *cb* ) @param {function} cb - */ + */ - - exports.popEvent = function(cb) { - var makeObj; - makeObj = function(pcb) { - return function(err, obj) { - return pcb(err, JSON.parse(obj)); + exports.popEvent = (function(_this) { + return function(cb) { + var makeObj; + makeObj = function(pcb) { + return function(err, obj) { + return pcb(err, JSON.parse(obj)); + }; }; + return _this.db.lpop('event_queue', makeObj(cb)); }; - return _this.db.lpop('event_queue', makeObj(cb)); - }; + })(this); + /* Purge the event queue. @public purgeEventQueue() - */ + */ + exports.purgeEventQueue = (function(_this) { + return function() { + return _this.db.del('event_queue', replyHandler('purging event queue')); + }; + })(this); - exports.purgeEventQueue = function() { - return _this.db.del('event_queue', replyHandler('purging event queue')); - }; /* Fetches all linked data set keys from a linking set, fetches the single @@ -187,50 +203,51 @@ Persistence per set entry @param {function} cb the callback(err, obj) function that receives all the retrieved data or an error - */ + */ - - getSetRecords = function(set, fSingle, cb) { - _this.log.info("DB | Fetching set records: '" + set + "'"); - return _this.db.smembers(set, function(err, arrReply) { - var fCallback, objReplies, reply, semaphore, _i, _len, _results; - if (err) { - _this.log.warn(err, "DB | fetching '" + set + "'"); - return cb(err); - } else if (arrReply.length === 0) { - return cb(); - } else { - semaphore = arrReply.length; - objReplies = {}; - setTimeout(function() { - if (semaphore > 0) { - return cb(new Error("Timeout fetching '" + set + "'")); - } - }, 2000); - fCallback = function(prop) { - return function(err, data) { - --semaphore; - if (err) { - _this.log.warn(err, "DB | fetching single element: '" + prop + "'"); - } else if (!data) { - _this.log.warn(new Error("Empty key in DB: '" + prop + "'")); - } else { - objReplies[prop] = data; - } - if (semaphore === 0) { - return cb(null, objReplies); + getSetRecords = (function(_this) { + return function(set, fSingle, cb) { + _this.log.info("DB | Fetching set records: '" + set + "'"); + return _this.db.smembers(set, function(err, arrReply) { + var fCallback, objReplies, reply, semaphore, _i, _len, _results; + if (err) { + _this.log.warn(err, "DB | fetching '" + set + "'"); + return cb(err); + } else if (arrReply.length === 0) { + return cb(); + } else { + semaphore = arrReply.length; + objReplies = {}; + setTimeout(function() { + if (semaphore > 0) { + return cb(new Error("Timeout fetching '" + set + "'")); } + }, 2000); + fCallback = function(prop) { + return function(err, data) { + --semaphore; + if (err) { + _this.log.warn(err, "DB | fetching single element: '" + prop + "'"); + } else if (!data) { + _this.log.warn(new Error("Empty key in DB: '" + prop + "'")); + } else { + objReplies[prop] = data; + } + if (semaphore === 0) { + return cb(null, objReplies); + } + }; }; - }; - _results = []; - for (_i = 0, _len = arrReply.length; _i < _len; _i++) { - reply = arrReply[_i]; - _results.push(fSingle(reply, fCallback(reply))); + _results = []; + for (_i = 0, _len = arrReply.length; _i < _len; _i++) { + reply = arrReply[_i]; + _results.push(fSingle(reply, fCallback(reply))); + } + return _results; } - return _results; - } - }); - }; + }); + }; + })(this); IndexedModules = (function() { function IndexedModules(setname, log) { @@ -259,14 +276,14 @@ Persistence return this.log.info("DB | (IdxedMods) Registered new DB connection for '" + this.setname + "'"); }; + /* 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) { this.log.info("DB | (IdxedMods) " + this.setname + ".storeModule( " + userId + ", oModule )"); @@ -323,26 +340,28 @@ Persistence }; IndexedModules.prototype.deleteModule = function(mId) { - var _this = this; this.log.info("DB | (IdxedMods) " + this.setname + ".deleteModule( " + mId + " )"); this.db.srem("" + this.setname + "s", mId, replyHandler("srem '" + mId + "' from " + this.setname + "s")); this.db.del("" + this.setname + ":" + mId, replyHandler("del of '" + this.setname + ":" + mId + "'")); this.unpublish(mId); - return this.db.smembers("" + this.setname + ":" + mId + ":users", function(err, obj) { - var userId, _i, _j, _len, _len1, _results; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - userId = obj[_i]; - _this.unlinkModule(mId, userId); - } - _results = []; - for (_j = 0, _len1 = obj.length; _j < _len1; _j++) { - userId = obj[_j]; - _results.push(_this.deleteUserParams(mId, userId)); - } - return _results; - }); + return this.db.smembers("" + this.setname + ":" + mId + ":users", (function(_this) { + return function(err, obj) { + var userId, _i, _j, _len, _len1, _results; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + userId = obj[_i]; + _this.unlinkModule(mId, userId); + } + _results = []; + for (_j = 0, _len1 = obj.length; _j < _len1; _j++) { + userId = obj[_j]; + _results.push(_this.deleteUserParams(mId, userId)); + } + return _results; + }; + })(this)); }; + /* 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! @@ -351,8 +370,7 @@ Persistence @param {String} mId @param {String} userId @param {object} encData - */ - + */ IndexedModules.prototype.storeUserParams = function(mId, userId, encData) { this.log.info("DB | (IdxedMods) " + this.setname + ".storeUserParams( " + mId + ", " + userId + ", encData )"); @@ -380,9 +398,10 @@ Persistence })(); + /* - ## Rules - */ + *# Rules + */ /* @@ -392,12 +411,14 @@ Persistence @param {String} userId @param {String} ruleId @param {String} message - */ + */ + exports.appendLog = (function(_this) { + return function(userId, ruleId, moduleId, message) { + return _this.db.append("" + userId + ":" + ruleId, "[" + ((new Date).toISOString()) + "] {" + moduleId + "} " + message + "\n"); + }; + })(this); - exports.appendLog = function(userId, ruleId, moduleId, message) { - return _this.db.append("" + userId + ":" + ruleId, "[" + ((new Date).toISOString()) + "] {" + moduleId + "} " + message + "\n"); - }; /* Retrieves a log entry. @@ -406,12 +427,14 @@ Persistence @param {String} userId @param {String} ruleId @param {function} cb - */ + */ + exports.getLog = (function(_this) { + return function(userId, ruleId, cb) { + return _this.db.get("" + userId + ":" + ruleId, cb); + }; + })(this); - exports.getLog = function(userId, ruleId, cb) { - return _this.db.get("" + userId + ":" + ruleId, cb); - }; /* Resets a log entry. @@ -419,12 +442,14 @@ Persistence @public resetLog( *userId, ruleId* ) @param {String} userId @param {String} ruleId - */ + */ + exports.resetLog = (function(_this) { + return function(userId, ruleId) { + return _this.db.del("" + userId + ":" + ruleId, replyHandler("RESET LOG '" + userId + ":" + ruleId + "'")); + }; + })(this); - exports.resetLog = function(userId, ruleId) { - return _this.db.del("" + userId + ":" + ruleId, replyHandler("RESET LOG '" + userId + ":" + ruleId + "'")); - }; /* Query the DB for a rule and pass it to cb(err, obj). @@ -432,39 +457,45 @@ Persistence @public getRule( *ruleId, cb* ) @param {String} ruleId @param {function} cb - */ + */ + exports.getRule = (function(_this) { + return function(ruleId, cb) { + _this.log.info("DB | getRule: '" + ruleId + "'"); + return _this.db.get("rule:" + ruleId, cb); + }; + })(this); - exports.getRule = function(ruleId, cb) { - _this.log.info("DB | getRule: '" + ruleId + "'"); - return _this.db.get("rule:" + ruleId, cb); - }; /* Fetch all rules and pass them to cb(err, obj). @public getRules( *cb* ) @param {function} cb - */ + */ + exports.getRules = (function(_this) { + return function(cb) { + _this.log.info('DB | Fetching all Rules'); + return getSetRecords('rules', exports.getRule, cb); + }; + })(this); - exports.getRules = function(cb) { - _this.log.info('DB | Fetching all Rules'); - return getSetRecords('rules', exports.getRule, cb); - }; /* Fetch all rule IDs and hand it to cb(err, obj). @public getRuleIds( *cb* ) @param {function} cb - */ + */ + exports.getRuleIds = (function(_this) { + return function(cb) { + _this.log.info('DB | Fetching all Rule IDs'); + return _this.db.smembers('rules', cb); + }; + })(this); - exports.getRuleIds = function(cb) { - _this.log.info('DB | Fetching all Rule IDs'); - return _this.db.smembers('rules', cb); - }; /* Store a string representation of a rule in the DB. @@ -472,14 +503,16 @@ Persistence @public storeRule( *ruleId, data* ) @param {String} ruleId @param {String} data - */ + */ + exports.storeRule = (function(_this) { + return function(ruleId, data) { + _this.log.info("DB | storeRule: '" + ruleId + "'"); + _this.db.sadd('rules', "" + ruleId, replyHandler("storing rule key '" + ruleId + "'")); + return _this.db.set("rule:" + ruleId, data, replyHandler("storing rule '" + ruleId + "'")); + }; + })(this); - exports.storeRule = function(ruleId, data) { - _this.log.info("DB | storeRule: '" + ruleId + "'"); - _this.db.sadd('rules', "" + ruleId, replyHandler("storing rule key '" + ruleId + "'")); - return _this.db.set("rule:" + ruleId, data, replyHandler("storing rule '" + ruleId + "'")); - }; /* Delete a string representation of a rule. @@ -487,40 +520,42 @@ Persistence @public deleteRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.deleteRule = (function(_this) { + return function(ruleId) { + _this.log.info("DB | deleteRule: '" + ruleId + "'"); + _this.db.srem("rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "'")); + _this.db.del("rule:" + ruleId, replyHandler("Deleting rule '" + ruleId + "'")); + _this.db.smembers("rule:" + ruleId + ":users", function(err, obj) { + var delLinkedUserRule, id, _i, _len, _results; + delLinkedUserRule = function(userId) { + return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in linked user '" + userId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delLinkedUserRule(id)); + } + return _results; + }); + _this.db.del("rule:" + ruleId + ":users", replyHandler("Deleting rule '" + ruleId + "' users")); + _this.db.smembers("rule:" + ruleId + ":active-users", function(err, obj) { + var delActiveUserRule, id, _i, _len, _results; + delActiveUserRule = function(userId) { + return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in active user '" + userId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delActiveUserRule(id)); + } + return _results; + }); + return _this.db.del("rule:" + ruleId + ":active-users", replyHandler("Deleting rule '" + ruleId + "' active users")); + }; + })(this); - exports.deleteRule = function(ruleId) { - _this.log.info("DB | deleteRule: '" + ruleId + "'"); - _this.db.srem("rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "'")); - _this.db.del("rule:" + ruleId, replyHandler("Deleting rule '" + ruleId + "'")); - _this.db.smembers("rule:" + ruleId + ":users", function(err, obj) { - var delLinkedUserRule, id, _i, _len, _results; - delLinkedUserRule = function(userId) { - return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in linked user '" + userId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delLinkedUserRule(id)); - } - return _results; - }); - _this.db.del("rule:" + ruleId + ":users", replyHandler("Deleting rule '" + ruleId + "' users")); - _this.db.smembers("rule:" + ruleId + ":active-users", function(err, obj) { - var delActiveUserRule, id, _i, _len, _results; - delActiveUserRule = function(userId) { - return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("Deleting rule key '" + ruleId + "' in active user '" + userId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delActiveUserRule(id)); - } - return _results; - }); - return _this.db.del("rule:" + ruleId + ":active-users", replyHandler("Deleting rule '" + ruleId + "' active users")); - }; /* Associate a rule to a user. @@ -528,14 +563,16 @@ Persistence @public linkRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.linkRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | linkRule: '" + ruleId + "' for user '" + userId + "'"); + _this.db.sadd("rule:" + ruleId + ":users", userId, replyHandler("storing user '" + userId + "' for rule key '" + ruleId + "'")); + return _this.db.sadd("user:" + userId + ":rules", ruleId, replyHandler("storing rule key '" + ruleId + "' for user '" + userId + "'")); + }; + })(this); - exports.linkRule = function(ruleId, userId) { - _this.log.info("DB | linkRule: '" + ruleId + "' for user '" + userId + "'"); - _this.db.sadd("rule:" + ruleId + ":users", userId, replyHandler("storing user '" + userId + "' for rule key '" + ruleId + "'")); - return _this.db.sadd("user:" + userId + ":rules", ruleId, replyHandler("storing rule key '" + ruleId + "' for user '" + userId + "'")); - }; /* Get rules linked to a user and hand it to cb(err, obj). @@ -543,13 +580,15 @@ Persistence @public getUserLinkRule( *userId, cb* ) @param {String} userId @param {function} cb - */ + */ + exports.getUserLinkedRules = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUserLinkedRules: for user '" + userId + "'"); + return _this.db.smembers("user:" + userId + ":rules", cb); + }; + })(this); - exports.getUserLinkedRules = function(userId, cb) { - _this.log.info("DB | getUserLinkedRules: for user '" + userId + "'"); - return _this.db.smembers("user:" + userId + ":rules", cb); - }; /* Get users linked to a rule and hand it to cb(err, obj). @@ -557,13 +596,15 @@ Persistence @public getRuleLinkedUsers( *ruleId, cb* ) @param {String} ruleId @param {function} cb - */ + */ + exports.getRuleLinkedUsers = (function(_this) { + return function(ruleId, cb) { + _this.log.info("DB | getRuleLinkedUsers: for rule '" + ruleId + "'"); + return _this.db.smembers("rule:" + ruleId + ":users", cb); + }; + })(this); - exports.getRuleLinkedUsers = function(ruleId, cb) { - _this.log.info("DB | getRuleLinkedUsers: for rule '" + ruleId + "'"); - return _this.db.smembers("rule:" + ruleId + ":users", cb); - }; /* Delete an association of a rule to a user. @@ -571,14 +612,16 @@ Persistence @public unlinkRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.unlinkRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | unlinkRule: '" + ruleId + ":" + userId + "'"); + _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("removing user '" + userId + "' for rule key '" + ruleId + "'")); + return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("removing rule key '" + ruleId + "' for user '" + userId + "'")); + }; + })(this); - exports.unlinkRule = function(ruleId, userId) { - _this.log.info("DB | unlinkRule: '" + ruleId + ":" + userId + "'"); - _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("removing user '" + userId + "' for rule key '" + ruleId + "'")); - return _this.db.srem("user:" + userId + ":rules", ruleId, replyHandler("removing rule key '" + ruleId + "' for user '" + userId + "'")); - }; /* Activate a rule. @@ -586,14 +629,16 @@ Persistence @public activateRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.activateRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | activateRule: '" + ruleId + "' for '" + userId + "'"); + _this.db.sadd("rule:" + ruleId + ":active-users", userId, replyHandler("storing activated user '" + userId + "' in rule '" + ruleId + "'")); + return _this.db.sadd("user:" + userId + ":active-rules", ruleId, replyHandler("storing activated rule '" + ruleId + "' in user '" + userId + "'")); + }; + })(this); - exports.activateRule = function(ruleId, userId) { - _this.log.info("DB | activateRule: '" + ruleId + "' for '" + userId + "'"); - _this.db.sadd("rule:" + ruleId + ":active-users", userId, replyHandler("storing activated user '" + userId + "' in rule '" + ruleId + "'")); - return _this.db.sadd("user:" + userId + ":active-rules", ruleId, replyHandler("storing activated rule '" + ruleId + "' in user '" + userId + "'")); - }; /* Get rules activated for a user and hand it to cb(err, obj). @@ -601,13 +646,15 @@ Persistence @public getUserLinkRule( *userId, cb* ) @param {String} userId @param {function} cb - */ + */ + exports.getUserActivatedRules = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUserActivatedRules: for user '" + userId + "'"); + return _this.db.smembers("user:" + userId + ":active-rules", cb); + }; + })(this); - exports.getUserActivatedRules = function(userId, cb) { - _this.log.info("DB | getUserActivatedRules: for user '" + userId + "'"); - return _this.db.smembers("user:" + userId + ":active-rules", cb); - }; /* Get users activated for a rule and hand it to cb(err, obj). @@ -615,13 +662,15 @@ Persistence @public getRuleActivatedUsers ( *ruleId, cb* ) @param {String} ruleId @param {function} cb - */ + */ + exports.getRuleActivatedUsers = (function(_this) { + return function(ruleId, cb) { + _this.log.info("DB | getRuleActivatedUsers: for rule '" + ruleId + "'"); + return _this.db.smembers("rule:" + ruleId + ":active-users", cb); + }; + })(this); - exports.getRuleActivatedUsers = function(ruleId, cb) { - _this.log.info("DB | getRuleActivatedUsers: for rule '" + ruleId + "'"); - return _this.db.smembers("rule:" + ruleId + ":active-users", cb); - }; /* Deactivate a rule. @@ -629,55 +678,59 @@ Persistence @public deactivateRule( *ruleId, userId* ) @param {String} ruleId @param {String} userId - */ + */ + exports.deactivateRule = (function(_this) { + return function(ruleId, userId) { + _this.log.info("DB | deactivateRule: '" + ruleId + "' for '" + userId + "'"); + _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("removing activated user '" + userId + "' in rule '" + ruleId + "'")); + return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("removing activated rule '" + ruleId + "' in user '" + userId + "'")); + }; + })(this); - exports.deactivateRule = function(ruleId, userId) { - _this.log.info("DB | deactivateRule: '" + ruleId + "' for '" + userId + "'"); - _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("removing activated user '" + userId + "' in rule '" + ruleId + "'")); - return _this.db.srem("user:" + userId + ":active-rules", ruleId, replyHandler("removing activated rule '" + ruleId + "' in user '" + userId + "'")); - }; /* Fetch all active ruleIds and pass them to cb(err, obj). @public getAllActivatedRuleIds( *cb* ) @param {function} cb - */ + */ - - exports.getAllActivatedRuleIdsPerUser = function(cb) { - _this.log.info("DB | Fetching all active rules"); - return _this.db.smembers('users', function(err, obj) { - var fFetchActiveUserRules, result, semaphore, user, _i, _len, _results; - result = {}; - if (obj.length === 0) { - return cb(null, result); - } else { - semaphore = obj.length; - fFetchActiveUserRules = function(userId) { - return _this.db.smembers("user:" + user + ":active-rules", function(err, obj) { - if (obj.length > 0) { - result[userId] = obj; - } - if (--semaphore === 0) { - return cb(null, result); - } - }); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - user = obj[_i]; - _results.push(fFetchActiveUserRules(user)); + exports.getAllActivatedRuleIdsPerUser = (function(_this) { + return function(cb) { + _this.log.info("DB | Fetching all active rules"); + return _this.db.smembers('users', function(err, obj) { + var fFetchActiveUserRules, result, semaphore, user, _i, _len, _results; + result = {}; + if (obj.length === 0) { + return cb(null, result); + } else { + semaphore = obj.length; + fFetchActiveUserRules = function(userId) { + return _this.db.smembers("user:" + user + ":active-rules", function(err, obj) { + if (obj.length > 0) { + result[userId] = obj; + } + if (--semaphore === 0) { + return cb(null, result); + } + }); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + user = obj[_i]; + _results.push(fFetchActiveUserRules(user)); + } + return _results; } - return _results; - } - }); - }; + }); + }; + })(this); + /* - ## Users - */ + *# Users + */ /* @@ -686,32 +739,36 @@ Persistence @public storeUser( *objUser* ) @param {Object} objUser - */ + */ + exports.storeUser = (function(_this) { + return function(objUser) { + _this.log.info("DB | storeUser: '" + objUser.username + "'"); + if (objUser && objUser.username && objUser.password) { + _this.db.sadd('users', objUser.username, replyHandler("storing user key '" + objUser.username + "'")); + objUser.password = objUser.password; + return _this.db.hmset("user:" + objUser.username, objUser, replyHandler("storing user properties '" + objUser.username + "'")); + } else { + return _this.log.warn(new Error('DB | username or password was missing')); + } + }; + })(this); - exports.storeUser = function(objUser) { - _this.log.info("DB | storeUser: '" + objUser.username + "'"); - if (objUser && objUser.username && objUser.password) { - _this.db.sadd('users', objUser.username, replyHandler("storing user key '" + objUser.username + "'")); - objUser.password = objUser.password; - return _this.db.hmset("user:" + objUser.username, objUser, replyHandler("storing user properties '" + objUser.username + "'")); - } else { - return _this.log.warn(new Error('DB | username or password was missing')); - } - }; /* Fetch all user IDs and pass them to cb(err, obj). @public getUserIds( *cb* ) @param {function} cb - */ + */ + exports.getUserIds = (function(_this) { + return function(cb) { + _this.log.info("DB | getUserIds"); + return _this.db.smembers("users", cb); + }; + })(this); - exports.getUserIds = function(cb) { - _this.log.info("DB | getUserIds"); - return _this.db.smembers("users", cb); - }; /* Fetch a user by id and pass it to cb(err, obj). @@ -719,66 +776,70 @@ Persistence @public getUser( *userId, cb* ) @param {String} userId @param {function} cb - */ + */ + exports.getUser = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUser: '" + userId + "'"); + return _this.db.hgetall("user:" + userId, cb); + }; + })(this); - exports.getUser = function(userId, cb) { - _this.log.info("DB | getUser: '" + userId + "'"); - return _this.db.hgetall("user:" + userId, cb); - }; /* Deletes a user and all his associated linked and active rules. @public deleteUser( *userId* ) @param {String} userId - */ + */ + exports.deleteUser = (function(_this) { + return function(userId) { + _this.log.info("DB | deleteUser: '" + userId + "'"); + _this.db.srem("users", userId, replyHandler("Deleting user key '" + userId + "'")); + _this.db.del("user:" + userId, replyHandler("Deleting user '" + userId + "'")); + _this.db.smembers("user:" + userId + ":rules", function(err, obj) { + var delLinkedRuleUser, id, _i, _len, _results; + delLinkedRuleUser = function(ruleId) { + return _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in linked rule '" + ruleId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delLinkedRuleUser(id)); + } + return _results; + }); + _this.db.del("user:" + userId + ":rules", replyHandler("Deleting user '" + userId + "' rules")); + _this.db.smembers("user:" + userId + ":active-rules", function(err, obj) { + var delActivatedRuleUser, id, _i, _len, _results; + delActivatedRuleUser = function(ruleId) { + return _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("Deleting user key '" + userId + "' in active rule '" + ruleId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delActivatedRuleUser(id)); + } + return _results; + }); + _this.db.del("user:" + userId + ":active-rules", replyHandler("Deleting user '" + userId + "' rules")); + _this.db.smembers("user:" + userId + ":roles", function(err, obj) { + var delRoleUser, id, _i, _len, _results; + delRoleUser = function(roleId) { + return _this.db.srem("role:" + roleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in role '" + roleId + "'")); + }; + _results = []; + for (_i = 0, _len = obj.length; _i < _len; _i++) { + id = obj[_i]; + _results.push(delRoleUser(id)); + } + return _results; + }); + return _this.db.del("user:" + userId + ":roles", replyHandler("Deleting user '" + userId + "' roles")); + }; + })(this); - exports.deleteUser = function(userId) { - _this.log.info("DB | deleteUser: '" + userId + "'"); - _this.db.srem("users", userId, replyHandler("Deleting user key '" + userId + "'")); - _this.db.del("user:" + userId, replyHandler("Deleting user '" + userId + "'")); - _this.db.smembers("user:" + userId + ":rules", function(err, obj) { - var delLinkedRuleUser, id, _i, _len, _results; - delLinkedRuleUser = function(ruleId) { - return _this.db.srem("rule:" + ruleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in linked rule '" + ruleId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delLinkedRuleUser(id)); - } - return _results; - }); - _this.db.del("user:" + userId + ":rules", replyHandler("Deleting user '" + userId + "' rules")); - _this.db.smembers("user:" + userId + ":active-rules", function(err, obj) { - var delActivatedRuleUser, id, _i, _len, _results; - delActivatedRuleUser = function(ruleId) { - return _this.db.srem("rule:" + ruleId + ":active-users", userId, replyHandler("Deleting user key '" + userId + "' in active rule '" + ruleId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delActivatedRuleUser(id)); - } - return _results; - }); - _this.db.del("user:" + userId + ":active-rules", replyHandler("Deleting user '" + userId + "' rules")); - _this.db.smembers("user:" + userId + ":roles", function(err, obj) { - var delRoleUser, id, _i, _len, _results; - delRoleUser = function(roleId) { - return _this.db.srem("role:" + roleId + ":users", userId, replyHandler("Deleting user key '" + userId + "' in role '" + roleId + "'")); - }; - _results = []; - for (_i = 0, _len = obj.length; _i < _len; _i++) { - id = obj[_i]; - _results.push(delRoleUser(id)); - } - return _results; - }); - return _this.db.del("user:" + userId + ":roles", replyHandler("Deleting user '" + userId + "' roles")); - }; /* Checks the credentials and on success returns the user object to the @@ -790,34 +851,36 @@ Persistence @param {String} userId @param {String} password @param {function} cb - */ + */ - - exports.loginUser = function(userId, password, cb) { - var fCheck; - _this.log.info("DB | User '" + userId + "' tries to log in"); - fCheck = function(pw) { - return function(err, obj) { - if (err) { - return cb(err, null); - } else if (obj && obj.password) { - if (pw === obj.password) { - _this.log.info("DB | User '" + obj.username + "' logged in!"); - return cb(null, obj); + exports.loginUser = (function(_this) { + return function(userId, password, cb) { + var fCheck; + _this.log.info("DB | User '" + userId + "' tries to log in"); + fCheck = function(pw) { + return function(err, obj) { + if (err) { + return cb(err, null); + } else if (obj && obj.password) { + if (pw === obj.password) { + _this.log.info("DB | User '" + obj.username + "' logged in!"); + return cb(null, obj); + } else { + return cb(new Error('Wrong credentials!'), null); + } } else { - return cb(new Error('Wrong credentials!'), null); + return cb(new Error('User not found!'), null); } - } else { - return cb(new Error('User not found!'), null); - } + }; }; + return _this.db.hgetall("user:" + userId, fCheck(password)); }; - return _this.db.hgetall("user:" + userId, fCheck(password)); - }; + })(this); + /* - ## User Roles - */ + *# User Roles + */ /* @@ -826,15 +889,17 @@ Persistence @public storeUserRole( *userId, role* ) @param {String} userId @param {String} role - */ + */ + exports.storeUserRole = (function(_this) { + return function(userId, role) { + _this.log.info("DB | storeUserRole: '" + userId + ":" + role + "'"); + _this.db.sadd('roles', role, replyHandler("adding role '" + role + "' to role index set")); + _this.db.sadd("user:" + userId + ":roles", role, replyHandler("adding role '" + role + "' to user '" + userId + "'")); + return _this.db.sadd("role:" + role + ":users", userId, replyHandler("adding user '" + userId + "' to role '" + role + "'")); + }; + })(this); - exports.storeUserRole = function(userId, role) { - _this.log.info("DB | storeUserRole: '" + userId + ":" + role + "'"); - _this.db.sadd('roles', role, replyHandler("adding role '" + role + "' to role index set")); - _this.db.sadd("user:" + userId + ":roles", role, replyHandler("adding role '" + role + "' to user '" + userId + "'")); - return _this.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). @@ -842,13 +907,15 @@ Persistence @public getUserRoles( *userId* ) @param {String} userId @param {function} cb - */ + */ + exports.getUserRoles = (function(_this) { + return function(userId, cb) { + _this.log.info("DB | getUserRoles: '" + userId + "'"); + return _this.db.smembers("user:" + userId + ":roles", cb); + }; + })(this); - exports.getUserRoles = function(userId, cb) { - _this.log.info("DB | getUserRoles: '" + userId + "'"); - return _this.db.smembers("user:" + userId + ":roles", cb); - }; /* Fetch all users of a role and pass them to cb(err, obj). @@ -856,13 +923,15 @@ Persistence @public getUserRoles( *role* ) @param {String} role @param {function} cb - */ + */ + exports.getRoleUsers = (function(_this) { + return function(role, cb) { + _this.log.info("DB | getRoleUsers: '" + role + "'"); + return _this.db.smembers("role:" + role + ":users", cb); + }; + })(this); - exports.getRoleUsers = function(role, cb) { - _this.log.info("DB | getRoleUsers: '" + role + "'"); - return _this.db.smembers("role:" + role + ":users", cb); - }; /* Remove a role from a user. @@ -870,25 +939,28 @@ Persistence @public removeRoleFromUser( *role, userId* ) @param {String} role @param {String} userId - */ + */ + exports.removeUserRole = (function(_this) { + return function(userId, role) { + _this.log.info("DB | removeRoleFromUser: role '" + role + "', user '" + userId + "'"); + _this.db.srem("user:" + userId + ":roles", role, replyHandler("Removing role '" + role + "' from user '" + userId + "'")); + return _this.db.srem("role:" + role + ":users", userId, replyHandler("Removing user '" + userId + "' from role '" + role + "'")); + }; + })(this); - exports.removeUserRole = function(userId, role) { - _this.log.info("DB | removeRoleFromUser: role '" + role + "', user '" + userId + "'"); - _this.db.srem("user:" + userId + ":roles", role, replyHandler("Removing role '" + role + "' from user '" + userId + "'")); - return _this.db.srem("role:" + role + ":users", userId, replyHandler("Removing user '" + userId + "' from role '" + role + "'")); - }; /* Shuts down the db link. @public shutDown() - */ + */ - - exports.shutDown = function() { - var _ref; - return (_ref = _this.db) != null ? _ref.quit() : void 0; - }; + exports.shutDown = (function(_this) { + return function() { + var _ref; + return (_ref = _this.db) != null ? _ref.quit() : void 0; + }; + })(this); }).call(this); diff --git a/js/request-handler.js b/js/request-handler.js index 88a95de..212cdc0 100644 --- a/js/request-handler.js +++ b/js/request-handler.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* Request Handler @@ -7,12 +8,10 @@ Request Handler > the [HTTP Listener](http-listener.html). It will handle user requests for > pages as well as POST requests such as user login, module storing, event > invocation and also admin commands. -*/ - + */ (function() { - var crypto, db, dirHandlers, exports, fs, getHandlerPath, getRemoteScripts, getScript, getTemplate, mustache, path, qs, renderPage, - _this = this; + var crypto, db, dirHandlers, exports, fs, getHandlerPath, getRemoteScripts, getScript, getTemplate, mustache, path, qs, renderPage; db = require('./persistence'); @@ -28,32 +27,35 @@ Request Handler dirHandlers = path.resolve(__dirname, '..', 'webpages', 'handlers'); - exports = module.exports = function(args) { - var fStoreUser, user, users; - _this.log = args.logger; - _this.userRequestHandler = args['request-service']; - _this.objAdminCmds = { - shutdown: function(obj, cb) { - var data; - data = { - code: 200, - message: 'Shutting down... BYE!' - }; - setTimeout(args['shutdown-function'], 500); - return cb(null, data); + exports = module.exports = (function(_this) { + return function(args) { + var fStoreUser, user, users; + _this.log = args.logger; + _this.userRequestHandler = args['request-service']; + _this.objAdminCmds = { + shutdown: function(obj, cb) { + var data; + data = { + code: 200, + message: 'Shutting down... BYE!' + }; + setTimeout(args['shutdown-function'], 500); + return cb(null, data); + } + }; + db(args); + users = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', 'config', 'users.json'))); + fStoreUser = function(username, oUser) { + oUser.username = username; + return db.storeUser(oUser); + }; + for (user in users) { + fStoreUser(user, users[user]); } + return module.exports; }; - db(args); - users = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', 'config', 'users.json'))); - fStoreUser = function(username, oUser) { - oUser.username = username; - return db.storeUser(oUser); - }; - for (user in users) { - fStoreUser(user, users[user]); - } - return module.exports; - }; + })(this); + /* Handles possible events that were posted to this server and pushes them into the @@ -65,8 +67,7 @@ Request Handler objects.* @public handleEvent( *req, resp* ) - */ - + */ exports.handleEvent = function(req, resp) { var body; @@ -102,6 +103,7 @@ Request Handler }); }; + /* Associates the user object with the session if login is successful. @@ -111,32 +113,34 @@ Request Handler objects.* @public handleLogin( *req, resp* ) - */ + */ - - exports.handleLogin = function(req, resp) { - var body; - body = ''; - req.on('data', function(data) { - return body += data; - }); - return req.on('end', function() { - var obj; - obj = qs.parse(body); - return db.loginUser(obj.username, obj.password, function(err, usr) { - if (err) { - _this.log.warn("RH | AUTH-UH-OH ( " + obj.username + " ): " + err.message); - } else { - req.session.user = usr; - } - if (req.session.user) { - return resp.send('OK!'); - } else { - return resp.send(401, 'NO!'); - } + exports.handleLogin = (function(_this) { + return function(req, resp) { + var body; + body = ''; + req.on('data', function(data) { + return body += data; }); - }); - }; + return req.on('end', function() { + var obj; + obj = qs.parse(body); + return db.loginUser(obj.username, obj.password, function(err, usr) { + if (err) { + _this.log.warn("RH | AUTH-UH-OH ( " + obj.username + " ): " + err.message); + } else { + req.session.user = usr; + } + if (req.session.user) { + return resp.send('OK!'); + } else { + return resp.send(401, 'NO!'); + } + }); + }); + }; + })(this); + /* A post request retrieved on this handler causes the user object to be @@ -148,8 +152,7 @@ Request Handler objects.* @public handleLogout( *req, resp* ) - */ - + */ exports.handleLogout = function(req, resp) { if (req.session) { @@ -158,25 +161,25 @@ Request Handler } }; + /* Resolves the path to a handler webpage. @private getHandlerPath( *name* ) @param {String} name - */ - + */ getHandlerPath = function(name) { return path.join(dirHandlers, name + '.html'); }; + /* Fetches a template. @private getTemplate( *name* ) @param {String} name - */ - + */ getTemplate = function(name) { var pth; @@ -184,13 +187,13 @@ Request Handler return fs.readFileSync(pth, 'utf8'); }; + /* Fetches a script. @private getScript( *name* ) @param {String} name - */ - + */ getScript = function(name) { var pth; @@ -198,13 +201,13 @@ Request Handler return fs.readFileSync(pth, 'utf8'); }; + /* Fetches remote scripts snippets. @private getRemoteScripts( *name* ) @param {String} name - */ - + */ getRemoteScripts = function(name) { var pth; @@ -212,6 +215,7 @@ Request Handler return fs.readFileSync(pth, 'utf8'); }; + /* Renders a page, with helps of mustache, depending on the user session and returns it. @@ -219,8 +223,7 @@ Request Handler @param {String} name @param {Object} sess @param {Object} msg - */ - + */ renderPage = function(name, req, resp, msg) { var code, content, data, err, menubar, page, pageElements, pathSkel, remote_scripts, script, skeleton; @@ -259,6 +262,7 @@ Request Handler return resp.send(code, mustache.render(page, data)); }; + /* Present the desired forge page to the user. @@ -268,8 +272,7 @@ Request Handler objects.* @public handleForge( *req, resp* ) - */ - + */ exports.handleForge = function(req, resp) { var page; @@ -280,6 +283,7 @@ Request Handler return renderPage(page, req, resp); }; + /* Handles the user command requests. @@ -289,27 +293,29 @@ Request Handler objects.* @public handleUser( *req, resp* ) - */ + */ - - exports.handleUserCommand = function(req, resp) { - var body; - if (req.session && req.session.user) { - body = ''; - req.on('data', function(data) { - return body += data; - }); - return req.on('end', function() { - var obj; - obj = qs.parse(body); - return _this.userRequestHandler(req.session.user, obj, function(obj) { - return resp.send(obj.code, obj); + exports.handleUserCommand = (function(_this) { + return function(req, resp) { + var body; + if (req.session && req.session.user) { + body = ''; + req.on('data', function(data) { + return body += data; }); - }); - } else { - return resp.send(401, 'Login first!'); - } - }; + return req.on('end', function() { + var obj; + obj = qs.parse(body); + return _this.userRequestHandler(req.session.user, obj, function(obj) { + return resp.send(obj.code, obj); + }); + }); + } else { + return resp.send(401, 'Login first!'); + } + }; + })(this); + /* Present the admin console to the user if he's allowed to see it. @@ -320,8 +326,7 @@ Request Handler objects.* @public handleForge( *req, resp* ) - */ - + */ exports.handleAdmin = function(req, resp) { var msg, page; @@ -336,6 +341,7 @@ Request Handler return renderPage(page, req, resp, msg); }; + /* Handles the admin command requests. @@ -345,31 +351,32 @@ Request Handler objects.* @public handleAdminCommand( *req, resp* ) - */ + */ - - exports.handleAdminCommand = function(req, resp) { - var body; - if (req.session && req.session.user && req.session.user.isAdmin === "true") { - body = ''; - req.on('data', function(data) { - return body += data; - }); - return req.on('end', function() { - var obj; - obj = qs.parse(body); - _this.log.info('RH | Received admin request: ' + obj.command); - if (obj.command && _this.objAdminCmds[obj.command]) { - return _this.objAdminCmds[obj.command](obj, function(err, obj) { - return resp.send(obj.code, obj); - }); - } else { - return resp.send(404, 'Command unknown!'); - } - }); - } else { - return resp.send(401, 'You need to be logged in as admin!'); - } - }; + exports.handleAdminCommand = (function(_this) { + return function(req, resp) { + var body; + if (req.session && req.session.user && req.session.user.isAdmin === "true") { + body = ''; + req.on('data', function(data) { + return body += data; + }); + return req.on('end', function() { + var obj; + obj = qs.parse(body); + _this.log.info('RH | Received admin request: ' + obj.command); + if (obj.command && _this.objAdminCmds[obj.command]) { + return _this.objAdminCmds[obj.command](obj, function(err, obj) { + return resp.send(obj.code, obj); + }); + } else { + return resp.send(404, 'Command unknown!'); + } + }); + } else { + return resp.send(401, 'You need to be logged in as admin!'); + } + }; + })(this); }).call(this); diff --git a/js/webapi-eca.js b/js/webapi-eca.js index 5a89e07..a0eaa22 100644 --- a/js/webapi-eca.js +++ b/js/webapi-eca.js @@ -1,4 +1,5 @@ -// Generated by CoffeeScript 1.6.3 +// Generated by CoffeeScript 1.7.1 + /* WebAPI-ECA Engine @@ -9,12 +10,10 @@ WebAPI-ECA Engine > node webapi-eca [opt] > > See below in the optimist CLI preparation for allowed optional parameters `[opt]`. -*/ - + */ (function() { - var argv, cm, conf, cp, db, engine, fs, http, init, logconf, logger, nameEP, opt, optimist, path, procCmds, shutDown, usage, - _this = this; + var argv, cm, conf, cp, db, engine, fs, http, init, logconf, logger, nameEP, opt, optimist, path, procCmds, shutDown, usage; logger = require('./logging'); @@ -40,10 +39,10 @@ WebAPI-ECA Engine procCmds = {}; + /* Let's prepare the optimist CLI optional arguments `[opt]`: - */ - + */ usage = 'This runs your webapi-based ECA engine'; @@ -130,72 +129,76 @@ WebAPI-ECA Engine this.log.info('RS | STARTING SERVER'); + /* This function is invoked right after the module is loaded and starts the server. @private init() - */ + */ - - init = function() { - var args; - args = { - logger: _this.log, - logconf: logconf + init = (function(_this) { + return function() { + var args; + args = { + logger: _this.log, + logconf: logconf + }; + args['http-port'] = parseInt(argv.w || conf.getHttpPort()); + args['db-port'] = parseInt(argv.d || conf.getDbPort()); + args['keygen'] = conf.getKeygenPassphrase(); + _this.log.info('RS | Initialzing DB'); + db(args); + return db.isConnected(function(err) { + var cliArgs, poller; + if (err) { + _this.log.error('RS | No DB connection, shutting down system!'); + return shutDown(); + } else { + _this.log.info('RS | Initialzing engine'); + engine(args); + _this.log.info('RS | Forking a child process for the event poller'); + cliArgs = [args.logconf['mode'], args.logconf['io-level'], args.logconf['file-level'], args.logconf['file-path'], args.logconf['nolog']]; + poller = cp.fork(path.resolve(__dirname, nameEP), cliArgs); + _this.log.info('RS | Initialzing module manager'); + cm(args); + cm.addRuleListener(engine.internalEvent); + cm.addRuleListener(function(evt) { + return poller.send(evt); + }); + _this.log.info('RS | Initialzing http listener'); + args['request-service'] = cm.processRequest; + args['shutdown-function'] = shutDown; + return http(args); + } + }); }; - args['http-port'] = parseInt(argv.w || conf.getHttpPort()); - args['db-port'] = parseInt(argv.d || conf.getDbPort()); - args['keygen'] = conf.getKeygenPassphrase(); - _this.log.info('RS | Initialzing DB'); - db(args); - return db.isConnected(function(err) { - var cliArgs, poller; - if (err) { - _this.log.error('RS | No DB connection, shutting down system!'); - return shutDown(); - } else { - _this.log.info('RS | Initialzing engine'); - engine(args); - _this.log.info('RS | Forking a child process for the event poller'); - cliArgs = [args.logconf['mode'], args.logconf['io-level'], args.logconf['file-level'], args.logconf['file-path'], args.logconf['nolog']]; - poller = cp.fork(path.resolve(__dirname, nameEP), cliArgs); - _this.log.info('RS | Initialzing module manager'); - cm(args); - cm.addRuleListener(engine.internalEvent); - cm.addRuleListener(function(evt) { - return poller.send(evt); - }); - _this.log.info('RS | Initialzing http listener'); - args['request-service'] = cm.processRequest; - args['shutdown-function'] = shutDown; - return http(args); - } - }); - }; + })(this); + /* Shuts down the server. @private shutDown() - */ + */ + shutDown = (function(_this) { + return function() { + _this.log.warn('RS | Received shut down command!'); + if (db != null) { + db.shutDown(); + } + engine.shutDown(); + return process.exit(); + }; + })(this); - shutDown = function() { - _this.log.warn('RS | Received shut down command!'); - if (db != null) { - db.shutDown(); - } - engine.shutDown(); - return process.exit(); - }; /* - ## Process Commands + *# Process Commands When the server is run as a child process, this function handles messages from the parent process (e.g. the testing suite) - */ - + */ process.on('message', function(cmd) { return typeof procCmds[cmd] === "function" ? procCmds[cmd]() : void 0; diff --git a/testing/test_components-manager.coffee b/testing/test_components-manager.coffee index a67206b..5ec4f7f 100644 --- a/testing/test_components-manager.coffee +++ b/testing/test_components-manager.coffee @@ -10,16 +10,16 @@ try catch err console.log 'Error fetching standard objects file: ' + err.message -logger = require path.join '..', 'js-coffee', 'logging' +logger = require path.join '..', 'js', 'logging' log = logger.getLogger nolog: true opts = logger: log -cm = require path.join '..', 'js-coffee', 'components-manager' +cm = require path.join '..', 'js', 'components-manager' cm opts -db = require path.join '..', 'js-coffee', 'persistence' +db = require path.join '..', 'js', 'persistence' db opts oUser = objects.users.userOne diff --git a/testing/test_config.coffee b/testing/test_config.coffee index 4cab3d8..5535ca7 100644 --- a/testing/test_config.coffee +++ b/testing/test_config.coffee @@ -1,8 +1,8 @@ path = require 'path' -logger = require path.join '..', 'js-coffee', 'logging' +logger = require path.join '..', 'js', 'logging' log = logger.getLogger nolog: true -conf = require path.join '..', 'js-coffee', 'config' +conf = require path.join '..', 'js', 'config' conf logger: log diff --git a/testing/test_dynamic-modules.coffee b/testing/test_dynamic-modules.coffee index c2c7c20..8bd7a92 100644 --- a/testing/test_dynamic-modules.coffee +++ b/testing/test_dynamic-modules.coffee @@ -16,20 +16,20 @@ try catch err console.log 'Error fetching standard objects file: ' + err.message -logger = require path.join '..', 'js-coffee', 'logging' +logger = require path.join '..', 'js', 'logging' log = logger.getLogger nolog: true opts = logger: log keygen: passPhrase -db = require path.join '..', 'js-coffee', 'persistence' +db = require path.join '..', 'js', 'persistence' db opts -engine = require path.join '..', 'js-coffee', 'engine' +engine = require path.join '..', 'js', 'engine' engine opts -dm = require path.join '..', 'js-coffee', 'dynamic-modules' +dm = require path.join '..', 'js', 'dynamic-modules' dm opts oUser = objects.users.userOne diff --git a/testing/test_engine.coffee b/testing/test_engine.coffee index f240a33..95e8d70 100644 --- a/testing/test_engine.coffee +++ b/testing/test_engine.coffee @@ -10,16 +10,16 @@ try catch err console.log 'Error fetching standard objects file: ' + err.message -logger = require path.join '..', 'js-coffee', 'logging' +logger = require path.join '..', 'js', 'logging' log = logger.getLogger nolog: true opts = logger: log -engine = require path.join '..', 'js-coffee', 'engine' +engine = require path.join '..', 'js', 'engine' engine opts -db = require path.join '..', 'js-coffee', 'persistence' +db = require path.join '..', 'js', 'persistence' db opts listRules = engine.getListUserRules() diff --git a/testing/test_http-listener.coffee b/testing/test_http-listener.coffee index c8b1cda..c766ea9 100644 --- a/testing/test_http-listener.coffee +++ b/testing/test_http-listener.coffee @@ -23,7 +23,7 @@ exports.testsGoInWebAPI_ECA_Module = ( test ) -> # path = require 'path' # http = require 'http' # needle = require 'needle' -# logger = require path.join '..', 'js-coffee', 'logging' +# logger = require path.join '..', 'js', 'logging' # log = logger.getLogger # nolog: true @@ -32,7 +32,7 @@ exports.testsGoInWebAPI_ECA_Module = ( test ) -> # pathFile = path.resolve 'webpages', 'public', 'style.css' # fl = fs.readFileSync pathFile, 'utf-8' -# hl = require path.join '..', 'js-coffee', 'http-listener' +# hl = require path.join '..', 'js', 'http-listener' # fWaitForTestEnd = () => # console.log 'hl end?' # process.kill() @@ -59,7 +59,7 @@ exports.testsGoInWebAPI_ECA_Module = ( test ) -> # exports.testWrongPort = ( test ) => # test.expect 1 -# hl = require path.join '..', 'js-coffee', 'http-listener' +# hl = require path.join '..', 'js', 'http-listener' # fWaitForTestEnd = () => # console.log 'hl end?' # process.kill() diff --git a/testing/test_logging.coffee b/testing/test_logging.coffee index d1d053e..f1c1507 100644 --- a/testing/test_logging.coffee +++ b/testing/test_logging.coffee @@ -1,7 +1,7 @@ path = require 'path' fs = require 'fs' stdPath = path.resolve __dirname, '..', 'logs', 'server.log' -logger = require path.join '..', 'js-coffee', 'logging' +logger = require path.join '..', 'js', 'logging' getLog = ( strPath, cb ) -> fWait = -> diff --git a/testing/test_persistence.coffee b/testing/test_persistence.coffee index 2f354cb..dc746ef 100644 --- a/testing/test_persistence.coffee +++ b/testing/test_persistence.coffee @@ -9,10 +9,10 @@ try catch err console.log 'Error fetching standard objects file: ' + err.message -logger = require path.join '..', 'js-coffee', 'logging' +logger = require path.join '..', 'js', 'logging' log = logger.getLogger nolog: true -db = require path.join '..', 'js-coffee', 'persistence' +db = require path.join '..', 'js', 'persistence' opts = logger: log opts[ 'db-port' ] = 6379 diff --git a/testing/test_request-handler.coffee b/testing/test_request-handler.coffee index bf0edb5..3d6e39a 100644 --- a/testing/test_request-handler.coffee +++ b/testing/test_request-handler.coffee @@ -14,16 +14,16 @@ try console.log 'Error parsing standard objects file: ' + err.message catch err console.log 'Error fetching standard objects file: ' + err.message -logger = require path.join '..', 'js-coffee', 'logging' +logger = require path.join '..', 'js', 'logging' log = logger.getLogger nolog: true opts = logger: log opts[ 'db-port' ] = 6379 -db = require path.join '..', 'js-coffee', 'persistence' +db = require path.join '..', 'js', 'persistence' db opts -rh = require path.join '..', 'js-coffee', 'request-handler' +rh = require path.join '..', 'js', 'request-handler' opts[ 'request-service' ] = ( usr, obj, cb ) -> test.ok false, 'testEvent should not cause a service request call' opts[ 'shutdown-function' ] = () -> diff --git a/testing/test_webapi-eca.coffee b/testing/test_webapi-eca.coffee index e6c20e2..9d34f3a 100644 --- a/testing/test_webapi-eca.coffee +++ b/testing/test_webapi-eca.coffee @@ -9,7 +9,7 @@ exports.testShutDown = ( test ) -> test.expect 1 isRunning = true - pth = path.resolve 'js-coffee', 'webapi-eca' + pth = path.resolve 'js', 'webapi-eca' engine = cp.fork pth, [ '-n', '-w', '8640' ] # [ '-i' , 'warn' ] engine.on 'error', ( err ) -> @@ -35,7 +35,7 @@ exports.testShutDown = ( test ) -> exports.testKill = ( test ) -> test.expect 1 - pth = path.resolve 'js-coffee', 'webapi-eca' + pth = path.resolve 'js', 'webapi-eca' engine = cp.fork pth, [ '-n', '-w', '8641' ] # [ '-i' , 'warn' ] engine.on 'error', ( err ) -> console.log err @@ -54,7 +54,7 @@ exports.testKill = ( test ) -> exports.testHttpPortAlreadyUsed = ( test ) => test.expect 1 isRunning = true - pth = path.resolve 'js-coffee', 'webapi-eca' + 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... @@ -89,7 +89,7 @@ exports.testHttpPortInvalid = ( test ) -> test.expect 1 isRunning = true - pth = path.resolve 'js-coffee', 'webapi-eca' + 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' @@ -111,7 +111,7 @@ exports.testDbPortInvalid = ( test ) -> test.expect 1 isRunning = true - pth = path.resolve 'js-coffee', 'webapi-eca' + pth = path.resolve 'js', 'webapi-eca' engine = cp.fork pth, [ '-n', '-d', '10'] # [ '-i' , 'warn' ] engine.on 'error', ( err ) -> console.log err diff --git a/unit_tests.sh b/unit_tests.sh index 285a4b7..ced1baf 100755 --- a/unit_tests.sh +++ b/unit_tests.sh @@ -3,7 +3,7 @@ process.chdir( __dirname ); var fs = require( 'fs' ), path = require( 'path' ), nodeunit = require( 'nodeunit' ), - db = require( './js-coffee/persistence' ), + db = require( './js/persistence' ), args = process.argv.slice( 2 ), fEnd = function() { console.log( 'Shutting down DB from unit_test.sh script...' );