webapi-eca/js/components-manager.js

652 lines
20 KiB
JavaScript
Raw Permalink Normal View History

2014-04-05 01:09:40 +00:00
// Generated by CoffeeScript 1.7.1
2013-11-19 13:53:36 +00:00
/*
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.
2014-04-05 01:09:40 +00:00
*/
(function() {
2014-04-26 00:16:06 +00:00
var commandFunctions, db, dynmod, encryption, eventEmitter, events, exports, forgeModule, fs, getModuleParams, getModuleUserArguments, getModuleUserParams, getModules, hasRequiredParams, path, rh, storeModule, storeRule;
db = require('./persistence');
dynmod = require('./dynamic-modules');
2014-04-19 01:49:48 +00:00
encryption = require('./encryption');
2014-04-26 00:16:06 +00:00
rh = require('./request-handler');
fs = require('fs');
path = require('path');
events = require('events');
2014-04-03 15:41:51 +00:00
eventEmitter = new events.EventEmitter();
2014-04-02 21:08:05 +00:00
2014-04-05 01:09:40 +00:00
/*
Module call
-----------
Initializes the Components Manager and constructs a new Event Emitter.
@param {Object} args
2014-04-05 01:09:40 +00:00
*/
2014-04-05 01:09:40 +00:00
exports = module.exports = (function(_this) {
return function(args) {
_this.log = args.logger;
db(args);
dynmod(args);
return module.exports;
};
})(this);
/*
2014-04-03 15:41:51 +00:00
Add an event handler (eh) that listens for rules.
2014-04-03 15:41:51 +00:00
@public addRuleListener ( *eh* )
@param {function} eh
2014-04-05 01:09:40 +00:00
*/
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(userName) {
return function(rule) {
2014-04-21 12:42:26 +00:00
return db.getRule(rule, function(err, strRule) {
2014-04-22 21:46:17 +00:00
var eventInfo, oRule;
2014-04-21 12:42:26 +00:00
try {
oRule = JSON.parse(strRule);
db.resetLog(userName, oRule.id);
2014-04-22 21:46:17 +00:00
eventInfo = '';
2014-04-26 00:16:06 +00:00
if (oRule.eventstart) {
eventInfo = "Starting at " + (new Date(oRule.eventstart)) + ", Interval set to " + oRule.eventinterval + " minutes";
2014-04-22 21:46:17 +00:00
}
db.appendLog(userName, oRule.id, "INIT", "Rule '" + oRule.id + "' initialized. " + eventInfo);
2014-04-21 12:42:26 +00:00
return eventEmitter.emit('rule', {
2014-04-26 00:16:06 +00:00
intevent: 'init',
2014-04-21 12:42:26 +00:00
user: userName,
rule: oRule
});
} catch (_error) {
err = _error;
return _this.log.warn("CM | There's an invalid rule in the system: " + strRule);
}
});
};
2014-04-05 01:09:40 +00:00
};
_results = [];
for (_i = 0, _len = rules.length; _i < _len; _i++) {
rule = rules[_i];
_results.push(fFetchRule(user)(rule));
2014-04-05 01:09:40 +00:00
}
return _results;
2014-04-03 15:41:51 +00:00
};
_results = [];
2014-04-05 01:09:40 +00:00
for (user in objUsers) {
rules = objUsers[user];
_results.push(fGoThroughUsers(user, rules));
2014-04-03 15:41:51 +00:00
}
return _results;
2014-04-05 01:09:40 +00:00
});
};
})(this);
2014-03-27 09:41:18 +00:00
2014-04-01 21:31:54 +00:00
/*
Processes a user request coming through the request-handler.
2014-04-05 01:09:40 +00:00
2014-04-01 21:31:54 +00:00
- `user` is the user object as it comes from the DB.
- `oReq` is the request object that contains:
2014-04-05 01:09:40 +00:00
- `command` as a string
- `body` an optional stringified JSON object
2014-04-01 21:47:54 +00:00
The callback function `callback( obj )` will receive an object
containing the HTTP response code and a corresponding message.
2014-04-01 21:31:54 +00:00
2014-04-01 21:47:54 +00:00
@public processRequest ( *user, oReq, callback* )
2014-04-05 01:09:40 +00:00
*/
2014-04-01 21:31:54 +00:00
2014-04-01 21:47:54 +00:00
exports.processRequest = function(user, oReq, callback) {
2014-04-01 21:31:54 +00:00
var dat, err;
if (!oReq.body) {
oReq.body = '{}';
2014-04-01 21:31:54 +00:00
}
try {
dat = JSON.parse(oReq.body);
2014-04-01 21:31:54 +00:00
} catch (_error) {
err = _error;
2014-04-01 21:47:54 +00:00
return callback({
2014-04-01 21:31:54 +00:00
code: 404,
message: 'You had a strange body in your request!'
2014-04-01 21:31:54 +00:00
});
}
if (commandFunctions[oReq.command]) {
2014-04-01 21:47:54 +00:00
return commandFunctions[oReq.command](user, dat, callback);
2014-03-27 09:41:18 +00:00
} else {
2014-04-01 21:47:54 +00:00
return callback({
2014-03-27 09:41:18 +00:00
code: 404,
2014-04-01 21:47:54 +00:00
message: 'What do you want from me?'
2014-03-27 09:41:18 +00:00
});
}
};
2014-04-05 01:09:40 +00:00
/*
Checks whether all required parameters are present in the body.
2014-04-05 01:09:40 +00:00
@private hasRequiredParams ( *arrParams, oBody* )
2014-04-05 01:09:40 +00:00
@param {Array} arrParams
@param {Object} oBody
2014-04-05 01:09:40 +00:00
*/
hasRequiredParams = function(arrParams, oBody) {
2014-04-01 21:31:54 +00:00
var answ, param, _i, _len;
answ = {
code: 400,
2014-04-03 15:41:51 +00:00
message: "Your request didn't contain all necessary fields! Requires: " + (arrParams.join())
2014-04-01 21:31:54 +00:00
};
for (_i = 0, _len = arrParams.length; _i < _len; _i++) {
param = arrParams[_i];
if (!oBody[param]) {
2014-04-01 21:31:54 +00:00
return answ;
}
}
answ.code = 200;
answ.message = 'All required properties found';
return answ;
};
2014-04-05 01:09:40 +00:00
/*
Fetches all available modules and return them together with the available functions.
@private getModules ( *user, oBody, dbMod, callback* )
2014-04-05 01:09:40 +00:00
@param {Object} user
@param {Object} oBody
2014-04-05 01:09:40 +00:00
@param {Object} dbMod
@param {function} callback
*/
getModules = function(user, oBody, dbMod, callback) {
var fProcessIds;
fProcessIds = function(userName) {
return function(err, arrNames) {
var answReq, fGetFunctions, id, oRes, sem, _i, _len, _results;
oRes = {};
answReq = function() {
return callback({
code: 200,
message: JSON.stringify(oRes)
});
};
sem = arrNames.length;
if (sem === 0) {
return answReq();
} else {
fGetFunctions = (function(_this) {
return function(id) {
return dbMod.getModule(userName, 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];
_results.push(fGetFunctions(id));
}
return _results;
}
};
};
return dbMod.getAvailableModuleIds(user.username, fProcessIds(user.username));
};
getModuleParams = function(user, oBody, dbMod, callback) {
var answ;
answ = hasRequiredParams(['id'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
return dbMod.getModuleField(user.username, oBody.id, "params", function(err, oBody) {
answ.message = oBody;
return callback(answ);
});
}
};
getModuleUserParams = function(user, oBody, dbMod, callback) {
2014-04-19 01:49:48 +00:00
var answ;
answ = hasRequiredParams(['id'], oBody);
2014-04-19 01:49:48 +00:00
if (answ.code !== 200) {
return callback(answ);
} else {
return dbMod.getUserParams(oBody.id, user.username, function(err, str) {
2014-04-19 01:49:48 +00:00
var name, oParam, oParams;
oParams = JSON.parse(str);
for (name in oParams) {
oParam = oParams[name];
if (!oParam.shielded) {
oParam.value = encryption.decrypt(oParam.value);
}
}
answ.message = JSON.stringify(oParams);
return callback(answ);
});
}
};
getModuleUserArguments = function(user, oBody, dbMod, callback) {
2014-04-19 01:49:48 +00:00
var answ;
answ = hasRequiredParams(['ruleId', 'moduleId'], oBody);
2014-04-19 01:49:48 +00:00
if (answ.code !== 200) {
return callback(answ);
} else {
return dbMod.getAllModuleUserArguments(user.username, oBody.ruleId, oBody.moduleId, function(err, oBody) {
answ.message = oBody;
2014-04-19 01:49:48 +00:00
return callback(answ);
});
}
};
2014-04-05 01:09:40 +00:00
forgeModule = (function(_this) {
return function(user, oBody, modType, dbMod, callback) {
2014-04-19 01:49:48 +00:00
var answ;
answ = hasRequiredParams(['id', 'params', 'lang', 'data'], oBody);
2014-04-05 01:09:40 +00:00
if (answ.code !== 200) {
return callback(answ);
} else {
if (oBody.overwrite) {
return storeModule(user, oBody, modType, dbMod, callback);
2014-04-19 01:49:48 +00:00
} else {
return dbMod.getModule(user.username, oBody.id, function(err, mod) {
2014-04-19 01:49:48 +00:00
if (mod) {
answ.code = 409;
answ.message = 'Module name already existing: ' + oBody.id;
2014-04-05 01:09:40 +00:00
return callback(answ);
2014-04-19 01:49:48 +00:00
} else {
return storeModule(user, oBody, modType, dbMod, callback);
2014-04-19 01:49:48 +00:00
}
});
}
}
};
})(this);
storeModule = (function(_this) {
return function(user, oBody, modType, dbMod, callback) {
2014-04-19 01:49:48 +00:00
var src;
src = oBody.data;
return dynmod.compileString(src, user.username, {
id: 'dummyRule'
}, oBody.id, oBody.lang, modType, null, function(cm) {
2014-04-19 01:49:48 +00:00
var answ, 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);
2014-04-05 01:09:40 +00:00
}
2014-04-19 01:49:48 +00:00
_this.log.info("CM | Storing new module with functions " + (funcs.join(', ')));
answ.message = " Module " + oBody.id + " successfully stored! Found following function(s): " + funcs;
oBody.functions = JSON.stringify(funcs);
oBody.functionArgs = JSON.stringify(cm.funcParams);
dbMod.storeModule(user.username, oBody);
2014-04-19 01:49:48 +00:00
}
return callback(answ);
});
};
})(this);
storeRule = (function(_this) {
return function(user, oBody, callback) {
var args, arr, epModId, eventInfo, id, oFuncArgs, oParams, params, rule, strRule;
2014-04-19 01:49:48 +00:00
rule = {
id: oBody.id,
eventtype: oBody.eventtype,
2014-04-26 00:16:06 +00:00
eventname: oBody.eventname,
eventstart: oBody.eventstart,
eventinterval: oBody.eventinterval,
conditions: oBody.conditions,
actions: oBody.actions
2014-04-19 01:49:48 +00:00
};
2014-04-26 00:16:06 +00:00
if (oBody.eventstart) {
rule.timestamp = (new Date()).toISOString();
}
2014-04-19 01:49:48 +00:00
strRule = JSON.stringify(rule);
db.storeRule(rule.id, strRule);
db.linkRule(rule.id, user.username);
db.activateRule(rule.id, user.username);
2014-04-26 00:16:06 +00:00
if (oBody.eventparams) {
epModId = rule.eventname.split(' -> ')[0];
db.eventPollers.storeUserParams(epModId, user.username, JSON.stringify(oBody.eventparams));
2014-04-05 01:09:40 +00:00
}
2014-04-26 00:16:06 +00:00
oFuncArgs = oBody.eventfunctions;
for (id in oFuncArgs) {
args = oFuncArgs[id];
arr = id.split(' -> ');
db.eventPollers.storeUserArguments(user.username, rule.id, arr[0], arr[1], JSON.stringify(args));
}
2014-04-26 00:16:06 +00:00
oParams = oBody.actionparams;
2014-04-19 01:49:48 +00:00
for (id in oParams) {
params = oParams[id];
db.actionInvokers.storeUserParams(id, user.username, JSON.stringify(params));
}
2014-04-26 00:16:06 +00:00
oFuncArgs = oBody.actionfunctions;
for (id in oFuncArgs) {
args = oFuncArgs[id];
2014-04-19 01:49:48 +00:00
arr = id.split(' -> ');
db.actionInvokers.storeUserArguments(user.username, rule.id, arr[0], arr[1], JSON.stringify(args));
2014-04-19 01:49:48 +00:00
}
eventInfo = '';
2014-04-26 00:16:06 +00:00
if (rule.eventstart) {
eventInfo = "Starting at " + (new Date(rule.eventstart)) + ", Interval set to " + rule.eventinterval + " minutes";
}
2014-04-19 01:49:48 +00:00
db.resetLog(user.username, rule.id);
db.appendLog(user.username, rule.id, "INIT", "Rule '" + rule.id + "' initialized. " + eventInfo);
2014-04-19 01:49:48 +00:00
eventEmitter.emit('rule', {
2014-04-26 00:16:06 +00:00
intevent: 'new',
2014-04-19 01:49:48 +00:00
user: user.username,
rule: rule
});
return callback({
code: 200,
message: "Rule '" + rule.id + "' stored and activated!"
});
2014-04-05 01:09:40 +00:00
};
})(this);
commandFunctions = {
get_public_key: function(user, oBody, callback) {
2014-04-03 15:41:51 +00:00
return callback({
code: 200,
2014-04-19 01:49:48 +00:00
message: encryption.getPublicKey()
2014-04-03 15:41:51 +00:00
});
},
get_event_pollers: function(user, oBody, callback) {
return getModules(user, oBody, db.eventPollers, callback);
},
get_full_event_poller: function(user, oBody, callback) {
return db.eventPollers.getModule(user.username, oBody.id, function(err, obj) {
return callback({
code: 200,
message: JSON.stringify(obj)
});
});
},
get_event_poller_params: function(user, oBody, callback) {
return getModuleParams(user, oBody, db.eventPollers, callback);
},
get_event_poller_user_params: function(user, oBody, callback) {
return getModuleUserParams(user, oBody, db.eventPollers, callback);
2014-04-19 01:49:48 +00:00
},
get_event_poller_user_arguments: function(user, oBody, callback) {
return getModuleUserArguments(user, oBody, db.eventPollers, callback);
2014-04-19 01:49:48 +00:00
},
get_event_poller_function_arguments: function(user, oBody, callback) {
var answ;
answ = hasRequiredParams(['id'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
return db.eventPollers.getModuleField(user.username, oBody.id, 'functionArgs', function(err, obj) {
return callback({
code: 200,
message: obj
});
});
}
},
forge_event_poller: function(user, oBody, callback) {
return forgeModule(user, oBody, "eventpoller", db.eventPollers, callback);
},
delete_event_poller: function(user, oBody, callback) {
var answ;
answ = hasRequiredParams(['id'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
db.eventPollers.deleteModule(user.username, oBody.id);
return callback({
code: 200,
message: 'OK!'
});
}
},
get_action_invokers: function(user, oBody, callback) {
return getModules(user, oBody, db.actionInvokers, callback);
},
get_full_action_invoker: function(user, oBody, callback) {
2014-04-09 14:07:31 +00:00
var answ;
answ = hasRequiredParams(['id'], oBody);
2014-04-09 14:07:31 +00:00
if (answ.code !== 200) {
return callback(answ);
} else {
return db.actionInvokers.getModule(user.username, oBody.id, function(err, obj) {
2014-04-09 14:07:31 +00:00
return callback({
code: 200,
message: JSON.stringify(obj)
});
});
2014-04-09 14:07:31 +00:00
}
},
get_action_invoker_params: function(user, oBody, callback) {
return getModuleParams(user, oBody, db.actionInvokers, callback);
},
get_action_invoker_user_params: function(user, oBody, callback) {
return getModuleUserParams(user, oBody, db.actionInvokers, callback);
2014-04-19 01:49:48 +00:00
},
get_action_invoker_user_arguments: function(user, oBody, callback) {
return getModuleUserArguments(user, oBody, db.actionInvokers, callback);
2014-04-19 01:49:48 +00:00
},
get_action_invoker_function_arguments: function(user, oBody, callback) {
2014-04-09 14:07:31 +00:00
var answ;
answ = hasRequiredParams(['id'], oBody);
2014-04-09 14:07:31 +00:00
if (answ.code !== 200) {
return callback(answ);
} else {
return db.actionInvokers.getModuleField(user.username, oBody.id, 'functionArgs', function(err, obj) {
2014-04-09 14:07:31 +00:00
return callback({
code: 200,
message: obj
});
});
}
},
forge_action_invoker: function(user, oBody, callback) {
return forgeModule(user, oBody, "actioninvoker", db.actionInvokers, callback);
2014-03-27 09:41:18 +00:00
},
delete_action_invoker: function(user, oBody, callback) {
var answ;
answ = hasRequiredParams(['id'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
db.actionInvokers.deleteModule(user.username, oBody.id);
return callback({
code: 200,
message: 'OK!'
});
}
},
get_rules: function(user, oBody, callback) {
return db.getUserLinkedRules(user.username, function(err, obj) {
return callback({
code: 200,
message: obj
});
});
},
get_rule: function(user, oBody, callback) {
2014-04-19 01:49:48 +00:00
var answ;
answ = hasRequiredParams(['id'], oBody);
2014-04-19 01:49:48 +00:00
if (answ.code !== 200) {
return callback(answ);
} else {
return db.getRule(oBody.id, function(err, obj) {
2014-04-19 01:49:48 +00:00
return callback({
code: 200,
message: obj
});
});
}
},
get_rule_log: function(user, oBody, callback) {
var answ;
answ = hasRequiredParams(['id'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
return db.getLog(user.username, oBody.id, function(err, obj) {
return callback({
code: 200,
message: obj
});
});
}
},
forge_rule: function(user, oBody, callback) {
2014-04-03 15:41:51 +00:00
var answ;
2014-04-26 00:16:06 +00:00
answ = hasRequiredParams(['id', 'eventname', 'conditions', 'actions'], oBody);
2014-04-03 15:41:51 +00:00
if (answ.code !== 200) {
return callback(answ);
} else {
if (oBody.overwrite) {
return storeRule(user, oBody, callback);
2014-04-19 01:49:48 +00:00
} else {
return db.getRule(oBody.id, (function(_this) {
2014-04-19 01:49:48 +00:00
return function(err, mod) {
if (mod) {
answ.code = 409;
answ.message = 'Rule name already existing: ' + oBody.id;
2014-04-19 01:49:48 +00:00
return callback(answ);
} else {
return storeRule(user, oBody, callback);
2014-04-19 01:49:48 +00:00
}
2014-04-03 15:41:51 +00:00
};
2014-04-19 01:49:48 +00:00
})(this));
}
2014-04-03 15:41:51 +00:00
}
},
delete_rule: function(user, oBody, callback) {
var answ;
answ = hasRequiredParams(['id'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
db.deleteRule(oBody.id);
eventEmitter.emit('rule', {
2014-04-26 00:16:06 +00:00
intevent: 'del',
user: user.username,
rule: null,
ruleId: oBody.id
});
return callback({
code: 200,
message: 'OK!'
});
}
},
create_webhook: function(user, oBody, callback) {
var answ;
answ = hasRequiredParams(['hookname'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
2014-04-26 22:37:15 +00:00
return db.getAllUserWebhookNames(user.username, (function(_this) {
return function(err, arrHooks) {
var hookExists, hookid, hookname;
hookExists = false;
for (hookid in arrHooks) {
hookname = arrHooks[hookid];
if (hookname === oBody.hookname) {
hookExists = true;
}
}
if (hookExists) {
return callback({
code: 409,
message: 'Webhook already existing: ' + oBody.hookname
});
} else {
2014-04-26 22:37:15 +00:00
return db.getAllWebhookIDs(function(err, arrHooks) {
var genHookID;
genHookID = function(arrHooks) {
2014-04-26 22:37:15 +00:00
var i, _i;
hookid = '';
for (i = _i = 0; _i <= 1; i = ++_i) {
hookid += Math.random().toString(36).substring(2);
}
if (arrHooks && arrHooks.indexOf(hookid) > -1) {
2014-04-26 22:37:15 +00:00
hookid = genHookID(arrHooks);
}
2014-04-26 22:37:15 +00:00
return hookid;
};
hookid = genHookID(arrHooks);
db.createWebhook(user.username, hookid, oBody.hookname);
rh.activateWebhook(user.username, hookid, oBody.hookname);
return callback({
code: 200,
message: JSON.stringify({
hookid: hookid,
hookname: oBody.hookname
})
});
});
}
};
})(this));
}
},
get_all_webhooks: function(user, oBody, callback) {
2014-04-26 22:37:15 +00:00
return db.getAllUserWebhookNames(user.username, function(err, data) {
if (err) {
return callback({
code: 400,
message: "We didn't like your request!"
});
} else {
2014-04-26 22:37:15 +00:00
data = JSON.stringify(data) || null;
return callback({
code: 200,
message: data
});
}
});
},
delete_webhook: function(user, oBody, callback) {
var answ;
2014-04-26 00:16:06 +00:00
answ = hasRequiredParams(['hookid'], oBody);
if (answ.code !== 200) {
return callback(answ);
} else {
2014-04-26 00:16:06 +00:00
rh.deactivateWebhook(oBody.hookid);
db.deleteWebhook(user.username, oBody.hookid);
return callback({
code: 200,
message: 'OK!'
});
}
2014-04-03 15:41:51 +00:00
}
};
}).call(this);