started with db_interface in coffee script, changed comment style

This commit is contained in:
Dominic Bosch 2013-11-21 00:20:06 +01:00
parent 8c115aa71d
commit 13c3f49c80
8 changed files with 917 additions and 359 deletions

View file

@ -1,3 +1,10 @@
###
Config
======
Loads the configuration file and acts as an interface to it.
###
'use strict'
path = require 'path'
@ -5,8 +12,9 @@ log = require './logging'
fs = require 'fs'
config = null
###
##Module call
Calling the module as a function will make it look for the `relPath` property in the
args object and then try to load a config file from that relative path.
@param {Object} args
@ -19,14 +27,14 @@ exports = module.exports = (args) ->
module.exports
###
@Function loadConfigFile
Tries to load a configuration file from the path relative to this module's parent folder.
Reads the config file synchronously from the file system and try to parse it.
@private loadConfigFile
@param {String} relPath
###
loadConfigFile = (relPath) ->
try
### We read the config file synchronously from the file system and try to parse it ###
config = JSON.parse fs.readFileSync path.resolve __dirname, '..', relPath
if config and config.http_port and config.db_port and
config.crypto_key and config.session_secret
@ -43,31 +51,45 @@ loadConfigFile = (relPath) ->
loadConfigFile path.join('config', 'config.json')
### Answer true if the config file is ready, else false ###
exports.isReady = -> config?
###
Fetch a property from the configuration
@private fetchProp( *prop* )
@param {String} prop
###
fetchProp = (prop) -> config?[prop]
###
Get the HTTP port
Answer true if the config file is ready, else false
@public isReady()
###
exports.isReady = -> config?
###
Returns the HTTP port
@public getHttpPort()
###
exports.getHttpPort = -> fetchProp 'http_port'
###
Get the DB port
Returns the DB port
@public getDBPort()
###
exports.getDBPort = -> fetchProp 'db_port'
###
Get the crypto key
Returns the crypto key
@public getCryptoKey()
###
exports.getCryptoKey = -> fetchProp 'crypto_key'
###
Get the session secret
Returns the session secret
@public getSessionSecret()
###
exports.getSessionSecret = -> fetchProp 'session_secret'

352
coffee/db_interface.coffee Normal file
View file

@ -0,0 +1,352 @@
###
DB Interface
============
>Handles the connection to the database and provides functionalities for
>event/action modules, rules and the encrypted storing of authentication tokens.
>General functionality as a wrapper for the module holds initialization,
>encryption/decryption, the retrieval of modules and shut down.
>
>The general structure for linked data is that the key is stored in a set.
>By fetching all set entries we can then fetch all elements, which is
>automated in this function.
>For example modules of the same group, e.g. action modules are registered in an
>unordered set in the database, from where they can be retrieved again. For example
>a new action module has its ID (e.g 'probinder') first registered in the set
>'action_modules' and then stored in the db with the key 'action\_module\_' + ID
>(e.g. action\_module\_probinder).
>
###
'use strict'
### Grab all required modules ###
redis = require 'redis'
crypto = require 'crypto'
log = require './logging'
crypto_key = null
db = null
###
##Module call
Initializes the DB connection. Requires a valid configuration file which contains
a db port and a crypto key.
@param {Object} args
###
exports = module.exports = (args) ->
args = args ? {}
log args
config = require './config'
config args
crypto_key = config.getCryptoKey()
db = redis.createClient config.getDBPort(), 'localhost', { connect_timeout: 2000 }
db.on "error", (err) ->
err.addInfo = 'message from DB'
log.error 'DB', err
###
Checks whether the db is connected and calls the callback function if successful,
or an error after ten attempts within five seconds.
@public isConnected( *cb* )
@param {function} cb
###
#}TODO check if timeout works with func in func
exports.isConnected = (cb) ->
if db.connected then cb()
else
numAttempts = 0
fCheckConnection = ->
if db.connected
log.print 'DB', 'Successfully connected to DB!'
cb()
else if numAttempts++ < 10
setTimeout fCheckConnection, 500
else
e = new Error 'Connection to DB failed!'
log.error 'DB', e
cb e
setTimeout fCheckConnection, 500
###
Encrypts a string using the crypto key from the config file, based on aes-256-cbc.
@private encrypt( *plainText* )
@param {String} plainText
###
encrypt = (plainText) ->
if !plainText? then return null
try
enciph = crypto.createCipher 'aes-256-cbc', crypto_key
et = enciph.update plainText, 'utf8', 'base64'
et + enciph.final 'base64'
catch err
err.addInfo = 'during encryption'
log.error 'DB', err
null
###
Decrypts an encrypted string and hands it back on success or null.
@private decrypt( *crypticText* )
@param {String} crypticText
###
decrypt = (crypticText) ->
if !crypticText? then return null;
try
deciph = crypto.createDecipher 'aes-256-cbc', crypto_key
dt = deciph.update crypticText, 'base64', 'utf8'
dt + deciph.final 'utf8'
catch err
err.addInfo = 'during decryption'
log.error 'DB', err
null
###
Abstracts logging for simple action replies from the DB.
@private replyHandler( *action* )
@param {String} action
###
replyHandler = (action) ->
(err, reply) ->
if err
err.addInfo = 'during "' + action + '"'
log.error 'DB', err
else
log.print 'DB', action + ': ' + reply
###
Fetches all linked data set keys from a linking set, fetches the single data objects
via the provided function and returns the results to the callback function.
@private getSetRecords( *set, fSingle, cb* )
@param {String} set the set name how it is stored in the DB
@param {function} fSingle a function to retrieve a single data element per set entry
@param {function} cb the callback function that receives all the retrieved data or an error
###
getSetRecords = (set, funcSingle, cb) ->
db?.smembers set, (err, arrReply) ->
if err
err.addInfo = 'fetching ' + set
log.error 'DB', err
else if arrReply.length == 0
cb()
else
semaphore = arrReply.length
objReplies = {}
# } TODO What if the DB needs longer than two seconds to respond?...
setTimeout ->
if semaphore > 0
cb new Error('Timeout fetching ' + set)
, 2000
fCallback = (prop) ->
(err, data) ->
if err
err.addInfo = 'fetching single element: ' + prop
log.error 'DB', err
else
objReplies[prop] = data
if --semaphore == 0
cb null, objReplies
fSingle reply, fCallback(reply) for reply in arrReply
###
@Function shutDown()
Shuts down the db link.
###
###exports.shutDown = function() { if(db) db.quit(); };
###
###
## Action Modules
@Function storeActionModule
Store a string representation of an action module in the DB.
@param {String} id the unique identifier of the module
@param {String} data the string representation
###
###exports.storeActionModule = function(id, data) {
if(db) {
db.sadd('action_modules', id, replyHandler('storing action module key ' + id));
db.set('action_module_' + id, data, replyHandler('storing action module ' + id));
}
};
###
###
@Function getActionModule(id, cb)
Query the DB for an action module.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
###
###exports.getActionModule = function(id, cb) {
if(cb && db) db.get('action_module_' + id, cb);
};
###
###
@Function getActionModules(cb)
Fetch all action modules.
@param {function} cb the cb to receive the answer (err, obj)
###
###exports.getActionModules = function(cb) {
getSetRecords('action_modules', exports.getActionModule, cb);
};
###
###
@Function storeActionModuleAuth(id, data)
Store a string representation of the authentication parameters for an action module.
@param {String} id the unique identifier of the module
@param {String} data the string representation
###
###exports.storeActionModuleAuth = function(id, data) {
if(data && db) {
db.sadd('action_modules_auth', id, replyHandler('storing action module auth key ' + id));
db.set('action_module_' + id +'_auth', encrypt(data), replyHandler('storing action module auth ' + id));
}
};
###
###
@Function getActionModuleAuth(id, cb)
Query the DB for an action module authentication token.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
###
###exports.getActionModuleAuth = function(id, cb) {
if(cb && db) db.get('action_module_' + id + '_auth', function(id) {
return function(err, txt) { cb(err, decrypt(txt, 'action_module_' + id + '_auth')); };
}(id));
};
###
###
## Event Modules
@Function storeEventModule(id, data)
Store a string representation of an event module in the DB.
@param {String} id the unique identifier of the module
@param {String} data the string representation
###
###exports.storeEventModule = function(id, data) {
if(db) {
db.sadd('event_modules', id, replyHandler('storing event module key ' + id));
db.set('event_module_' + id, data, replyHandler('storing event module ' + id));
}
};
###
###
@Function getEventModule(id, cb)
Query the DB for an event module.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
###
###exports.getEventModule = function(id, cb) {
if(cb && db) db.get('event_module_' + id, cb);
};
###
###
@Function getEventModules(cb)
Fetch all event modules.
@param {function} cb the cb that receives the arguments (err, obj)
###
###exports.getEventModules = function(cb) {
getSetRecords('event_modules', exports.getEventModule, cb);
};
###
###
@Function storeEventModuleAuth(id, data)
Store a string representation of he authentication parameters for an event module.
@param {String} id the unique identifier of the module
@param {String} data the string representation
###
###exports.storeEventModuleAuth = function(id, data) {
if(data && db) {
db.sadd('event_modules_auth', id, replyHandler('storing event module auth key ' + id));
db.set('event_module_' + id +'_auth', encrypt(data), replyHandler('storing event module auth ' + id));
}
};
###
###
@Function getEventModuleAuth(id, cb)
Query the DB for an event module authentication token.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
###
###exports.getEventModuleAuth = function(id, cb) {
if(cb) db.get('event_module_' + id +'_auth', function(id) {
return function(err, txt) { cb(err, decrypt(txt, 'event_module_' + id + '_auth')); };
}(id));
};
###
###
## Rules
@Function storeRule(id, data)
Store a string representation of a rule in the DB.
@param {String} id the unique identifier of the rule
@param {String} data the string representation
###
###exports.storeRule = function(id, data) {
if(db) {
db.sadd('rules', id, replyHandler('storing rule key ' + id));
db.set('rule_' + id, data, replyHandler('storing rule ' + id));
}
};
###
###
@Function getRule(id, cb)
Query the DB for a rule.
@param {String} id the rule id
@param {function} cb the cb to receive the answer (err, obj)
###
###exports.getRule = function(id, cb) {
if(db) db.get('rule_' + id, cb);
};
###
###
@Function getRules(cb)
Fetch all rules from the database.
@param {function} cb
###
###exports.getRules = function(cb) {
getSetRecords('rules', exports.getRule, cb);
};
###
###
@Function storeUser
@param {Object} objUser
@param {function} cb
###
###exports.storeUser = function(objUser, cb) {
if(db && objUser && objUser.username && objUser.password) {
db.sadd('users', objUser.username, replyHandler('storing user key ' + objUser.username));
objUser.password = encrypt(objUser.password);
db.set('user:' + objUser.username, objUser, replyHandler('storing user properties ' + objUser.username));
}
};
###
###
Checks the credentials and on success returns the user object.
@param {Object} objUser
@param {function} cb
###
### exports.loginUser = function(username, password, cb) {
if(typeof cb !== 'function') return;
if(db) db.get('user:' + username, function(p) {
return function(err, obj) {
if(err) cb(err);
else if(encrypt(obj.password) === p) cb(null, obj);
else cb(new Error('Wrong credentials!'));
};
}(password));
else cb(new Error('No database link available!'));
};
###

View file

@ -1,4 +1,3 @@
###
Rules Server
============
@ -57,8 +56,9 @@ process.on 'uncaughtException', (err) ->
null
###
## Initialize the Server
This function is invoked right after the module is loaded and starts the server.
@private init()
###
init = ->
@ -103,15 +103,17 @@ init = ->
log.print 'RS', 'Passing handlers to engine'
engine.addDBLinkAndLoadActionsAndRules db
log.print 'RS', 'Passing handlers to http listener'
http_listener.addHandlers db, handleAdminCommands, engine.pushEvent
http_listener.addHandlers db, fAdminCommands, engine.pushEvent
log.print 'RS', 'Passing handlers to module manager'
mm.addHandlers db, engine.loadActionModule, engine.addRule
###
admin commands handler receives all command arguments and an answerHandler
object that eases response handling to the HTTP request issuer.
@private fAdminCommands( *args, answHandler* )
###
handleAdminCommands = (args, answHandler) ->
fAdminCommands = (args, answHandler) ->
if args and args.cmd
adminCmds[args.cmd]? args, answHandler
else
@ -137,6 +139,8 @@ handleAdminCommands = (args, answHandler) ->
###
Shuts down the server.
@private shutDown( *args, answHandler* )
@param {Object} args
@param {Object} answHandler
###

View file

@ -1,3 +1,23 @@
/*
* # groc Documentation
* Create the documentation to be displayed through the webserver.
*/
//
require('groc').CLI(
[
"README.md",
"LICENSE.md",
"coffee/*.coffee",
"mod_actions/**/*.js",
"mod_events/**/*.js",
"-o./webpages/doc"
],
function(err) {
if (err) console.error(err);
else console.log('Done!');
}
);
/*
* # docco Documentation
@ -28,23 +48,3 @@
// }
// });
// }
/*
* # groc Documentation
* Create the documentation to be displayed through the webserver.
*/
//
require('groc').CLI(
[
"README.md",
"LICENSE.md",
"coffee/*.coffee",
"mod_actions/**/*.js",
"mod_events/**/*.js",
"-o./webpages/doc"
],
function(err) {
if (err) console.error(err);
else console.log('Done!');
}
);

View file

@ -1,4 +1,13 @@
// Generated by CoffeeScript 1.6.3
/*
Config
======
Loads the configuration file and acts as an interface to it.
*/
(function() {
'use strict';
var config, exports, fetchProp, fs, loadConfigFile, log, path;
@ -12,6 +21,8 @@
config = null;
/*
##Module call
Calling the module as a function will make it look for the `relPath` property in the
args object and then try to load a config file from that relative path.
@param {Object} args
@ -28,9 +39,10 @@
};
/*
@Function loadConfigFile
Tries to load a configuration file from the path relative to this module's parent folder.
Reads the config file synchronously from the file system and try to parse it.
@private loadConfigFile
@param {String} relPath
*/
@ -38,8 +50,6 @@
loadConfigFile = function(relPath) {
var e;
try {
/* We read the config file synchronously from the file system and try to parse it*/
config = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', relPath)));
if (config && config.http_port && config.db_port && config.crypto_key && config.session_secret) {
return log.print('CF', 'config file loaded successfully');
@ -55,15 +65,10 @@
loadConfigFile(path.join('config', 'config.json'));
/* Answer true if the config file is ready, else false*/
exports.isReady = function() {
return config != null;
};
/*
Fetch a property from the configuration
@private fetchProp( *prop* )
@param {String} prop
*/
@ -73,7 +78,20 @@
};
/*
Get the HTTP port
Answer true if the config file is ready, else false
@public isReady()
*/
exports.isReady = function() {
return config != null;
};
/*
Returns the HTTP port
@public getHttpPort()
*/
@ -82,7 +100,9 @@
};
/*
Get the DB port
Returns the DB port
@public getDBPort()
*/
@ -91,7 +111,9 @@
};
/*
Get the crypto key
Returns the crypto key
@public getCryptoKey()
*/
@ -100,7 +122,9 @@
};
/*
Get the session secret
Returns the session secret
@public getSessionSecret()
*/

View file

@ -1,322 +1,473 @@
/**
* # DB Interface
* Handles the connection to the database and provides functionalities for
* event/action modules, rules and the encrypted storing of authentication tokens.
*
* ## General
* General functionality as a wrapper for the module holds initialization,
* encryption/decryption, the retrieval of modules and shut down.
* Modules of the same group, e.g. action modules are registered in an unordered
* set in the database, from where they can be retrieved again. For example a new
* action module has its ID (e.g 'probinder') first registered in the set
* 'action_modules' and then stored in the db with the key 'action\_module\_' + ID
* (e.g. action\_module\_probinder).
*/
'use strict';
// Generated by CoffeeScript 1.6.3
/*
var redis = require('redis'),
crypto = require('crypto'),
log = require('./logging'),
crypto_key, db;
DB Interface
============
>Handles the connection to the database and provides functionalities for
>event/action modules, rules and the encrypted storing of authentication tokens.
>General functionality as a wrapper for the module holds initialization,
>encryption/decryption, the retrieval of modules and shut down.
>
>The general structure for linked data is that the key is stored in a set.
>By fetching all set entries we can then fetch all elements, which is
>automated in this function.
>For example modules of the same group, e.g. action modules are registered in an
>unordered set in the database, from where they can be retrieved again. For example
>a new action module has its ID (e.g 'probinder') first registered in the set
>'action_modules' and then stored in the db with the key 'action\_module\_' + ID
>(e.g. action\_module\_probinder).
>
*/
/**
* Initializes the DB connection. Requires a valid configuration file which contains
* a db port and a crypto key.
*
*/
exports = module.exports = function(args) {
args = args || {};
log(args);
(function() {
'use strict';
/* Grab all required modules*/
var crypto, crypto_key, db, decrypt, encrypt, exports, getSetRecords, log, redis, replyHandler;
redis = require('redis');
crypto = require('crypto');
log = require('./logging');
crypto_key = null;
db = null;
/*
##Module call
var config = require('./config')(args);
crypto_key = config.getCryptoKey();
db = redis.createClient(config.getDBPort(), 'localhost', { connect_timeout: 2000 });
db.on("error", function (err) {
err.addInfo = 'message from DB';
log.error('DB', err);
});
return module.exports;
};
Initializes the DB connection. Requires a valid configuration file which contains
a db port and a crypto key.
@param {Object} args
*/
exports.isConnected = function(cb) {
if(db.connected) cb(null);
else setTimeout(function() {
if(db.connected) {
log.print('DB', 'Successfully connected to DB!');
cb(null);
} else {
var e = new Error('Connection to DB failed!');
log.error('DB', e);
cb(e);
}
}, 3000);
};
/**
* ### encrypt
* this is used to decrypt
* @param {String} plainText
*/
function encrypt(plainText) {
if(!plainText) return null;
try {
var enciph = crypto.createCipher('aes-256-cbc', crypto_key);
var et = enciph.update(plainText, 'utf8', 'base64') + enciph.final('base64');
log.print('DB', 'Encrypted credentials into: ' + et);
return et;
} catch (err) {
log.error('DB', 'in encrypting: ' + err);
return null;
}
}
/**
* ### decrypt
*/
function decrypt(crypticText, id) {
if(!crypticText) return null;
try {
var deciph = crypto.createDecipher('aes-256-cbc', crypto_key);
return deciph.update(crypticText, 'base64', 'utf8') + deciph.final('utf8');
} catch (err) {
log.error('DB', 'in decrypting "' + id + '": ' + err);
return null;
}
}
/**
* ### replyHandler
* Abstraction answer handling for simple information replies from the DB.
* @param {String} action the action to be displayed in the output string.
*/
function replyHandler(action) {
return function(err, reply) {
if(err) log.error('DB', ' during "' + action + '": ' + err);
else log.print('DB', action + ': ' + reply);
exports = module.exports = function(args) {
var config;
args = args != null ? args : {};
log(args);
config = require('./config');
config(args);
crypto_key = config.getCryptoKey();
db = redis.createClient(config.getDBPort(), 'localhost', {
connect_timeout: 2000
});
return db.on("error", function(err) {
err.addInfo = 'message from DB';
return log.error('DB', err);
});
};
}
/**
* ### getSetRecords
* The general structure for modules is that the key is stored in a set.
* By fetching all set entries we can then fetch all modules, which is
* automated in this function.
*
* @param {String} set the set name how it is stored in the DB
* @param {function} funcSingle the function that fetches single entries from the DB
* @param {function} cb the function to be called on success or error, receives
* arguments (err, obj)
*/
function getSetRecords(set, funcSingle, cb) {
if(db) db.smembers(set, function(err, reply) {
if(err) log.error('DB', 'fetching ' + set + ': ' + err);
else {
if(reply.length === 0) {
cb(null, null);
} else {
var semaphore = reply.length, objReplies = {};
setTimeout(function() {
if(semaphore > 0) {
cb('Timeout fetching ' + set, null);
}
}, 1000);
for(var i = 0; i < reply.length; i++){
funcSingle(reply[i], function(prop) {
return function(err, reply) {
if(err) log.error('DB', ' fetching single element: ' + prop);
else {
objReplies[prop] = reply;
if(--semaphore === 0) cb(null, objReplies);
}
};
}(reply[i]));
/*
Checks whether the db is connected and calls the callback function if successful,
or an error after ten attempts within five seconds.
@public isConnected( *cb* )
@param {function} cb
*/
exports.isConnected = function(cb) {
var fCheckConnection, numAttempts;
if (db.connected) {
return cb();
} else {
numAttempts = 0;
fCheckConnection = function() {
var e;
if (db.connected) {
log.print('DB', 'Successfully connected to DB!');
return cb();
} else if (numAttempts++ < 10) {
return setTimeout(fCheckConnection, 500);
} else {
e = new Error('Connection to DB failed!');
log.error('DB', e);
return cb(e);
}
}
};
return setTimeout(fCheckConnection, 500);
}
});
}
};
// @method shutDown()
// Shuts down the db link.
exports.shutDown = function() { if(db) db.quit(); };
/*
Encrypts a string using the crypto key from the config file, based on aes-256-cbc.
@private encrypt( *plainText* )
@param {String} plainText
*/
// ## Action Modules
encrypt = function(plainText) {
var enciph, err, et;
if (plainText == null) {
return null;
}
try {
enciph = crypto.createCipher('aes-256-cbc', crypto_key);
et = enciph.update(plainText, 'utf8', 'base64');
return et + enciph.final('base64');
} catch (_error) {
err = _error;
err.addInfo = 'during encryption';
log.error('DB', err);
return null;
}
};
/**
* ### storeActionModule
* Store a string representation of an action module in the DB.
* @param {String} id the unique identifier of the module
* @param {String} data the string representation
*/
exports.storeActionModule = function(id, data) {
if(db) {
db.sadd('action_modules', id, replyHandler('storing action module key ' + id));
db.set('action_module_' + id, data, replyHandler('storing action module ' + id));
}
};
/*
Decrypts an encrypted string and hands it back on success or null.
@private decrypt( *crypticText* )
@param {String} crypticText
*/
/**
* ### getActionModule(id, cb)
* Query the DB for an action module.
* @param {String} id the module id
* @param {function} cb the cb to receive the answer (err, obj)
*/
exports.getActionModule = function(id, cb) {
if(cb && db) db.get('action_module_' + id, cb);
};
/**
* ### getActionModules(cb)
* Fetch all action modules.
* @param {function} cb the cb to receive the answer (err, obj)
*/
exports.getActionModules = function(cb) {
getSetRecords('action_modules', exports.getActionModule, cb);
};
decrypt = function(crypticText) {
var deciph, dt, err;
if (crypticText == null) {
return null;
}
try {
deciph = crypto.createDecipher('aes-256-cbc', crypto_key);
dt = deciph.update(crypticText, 'base64', 'utf8');
return dt + deciph.final('utf8');
} catch (_error) {
err = _error;
err.addInfo = 'during decryption';
log.error('DB', err);
return null;
}
};
/**
* storeActionModuleAuth(id, data)
* Store a string representation of the authentication parameters for an action module.
* @param {String} id the unique identifier of the module
* @param {String} data the string representation
*/
exports.storeActionModuleAuth = function(id, data) {
if(data && db) {
db.sadd('action_modules_auth', id, replyHandler('storing action module auth key ' + id));
db.set('action_module_' + id +'_auth', encrypt(data), replyHandler('storing action module auth ' + id));
}
};
/*
Abstracts logging for simple action replies from the DB.
@private replyHandler( *action* )
@param {String} action
*/
/**
* ### getActionModuleAuth(id, cb)
* Query the DB for an action module authentication token.
* @param {String} id the module id
* @param {function} cb the cb to receive the answer (err, obj)
*/
exports.getActionModuleAuth = function(id, cb) {
if(cb && db) db.get('action_module_' + id + '_auth', function(id) {
return function(err, txt) { cb(err, decrypt(txt, 'action_module_' + id + '_auth')); };
}(id));
};
// ## Event Modules
/**
* ### storeEventModule(id, data)
* Store a string representation of an event module in the DB.
* @param {String} id the unique identifier of the module
* @param {String} data the string representation
*/
exports.storeEventModule = function(id, data) {
if(db) {
db.sadd('event_modules', id, replyHandler('storing event module key ' + id));
db.set('event_module_' + id, data, replyHandler('storing event module ' + id));
}
};
/**
* ### getEventModule(id, cb)
* Query the DB for an event module.
* @param {String} id the module id
* @param {function} cb the cb to receive the answer (err, obj)
*/
exports.getEventModule = function(id, cb) {
if(cb && db) db.get('event_module_' + id, cb);
};
/**
* ### getEventModules(cb)
* Fetch all event modules.
* @param {function} cb the cb that receives the arguments (err, obj)
*/
exports.getEventModules = function(cb) {
getSetRecords('event_modules', exports.getEventModule, cb);
};
/**
* ### storeEventModuleAuth(id, data)
* Store a string representation of he authentication parameters for an event module.
* @param {String} id the unique identifier of the module
* @param {String} data the string representation
*/
exports.storeEventModuleAuth = function(id, data) {
if(data && db) {
db.sadd('event_modules_auth', id, replyHandler('storing event module auth key ' + id));
db.set('event_module_' + id +'_auth', encrypt(data), replyHandler('storing event module auth ' + id));
}
};
// @method getEventModuleAuth(id, cb)
// Query the DB for an event module authentication token.
// @param {String} id the module id
// @param {function} cb the cb to receive the answer (err, obj)
exports.getEventModuleAuth = function(id, cb) {
if(cb) db.get('event_module_' + id +'_auth', function(id) {
return function(err, txt) { cb(err, decrypt(txt, 'event_module_' + id + '_auth')); };
}(id));
};
// ## Rules
// @method storeRule(id, data)
// Store a string representation of a rule in the DB.
// @param {String} id the unique identifier of the rule
// @param {String} data the string representation
exports.storeRule = function(id, data) {
if(db) {
db.sadd('rules', id, replyHandler('storing rule key ' + id));
db.set('rule_' + id, data, replyHandler('storing rule ' + id));
}
};
// @method getRule(id, cb)
// Query the DB for a rule.
// @param {String} id the rule id
// @param {function} cb the cb to receive the answer (err, obj)
exports.getRule = function(id, cb) {
if(db) db.get('rule_' + id, cb);
};
// @method getRules(cb)
// Fetch all rules from the database.
// @param {function} cb
exports.getRules = function(cb) {
getSetRecords('rules', exports.getRule, cb);
};
/**
*
* @param {Object} objUser
* @param {function} cb
*/
exports.storeUser = function(objUser, cb) {
if(db && objUser && objUser.username && objUser.password) {
db.sadd('users', objUser.username, replyHandler('storing user key ' + objUser.username));
objUser.password = encrypt(objUser.password);
db.set('user:' + objUser.username, objUser, replyHandler('storing user properties ' + objUser.username));
}
};
/**
* Checks the credentials and on success returns the user object.
* @param {Object} objUser
* @param {function} cb
*/
exports.loginUser = function(username, password, cb) {
if(typeof cb !== 'function') return;
if(db) db.get('user:' + username, function(p) {
return function(err, obj) {
if(err) cb(err);
else if(encrypt(obj.password) === p) cb(null, obj);
else cb(new Error('Wrong credentials!'));
replyHandler = function(action) {
return function(err, reply) {
if (err) {
err.addInfo = 'during "' + action + '"';
return log.error('DB', err);
} else {
return log.print('DB', action + ': ' + reply);
}
};
}(password));
else cb(new Error('No database link available!'));
};
};
/*
Fetches all linked data set keys from a linking set, fetches the single data objects
via the provided function and returns the results to the callback function.
@private getSetRecords( *set, fSingle, cb* )
@param {String} set the set name how it is stored in the DB
@param {function} fSingle a function to retrieve a single data element per set entry
@param {function} cb the callback function that receives all the retrieved data or an error
*/
getSetRecords = function(set, funcSingle, cb) {
return db != null ? db.smembers(set, function(err, arrReply) {
var fCallback, objReplies, reply, semaphore, _i, _len, _results;
if (err) {
err.addInfo = 'fetching ' + set;
return log.error('DB', 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) {
if (err) {
err.addInfo = 'fetching single element: ' + prop;
return log.error('DB', err);
} 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)));
}
return _results;
}
}) : void 0;
};
/*
@Function shutDown()
Shuts down the db link.
*/
/*exports.shutDown = function() { if(db) db.quit(); };
*/
/*
## Action Modules
@Function storeActionModule
Store a string representation of an action module in the DB.
@param {String} id the unique identifier of the module
@param {String} data the string representation
*/
/*exports.storeActionModule = function(id, data) {
if(db) {
db.sadd('action_modules', id, replyHandler('storing action module key ' + id));
db.set('action_module_' + id, data, replyHandler('storing action module ' + id));
}
};
*/
/*
@Function getActionModule(id, cb)
Query the DB for an action module.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
*/
/*exports.getActionModule = function(id, cb) {
if(cb && db) db.get('action_module_' + id, cb);
};
*/
/*
@Function getActionModules(cb)
Fetch all action modules.
@param {function} cb the cb to receive the answer (err, obj)
*/
/*exports.getActionModules = function(cb) {
getSetRecords('action_modules', exports.getActionModule, cb);
};
*/
/*
@Function storeActionModuleAuth(id, data)
Store a string representation of the authentication parameters for an action module.
@param {String} id the unique identifier of the module
@param {String} data the string representation
*/
/*exports.storeActionModuleAuth = function(id, data) {
if(data && db) {
db.sadd('action_modules_auth', id, replyHandler('storing action module auth key ' + id));
db.set('action_module_' + id +'_auth', encrypt(data), replyHandler('storing action module auth ' + id));
}
};
*/
/*
@Function getActionModuleAuth(id, cb)
Query the DB for an action module authentication token.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
*/
/*exports.getActionModuleAuth = function(id, cb) {
if(cb && db) db.get('action_module_' + id + '_auth', function(id) {
return function(err, txt) { cb(err, decrypt(txt, 'action_module_' + id + '_auth')); };
}(id));
};
*/
/*
## Event Modules
@Function storeEventModule(id, data)
Store a string representation of an event module in the DB.
@param {String} id the unique identifier of the module
@param {String} data the string representation
*/
/*exports.storeEventModule = function(id, data) {
if(db) {
db.sadd('event_modules', id, replyHandler('storing event module key ' + id));
db.set('event_module_' + id, data, replyHandler('storing event module ' + id));
}
};
*/
/*
@Function getEventModule(id, cb)
Query the DB for an event module.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
*/
/*exports.getEventModule = function(id, cb) {
if(cb && db) db.get('event_module_' + id, cb);
};
*/
/*
@Function getEventModules(cb)
Fetch all event modules.
@param {function} cb the cb that receives the arguments (err, obj)
*/
/*exports.getEventModules = function(cb) {
getSetRecords('event_modules', exports.getEventModule, cb);
};
*/
/*
@Function storeEventModuleAuth(id, data)
Store a string representation of he authentication parameters for an event module.
@param {String} id the unique identifier of the module
@param {String} data the string representation
*/
/*exports.storeEventModuleAuth = function(id, data) {
if(data && db) {
db.sadd('event_modules_auth', id, replyHandler('storing event module auth key ' + id));
db.set('event_module_' + id +'_auth', encrypt(data), replyHandler('storing event module auth ' + id));
}
};
*/
/*
@Function getEventModuleAuth(id, cb)
Query the DB for an event module authentication token.
@param {String} id the module id
@param {function} cb the cb to receive the answer (err, obj)
*/
/*exports.getEventModuleAuth = function(id, cb) {
if(cb) db.get('event_module_' + id +'_auth', function(id) {
return function(err, txt) { cb(err, decrypt(txt, 'event_module_' + id + '_auth')); };
}(id));
};
*/
/*
## Rules
@Function storeRule(id, data)
Store a string representation of a rule in the DB.
@param {String} id the unique identifier of the rule
@param {String} data the string representation
*/
/*exports.storeRule = function(id, data) {
if(db) {
db.sadd('rules', id, replyHandler('storing rule key ' + id));
db.set('rule_' + id, data, replyHandler('storing rule ' + id));
}
};
*/
/*
@Function getRule(id, cb)
Query the DB for a rule.
@param {String} id the rule id
@param {function} cb the cb to receive the answer (err, obj)
*/
/*exports.getRule = function(id, cb) {
if(db) db.get('rule_' + id, cb);
};
*/
/*
@Function getRules(cb)
Fetch all rules from the database.
@param {function} cb
*/
/*exports.getRules = function(cb) {
getSetRecords('rules', exports.getRule, cb);
};
*/
/*
@Function storeUser
@param {Object} objUser
@param {function} cb
*/
/*exports.storeUser = function(objUser, cb) {
if(db && objUser && objUser.username && objUser.password) {
db.sadd('users', objUser.username, replyHandler('storing user key ' + objUser.username));
objUser.password = encrypt(objUser.password);
db.set('user:' + objUser.username, objUser, replyHandler('storing user properties ' + objUser.username));
}
};
*/
/*
Checks the credentials and on success returns the user object.
@param {Object} objUser
@param {function} cb
*/
/* exports.loginUser = function(username, password, cb) {
if(typeof cb !== 'function') return;
if(db) db.get('user:' + username, function(p) {
return function(err, obj) {
if(err) cb(err);
else if(encrypt(obj.password) === p) cb(null, obj);
else cb(new Error('Wrong credentials!'));
};
}(password));
else cb(new Error('No database link available!'));
};
*/
}).call(this);

View file

@ -23,7 +23,7 @@ Rules Server
'use strict';
/* Grab all required modules*/
var adminCmds, args, conf, db, engine, handleAdminCommands, http_listener, init, log, mm, path, procCmds, shutDown;
var adminCmds, args, conf, db, engine, fAdminCommands, http_listener, init, log, mm, path, procCmds, shutDown;
path = require('path');
@ -77,8 +77,9 @@ Rules Server
});
/*
## Initialize the Server
This function is invoked right after the module is loaded and starts the server.
@private init()
*/
@ -137,7 +138,7 @@ Rules Server
log.print('RS', 'Passing handlers to engine');
engine.addDBLinkAndLoadActionsAndRules(db);
log.print('RS', 'Passing handlers to http listener');
http_listener.addHandlers(db, handleAdminCommands, engine.pushEvent);
http_listener.addHandlers(db, fAdminCommands, engine.pushEvent);
log.print('RS', 'Passing handlers to module manager');
return mm.addHandlers(db, engine.loadActionModule, engine.addRule);
}
@ -147,10 +148,12 @@ Rules Server
/*
admin commands handler receives all command arguments and an answerHandler
object that eases response handling to the HTTP request issuer.
@private fAdminCommands( *args, answHandler* )
*/
handleAdminCommands = function(args, answHandler) {
fAdminCommands = function(args, answHandler) {
var fAnsw, _name;
if (args && args.cmd) {
if (typeof adminCmds[_name = args.cmd] === "function") {
@ -185,6 +188,8 @@ Rules Server
/*
Shuts down the server.
@private shutDown( *args, answHandler* )
@param {Object} args
@param {Object} answHandler
*/

View file

@ -10,9 +10,7 @@
},
"dependencies": {
"connect-redis": "1.4.6",
"docco": "0.6.2",
"express": "3.4.0",
"glob" :"3.2.7",
"groc": "0.6.1",
"needle": "0.6.1",
"nodeunit": "0.8.2",
@ -21,6 +19,8 @@
},
"__comment": {
"dependencies": {
"glob" :"3.2.7",
"docco": "0.6.2",
"groc": "0.6.1",
"diff": "1.0.5",
"socket.io": "0.9.16",