2014-04-05 01:09:40 +00:00
|
|
|
// Generated by CoffeeScript 1.7.1
|
|
|
|
|
|
2014-04-05 00:05:51 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
Dynamic Modules
|
|
|
|
|
===============
|
|
|
|
|
> Compiles CoffeeScript modules and loads JS modules in a VM, together
|
|
|
|
|
> with only a few allowed node.js modules.
|
2014-04-05 01:09:40 +00:00
|
|
|
*/
|
2014-04-05 00:05:51 +00:00
|
|
|
|
|
|
|
|
(function() {
|
2014-04-22 21:42:31 +00:00
|
|
|
var cryptoJS, cs, db, encryption, exports, fPushEvent, fTryToLoadModule, getFunctionParamNames, importio, logFunction, needle, regexpComments, request, vm;
|
2014-04-05 00:05:51 +00:00
|
|
|
|
|
|
|
|
db = require('./persistence');
|
|
|
|
|
|
2014-04-19 01:49:48 +00:00
|
|
|
encryption = require('./encryption');
|
|
|
|
|
|
2014-04-05 00:05:51 +00:00
|
|
|
vm = require('vm');
|
|
|
|
|
|
|
|
|
|
needle = require('needle');
|
|
|
|
|
|
2014-04-06 19:36:34 +00:00
|
|
|
request = require('request');
|
|
|
|
|
|
2014-04-05 00:05:51 +00:00
|
|
|
cs = require('coffee-script');
|
|
|
|
|
|
2014-04-06 19:36:34 +00:00
|
|
|
cryptoJS = require('crypto-js');
|
|
|
|
|
|
2014-04-16 15:42:56 +00:00
|
|
|
importio = require('import-io').client;
|
|
|
|
|
|
2014-04-05 01:09:40 +00:00
|
|
|
|
2014-04-05 00:05:51 +00:00
|
|
|
/*
|
|
|
|
|
Module call
|
|
|
|
|
-----------
|
|
|
|
|
Initializes the dynamic module handler.
|
|
|
|
|
|
|
|
|
|
@param {Object} args
|
2014-04-05 01:09:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
exports = module.exports = (function(_this) {
|
|
|
|
|
return function(args) {
|
|
|
|
|
_this.log = args.logger;
|
|
|
|
|
return module.exports;
|
|
|
|
|
};
|
|
|
|
|
})(this);
|
|
|
|
|
|
2014-04-05 17:02:03 +00:00
|
|
|
logFunction = function(uId, rId, mId) {
|
|
|
|
|
return function(msg) {
|
|
|
|
|
return db.appendLog(uId, rId, mId, msg);
|
|
|
|
|
};
|
|
|
|
|
};
|
2014-04-05 01:09:40 +00:00
|
|
|
|
2014-04-09 14:07:31 +00:00
|
|
|
regexpComments = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
|
|
|
|
|
|
|
|
|
|
getFunctionParamNames = function(fName, func, oFuncs) {
|
|
|
|
|
var fnStr, result;
|
|
|
|
|
fnStr = func.toString().replace(regexpComments, '');
|
|
|
|
|
result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(/([^\s,]+)/g);
|
|
|
|
|
if (!result) {
|
|
|
|
|
result = [];
|
|
|
|
|
}
|
|
|
|
|
return oFuncs[fName] = result;
|
|
|
|
|
};
|
|
|
|
|
|
2014-04-05 00:05:51 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Try to run a JS module from a string, together with the
|
|
|
|
|
given parameters. If it is written in CoffeeScript we
|
|
|
|
|
compile it first into JS.
|
|
|
|
|
|
|
|
|
|
@public compileString ( *src, id, params, lang* )
|
|
|
|
|
@param {String} src
|
|
|
|
|
@param {String} id
|
|
|
|
|
@param {Object} params
|
|
|
|
|
@param {String} lang
|
2014-04-05 01:09:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
exports.compileString = (function(_this) {
|
2014-04-22 21:42:31 +00:00
|
|
|
return function(src, userId, oRule, modId, lang, modType, dbMod, cb) {
|
2014-04-16 15:42:56 +00:00
|
|
|
var err;
|
2014-04-05 01:09:40 +00:00
|
|
|
if (lang === 'CoffeeScript') {
|
2014-04-05 00:05:51 +00:00
|
|
|
try {
|
2014-04-16 15:42:56 +00:00
|
|
|
_this.log.info("DM | Compiling module '" + modId + "' for user '" + userId + "'");
|
2014-04-05 01:09:40 +00:00
|
|
|
src = cs.compile(src);
|
2014-04-05 00:05:51 +00:00
|
|
|
} catch (_error) {
|
|
|
|
|
err = _error;
|
2014-04-16 15:42:56 +00:00
|
|
|
cb({
|
2014-04-16 21:38:41 +00:00
|
|
|
answ: {
|
|
|
|
|
code: 400,
|
|
|
|
|
message: 'Compilation of CoffeeScript failed at line ' + err.location.first_line
|
|
|
|
|
}
|
2014-04-16 15:42:56 +00:00
|
|
|
});
|
|
|
|
|
return;
|
2014-04-05 00:05:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
2014-04-16 15:42:56 +00:00
|
|
|
_this.log.info("DM | Trying to fetch user specific module '" + modId + "' paramters for user '" + userId + "'");
|
|
|
|
|
if (dbMod) {
|
|
|
|
|
return dbMod.getUserParams(modId, userId, function(err, obj) {
|
2014-04-19 01:49:48 +00:00
|
|
|
var name, oParam, oParams, _ref;
|
2014-04-05 01:09:40 +00:00
|
|
|
try {
|
2014-04-19 01:49:48 +00:00
|
|
|
oParams = {};
|
|
|
|
|
_ref = JSON.parse(obj);
|
|
|
|
|
for (name in _ref) {
|
|
|
|
|
oParam = _ref[name];
|
|
|
|
|
oParams[name] = encryption.decrypt(oParam.value);
|
|
|
|
|
}
|
2014-04-22 21:42:31 +00:00
|
|
|
_this.log.info("DM | Loaded user defined params for " + userId + ", " + oRule.id + ", " + modId);
|
2014-04-05 01:09:40 +00:00
|
|
|
} catch (_error) {
|
|
|
|
|
err = _error;
|
2014-04-22 21:42:31 +00:00
|
|
|
_this.log.warn("DM | Error during parsing of user defined params for " + userId + ", " + oRule.id + ", " + modId);
|
2014-04-05 17:02:03 +00:00
|
|
|
_this.log.warn(err);
|
2014-04-06 00:22:39 +00:00
|
|
|
}
|
2014-04-22 21:42:31 +00:00
|
|
|
return fTryToLoadModule(userId, oRule, modId, src, modType, dbMod, oParams, cb);
|
2014-04-05 01:09:40 +00:00
|
|
|
});
|
2014-04-16 15:42:56 +00:00
|
|
|
} else {
|
2014-04-22 21:42:31 +00:00
|
|
|
return fTryToLoadModule(userId, oRule, modId, src, modType, dbMod, null, cb);
|
2014-04-16 15:42:56 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
})(this);
|
|
|
|
|
|
2014-04-22 21:42:31 +00:00
|
|
|
fPushEvent = function(userId, oRule, modType) {
|
|
|
|
|
return function(obj) {
|
2014-04-26 00:16:06 +00:00
|
|
|
var timestamp;
|
2014-04-22 21:42:31 +00:00
|
|
|
timestamp = (new Date()).toISOString();
|
|
|
|
|
if (modType === 'eventpoller') {
|
|
|
|
|
return db.pushEvent({
|
2014-04-26 00:16:06 +00:00
|
|
|
eventname: oRule.eventname + '_created:' + oRule.timestamp,
|
2014-04-24 15:34:00 +00:00
|
|
|
body: obj
|
2014-04-22 21:42:31 +00:00
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
return db.pushEvent(obj);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2014-04-16 15:42:56 +00:00
|
|
|
fTryToLoadModule = (function(_this) {
|
2014-04-22 21:42:31 +00:00
|
|
|
return function(userId, oRule, modId, src, modType, dbMod, params, cb) {
|
2014-04-19 20:35:05 +00:00
|
|
|
var answ, err, fName, fRegisterArguments, func, logFunc, msg, oFuncArgs, oFuncParams, sandbox, _ref;
|
2014-04-16 15:42:56 +00:00
|
|
|
if (!params) {
|
|
|
|
|
params = {};
|
|
|
|
|
}
|
2014-04-16 21:38:41 +00:00
|
|
|
answ = {
|
|
|
|
|
code: 200,
|
|
|
|
|
message: 'Successfully compiled'
|
|
|
|
|
};
|
2014-04-16 15:42:56 +00:00
|
|
|
_this.log.info("DM | Running module '" + modId + "' for user '" + userId + "'");
|
2014-04-22 21:42:31 +00:00
|
|
|
logFunc = logFunction(userId, oRule.id, modId);
|
2014-04-16 15:42:56 +00:00
|
|
|
sandbox = {
|
2014-04-22 21:42:31 +00:00
|
|
|
id: "" + userId + "." + oRule.id + "." + modId + ".vm",
|
2014-04-16 15:42:56 +00:00
|
|
|
params: params,
|
|
|
|
|
needle: needle,
|
|
|
|
|
importio: importio,
|
|
|
|
|
request: request,
|
|
|
|
|
cryptoJS: cryptoJS,
|
|
|
|
|
log: logFunc,
|
|
|
|
|
debug: console.log,
|
2014-04-22 21:42:31 +00:00
|
|
|
exports: {},
|
2014-04-24 07:32:29 +00:00
|
|
|
setTimeout: setTimeout,
|
2014-04-22 21:42:31 +00:00
|
|
|
pushEvent: fPushEvent(userId, oRule, modType)
|
2014-04-05 01:09:40 +00:00
|
|
|
};
|
2014-04-16 15:42:56 +00:00
|
|
|
try {
|
|
|
|
|
vm.runInNewContext(src, sandbox, sandbox.id);
|
|
|
|
|
} catch (_error) {
|
|
|
|
|
err = _error;
|
|
|
|
|
answ.code = 400;
|
|
|
|
|
msg = err.message;
|
|
|
|
|
if (!msg) {
|
|
|
|
|
msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number';
|
|
|
|
|
}
|
|
|
|
|
answ.message = 'Loading Module failed: ' + msg;
|
|
|
|
|
}
|
2014-04-22 21:42:31 +00:00
|
|
|
_this.log.info("DM | Module '" + modId + "' ran successfully for user '" + userId + "' in rule '" + oRule.id + "'");
|
2014-04-16 15:42:56 +00:00
|
|
|
oFuncParams = {};
|
|
|
|
|
oFuncArgs = {};
|
|
|
|
|
_ref = sandbox.exports;
|
|
|
|
|
for (fName in _ref) {
|
|
|
|
|
func = _ref[fName];
|
|
|
|
|
getFunctionParamNames(fName, func, oFuncParams);
|
|
|
|
|
}
|
2014-04-05 01:09:40 +00:00
|
|
|
if (dbMod) {
|
2014-04-16 15:42:56 +00:00
|
|
|
oFuncArgs = {};
|
2014-04-19 20:35:05 +00:00
|
|
|
fRegisterArguments = function(fName) {
|
|
|
|
|
return function(err, obj) {
|
2014-04-16 21:38:41 +00:00
|
|
|
if (obj) {
|
|
|
|
|
try {
|
2014-04-19 20:35:05 +00:00
|
|
|
oFuncArgs[fName] = JSON.parse(obj);
|
2014-04-22 21:42:31 +00:00
|
|
|
return _this.log.info("DM | Found and attached user-specific arguments to " + userId + ", " + oRule.id + ", " + modId + ": " + obj);
|
2014-04-16 21:38:41 +00:00
|
|
|
} catch (_error) {
|
|
|
|
|
err = _error;
|
2014-04-22 21:42:31 +00:00
|
|
|
_this.log.warn("DM | Error during parsing of user-specific arguments for " + userId + ", " + oRule.id + ", " + modId);
|
2014-04-16 21:38:41 +00:00
|
|
|
return _this.log.warn(err);
|
|
|
|
|
}
|
2014-04-16 15:42:56 +00:00
|
|
|
}
|
2014-04-19 20:35:05 +00:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
for (func in oFuncParams) {
|
2014-04-22 21:42:31 +00:00
|
|
|
dbMod.getUserArguments(userId, oRule.id, modId, func, fRegisterArguments(func));
|
2014-04-16 15:42:56 +00:00
|
|
|
}
|
2014-04-05 00:05:51 +00:00
|
|
|
}
|
2014-04-16 15:42:56 +00:00
|
|
|
return cb({
|
|
|
|
|
answ: answ,
|
|
|
|
|
module: sandbox.exports,
|
|
|
|
|
funcParams: oFuncParams,
|
|
|
|
|
funcArgs: oFuncArgs,
|
|
|
|
|
logger: sandbox.log
|
|
|
|
|
});
|
2014-04-05 00:05:51 +00:00
|
|
|
};
|
2014-04-05 01:09:40 +00:00
|
|
|
})(this);
|
2014-04-05 00:05:51 +00:00
|
|
|
|
|
|
|
|
}).call(this);
|