mirror of
https://github.com/Hopiu/webapi-eca.git
synced 2026-03-16 22:10:31 +00:00
major implementations to get a running server
This commit is contained in:
parent
a8f85d74c3
commit
8a6d357439
30 changed files with 2262 additions and 784 deletions
323
coffee/components-manager.coffee
Normal file
323
coffee/components-manager.coffee
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
###
|
||||
|
||||
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.
|
||||
|
||||
###
|
||||
|
||||
# **Loads Modules:**
|
||||
|
||||
# - [Persistence](persistence.html)
|
||||
db = require './persistence'
|
||||
# - [Dynamic Modules](dynamic-modules.html)
|
||||
dynmod = require './dynamic-modules'
|
||||
|
||||
# - Node.js Modules: [fs](http://nodejs.org/api/fs.html),
|
||||
# [vm](http://nodejs.org/api/vm.html) and
|
||||
# [path](http://nodejs.org/api/path.html),
|
||||
# [events](http://nodejs.org/api/events.html)
|
||||
fs = require 'fs'
|
||||
vm = require 'vm'
|
||||
path = require 'path'
|
||||
events = require 'events'
|
||||
|
||||
###
|
||||
Module call
|
||||
-----------
|
||||
Initializes the HTTP listener and its request handler.
|
||||
|
||||
@param {Object} args
|
||||
###
|
||||
exports = module.exports = ( args ) =>
|
||||
@log = args.logger
|
||||
@ee = new events.EventEmitter()
|
||||
db args
|
||||
dynmod args
|
||||
module.exports
|
||||
|
||||
exports.addListener = ( evt, eh ) =>
|
||||
@ee.addListener evt, eh
|
||||
#TODO as soon as an event handler is added it needs to receive the
|
||||
#full list of existing and activated rules
|
||||
|
||||
|
||||
# cb ( obj ) where obj should contain at least the HTTP response code and a message
|
||||
exports.processRequest = ( user, obj, cb ) =>
|
||||
if commandFunctions[obj.command]
|
||||
answ = commandFunctions[obj.command] user, obj, cb
|
||||
else
|
||||
cb
|
||||
code: 404
|
||||
message: 'Strange request!'
|
||||
|
||||
commandFunctions =
|
||||
forge_event_poller: ( user, obj, cb ) =>
|
||||
answ =
|
||||
code: 200
|
||||
|
||||
db.getEventPoller obj.id, ( err, mod ) =>
|
||||
if mod
|
||||
answ.code = 409
|
||||
answ.message = 'Event Poller module name already existing: ' + obj.id
|
||||
|
||||
else
|
||||
src = obj.data
|
||||
cm = dynmod.compileString src, obj.id, {}, obj.lang
|
||||
answ = cm.answ
|
||||
if answ.code is 200
|
||||
events = []
|
||||
events.push name for name, id of cm.module
|
||||
@log.info "CM | Storing new eventpoller with events #{ events }"
|
||||
answ.message =
|
||||
"Event Poller module successfully stored! Found following event(s): #{ events }"
|
||||
db.storeEventPoller obj.id, user.username,
|
||||
code: obj.data
|
||||
lang: obj.lang
|
||||
params: obj.params
|
||||
events: events
|
||||
if obj.public is 'true'
|
||||
db.publishEventPoller obj.id
|
||||
cb answ
|
||||
|
||||
get_event_pollers: ( user, obj, cb ) ->
|
||||
db.getAvailableEventPollerIds user.username, ( err, obj ) ->
|
||||
oRes = {}
|
||||
sem = obj.length
|
||||
fGetEvents = ( id ) ->
|
||||
db.getEventPoller id, ( err, obj ) ->
|
||||
oRes[id] = obj.events
|
||||
if --sem is 0
|
||||
cb
|
||||
code: 200
|
||||
message: oRes
|
||||
fGetEvents id for id in obj
|
||||
|
||||
get_event_poller_params: ( user, obj, cb ) ->
|
||||
db.getEventPollerRequiredParams obj.id, ( err, obj ) ->
|
||||
cb
|
||||
code: 200
|
||||
message: obj
|
||||
|
||||
get_action_invokers: ( user, obj, cb ) ->
|
||||
db.getAvailableActionInvokerIds user.username, ( err, obj ) ->
|
||||
oRes = {}
|
||||
sem = obj.length
|
||||
fGetActions = ( id ) ->
|
||||
db.getActionInvoker id, ( err, obj ) ->
|
||||
oRes[id] = obj.actions
|
||||
if --sem is 0
|
||||
cb
|
||||
code: 200
|
||||
message: oRes
|
||||
fGetActions id for id in obj
|
||||
|
||||
get_action_invoker_params: ( user, obj, cb ) ->
|
||||
db.getActionInvokerRequiredParams obj.id, ( err, obj ) ->
|
||||
cb
|
||||
code: 200
|
||||
message: obj
|
||||
|
||||
forge_action_invoker: ( user, obj, cb ) =>
|
||||
answ =
|
||||
code: 200
|
||||
|
||||
db.getActionInvoker obj.id, ( err, mod ) =>
|
||||
if mod
|
||||
answ.code = 409
|
||||
answ.message = 'Action Invoker module name already existing: ' + obj.id
|
||||
|
||||
else
|
||||
src = obj.data
|
||||
cm = dynmod.compileString src, obj.id, {}, obj.lang
|
||||
answ = cm.answ
|
||||
if answ.code is 200
|
||||
actions = []
|
||||
actions.push name for name, id of cm.module
|
||||
@log.info "CM | Storing new eventpoller with actions #{ actions }"
|
||||
answ.message =
|
||||
"Action Invoker module successfully stored! Found following action(s): #{ actions }"
|
||||
db.storeActionInvoker obj.id, user.username,
|
||||
code: obj.data
|
||||
lang: obj.lang
|
||||
params: obj.params
|
||||
actions: actions
|
||||
if obj.public is 'true'
|
||||
db.publishActionInvoker obj.id
|
||||
cb answ
|
||||
|
||||
get_rules: ( user, obj, cb ) ->
|
||||
console.log 'CM | Implement get_rules'
|
||||
|
||||
forge_rule: ( user, obj, cb ) =>
|
||||
obj.event = JSON.parse obj.event
|
||||
console.log obj
|
||||
db.getRule obj.id, ( err, objRule ) =>
|
||||
if objRule isnt null
|
||||
answ =
|
||||
code: 409
|
||||
message: 'Rule name already existing!'
|
||||
else
|
||||
answ =
|
||||
code: 200
|
||||
message: 'Rule stored and activated!'
|
||||
rule =
|
||||
id: obj.id
|
||||
event: "#{ obj.event.module } -> #{ obj.event.function }"
|
||||
conditions: JSON.parse obj.conditions
|
||||
actions: JSON.parse obj.actions
|
||||
console.log rule
|
||||
modules = JSON.parse obj.event.action_params
|
||||
console.log 'store rule'
|
||||
db.storeRule rule.id, JSON.stringify rule
|
||||
console.log 'link rule'
|
||||
db.linkRule rule.id, user.username
|
||||
console.log 'activate rule'
|
||||
db.activateRule rule.id, user.username
|
||||
console.log 'store event params'
|
||||
db.storeEventUserParams obj.event.module, user.username, obj.event_params
|
||||
console.log 'store action params'
|
||||
db.storeActionUserParams id, user.username, params for id, params of modules
|
||||
#TODO implement ID approach, check for existing
|
||||
|
||||
@ee.emit 'newRule', rule
|
||||
cb answ
|
||||
|
||||
# exports.loadModule = function(directory, name, callback) {
|
||||
# try {
|
||||
# fs.readFile(path.resolve(__dirname, '..', directory, name, name + '.js'), 'utf8', function (err, data) {
|
||||
# if (err) {
|
||||
# log.error('LM', 'Loading module file!');
|
||||
# return;
|
||||
# }
|
||||
# var mod = exports.requireFromString(data, name, directory);
|
||||
# if(mod && fs.existsSync(path.resolve(__dirname, '..', directory, name, 'credentials.json'))) {
|
||||
# fs.readFile(path.resolve(__dirname, '..', directory, name, 'credentials.json'), 'utf8', function (err, auth) {
|
||||
# if (err) {
|
||||
# log.error('LM', 'Loading credentials file for "' + name + '"!');
|
||||
# callback(name, data, mod, null);
|
||||
# return;
|
||||
# }
|
||||
# if(mod.loadCredentials) mod.loadCredentials(JSON.parse(auth));
|
||||
# callback(name, data, mod, auth);
|
||||
# });
|
||||
# } else {
|
||||
# // Hand back the name, the string contents and the compiled module
|
||||
# callback(name, data, mod, null);
|
||||
# }
|
||||
# });
|
||||
# } catch(err) {
|
||||
# log.error('LM', 'Failed loading module "' + name + '"');
|
||||
# }
|
||||
# };
|
||||
|
||||
# exports.loadModules = function(directory, callback) {
|
||||
# fs.readdir(path.resolve(__dirname, '..', directory), function (err, list) {
|
||||
# if (err) {
|
||||
# log.error('LM', 'loading modules directory: ' + err);
|
||||
# return;
|
||||
# }
|
||||
# log.info('LM', 'Loading ' + list.length + ' modules from "' + directory + '"');
|
||||
# list.forEach(function (file) {
|
||||
# fs.stat(path.resolve(__dirname, '..', directory, file), function (err, stat) {
|
||||
# if (stat && stat.isDirectory()) {
|
||||
# exports.loadModule(directory, file, callback);
|
||||
# }
|
||||
# });
|
||||
# });
|
||||
# });
|
||||
# };
|
||||
|
||||
|
||||
# exports.storeEventModule = function (objUser, obj, answHandler) {
|
||||
# try {
|
||||
# // TODO in the future we might want to link the modules close to the user
|
||||
# // and allow for e.g. private modules
|
||||
# // we need a child process to run this code and kill it after invocation
|
||||
# var m = exports.requireFromString(obj.data, obj.id);
|
||||
# obj.methods = Object.keys(m);
|
||||
# answHandler.answerSuccess('Thank you for the event module!');
|
||||
# db.storeEventModule(obj.id, obj);
|
||||
# } catch (err) {
|
||||
# answHandler.answerError(err.message);
|
||||
# console.error(err);
|
||||
# }
|
||||
# };
|
||||
|
||||
# exports.getAllEventModules = function ( objUser, obj, answHandler ) {
|
||||
# db.getEventModules(function(err, obj) {
|
||||
# if(err) answHandler.answerError('Failed fetching event modules: ' + err.message);
|
||||
# else answHandler.answerSuccess(obj);
|
||||
# });
|
||||
# };
|
||||
|
||||
# exports.storeActionModule = function (objUser, obj, answHandler) {
|
||||
# var m = exports.requireFromString(obj.data, obj.id);
|
||||
# obj.methods = Object.keys(m);
|
||||
# answHandler.answerSuccess('Thank you for the action module!');
|
||||
# db.storeActionModule(obj.id, obj);
|
||||
# };
|
||||
|
||||
# exports.getAllActionModules = function ( objUser, obj, answHandler ) {
|
||||
# db.getActionModules(function(err, obj) {
|
||||
# if(err) answHandler.answerError('Failed fetching action modules: ' + err.message);
|
||||
# else answHandler.answerSuccess(obj);
|
||||
# });
|
||||
# };
|
||||
|
||||
# exports.storeRule = function (objUser, obj, answHandler) {
|
||||
# //TODO fix, twice same logic
|
||||
# var cbEventModule = function (lstParams) {
|
||||
# return function(err, data) {
|
||||
# if(err) {
|
||||
# err.addInfo = 'fetching event module';
|
||||
# log.error('MM', err);
|
||||
# }
|
||||
# if(!err && data) {
|
||||
# if(data.params) {
|
||||
# lstParams.eventmodules[data.id] = data.params;
|
||||
# }
|
||||
# }
|
||||
# if(--semaphore === 0) answHandler.answerSuccess(lstParams);
|
||||
# };
|
||||
# };
|
||||
# var cbActionModule = function (lstParams) {
|
||||
# return function(err, data) {
|
||||
# if(err) {
|
||||
# err.addInfo = 'fetching action module';
|
||||
# log.error('MM', err);
|
||||
# }
|
||||
# if(!err && data) {
|
||||
# if(data.params) {
|
||||
# lstParams.actionmodules[data.id] = data.params;
|
||||
# }
|
||||
# }
|
||||
# if(--semaphore === 0) answHandler.answerSuccess(lstParams);
|
||||
# };
|
||||
# };
|
||||
|
||||
# var semaphore = 1;
|
||||
# var lst = {
|
||||
# eventmodules: {},
|
||||
# actionmodules: {}
|
||||
# };
|
||||
# try {
|
||||
# var objRule = JSON.parse(obj.data);
|
||||
# for(var i = 0; i < objRule.actions.length; i++) {
|
||||
# semaphore++;
|
||||
# db.getActionModule(objRule.actions[i].module.split('->')[0], cbActionModule(lst));
|
||||
# }
|
||||
# db.getEventModule(objRule.event.split('->')[0], cbEventModule(lst));
|
||||
# db.storeRule(objRule.id, objUser.username, obj.data);
|
||||
# ee.emit('newRule', objRule);
|
||||
# // for( var i = 0; i < eventHandlers.length; i++ ) {
|
||||
# // eventHandlers[i]( objRule );
|
||||
# // }
|
||||
# } catch(err) {
|
||||
# answHandler.answerError(err.message);
|
||||
# log.error('MM', err);
|
||||
# }
|
||||
|
||||
# };
|
||||
71
coffee/dynamic-modules.coffee
Normal file
71
coffee/dynamic-modules.coffee
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
###
|
||||
|
||||
Dynamic Modules
|
||||
===============
|
||||
> Compiles CoffeeScript modules and loads JS modules in a VM, together
|
||||
> with only a few allowed node.js modules.
|
||||
###
|
||||
|
||||
# - Node.js Modules: [vm](http://nodejs.org/api/vm.html) and
|
||||
# [events](http://nodejs.org/api/events.html)
|
||||
vm = require 'vm'
|
||||
needle = require 'needle'
|
||||
|
||||
# - External Modules: [coffee-script](http://coffeescript.org/)
|
||||
cs = require 'coffee-script'
|
||||
|
||||
###
|
||||
Module call
|
||||
-----------
|
||||
Initializes the dynamic module handler.
|
||||
|
||||
@param {Object} args
|
||||
###
|
||||
exports = module.exports = ( args ) =>
|
||||
@log = args.logger
|
||||
module.exports
|
||||
|
||||
|
||||
###
|
||||
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
|
||||
###
|
||||
exports.compileString = ( src, id, params, lang ) =>
|
||||
answ =
|
||||
code: 200
|
||||
message: 'Successfully compiled'
|
||||
src = "'use strict;'\n" + src
|
||||
if lang is '0'
|
||||
try
|
||||
src = cs.compile src
|
||||
catch err
|
||||
answ.code = 400
|
||||
answ.message = 'Compilation of CoffeeScript failed at line ' +
|
||||
err.location.first_line
|
||||
|
||||
#FIXME not log but debug module is required to provide information to the user
|
||||
sandbox =
|
||||
id: id
|
||||
params: params
|
||||
needle: needle
|
||||
log: @log
|
||||
exports: {}
|
||||
#TODO child_process to run module!
|
||||
#Define max runtime per loop as 10 seconds, after that the child will be killed
|
||||
#it can still be active after that if there was a timing function or a callback used...
|
||||
#kill the child each time? how to determine whether there's still a token in the module?
|
||||
try
|
||||
vm.runInNewContext src, sandbox, id + '.vm'
|
||||
catch err
|
||||
answ.code = 400
|
||||
answ.message = 'Loading Module failed: ' + err.message
|
||||
ret =
|
||||
answ: answ
|
||||
module: sandbox.exports
|
||||
|
|
@ -44,7 +44,7 @@ exports = module.exports = ( args ) =>
|
|||
# Eventually we try to connect to the wrong port, redis will emit an error that we
|
||||
# need to catch and take into account when answering the isConnected function call
|
||||
@db.on 'error', ( err ) =>
|
||||
if err.message.indexOf 'ECONNREFUSED' > -1
|
||||
if err.message.indexOf( 'ECONNREFUSED' ) > -1
|
||||
@connRefused = true
|
||||
@log.error err, 'DB | Wrong port?'
|
||||
@ep = new IndexedModules( 'event-poller', @db, @log )
|
||||
|
|
@ -161,7 +161,7 @@ decrypt = ( crypticText ) =>
|
|||
if !crypticText? then return null;
|
||||
try
|
||||
dec = crypto.AES.decrypt crypticText, @crypto_key
|
||||
dec.toString(crypto.enc.Utf8)
|
||||
dec.toString crypto.enc.Utf8
|
||||
catch err
|
||||
@log.warn err, 'DB | during decryption'
|
||||
null
|
||||
|
|
@ -220,8 +220,9 @@ getSetRecords = ( set, fSingle, cb ) =>
|
|||
# Since we retrieved an array of keys, we now execute the fSingle function
|
||||
# on each of them, to retrieve the ata behind the key. Our fCallback function
|
||||
# is used to preprocess the answer to determine correct execution
|
||||
fSingle reply, fCallback( reply ) for reply in arrReply
|
||||
fSingle reply, fCallback reply for reply in arrReply
|
||||
|
||||
# TODO remove specific functions and allow direct access to instances of this class
|
||||
class IndexedModules
|
||||
constructor: ( @setname, @db, @log ) ->
|
||||
@log.info "DB | Instantiated indexed modules for '#{ @setname }'"
|
||||
|
|
@ -230,12 +231,50 @@ class IndexedModules
|
|||
@log.info "DB | storeModule(#{ @setname }): #{ mId }"
|
||||
@db.sadd "#{ @setname }s", mId,
|
||||
replyHandler "Storing '#{ @setname }' key '#{ mId }'"
|
||||
@db.set "#{ @setname }:#{ mId }", data,
|
||||
@db.hmset "#{ @setname }:#{ mId }", data,
|
||||
replyHandler "Storing '#{ @setname }:#{ mId }'"
|
||||
|
||||
#TODO add testing
|
||||
linkModule: ( mId, userId ) =>
|
||||
@log.info "DB | linkModule(#{ @setname }): #{ mId } to #{ userId }"
|
||||
@db.sadd "#{ @setname }:#{ mId }:users", userId,
|
||||
replyHandler "Linking '#{ @setname }:#{ mId }:users' #{ userId }"
|
||||
@db.sadd "user:#{ userId }:#{ @setname }s", mId,
|
||||
replyHandler "Linking 'user:#{ userId }:#{ @setname }s' #{ mId }"
|
||||
|
||||
#TODO add testing
|
||||
unlinkModule: ( mId, userId ) =>
|
||||
@log.info "DB | unlinkModule(#{ @setname }): #{ mId } to #{ userId }"
|
||||
@db.srem "#{ @setname }:#{ mId }:users", userId,
|
||||
replyHandler "Unlinking '#{ @setname }:#{ mId }:users' #{ userId }"
|
||||
@db.srem "user:#{ userId }:#{ @setname }s", mId,
|
||||
replyHandler "Unlinking 'user:#{ userId }:#{ @setname }s' #{ mId }"
|
||||
|
||||
#TODO add testing
|
||||
publish: ( mId ) =>
|
||||
@log.info "DB | publish(#{ @setname }): #{ mId }"
|
||||
@db.sadd "public-#{ @setname }s", mId,
|
||||
replyHandler "Publishing '#{ @setname }' key '#{ mId }'"
|
||||
|
||||
#TODO add testing
|
||||
unpublish: ( mId ) =>
|
||||
@log.info "DB | unpublish(#{ @setname }): #{ mId }"
|
||||
@db.srem "public-#{ @setname }s", mId,
|
||||
replyHandler "Unpublishing '#{ @setname }' key '#{ mId }'"
|
||||
|
||||
getModule: ( mId, cb ) =>
|
||||
@log.info "DB | getModule('#{ @setname }): #{ mId }'"
|
||||
@db.get "#{ @setname }:#{ mId }", cb
|
||||
@db.hgetall "#{ @setname }:#{ mId }", cb
|
||||
|
||||
#TODO add testing
|
||||
getModuleParams: ( mId, cb ) =>
|
||||
@log.info "DB | getModule('#{ @setname }): #{ mId }'"
|
||||
@db.hget "#{ @setname }:#{ mId }", "params", cb
|
||||
|
||||
#TODO add testing
|
||||
getAvailableModuleIds: ( userId, cb ) =>
|
||||
@log.info "DB | getPublicModuleIds(#{ @setname })"
|
||||
@db.sunion "public-#{ @setname }s", "user:#{ userId }:#{ @setname }s", cb
|
||||
|
||||
getModuleIds: ( cb ) =>
|
||||
@log.info "DB | getModuleIds(#{ @setname })"
|
||||
|
|
@ -251,25 +290,27 @@ class IndexedModules
|
|||
replyHandler "Deleting '#{ @setname }' key '#{ mId }'"
|
||||
@db.del "#{ @setname }:#{ mId }",
|
||||
replyHandler "Deleting '#{ @setname }:#{ mId }'"
|
||||
#TODO remove published ids
|
||||
#TODO remove from linked users
|
||||
|
||||
storeParameters: ( mId, userId, data ) =>
|
||||
@log.info "DB | storeParameters(#{ @setname }): '#{ mId }:#{ userId }'"
|
||||
storeUserParameters: ( mId, userId, data ) =>
|
||||
@log.info "DB | storeUserParameters(#{ @setname }): '#{ mId }:#{ userId }'"
|
||||
@db.sadd "#{ @setname }-params", "#{ mId }:#{ userId }",
|
||||
replyHandler "Storing '#{ @setname }' module parameters key '#{ mId }'"
|
||||
@db.set "#{ @setname }-params:#{ mId }:#{ userId }", encrypt(data),
|
||||
@db.set "#{ @setname }-params:#{ mId }:#{ userId }", encrypt( data ),
|
||||
replyHandler "Storing '#{ @setname }' module parameters '#{ mId }:#{ userId }'"
|
||||
|
||||
getParameters: ( mId, userId, cb ) =>
|
||||
@log.info "DB | getParameters(#{ @setname }): '#{ mId }:#{ userId }'"
|
||||
getUserParameters: ( mId, userId, cb ) =>
|
||||
@log.info "DB | getUserParameters(#{ @setname }): '#{ mId }:#{ userId }'"
|
||||
@db.get "#{ @setname }-params:#{ mId }:#{ userId }", ( err, data ) ->
|
||||
cb err, decrypt data
|
||||
|
||||
getParametersIds: ( cb ) =>
|
||||
@log.info "DB | getParametersIds(#{ @setname })"
|
||||
getUserParametersIds: ( cb ) =>
|
||||
@log.info "DB | getUserParametersIds(#{ @setname })"
|
||||
@db.smembers "#{ @setname }-params", cb
|
||||
|
||||
deleteParameters: ( mId, userId ) =>
|
||||
@log.info "DB | deleteParameters(#{ @setname }): '#{ mId }:#{ userId }'"
|
||||
deleteUserParameters: ( mId, userId ) =>
|
||||
@log.info "DB | deleteUserParameters(#{ @setname }): '#{ mId }:#{ userId }'"
|
||||
@db.srem "#{ @setname }-params", "#{ mId }:#{ userId }",
|
||||
replyHandler "Deleting '#{ @setname }-params' key '#{ mId }:#{ userId }'"
|
||||
@db.del "#{ @setname }-params:#{ mId }:#{ userId }",
|
||||
|
|
@ -283,12 +324,35 @@ class IndexedModules
|
|||
###
|
||||
Store a string representation of an action invoker in the DB.
|
||||
|
||||
@public storeActionInvoker ( *aiId, data* )
|
||||
@public storeActionInvoker ( *aiId, userId, data* )
|
||||
@param {String} aiId
|
||||
@param {String} userId
|
||||
@param {String} data
|
||||
###
|
||||
exports.storeActionInvoker = ( aiId, data ) =>
|
||||
@ai.storeModule( aiId, data )
|
||||
#TODO adapt testing
|
||||
exports.storeActionInvoker = ( aiId, userId, data ) =>
|
||||
@ai.storeModule aiId, data
|
||||
@ai.linkModule aiId, userId
|
||||
|
||||
###
|
||||
Make an action invoker public.
|
||||
|
||||
@public publishActionInvoker ( *aiId* )
|
||||
@param {String} aiId
|
||||
###
|
||||
|
||||
exports.publishActionInvoker = ( aiId ) =>
|
||||
@ai.publish aiId
|
||||
|
||||
###
|
||||
Make an action invoker private.
|
||||
|
||||
@public unpublishActionInvoker ( *aiId* )
|
||||
@param {String} aiId
|
||||
###
|
||||
|
||||
exports.unpublishActionInvoker = ( aiId ) =>
|
||||
@ai.unpublish aiId
|
||||
|
||||
###
|
||||
Query the DB for an action invoker and pass it to cb(err, obj).
|
||||
|
|
@ -300,6 +364,16 @@ Query the DB for an action invoker and pass it to cb(err, obj).
|
|||
exports.getActionInvoker = ( aiId, cb ) =>
|
||||
@ai.getModule aiId, cb
|
||||
|
||||
###
|
||||
Query the DB for action invoker required params and pass it to cb(err, obj).
|
||||
|
||||
@public getActionInvokerEventPollerRequiredParams( *epId, cb* )
|
||||
@param {String} epId
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getActionInvokerRequiredParams = ( epId, cb ) =>
|
||||
@ai.getModuleParams epId, cb
|
||||
|
||||
###
|
||||
Fetch all action invoker IDs and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -309,6 +383,25 @@ Fetch all action invoker IDs and hand them to cb(err, obj).
|
|||
exports.getActionInvokerIds = ( cb ) =>
|
||||
@ai.getModuleIds cb
|
||||
|
||||
###
|
||||
Fetch all available actin invoker IDs for a user and
|
||||
hand them to cb(err, obj).
|
||||
|
||||
@public getAvailableActionInvokerIds( *userId, cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getAvailableActionInvokerIds = ( userId, cb ) =>
|
||||
@ai.getAvailableModuleIds userId, cb
|
||||
|
||||
###
|
||||
Fetch all public action invoker IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getPublicActionInvokerIds( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getPublicActionInvokerIds = ( cb ) =>
|
||||
@ai.getPublicModuleIds cb
|
||||
|
||||
###
|
||||
Fetch all action invokers and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -330,43 +423,43 @@ exports.deleteActionInvoker = ( aiId ) =>
|
|||
###
|
||||
Store user-specific action invoker parameters .
|
||||
|
||||
@public storeActionParams( *userId, aiId, data* )
|
||||
@public storeActionUserParams( *userId, aiId, data* )
|
||||
@param {String} userId
|
||||
@param {String} aiId
|
||||
@param {String} data
|
||||
###
|
||||
exports.storeActionParams = ( aiId, userId, data ) =>
|
||||
@ai.storeParameters aiId, userId, data
|
||||
exports.storeActionUserParams = ( aiId, userId, data ) =>
|
||||
@ai.storeUserParameters aiId, userId, data
|
||||
|
||||
###
|
||||
Query the DB for user-specific action module parameters,
|
||||
and pass it to cb(err, obj).
|
||||
|
||||
@public getActionParams( *userId, aiId, cb* )
|
||||
@public getActionUserParams( *userId, aiId, cb* )
|
||||
@param {String} userId
|
||||
@param {String} aiId
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getActionParams = ( aiId, userId, cb ) =>
|
||||
@ai.getParameters aiId, userId, cb
|
||||
exports.getActionUserParams = ( aiId, userId, cb ) =>
|
||||
@ai.getUserParameters aiId, userId, cb
|
||||
|
||||
###
|
||||
Fetch all action params IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getActionParamsIds( *cb* )
|
||||
@public getActionUserParamsIds( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getActionParamsIds = ( cb ) =>
|
||||
@ai.getParametersIds cb
|
||||
exports.getActionUserParamsIds = ( cb ) =>
|
||||
@ai.getUserParametersIds cb
|
||||
|
||||
###
|
||||
Fetch all action modules and hand them to cb(err, obj).
|
||||
|
||||
@public deleteActionParams( *cb* )
|
||||
@public deleteActionUserParams( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.deleteActionParams = ( aiId, userId ) =>
|
||||
@ai.deleteParameters aiId, userId
|
||||
exports.deleteActionUserParams = ( aiId, userId ) =>
|
||||
@ai.deleteUserParameters aiId, userId
|
||||
|
||||
|
||||
###
|
||||
|
|
@ -376,12 +469,35 @@ exports.deleteActionParams = ( aiId, userId ) =>
|
|||
###
|
||||
Store a string representation of an event poller in the DB.
|
||||
|
||||
@public storeEventPoller ( *epId, data* )
|
||||
@public storeEventPoller ( *epId, userId, data* )
|
||||
@param {String} epId
|
||||
@param {String} userId
|
||||
@param {String} data
|
||||
###
|
||||
exports.storeEventPoller = ( epId, data ) =>
|
||||
@ep.storeModule( epId, data )
|
||||
#TODO adapt testing
|
||||
exports.storeEventPoller = ( epId, userId, data ) =>
|
||||
@ep.storeModule epId, data
|
||||
@ep.linkModule epId, userId
|
||||
|
||||
###
|
||||
Make an event poller public.
|
||||
|
||||
@public publishEventPoller ( *epId* )
|
||||
@param {String} epId
|
||||
###
|
||||
|
||||
exports.publishEventPoller = ( epId ) =>
|
||||
@ep.publish epId
|
||||
|
||||
###
|
||||
Make an event poller private.
|
||||
|
||||
@public unpublishEventPoller ( *epId* )
|
||||
@param {String} epId
|
||||
###
|
||||
|
||||
exports.unpublishEventPoller = ( epId ) =>
|
||||
@ep.unpublish epId
|
||||
|
||||
###
|
||||
Query the DB for an event poller and pass it to cb(err, obj).
|
||||
|
|
@ -393,6 +509,16 @@ Query the DB for an event poller and pass it to cb(err, obj).
|
|||
exports.getEventPoller = ( epId, cb ) =>
|
||||
@ep.getModule epId, cb
|
||||
|
||||
###
|
||||
Query the DB for event poller required params and pass it to cb(err, obj).
|
||||
|
||||
@public getEventPollerRequiredParams( *epId, cb* )
|
||||
@param {String} epId
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getEventPollerRequiredParams = ( epId, cb ) =>
|
||||
@ep.getModuleParams epId, cb
|
||||
|
||||
###
|
||||
Fetch all event poller IDs and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -402,6 +528,25 @@ Fetch all event poller IDs and hand them to cb(err, obj).
|
|||
exports.getEventPollerIds = ( cb ) =>
|
||||
@ep.getModuleIds cb
|
||||
|
||||
###
|
||||
Fetch all available event poller IDs for a user and
|
||||
hand them to cb(err, obj).
|
||||
|
||||
@public getAvailableEventPollerIds( *userId, cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getAvailableEventPollerIds = ( userId, cb ) =>
|
||||
@ep.getAvailableModuleIds userId, cb
|
||||
|
||||
###
|
||||
Fetch all public event poller IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getPublicEventPollerIds( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getPublicEventPollerIds = ( cb ) =>
|
||||
@ep.getPublicModuleIds cb
|
||||
|
||||
###
|
||||
Fetch all event pollers and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -418,48 +563,51 @@ Fetch all event pollers and hand them to cb(err, obj).
|
|||
@param {function} cb
|
||||
###
|
||||
exports.deleteEventPoller = ( epId ) =>
|
||||
# TODO remove from public modules
|
||||
# TODO remove parameters
|
||||
# TODO also do this for action invokers
|
||||
@ep.deleteModule epId
|
||||
|
||||
###
|
||||
Store user-specific event poller parameters .
|
||||
|
||||
@public storeEventParams( *userId, epId, data* )
|
||||
@public storeEventUserParams( *userId, epId, data* )
|
||||
@param {String} userId
|
||||
@param {String} epId
|
||||
@param {String} data
|
||||
###
|
||||
exports.storeEventParams = ( epId, userId, data ) =>
|
||||
@ep.storeParameters epId, userId, data
|
||||
exports.storeEventUserParams = ( epId, userId, data ) =>
|
||||
@ep.storeUserParameters epId, userId, data
|
||||
|
||||
###
|
||||
Query the DB for user-specific event module parameters,
|
||||
and pass it to cb(err, obj).
|
||||
|
||||
@public getEventParams( *userId, epId, cb* )
|
||||
@public getEventUserParams( *userId, epId, cb* )
|
||||
@param {String} userId
|
||||
@param {String} epId
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getEventParams = ( epId, userId, cb ) =>
|
||||
@ep.getParameters epId, userId, cb
|
||||
exports.getEventUserParams = ( epId, userId, cb ) =>
|
||||
@ep.getUserParameters epId, userId, cb
|
||||
|
||||
###
|
||||
Fetch all event params IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getEventParamsIds( *cb* )
|
||||
@public getEventUserParamsIds( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getEventParamsIds = ( cb ) =>
|
||||
@ep.getParametersIds cb
|
||||
exports.getEventUserParamsIds = ( cb ) =>
|
||||
@ep.getUserParametersIds cb
|
||||
|
||||
###
|
||||
Fetch all event modules and hand them to cb(err, obj).
|
||||
|
||||
@public deleteEventParams( *cb* )
|
||||
@public deleteEventUserParams( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.deleteEventParams = ( epId, userId ) =>
|
||||
@ep.deleteParameters epId, userId
|
||||
exports.deleteEventUserParams = ( epId, userId ) =>
|
||||
@ep.deleteUserParameters epId, userId
|
||||
|
||||
|
||||
###
|
||||
|
|
@ -528,14 +676,14 @@ exports.deleteRule = ( ruleId ) =>
|
|||
delLinkedUserRule = ( userId ) =>
|
||||
@db.srem "user:#{ userId }:rules", ruleId,
|
||||
replyHandler "Deleting rule key '#{ ruleId }' in linked user '#{ userId }'"
|
||||
delLinkedUserRule( id ) for id in obj
|
||||
delLinkedUserRule id for id in obj
|
||||
@db.del "rule:#{ ruleId }:users", replyHandler "Deleting rule '#{ ruleId }' users"
|
||||
|
||||
@db.smembers "rule:#{ ruleId }:active-users", ( err, obj ) =>
|
||||
delActiveUserRule = ( userId ) =>
|
||||
@db.srem "user:#{ userId }:active-rules", ruleId,
|
||||
replyHandler "Deleting rule key '#{ ruleId }' in active user '#{ userId }'"
|
||||
delActiveUserRule( id ) for id in obj
|
||||
delActiveUserRule id for id in obj
|
||||
@db.del "rule:#{ ruleId }:active-users",
|
||||
replyHandler "Deleting rule '#{ ruleId }' active users"
|
||||
|
||||
|
|
@ -659,7 +807,7 @@ exports.getAllActivatedRuleIdsPerUser = ( cb ) =>
|
|||
result[userId] = obj
|
||||
if --semaphore is 0
|
||||
cb null, result
|
||||
fFetchActiveUserRules(user) for user in obj
|
||||
fFetchActiveUserRules user for user in obj
|
||||
|
||||
|
||||
###
|
||||
|
|
@ -723,7 +871,7 @@ exports.deleteUser = ( userId ) =>
|
|||
delLinkedRuleUser = ( ruleId ) =>
|
||||
@db.srem "rule:#{ ruleId }:users", userId,
|
||||
replyHandler "Deleting user key '#{ userId }' in linked rule '#{ ruleId }'"
|
||||
delLinkedRuleUser( id ) for id in obj
|
||||
delLinkedRuleUser id for id in obj
|
||||
@db.del "user:#{ userId }:rules",
|
||||
replyHandler "Deleting user '#{ userId }' rules"
|
||||
|
||||
|
|
@ -732,7 +880,7 @@ exports.deleteUser = ( userId ) =>
|
|||
delActivatedRuleUser = ( ruleId ) =>
|
||||
@db.srem "rule:#{ ruleId }:active-users", userId,
|
||||
replyHandler "Deleting user key '#{ userId }' in active rule '#{ ruleId }'"
|
||||
delActivatedRuleUser( id ) for id in obj
|
||||
delActivatedRuleUser id for id in obj
|
||||
@db.del "user:#{ userId }:active-rules",
|
||||
replyHandler "Deleting user '#{ userId }' rules"
|
||||
|
||||
|
|
@ -741,7 +889,7 @@ exports.deleteUser = ( userId ) =>
|
|||
delRoleUser = ( roleId ) =>
|
||||
@db.srem "role:#{ roleId }:users", userId,
|
||||
replyHandler "Deleting user key '#{ userId }' in role '#{ roleId }'"
|
||||
delRoleUser( id ) for id in obj
|
||||
delRoleUser id for id in obj
|
||||
@db.del "user:#{ userId }:roles",
|
||||
replyHandler "Deleting user '#{ userId }' roles"
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,12 @@ exports = module.exports = ( args ) =>
|
|||
|
||||
# Register the shutdown handler to the admin command.
|
||||
@objAdminCmds =
|
||||
shutdown: ( args, answerHandler ) ->
|
||||
answerHandler.answerSuccess 'Shutting down... BYE!'
|
||||
shutdown: ( obj, cb ) ->
|
||||
data =
|
||||
code: 200
|
||||
message: 'Shutting down... BYE!'
|
||||
setTimeout args[ 'shutdown-function' ], 500
|
||||
cb null, data
|
||||
db args
|
||||
|
||||
# Load the standard users from the user config file
|
||||
|
|
@ -63,13 +66,22 @@ exports.handleEvent = ( req, resp ) ->
|
|||
req.on 'data', ( data ) ->
|
||||
body += data
|
||||
req.on 'end', ->
|
||||
obj = qs.parse body
|
||||
# If required event properties are present we process the event #
|
||||
if obj and obj.event and obj.eventid
|
||||
resp.send 'Thank you for the event: ' + obj.event + ' (' + obj.eventid + ')!'
|
||||
db.pushEvent obj
|
||||
if req.session and req.session.user
|
||||
obj = qs.parse body
|
||||
# If required event properties are present we process the event #
|
||||
if obj and obj.event
|
||||
timestamp = ( new Date ).toISOString()
|
||||
rand = ( Math.floor Math.random() * 10e9 ).toString( 16 ).toUpperCase()
|
||||
obj.eventid = "#{ obj.event }_#{ timestamp }_#{ rand }"
|
||||
answ =
|
||||
code: 200
|
||||
message: "Thank you for the event: #{ obj.eventid }"
|
||||
resp.send answ.code, answ
|
||||
db.pushEvent obj
|
||||
else
|
||||
resp.send 400, 'Your event was missing important parameters!'
|
||||
else
|
||||
resp.send 400, 'Your event was missing important parameters!'
|
||||
resp.send 401, 'Please login!'
|
||||
|
||||
|
||||
###
|
||||
|
|
@ -170,6 +182,7 @@ renderPage = ( name, req, resp, msg ) ->
|
|||
code = 200
|
||||
data =
|
||||
message: msg
|
||||
user: req.session.user
|
||||
|
||||
# Try to grab the script belonging to this page. But don't bother if it's not existing
|
||||
try
|
||||
|
|
@ -187,21 +200,22 @@ renderPage = ( name, req, resp, msg ) ->
|
|||
content = getTemplate 'error'
|
||||
script = getScript 'error'
|
||||
code = 404
|
||||
data =
|
||||
message: 'Invalid Page!'
|
||||
|
||||
content = mustache.render content, data
|
||||
data.message = 'Invalid Page!'
|
||||
|
||||
if req.session.user
|
||||
menubar = getTemplate 'menubar'
|
||||
|
||||
view =
|
||||
user: req.session.user,
|
||||
content: content,
|
||||
script: script,
|
||||
remote_scripts: remote_scripts,
|
||||
pageElements =
|
||||
content: content
|
||||
script: script
|
||||
remote_scripts: remote_scripts
|
||||
menubar: menubar
|
||||
resp.send code, mustache.render skeleton, view
|
||||
|
||||
# First we render the page by including all page elements into the skeleton
|
||||
page = mustache.render skeleton, pageElements
|
||||
|
||||
# Then we complete the rendering by adding the data, and send the result to the user
|
||||
resp.send code, mustache.render page, data
|
||||
|
||||
###
|
||||
Present the desired forge page to the user.
|
||||
|
|
@ -230,19 +244,17 @@ objects.*
|
|||
@public handleUser( *req, resp* )
|
||||
###
|
||||
exports.handleUserCommand = ( req, resp ) =>
|
||||
if not req.session or not req.session.user
|
||||
resp.send 401, 'Login first!'
|
||||
else
|
||||
if req.session and req.session.user
|
||||
body = ''
|
||||
req.on 'data', ( data ) ->
|
||||
body += data
|
||||
req.on 'end', =>
|
||||
obj = qs.parse body
|
||||
@userRequestHandler req.session.user, obj, ( err, obj ) ->
|
||||
if err
|
||||
resp.send 404, 'Rethink your request!'
|
||||
else
|
||||
resp.send obj
|
||||
@userRequestHandler req.session.user, obj, ( obj ) ->
|
||||
resp.send obj.code, obj
|
||||
else
|
||||
resp.send 401, 'Login first!'
|
||||
|
||||
|
||||
###
|
||||
Present the admin console to the user if he's allowed to see it.
|
||||
|
|
@ -276,46 +288,20 @@ objects.*
|
|||
@public handleAdminCommand( *req, resp* )
|
||||
###
|
||||
exports.handleAdminCommand = ( req, resp ) =>
|
||||
if req.session and req.session.user
|
||||
if req.session.user.isAdmin is "true"
|
||||
q = req.query
|
||||
@log.info 'RH | Received admin request: ' + req.originalUrl
|
||||
if q.cmd
|
||||
@objAdminCmds[q.cmd]? q, answerHandler req, resp, true
|
||||
if req.session and
|
||||
req.session.user and
|
||||
req.session.user.isAdmin is "true"
|
||||
body = ''
|
||||
req.on 'data', ( data ) ->
|
||||
body += data
|
||||
req.on 'end', =>
|
||||
obj = qs.parse body
|
||||
@log.info 'RH | Received admin request: ' + obj.command
|
||||
if obj.command and @objAdminCmds[obj.command]
|
||||
@objAdminCmds[obj.command] obj, ( err, obj ) ->
|
||||
resp.send obj.code, obj
|
||||
else
|
||||
resp.send 404, 'Command unknown!'
|
||||
else
|
||||
resp.send renderPage 'unauthorized', req.session
|
||||
else
|
||||
resp.sendfile getHandlerPath 'login'
|
||||
|
||||
|
||||
#TODO remove this ugly legacy blob
|
||||
answerHandler = (req, resp, ntbr) ->
|
||||
request = req
|
||||
response = resp
|
||||
needsToBeRendered = ntbr
|
||||
hasBeenAnswered = false
|
||||
ret =
|
||||
answerSuccess: (msg) ->
|
||||
if not hasBeenAnswered
|
||||
if needsToBeRendered
|
||||
response.send renderPage 'command_answer', request.session, msg
|
||||
else
|
||||
response.send msg
|
||||
hasBeenAnswered = true
|
||||
,
|
||||
answerError: (msg) ->
|
||||
if not hasBeenAnswered
|
||||
if needsToBeRendered
|
||||
response.send 400, renderPage 'error', request.session, msg
|
||||
else
|
||||
response.send 400, msg
|
||||
hasBeenAnswered = true
|
||||
,
|
||||
isAnswered: -> hasBeenAnswered
|
||||
setTimeout(() ->
|
||||
ret.answerError 'Strange... maybe try again?'
|
||||
, 5000)
|
||||
ret
|
||||
|
||||
resp.send 401, 'You need to be logged in as admin!'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,204 +1,246 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
/*
|
||||
# Module Manager
|
||||
> The module manager takes care of the module and rules loading in the initialization
|
||||
> phase and on user request.
|
||||
|
||||
> Event and Action modules are loaded as strings and stored in the database,
|
||||
> then compiled into node modules and rules
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
// # **Loads Modules:**
|
||||
(function() {
|
||||
var commandFunctions, db, dynmod, events, exports, fs, path, vm,
|
||||
_this = this;
|
||||
|
||||
// # - [Persistence](persistence.html)
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
db = require('./persistence'),
|
||||
events = require('events'),
|
||||
log, ee,
|
||||
eventHandlers = [],
|
||||
funcLoadAction, funcLoadRule;
|
||||
db = require('./persistence');
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
args = args || {};
|
||||
ee = new events.EventEmitter();
|
||||
log = args.logger;
|
||||
db(args);
|
||||
return module.exports;
|
||||
};
|
||||
dynmod = require('./dynamic-modules');
|
||||
|
||||
exports.addListener = function( evt, eh ) {
|
||||
ee.addListener( evt, eh );
|
||||
//TODO as soon as an event handler is added it needs to receive the full list of existing and activated rules
|
||||
}
|
||||
fs = require('fs');
|
||||
|
||||
exports.processRequest = function( user, obj, cb ) {
|
||||
console.log('module manager needs to process request: ');
|
||||
console.log(obj.command);
|
||||
var answ = {
|
||||
test: 'object',
|
||||
should: 'work'
|
||||
}
|
||||
cb(null, answ);
|
||||
}
|
||||
vm = require('vm');
|
||||
|
||||
exports.requireFromString = function(src, name, dir) {
|
||||
if(!dir) dir = __dirname;
|
||||
var id = path.resolve(dir, name, name + '.vm');
|
||||
var vm = require('vm'),
|
||||
// FIXME not log but debug module is required to provide information to the user
|
||||
sandbox = {
|
||||
id: id, // use this to gather kill info
|
||||
needle: require('needle'), //https://github.com/tomas/needle
|
||||
log: log,
|
||||
exports: {}
|
||||
};
|
||||
//TODO child_process to run module!
|
||||
// Define max runtime per loop as 10 seconds, after that the child will be killed
|
||||
// it can still be active after that if there was a timing function or a callback used...
|
||||
// kill the child each time? how to determine whether there's still a token in the module?
|
||||
try {
|
||||
var mod = vm.runInNewContext(src, sandbox, id);
|
||||
|
||||
} catch (err) {
|
||||
log.error('ML', 'Error running module in sandbox: ' + err.message);
|
||||
}
|
||||
return sandbox.exports;
|
||||
};
|
||||
path = require('path');
|
||||
|
||||
exports.loadModule = function(directory, name, callback) {
|
||||
try {
|
||||
fs.readFile(path.resolve(__dirname, '..', directory, name, name + '.js'), 'utf8', function (err, data) {
|
||||
if (err) {
|
||||
log.error('LM', 'Loading module file!');
|
||||
return;
|
||||
}
|
||||
var mod = exports.requireFromString(data, name, directory);
|
||||
if(mod && fs.existsSync(path.resolve(__dirname, '..', directory, name, 'credentials.json'))) {
|
||||
fs.readFile(path.resolve(__dirname, '..', directory, name, 'credentials.json'), 'utf8', function (err, auth) {
|
||||
if (err) {
|
||||
log.error('LM', 'Loading credentials file for "' + name + '"!');
|
||||
callback(name, data, mod, null);
|
||||
return;
|
||||
}
|
||||
if(mod.loadCredentials) mod.loadCredentials(JSON.parse(auth));
|
||||
callback(name, data, mod, auth);
|
||||
});
|
||||
} else {
|
||||
// Hand back the name, the string contents and the compiled module
|
||||
callback(name, data, mod, null);
|
||||
}
|
||||
});
|
||||
} catch(err) {
|
||||
log.error('LM', 'Failed loading module "' + name + '"');
|
||||
}
|
||||
};
|
||||
events = require('events');
|
||||
|
||||
exports.loadModules = function(directory, callback) {
|
||||
fs.readdir(path.resolve(__dirname, '..', directory), function (err, list) {
|
||||
if (err) {
|
||||
log.error('LM', 'loading modules directory: ' + err);
|
||||
return;
|
||||
}
|
||||
log.info('LM', 'Loading ' + list.length + ' modules from "' + directory + '"');
|
||||
list.forEach(function (file) {
|
||||
fs.stat(path.resolve(__dirname, '..', directory, file), function (err, stat) {
|
||||
if (stat && stat.isDirectory()) {
|
||||
exports.loadModule(directory, file, callback);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
exports.storeEventModule = function (objUser, obj, answHandler) {
|
||||
try {
|
||||
// TODO in the future we might want to link the modules close to the user
|
||||
// and allow for e.g. private modules
|
||||
// we need a child process to run this code and kill it after invocation
|
||||
var m = exports.requireFromString(obj.data, obj.id);
|
||||
obj.methods = Object.keys(m);
|
||||
answHandler.answerSuccess('Thank you for the event module!');
|
||||
db.storeEventModule(obj.id, obj);
|
||||
} catch (err) {
|
||||
answHandler.answerError(err.message);
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
exports.getAllEventModules = function ( objUser, obj, answHandler ) {
|
||||
db.getEventModules(function(err, obj) {
|
||||
if(err) answHandler.answerError('Failed fetching event modules: ' + err.message);
|
||||
else answHandler.answerSuccess(obj);
|
||||
});
|
||||
};
|
||||
|
||||
exports.storeActionModule = function (objUser, obj, answHandler) {
|
||||
var m = exports.requireFromString(obj.data, obj.id);
|
||||
obj.methods = Object.keys(m);
|
||||
answHandler.answerSuccess('Thank you for the action module!');
|
||||
db.storeActionModule(obj.id, obj);
|
||||
};
|
||||
|
||||
exports.getAllActionModules = function ( objUser, obj, answHandler ) {
|
||||
db.getActionModules(function(err, obj) {
|
||||
if(err) answHandler.answerError('Failed fetching action modules: ' + err.message);
|
||||
else answHandler.answerSuccess(obj);
|
||||
});
|
||||
};
|
||||
|
||||
exports.storeRule = function (objUser, obj, answHandler) {
|
||||
//TODO fix, twice same logic
|
||||
var cbEventModule = function (lstParams) {
|
||||
return function(err, data) {
|
||||
if(err) {
|
||||
err.addInfo = 'fetching event module';
|
||||
log.error('MM', err);
|
||||
}
|
||||
if(!err && data) {
|
||||
if(data.params) {
|
||||
lstParams.eventmodules[data.id] = data.params;
|
||||
}
|
||||
}
|
||||
if(--semaphore === 0) answHandler.answerSuccess(lstParams);
|
||||
};
|
||||
};
|
||||
var cbActionModule = function (lstParams) {
|
||||
return function(err, data) {
|
||||
if(err) {
|
||||
err.addInfo = 'fetching action module';
|
||||
log.error('MM', err);
|
||||
}
|
||||
if(!err && data) {
|
||||
if(data.params) {
|
||||
lstParams.actionmodules[data.id] = data.params;
|
||||
}
|
||||
}
|
||||
if(--semaphore === 0) answHandler.answerSuccess(lstParams);
|
||||
};
|
||||
};
|
||||
/*
|
||||
Module call
|
||||
-----------
|
||||
Initializes the HTTP listener and its request handler.
|
||||
|
||||
var semaphore = 1;
|
||||
var lst = {
|
||||
eventmodules: {},
|
||||
actionmodules: {}
|
||||
};
|
||||
try {
|
||||
var objRule = JSON.parse(obj.data);
|
||||
for(var i = 0; i < objRule.actions.length; i++) {
|
||||
semaphore++;
|
||||
db.getActionModule(objRule.actions[i].module.split('->')[0], cbActionModule(lst));
|
||||
}
|
||||
db.getEventModule(objRule.event.split('->')[0], cbEventModule(lst));
|
||||
db.storeRule(objRule.id, objUser.username, obj.data);
|
||||
ee.emit('newRule', objRule);
|
||||
// for( var i = 0; i < eventHandlers.length; i++ ) {
|
||||
// eventHandlers[i]( objRule );
|
||||
// }
|
||||
} catch(err) {
|
||||
answHandler.answerError(err.message);
|
||||
log.error('MM', err);
|
||||
}
|
||||
@param {Object} args
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
_this.log = args.logger;
|
||||
_this.ee = new events.EventEmitter();
|
||||
db(args);
|
||||
dynmod(args);
|
||||
return module.exports;
|
||||
};
|
||||
|
||||
exports.addListener = function(evt, eh) {
|
||||
return _this.ee.addListener(evt, eh);
|
||||
};
|
||||
|
||||
exports.processRequest = function(user, obj, cb) {
|
||||
var answ;
|
||||
if (commandFunctions[obj.command]) {
|
||||
return answ = commandFunctions[obj.command](user, obj, cb);
|
||||
} else {
|
||||
return cb({
|
||||
code: 404,
|
||||
message: 'Strange request!'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
commandFunctions = {
|
||||
forge_event_poller: function(user, obj, cb) {
|
||||
var answ;
|
||||
answ = {
|
||||
code: 200
|
||||
};
|
||||
return db.getEventPoller(obj.id, function(err, mod) {
|
||||
var cm, id, name, src, _ref;
|
||||
if (mod) {
|
||||
answ.code = 409;
|
||||
answ.message = 'Event Poller module name already existing: ' + obj.id;
|
||||
} else {
|
||||
src = obj.data;
|
||||
cm = dynmod.compileString(src, obj.id, {}, obj.lang);
|
||||
answ = cm.answ;
|
||||
if (answ.code === 200) {
|
||||
events = [];
|
||||
_ref = cm.module;
|
||||
for (name in _ref) {
|
||||
id = _ref[name];
|
||||
events.push(name);
|
||||
}
|
||||
_this.log.info("CM | Storing new eventpoller with events " + events);
|
||||
answ.message = "Event Poller module successfully stored! Found following event(s): " + events;
|
||||
db.storeEventPoller(obj.id, user.username, {
|
||||
code: obj.data,
|
||||
lang: obj.lang,
|
||||
params: obj.params,
|
||||
events: events
|
||||
});
|
||||
if (obj["public"] === 'true') {
|
||||
db.publishEventPoller(obj.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cb(answ);
|
||||
});
|
||||
},
|
||||
get_event_pollers: function(user, obj, cb) {
|
||||
return db.getAvailableEventPollerIds(user.username, function(err, obj) {
|
||||
var fGetEvents, id, oRes, sem, _i, _len, _results;
|
||||
oRes = {};
|
||||
sem = obj.length;
|
||||
fGetEvents = function(id) {
|
||||
return db.getEventPoller(id, function(err, obj) {
|
||||
oRes[id] = obj.events;
|
||||
if (--sem === 0) {
|
||||
return cb({
|
||||
code: 200,
|
||||
message: oRes
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
_results = [];
|
||||
for (_i = 0, _len = obj.length; _i < _len; _i++) {
|
||||
id = obj[_i];
|
||||
_results.push(fGetEvents(id));
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
},
|
||||
get_event_poller_params: function(user, obj, cb) {
|
||||
return db.getEventPollerRequiredParams(obj.id, function(err, obj) {
|
||||
return cb({
|
||||
code: 200,
|
||||
message: obj
|
||||
});
|
||||
});
|
||||
},
|
||||
get_action_invokers: function(user, obj, cb) {
|
||||
return db.getAvailableActionInvokerIds(user.username, function(err, obj) {
|
||||
var fGetActions, id, oRes, sem, _i, _len, _results;
|
||||
oRes = {};
|
||||
sem = obj.length;
|
||||
fGetActions = function(id) {
|
||||
return db.getActionInvoker(id, function(err, obj) {
|
||||
oRes[id] = obj.actions;
|
||||
if (--sem === 0) {
|
||||
return cb({
|
||||
code: 200,
|
||||
message: oRes
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
_results = [];
|
||||
for (_i = 0, _len = obj.length; _i < _len; _i++) {
|
||||
id = obj[_i];
|
||||
_results.push(fGetActions(id));
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
},
|
||||
get_action_invoker_params: function(user, obj, cb) {
|
||||
return db.getActionInvokerRequiredParams(obj.id, function(err, obj) {
|
||||
return cb({
|
||||
code: 200,
|
||||
message: obj
|
||||
});
|
||||
});
|
||||
},
|
||||
forge_action_invoker: function(user, obj, cb) {
|
||||
var answ;
|
||||
answ = {
|
||||
code: 200
|
||||
};
|
||||
return db.getActionInvoker(obj.id, function(err, mod) {
|
||||
var actions, cm, id, name, src, _ref;
|
||||
if (mod) {
|
||||
answ.code = 409;
|
||||
answ.message = 'Action Invoker module name already existing: ' + obj.id;
|
||||
} else {
|
||||
src = obj.data;
|
||||
cm = dynmod.compileString(src, obj.id, {}, obj.lang);
|
||||
answ = cm.answ;
|
||||
if (answ.code === 200) {
|
||||
actions = [];
|
||||
_ref = cm.module;
|
||||
for (name in _ref) {
|
||||
id = _ref[name];
|
||||
actions.push(name);
|
||||
}
|
||||
_this.log.info("CM | Storing new eventpoller with actions " + actions);
|
||||
answ.message = "Action Invoker module successfully stored! Found following action(s): " + actions;
|
||||
db.storeActionInvoker(obj.id, user.username, {
|
||||
code: obj.data,
|
||||
lang: obj.lang,
|
||||
params: obj.params,
|
||||
actions: actions
|
||||
});
|
||||
if (obj["public"] === 'true') {
|
||||
db.publishActionInvoker(obj.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cb(answ);
|
||||
});
|
||||
},
|
||||
get_rules: function(user, obj, cb) {
|
||||
return console.log('CM | Implement get_rules');
|
||||
},
|
||||
forge_rule: function(user, obj, cb) {
|
||||
obj.event = JSON.parse(obj.event);
|
||||
console.log(obj);
|
||||
return db.getRule(obj.id, function(err, objRule) {
|
||||
var answ, id, modules, params, rule;
|
||||
if (objRule !== null) {
|
||||
answ = {
|
||||
code: 409,
|
||||
message: 'Rule name already existing!'
|
||||
};
|
||||
} else {
|
||||
answ = {
|
||||
code: 200,
|
||||
message: 'Rule stored and activated!'
|
||||
};
|
||||
rule = {
|
||||
id: obj.id,
|
||||
event: "" + obj.event.module + " -> " + obj.event["function"],
|
||||
conditions: JSON.parse(obj.conditions),
|
||||
actions: JSON.parse(obj.actions)
|
||||
};
|
||||
console.log(rule);
|
||||
modules = JSON.parse(obj.event.action_params);
|
||||
console.log('store rule');
|
||||
db.storeRule(rule.id, JSON.stringify(rule));
|
||||
console.log('link rule');
|
||||
db.linkRule(rule.id, user.username);
|
||||
console.log('activate rule');
|
||||
db.activateRule(rule.id, user.username);
|
||||
console.log('store event params');
|
||||
db.storeEventUserParams(obj.event.module, user.username, obj.event_params);
|
||||
console.log('store action params');
|
||||
for (id in modules) {
|
||||
params = modules[id];
|
||||
db.storeActionUserParams(id, user.username, params);
|
||||
}
|
||||
_this.ee.emit('newRule', rule);
|
||||
}
|
||||
return cb(answ);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
|
|
|||
84
js-coffee/dynamic-modules.js
Normal file
84
js-coffee/dynamic-modules.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
/*
|
||||
|
||||
Dynamic Modules
|
||||
===============
|
||||
> Compiles CoffeeScript modules and loads JS modules in a VM, together
|
||||
> with only a few allowed node.js modules.
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
var cs, exports, needle, vm,
|
||||
_this = this;
|
||||
|
||||
vm = require('vm');
|
||||
|
||||
needle = require('needle');
|
||||
|
||||
cs = require('coffee-script');
|
||||
|
||||
/*
|
||||
Module call
|
||||
-----------
|
||||
Initializes the dynamic module handler.
|
||||
|
||||
@param {Object} args
|
||||
*/
|
||||
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
_this.log = args.logger;
|
||||
return module.exports;
|
||||
};
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
exports.compileString = function(src, id, params, lang) {
|
||||
var answ, err, ret, sandbox;
|
||||
answ = {
|
||||
code: 200,
|
||||
message: 'Successfully compiled'
|
||||
};
|
||||
src = "'use strict;'\n" + src;
|
||||
if (lang === '0') {
|
||||
try {
|
||||
src = cs.compile(src);
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
answ.code = 400;
|
||||
answ.message = 'Compilation of CoffeeScript failed at line ' + err.location.first_line;
|
||||
}
|
||||
}
|
||||
sandbox = {
|
||||
id: id,
|
||||
params: params,
|
||||
needle: needle,
|
||||
log: _this.log,
|
||||
exports: {}
|
||||
};
|
||||
try {
|
||||
vm.runInNewContext(src, sandbox, id + '.vm');
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
answ.code = 400;
|
||||
answ.message = 'Loading Module failed: ' + err.message;
|
||||
}
|
||||
return ret = {
|
||||
answ: answ,
|
||||
module: sandbox.exports
|
||||
};
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
|
@ -49,7 +49,7 @@ Persistence
|
|||
connect_timeout: 2000
|
||||
});
|
||||
_this.db.on('error', function(err) {
|
||||
if (err.message.indexOf('ECONNREFUSED' > -1)) {
|
||||
if (err.message.indexOf('ECONNREFUSED') > -1) {
|
||||
_this.connRefused = true;
|
||||
return _this.log.error(err, 'DB | Wrong port?');
|
||||
}
|
||||
|
|
@ -284,14 +284,20 @@ Persistence
|
|||
this.setname = setname;
|
||||
this.db = db;
|
||||
this.log = log;
|
||||
this.deleteParameters = __bind(this.deleteParameters, this);
|
||||
this.getParametersIds = __bind(this.getParametersIds, this);
|
||||
this.getParameters = __bind(this.getParameters, this);
|
||||
this.storeParameters = __bind(this.storeParameters, this);
|
||||
this.deleteUserParameters = __bind(this.deleteUserParameters, this);
|
||||
this.getUserParametersIds = __bind(this.getUserParametersIds, this);
|
||||
this.getUserParameters = __bind(this.getUserParameters, this);
|
||||
this.storeUserParameters = __bind(this.storeUserParameters, this);
|
||||
this.deleteModule = __bind(this.deleteModule, this);
|
||||
this.getModules = __bind(this.getModules, this);
|
||||
this.getModuleIds = __bind(this.getModuleIds, this);
|
||||
this.getAvailableModuleIds = __bind(this.getAvailableModuleIds, this);
|
||||
this.getModuleParams = __bind(this.getModuleParams, this);
|
||||
this.getModule = __bind(this.getModule, this);
|
||||
this.unpublish = __bind(this.unpublish, this);
|
||||
this.publish = __bind(this.publish, this);
|
||||
this.unlinkModule = __bind(this.unlinkModule, this);
|
||||
this.linkModule = __bind(this.linkModule, this);
|
||||
this.storeModule = __bind(this.storeModule, this);
|
||||
this.log.info("DB | Instantiated indexed modules for '" + this.setname + "'");
|
||||
}
|
||||
|
|
@ -299,12 +305,44 @@ Persistence
|
|||
IndexedModules.prototype.storeModule = function(mId, data) {
|
||||
this.log.info("DB | storeModule(" + this.setname + "): " + mId);
|
||||
this.db.sadd("" + this.setname + "s", mId, replyHandler("Storing '" + this.setname + "' key '" + mId + "'"));
|
||||
return this.db.set("" + this.setname + ":" + mId, data, replyHandler("Storing '" + this.setname + ":" + mId + "'"));
|
||||
return this.db.hmset("" + this.setname + ":" + mId, data, replyHandler("Storing '" + this.setname + ":" + mId + "'"));
|
||||
};
|
||||
|
||||
IndexedModules.prototype.linkModule = function(mId, userId) {
|
||||
this.log.info("DB | linkModule(" + this.setname + "): " + mId + " to " + userId);
|
||||
this.db.sadd("" + this.setname + ":" + mId + ":users", userId, replyHandler("Linking '" + this.setname + ":" + mId + ":users' " + userId));
|
||||
return this.db.sadd("user:" + userId + ":" + this.setname + "s", mId, replyHandler("Linking 'user:" + userId + ":" + this.setname + "s' " + mId));
|
||||
};
|
||||
|
||||
IndexedModules.prototype.unlinkModule = function(mId, userId) {
|
||||
this.log.info("DB | unlinkModule(" + this.setname + "): " + mId + " to " + userId);
|
||||
this.db.srem("" + this.setname + ":" + mId + ":users", userId, replyHandler("Unlinking '" + this.setname + ":" + mId + ":users' " + userId));
|
||||
return this.db.srem("user:" + userId + ":" + this.setname + "s", mId, replyHandler("Unlinking 'user:" + userId + ":" + this.setname + "s' " + mId));
|
||||
};
|
||||
|
||||
IndexedModules.prototype.publish = function(mId) {
|
||||
this.log.info("DB | publish(" + this.setname + "): " + mId);
|
||||
return this.db.sadd("public-" + this.setname + "s", mId, replyHandler("Publishing '" + this.setname + "' key '" + mId + "'"));
|
||||
};
|
||||
|
||||
IndexedModules.prototype.unpublish = function(mId) {
|
||||
this.log.info("DB | unpublish(" + this.setname + "): " + mId);
|
||||
return this.db.srem("public-" + this.setname + "s", mId, replyHandler("Unpublishing '" + this.setname + "' key '" + mId + "'"));
|
||||
};
|
||||
|
||||
IndexedModules.prototype.getModule = function(mId, cb) {
|
||||
this.log.info("DB | getModule('" + this.setname + "): " + mId + "'");
|
||||
return this.db.get("" + this.setname + ":" + mId, cb);
|
||||
return this.db.hgetall("" + this.setname + ":" + mId, cb);
|
||||
};
|
||||
|
||||
IndexedModules.prototype.getModuleParams = function(mId, cb) {
|
||||
this.log.info("DB | getModule('" + this.setname + "): " + mId + "'");
|
||||
return this.db.hget("" + this.setname + ":" + mId, "params", cb);
|
||||
};
|
||||
|
||||
IndexedModules.prototype.getAvailableModuleIds = function(userId, cb) {
|
||||
this.log.info("DB | getPublicModuleIds(" + this.setname + ")");
|
||||
return this.db.sunion("public-" + this.setname + "s", "user:" + userId + ":" + this.setname + "s", cb);
|
||||
};
|
||||
|
||||
IndexedModules.prototype.getModuleIds = function(cb) {
|
||||
|
|
@ -323,26 +361,26 @@ Persistence
|
|||
return this.db.del("" + this.setname + ":" + mId, replyHandler("Deleting '" + this.setname + ":" + mId + "'"));
|
||||
};
|
||||
|
||||
IndexedModules.prototype.storeParameters = function(mId, userId, data) {
|
||||
this.log.info("DB | storeParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
|
||||
IndexedModules.prototype.storeUserParameters = function(mId, userId, data) {
|
||||
this.log.info("DB | storeUserParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
|
||||
this.db.sadd("" + this.setname + "-params", "" + mId + ":" + userId, replyHandler("Storing '" + this.setname + "' module parameters key '" + mId + "'"));
|
||||
return this.db.set("" + this.setname + "-params:" + mId + ":" + userId, encrypt(data), replyHandler("Storing '" + this.setname + "' module parameters '" + mId + ":" + userId + "'"));
|
||||
};
|
||||
|
||||
IndexedModules.prototype.getParameters = function(mId, userId, cb) {
|
||||
this.log.info("DB | getParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
|
||||
IndexedModules.prototype.getUserParameters = function(mId, userId, cb) {
|
||||
this.log.info("DB | getUserParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
|
||||
return this.db.get("" + this.setname + "-params:" + mId + ":" + userId, function(err, data) {
|
||||
return cb(err, decrypt(data));
|
||||
});
|
||||
};
|
||||
|
||||
IndexedModules.prototype.getParametersIds = function(cb) {
|
||||
this.log.info("DB | getParametersIds(" + this.setname + ")");
|
||||
IndexedModules.prototype.getUserParametersIds = function(cb) {
|
||||
this.log.info("DB | getUserParametersIds(" + this.setname + ")");
|
||||
return this.db.smembers("" + this.setname + "-params", cb);
|
||||
};
|
||||
|
||||
IndexedModules.prototype.deleteParameters = function(mId, userId) {
|
||||
this.log.info("DB | deleteParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
|
||||
IndexedModules.prototype.deleteUserParameters = function(mId, userId) {
|
||||
this.log.info("DB | deleteUserParameters(" + this.setname + "): '" + mId + ":" + userId + "'");
|
||||
this.db.srem("" + this.setname + "-params", "" + mId + ":" + userId, replyHandler("Deleting '" + this.setname + "-params' key '" + mId + ":" + userId + "'"));
|
||||
return this.db.del("" + this.setname + "-params:" + mId + ":" + userId, replyHandler("Deleting '" + this.setname + "-params:" + mId + ":" + userId + "'"));
|
||||
};
|
||||
|
|
@ -359,14 +397,40 @@ Persistence
|
|||
/*
|
||||
Store a string representation of an action invoker in the DB.
|
||||
|
||||
@public storeActionInvoker ( *aiId, data* )
|
||||
@public storeActionInvoker ( *aiId, userId, data* )
|
||||
@param {String} aiId
|
||||
@param {String} userId
|
||||
@param {String} data
|
||||
*/
|
||||
|
||||
|
||||
exports.storeActionInvoker = function(aiId, data) {
|
||||
return _this.ai.storeModule(aiId, data);
|
||||
exports.storeActionInvoker = function(aiId, userId, data) {
|
||||
_this.ai.storeModule(aiId, data);
|
||||
return _this.ai.linkModule(aiId, userId);
|
||||
};
|
||||
|
||||
/*
|
||||
Make an action invoker public.
|
||||
|
||||
@public publishActionInvoker ( *aiId* )
|
||||
@param {String} aiId
|
||||
*/
|
||||
|
||||
|
||||
exports.publishActionInvoker = function(aiId) {
|
||||
return _this.ai.publish(aiId);
|
||||
};
|
||||
|
||||
/*
|
||||
Make an action invoker private.
|
||||
|
||||
@public unpublishActionInvoker ( *aiId* )
|
||||
@param {String} aiId
|
||||
*/
|
||||
|
||||
|
||||
exports.unpublishActionInvoker = function(aiId) {
|
||||
return _this.ai.unpublish(aiId);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -382,6 +446,19 @@ Persistence
|
|||
return _this.ai.getModule(aiId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Query the DB for action invoker required params and pass it to cb(err, obj).
|
||||
|
||||
@public getActionInvokerEventPollerRequiredParams( *epId, cb* )
|
||||
@param {String} epId
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getActionInvokerRequiredParams = function(epId, cb) {
|
||||
return _this.ai.getModuleParams(epId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all action invoker IDs and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -394,6 +471,31 @@ Persistence
|
|||
return _this.ai.getModuleIds(cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all available actin invoker IDs for a user and
|
||||
hand them to cb(err, obj).
|
||||
|
||||
@public getAvailableActionInvokerIds( *userId, cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getAvailableActionInvokerIds = function(userId, cb) {
|
||||
return _this.ai.getAvailableModuleIds(userId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all public action invoker IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getPublicActionInvokerIds( *cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getPublicActionInvokerIds = function(cb) {
|
||||
return _this.ai.getPublicModuleIds(cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all action invokers and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -421,54 +523,54 @@ Persistence
|
|||
/*
|
||||
Store user-specific action invoker parameters .
|
||||
|
||||
@public storeActionParams( *userId, aiId, data* )
|
||||
@public storeActionUserParams( *userId, aiId, data* )
|
||||
@param {String} userId
|
||||
@param {String} aiId
|
||||
@param {String} data
|
||||
*/
|
||||
|
||||
|
||||
exports.storeActionParams = function(aiId, userId, data) {
|
||||
return _this.ai.storeParameters(aiId, userId, data);
|
||||
exports.storeActionUserParams = function(aiId, userId, data) {
|
||||
return _this.ai.storeUserParameters(aiId, userId, data);
|
||||
};
|
||||
|
||||
/*
|
||||
Query the DB for user-specific action module parameters,
|
||||
and pass it to cb(err, obj).
|
||||
|
||||
@public getActionParams( *userId, aiId, cb* )
|
||||
@public getActionUserParams( *userId, aiId, cb* )
|
||||
@param {String} userId
|
||||
@param {String} aiId
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getActionParams = function(aiId, userId, cb) {
|
||||
return _this.ai.getParameters(aiId, userId, cb);
|
||||
exports.getActionUserParams = function(aiId, userId, cb) {
|
||||
return _this.ai.getUserParameters(aiId, userId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all action params IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getActionParamsIds( *cb* )
|
||||
@public getActionUserParamsIds( *cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getActionParamsIds = function(cb) {
|
||||
return _this.ai.getParametersIds(cb);
|
||||
exports.getActionUserParamsIds = function(cb) {
|
||||
return _this.ai.getUserParametersIds(cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all action modules and hand them to cb(err, obj).
|
||||
|
||||
@public deleteActionParams( *cb* )
|
||||
@public deleteActionUserParams( *cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.deleteActionParams = function(aiId, userId) {
|
||||
return _this.ai.deleteParameters(aiId, userId);
|
||||
exports.deleteActionUserParams = function(aiId, userId) {
|
||||
return _this.ai.deleteUserParameters(aiId, userId);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -479,14 +581,40 @@ Persistence
|
|||
/*
|
||||
Store a string representation of an event poller in the DB.
|
||||
|
||||
@public storeEventPoller ( *epId, data* )
|
||||
@public storeEventPoller ( *epId, userId, data* )
|
||||
@param {String} epId
|
||||
@param {String} userId
|
||||
@param {String} data
|
||||
*/
|
||||
|
||||
|
||||
exports.storeEventPoller = function(epId, data) {
|
||||
return _this.ep.storeModule(epId, data);
|
||||
exports.storeEventPoller = function(epId, userId, data) {
|
||||
_this.ep.storeModule(epId, data);
|
||||
return _this.ep.linkModule(epId, userId);
|
||||
};
|
||||
|
||||
/*
|
||||
Make an event poller public.
|
||||
|
||||
@public publishEventPoller ( *epId* )
|
||||
@param {String} epId
|
||||
*/
|
||||
|
||||
|
||||
exports.publishEventPoller = function(epId) {
|
||||
return _this.ep.publish(epId);
|
||||
};
|
||||
|
||||
/*
|
||||
Make an event poller private.
|
||||
|
||||
@public unpublishEventPoller ( *epId* )
|
||||
@param {String} epId
|
||||
*/
|
||||
|
||||
|
||||
exports.unpublishEventPoller = function(epId) {
|
||||
return _this.ep.unpublish(epId);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -502,6 +630,19 @@ Persistence
|
|||
return _this.ep.getModule(epId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Query the DB for event poller required params and pass it to cb(err, obj).
|
||||
|
||||
@public getEventPollerRequiredParams( *epId, cb* )
|
||||
@param {String} epId
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getEventPollerRequiredParams = function(epId, cb) {
|
||||
return _this.ep.getModuleParams(epId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all event poller IDs and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -514,6 +655,31 @@ Persistence
|
|||
return _this.ep.getModuleIds(cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all available event poller IDs for a user and
|
||||
hand them to cb(err, obj).
|
||||
|
||||
@public getAvailableEventPollerIds( *userId, cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getAvailableEventPollerIds = function(userId, cb) {
|
||||
return _this.ep.getAvailableModuleIds(userId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all public event poller IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getPublicEventPollerIds( *cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getPublicEventPollerIds = function(cb) {
|
||||
return _this.ep.getPublicModuleIds(cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all event pollers and hand them to cb(err, obj).
|
||||
|
||||
|
|
@ -541,54 +707,54 @@ Persistence
|
|||
/*
|
||||
Store user-specific event poller parameters .
|
||||
|
||||
@public storeEventParams( *userId, epId, data* )
|
||||
@public storeEventUserParams( *userId, epId, data* )
|
||||
@param {String} userId
|
||||
@param {String} epId
|
||||
@param {String} data
|
||||
*/
|
||||
|
||||
|
||||
exports.storeEventParams = function(epId, userId, data) {
|
||||
return _this.ep.storeParameters(epId, userId, data);
|
||||
exports.storeEventUserParams = function(epId, userId, data) {
|
||||
return _this.ep.storeUserParameters(epId, userId, data);
|
||||
};
|
||||
|
||||
/*
|
||||
Query the DB for user-specific event module parameters,
|
||||
and pass it to cb(err, obj).
|
||||
|
||||
@public getEventParams( *userId, epId, cb* )
|
||||
@public getEventUserParams( *userId, epId, cb* )
|
||||
@param {String} userId
|
||||
@param {String} epId
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getEventParams = function(epId, userId, cb) {
|
||||
return _this.ep.getParameters(epId, userId, cb);
|
||||
exports.getEventUserParams = function(epId, userId, cb) {
|
||||
return _this.ep.getUserParameters(epId, userId, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all event params IDs and hand them to cb(err, obj).
|
||||
|
||||
@public getEventParamsIds( *cb* )
|
||||
@public getEventUserParamsIds( *cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getEventParamsIds = function(cb) {
|
||||
return _this.ep.getParametersIds(cb);
|
||||
exports.getEventUserParamsIds = function(cb) {
|
||||
return _this.ep.getUserParametersIds(cb);
|
||||
};
|
||||
|
||||
/*
|
||||
Fetch all event modules and hand them to cb(err, obj).
|
||||
|
||||
@public deleteEventParams( *cb* )
|
||||
@public deleteEventUserParams( *cb* )
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.deleteEventParams = function(epId, userId) {
|
||||
return _this.ep.deleteParameters(epId, userId);
|
||||
exports.deleteEventUserParams = function(epId, userId) {
|
||||
return _this.ep.deleteUserParameters(epId, userId);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Request Handler
|
|||
|
||||
|
||||
(function() {
|
||||
var answerHandler, crypto, db, dirHandlers, exports, fs, getHandlerPath, getRemoteScripts, getScript, getTemplate, mustache, path, qs, renderPage,
|
||||
var crypto, db, dirHandlers, exports, fs, getHandlerPath, getRemoteScripts, getScript, getTemplate, mustache, path, qs, renderPage,
|
||||
_this = this;
|
||||
|
||||
db = require('./persistence');
|
||||
|
|
@ -33,9 +33,14 @@ Request Handler
|
|||
_this.log = args.logger;
|
||||
_this.userRequestHandler = args['request-service'];
|
||||
_this.objAdminCmds = {
|
||||
shutdown: function(args, answerHandler) {
|
||||
answerHandler.answerSuccess('Shutting down... BYE!');
|
||||
return setTimeout(args['shutdown-function'], 500);
|
||||
shutdown: function(obj, cb) {
|
||||
var data;
|
||||
data = {
|
||||
code: 200,
|
||||
message: 'Shutting down... BYE!'
|
||||
};
|
||||
setTimeout(args['shutdown-function'], 500);
|
||||
return cb(null, data);
|
||||
}
|
||||
};
|
||||
db(args);
|
||||
|
|
@ -67,13 +72,24 @@ Request Handler
|
|||
return body += data;
|
||||
});
|
||||
return req.on('end', function() {
|
||||
var obj;
|
||||
obj = qs.parse(body);
|
||||
if (obj && obj.event && obj.eventid) {
|
||||
resp.send('Thank you for the event: ' + obj.event + ' (' + obj.eventid + ')!');
|
||||
return db.pushEvent(obj);
|
||||
var answ, obj, rand, timestamp;
|
||||
if (req.session && req.session.user) {
|
||||
obj = qs.parse(body);
|
||||
if (obj && obj.event) {
|
||||
timestamp = (new Date).toISOString();
|
||||
rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase();
|
||||
obj.eventid = "" + obj.event + "_" + timestamp + "_" + rand;
|
||||
answ = {
|
||||
code: 200,
|
||||
message: "Thank you for the event: " + obj.eventid
|
||||
};
|
||||
resp.send(answ.code, answ);
|
||||
return db.pushEvent(obj);
|
||||
} else {
|
||||
return resp.send(400, 'Your event was missing important parameters!');
|
||||
}
|
||||
} else {
|
||||
return resp.send(400, 'Your event was missing important parameters!');
|
||||
return resp.send(401, 'Please login!');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -199,12 +215,13 @@ Request Handler
|
|||
|
||||
|
||||
renderPage = function(name, req, resp, msg) {
|
||||
var code, content, data, err, menubar, pathSkel, remote_scripts, script, skeleton, view;
|
||||
var code, content, data, err, menubar, page, pageElements, pathSkel, remote_scripts, script, skeleton;
|
||||
pathSkel = path.join(dirHandlers, 'skeleton.html');
|
||||
skeleton = fs.readFileSync(pathSkel, 'utf8');
|
||||
code = 200;
|
||||
data = {
|
||||
message: msg
|
||||
message: msg,
|
||||
user: req.session.user
|
||||
};
|
||||
try {
|
||||
script = getScript(name);
|
||||
|
|
@ -219,22 +236,19 @@ Request Handler
|
|||
content = getTemplate('error');
|
||||
script = getScript('error');
|
||||
code = 404;
|
||||
data = {
|
||||
message: 'Invalid Page!'
|
||||
};
|
||||
data.message = 'Invalid Page!';
|
||||
}
|
||||
content = mustache.render(content, data);
|
||||
if (req.session.user) {
|
||||
menubar = getTemplate('menubar');
|
||||
}
|
||||
view = {
|
||||
user: req.session.user,
|
||||
pageElements = {
|
||||
content: content,
|
||||
script: script,
|
||||
remote_scripts: remote_scripts,
|
||||
menubar: menubar
|
||||
};
|
||||
return resp.send(code, mustache.render(skeleton, view));
|
||||
page = mustache.render(skeleton, pageElements);
|
||||
return resp.send(code, mustache.render(page, data));
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -272,9 +286,7 @@ Request Handler
|
|||
|
||||
exports.handleUserCommand = function(req, resp) {
|
||||
var body;
|
||||
if (!req.session || !req.session.user) {
|
||||
return resp.send(401, 'Login first!');
|
||||
} else {
|
||||
if (req.session && req.session.user) {
|
||||
body = '';
|
||||
req.on('data', function(data) {
|
||||
return body += data;
|
||||
|
|
@ -282,14 +294,12 @@ Request Handler
|
|||
return req.on('end', function() {
|
||||
var obj;
|
||||
obj = qs.parse(body);
|
||||
return _this.userRequestHandler(req.session.user, obj, function(err, obj) {
|
||||
if (err) {
|
||||
return resp.send(404, 'Rethink your request!');
|
||||
} else {
|
||||
return resp.send(obj);
|
||||
}
|
||||
return _this.userRequestHandler(req.session.user, obj, function(obj) {
|
||||
return resp.send(obj.code, obj);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return resp.send(401, 'Login first!');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -331,59 +341,27 @@ Request Handler
|
|||
|
||||
|
||||
exports.handleAdminCommand = function(req, resp) {
|
||||
var q, _base, _name;
|
||||
if (req.session && req.session.user) {
|
||||
if (req.session.user.isAdmin === "true") {
|
||||
q = req.query;
|
||||
_this.log.info('RH | Received admin request: ' + req.originalUrl);
|
||||
if (q.cmd) {
|
||||
return typeof (_base = _this.objAdminCmds)[_name = q.cmd] === "function" ? _base[_name](q, answerHandler(req, resp, true)) : void 0;
|
||||
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(renderPage('unauthorized', req.session));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return resp.sendfile(getHandlerPath('login'));
|
||||
return resp.send(401, 'You need to be logged in as admin!');
|
||||
}
|
||||
};
|
||||
|
||||
answerHandler = function(req, resp, ntbr) {
|
||||
var hasBeenAnswered, needsToBeRendered, request, response, ret;
|
||||
request = req;
|
||||
response = resp;
|
||||
needsToBeRendered = ntbr;
|
||||
hasBeenAnswered = false;
|
||||
ret = {
|
||||
answerSuccess: function(msg) {
|
||||
if (!hasBeenAnswered) {
|
||||
if (needsToBeRendered) {
|
||||
response.send(renderPage('command_answer', request.session, msg));
|
||||
} else {
|
||||
response.send(msg);
|
||||
}
|
||||
}
|
||||
return hasBeenAnswered = true;
|
||||
},
|
||||
answerError: function(msg) {
|
||||
if (!hasBeenAnswered) {
|
||||
if (needsToBeRendered) {
|
||||
response.send(400, renderPage('error', request.session, msg));
|
||||
} else {
|
||||
response.send(400, msg);
|
||||
}
|
||||
}
|
||||
return hasBeenAnswered = true;
|
||||
},
|
||||
isAnswered: function() {
|
||||
return hasBeenAnswered;
|
||||
}
|
||||
};
|
||||
setTimeout(function() {
|
||||
return ret.answerError('Strange... maybe try again?');
|
||||
}, 5000);
|
||||
return ret;
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
|
|
|||
|
|
@ -139,73 +139,76 @@ exports.EventQueue =
|
|||
# Test ACTION INVOKER
|
||||
###
|
||||
exports.ActionInvoker =
|
||||
setUp: ( cb ) =>
|
||||
@action1id = 'test-action-invoker_1'
|
||||
@action2id = 'test-action-invoker_2'
|
||||
@action1 =
|
||||
code: 'unit-test action invoker 1 content'
|
||||
reqparams:'[param11,param12]'
|
||||
@action2 =
|
||||
code: 'unit-test action invoker 2 content'
|
||||
reqparams:'[param21,param22]'
|
||||
cb()
|
||||
|
||||
tearDown: ( cb ) =>
|
||||
@db.deleteActionInvoker @action1id
|
||||
@db.deleteActionInvoker @action2id
|
||||
cb()
|
||||
|
||||
testCreateAndRead: ( test ) =>
|
||||
test.expect 3
|
||||
|
||||
id = 'test-action-invoker'
|
||||
action = 'unit-test action invoker content'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeActionInvoker id, action
|
||||
@db.storeActionInvoker @action1id, @action1
|
||||
|
||||
# test that the ID shows up in the set
|
||||
@db.getActionInvokerIds ( err , obj ) =>
|
||||
test.ok id in obj,
|
||||
test.ok @action1id in obj,
|
||||
'Expected key not in action-invokers set'
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getActionInvoker id, ( err , obj ) =>
|
||||
test.strictEqual obj, action,
|
||||
@db.getActionInvoker @action1id, ( err , obj ) =>
|
||||
test.deepEqual obj, @action1,
|
||||
'Retrieved Action Invoker is not what we expected'
|
||||
|
||||
# Ensure the action invoker is in the list of all existing ones
|
||||
@db.getActionInvokers ( err , obj ) =>
|
||||
test.deepEqual action, obj[id],
|
||||
test.deepEqual @action1, obj[@action1id],
|
||||
'Action Invoker ist not in result set'
|
||||
@db.deleteActionInvoker id
|
||||
test.done()
|
||||
|
||||
testUpdate: ( test ) =>
|
||||
test.expect 2
|
||||
|
||||
id = 'test-action-invoker'
|
||||
action = 'unit-test action invoker content'
|
||||
actionNew = 'unit-test action invoker new content'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeActionInvoker id, action
|
||||
@db.storeActionInvoker id, actionNew
|
||||
@db.storeActionInvoker @action1id, @action1
|
||||
@db.storeActionInvoker @action1id, @action2
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getActionInvoker id, ( err , obj ) =>
|
||||
test.strictEqual obj, actionNew,
|
||||
@db.getActionInvoker @action1id, ( err , obj ) =>
|
||||
test.deepEqual obj, @action2,
|
||||
'Retrieved Action Invoker is not what we expected'
|
||||
|
||||
# Ensure the action invoker is in the list of all existing ones
|
||||
@db.getActionInvokers ( err , obj ) =>
|
||||
test.deepEqual actionNew, obj[id],
|
||||
test.deepEqual @action2, obj[@action1id],
|
||||
'Action Invoker ist not in result set'
|
||||
@db.deleteActionInvoker id
|
||||
test.done()
|
||||
|
||||
testDelete: ( test ) =>
|
||||
test.expect 2
|
||||
|
||||
id = 'test-action-invoker'
|
||||
action = 'unit-test action invoker content'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeActionInvoker id, action
|
||||
@db.storeActionInvoker @action1id, @action1
|
||||
|
||||
# Ensure the action invoker has been deleted
|
||||
@db.deleteActionInvoker id
|
||||
@db.getActionInvoker id, ( err , obj ) =>
|
||||
@db.deleteActionInvoker @action1id
|
||||
@db.getActionInvoker @action1id, ( err , obj ) =>
|
||||
test.strictEqual obj, null,
|
||||
'Action Invoker still exists'
|
||||
|
||||
# Ensure the ID has been removed from the set
|
||||
@db.getActionInvokerIds ( err , obj ) =>
|
||||
test.ok id not in obj,
|
||||
test.ok @action1id not in obj,
|
||||
'Action Invoker key still exists in set'
|
||||
test.done()
|
||||
|
||||
|
|
@ -214,33 +217,29 @@ exports.ActionInvoker =
|
|||
test.expect 3
|
||||
|
||||
semaphore = 2
|
||||
action1name = 'test-action-invoker_1'
|
||||
action2name = 'test-action-invoker_2'
|
||||
action1 = 'unit-test action invoker 1 content'
|
||||
action2 = 'unit-test action invoker 2 content'
|
||||
|
||||
fCheckInvoker = ( modname, mod ) =>
|
||||
myTest = test
|
||||
forkEnds = () ->
|
||||
myTest.done() if --semaphore is 0
|
||||
( err, obj ) =>
|
||||
myTest.strictEqual mod, obj,
|
||||
myTest.deepEqual mod, obj,
|
||||
"Invoker #{ modname } does not equal the expected one"
|
||||
@db.deleteActionInvoker modname
|
||||
forkEnds()
|
||||
|
||||
@db.storeActionInvoker action1name, action1
|
||||
@db.storeActionInvoker action2name, action2
|
||||
@db.storeActionInvoker @action1id, @action1
|
||||
@db.storeActionInvoker @action2id, @action2
|
||||
@db.getActionInvokerIds ( err, obj ) =>
|
||||
test.ok action1name in obj and action2name in obj,
|
||||
test.ok @action1id in obj and @action2id in obj,
|
||||
'Not all action invoker Ids in set'
|
||||
@db.getActionInvoker action1name, fCheckInvoker action1name, action1
|
||||
@db.getActionInvoker action2name, fCheckInvoker action2name, action2
|
||||
@db.getActionInvoker @action1id, fCheckInvoker @action1id, @action1
|
||||
@db.getActionInvoker @action2id, fCheckInvoker @action2id, @action2
|
||||
|
||||
|
||||
###
|
||||
# Test ACTION INVOKER PARAMS
|
||||
###
|
||||
#TODO add tests for required parameters per module
|
||||
exports.ActionInvokerParams =
|
||||
testCreateAndRead: ( test ) =>
|
||||
test.expect 2
|
||||
|
|
@ -250,18 +249,18 @@ exports.ActionInvokerParams =
|
|||
params = 'shouldn\'t this be an object?'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeActionParams actionId, userId, params
|
||||
@db.storeActionUserParams actionId, userId, params
|
||||
|
||||
# test that the ID shows up in the set
|
||||
@db.getActionParamsIds ( err, obj ) =>
|
||||
@db.getActionUserParamsIds ( err, obj ) =>
|
||||
test.ok actionId+':'+userId in obj,
|
||||
'Expected key not in action-params set'
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getActionParams actionId, userId, ( err, obj ) =>
|
||||
@db.getActionUserParams actionId, userId, ( err, obj ) =>
|
||||
test.strictEqual obj, params,
|
||||
'Retrieved action params is not what we expected'
|
||||
@db.deleteActionParams actionId, userId
|
||||
@db.deleteActionUserParams actionId, userId
|
||||
test.done()
|
||||
|
||||
testUpdate: ( test ) =>
|
||||
|
|
@ -273,14 +272,14 @@ exports.ActionInvokerParams =
|
|||
paramsNew = 'shouldn\'t this be a new object?'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeActionParams actionId, userId, params
|
||||
@db.storeActionParams actionId, userId, paramsNew
|
||||
@db.storeActionUserParams actionId, userId, params
|
||||
@db.storeActionUserParams actionId, userId, paramsNew
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getActionParams actionId, userId, ( err, obj ) =>
|
||||
@db.getActionUserParams actionId, userId, ( err, obj ) =>
|
||||
test.strictEqual obj, paramsNew,
|
||||
'Retrieved action params is not what we expected'
|
||||
@db.deleteActionParams actionId, userId
|
||||
@db.deleteActionUserParams actionId, userId
|
||||
test.done()
|
||||
|
||||
testDelete: ( test ) =>
|
||||
|
|
@ -291,15 +290,15 @@ exports.ActionInvokerParams =
|
|||
params = 'shouldn\'t this be an object?'
|
||||
|
||||
# store an entry to start with and delte it right away
|
||||
@db.storeActionParams actionId, userId, params
|
||||
@db.deleteActionParams actionId, userId
|
||||
@db.storeActionUserParams actionId, userId, params
|
||||
@db.deleteActionUserParams actionId, userId
|
||||
|
||||
# Ensure the action params have been deleted
|
||||
@db.getActionParams actionId, userId, ( err, obj ) =>
|
||||
@db.getActionUserParams actionId, userId, ( err, obj ) =>
|
||||
test.strictEqual obj, null,
|
||||
'Action params still exists'
|
||||
# Ensure the ID has been removed from the set
|
||||
@db.getActionParamsIds ( err, obj ) =>
|
||||
@db.getActionUserParamsIds ( err, obj ) =>
|
||||
test.ok actionId+':'+userId not in obj,
|
||||
'Action Params key still exists in set'
|
||||
test.done()
|
||||
|
|
@ -309,73 +308,76 @@ exports.ActionInvokerParams =
|
|||
# Test EVENT POLLER
|
||||
###
|
||||
exports.EventPoller =
|
||||
setUp: ( cb ) =>
|
||||
@event1id = 'test-event-poller_1'
|
||||
@event2id = 'test-event-poller_2'
|
||||
@event1 =
|
||||
code: 'unit-test event poller 1 content'
|
||||
reqparams:'[param11,param12]'
|
||||
@event2 =
|
||||
code: 'unit-test event poller 2 content'
|
||||
reqparams:'[param21,param22]'
|
||||
cb()
|
||||
|
||||
tearDown: ( cb ) =>
|
||||
@db.deleteEventPoller @event1id
|
||||
@db.deleteEventPoller @event2id
|
||||
cb()
|
||||
|
||||
testCreateAndRead: ( test ) =>
|
||||
test.expect 3
|
||||
|
||||
id = 'test-event-poller'
|
||||
event = 'unit-test event poller content'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeEventPoller id, event
|
||||
@db.storeEventPoller @event1id, @event1
|
||||
|
||||
# test that the ID shows up in the set
|
||||
@db.getEventPollerIds ( err , obj ) =>
|
||||
test.ok id in obj,
|
||||
test.ok @event1id in obj,
|
||||
'Expected key not in event-pollers set'
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getEventPoller id, ( err , obj ) =>
|
||||
test.strictEqual obj, event,
|
||||
@db.getEventPoller @event1id, ( err , obj ) =>
|
||||
test.deepEqual obj, @event1,
|
||||
'Retrieved Event Poller is not what we expected'
|
||||
|
||||
# Ensure the event poller is in the list of all existing ones
|
||||
@db.getEventPollers ( err , obj ) =>
|
||||
test.deepEqual event, obj[id],
|
||||
test.deepEqual @event1, obj[@event1id],
|
||||
'Event Poller ist not in result set'
|
||||
@db.deleteEventPoller id
|
||||
test.done()
|
||||
|
||||
testUpdate: ( test ) =>
|
||||
test.expect 2
|
||||
|
||||
id = 'test-event-poller'
|
||||
event = 'unit-test event poller content'
|
||||
eventNew = 'unit-test event poller new content'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeEventPoller id, event
|
||||
@db.storeEventPoller id, eventNew
|
||||
@db.storeEventPoller @event1id, @event1
|
||||
@db.storeEventPoller @event1id, @event2
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getEventPoller id, ( err , obj ) =>
|
||||
test.strictEqual obj, eventNew,
|
||||
@db.getEventPoller @event1id, ( err , obj ) =>
|
||||
test.deepEqual obj, @event2,
|
||||
'Retrieved Event Poller is not what we expected'
|
||||
|
||||
# Ensure the event poller is in the list of all existing ones
|
||||
@db.getEventPollers ( err , obj ) =>
|
||||
test.deepEqual eventNew, obj[id],
|
||||
test.deepEqual @event2, obj[@event1id],
|
||||
'Event Poller ist not in result set'
|
||||
@db.deleteEventPoller id
|
||||
test.done()
|
||||
|
||||
testDelete: ( test ) =>
|
||||
test.expect 2
|
||||
|
||||
id = 'test-event-poller'
|
||||
event = 'unit-test event poller content'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeEventPoller id, event
|
||||
@db.storeEventPoller @event1id, @event1
|
||||
|
||||
# Ensure the event poller has been deleted
|
||||
@db.deleteEventPoller id
|
||||
@db.getEventPoller id, ( err , obj ) =>
|
||||
@db.deleteEventPoller @event1id
|
||||
@db.getEventPoller @event1id, ( err , obj ) =>
|
||||
test.strictEqual obj, null,
|
||||
'Event Poller still exists'
|
||||
|
||||
# Ensure the ID has been removed from the set
|
||||
@db.getEventPollerIds ( err , obj ) =>
|
||||
test.ok id not in obj,
|
||||
test.ok @event1id not in obj,
|
||||
'Event Poller key still exists in set'
|
||||
test.done()
|
||||
|
||||
|
|
@ -384,28 +386,23 @@ exports.EventPoller =
|
|||
test.expect 3
|
||||
|
||||
semaphore = 2
|
||||
event1name = 'test-event-poller_1'
|
||||
event2name = 'test-event-poller_2'
|
||||
event1 = 'unit-test event poller 1 content'
|
||||
event2 = 'unit-test event poller 2 content'
|
||||
|
||||
fCheckPoller = ( modname, mod ) =>
|
||||
fCheckInvoker = ( modname, mod ) =>
|
||||
myTest = test
|
||||
forkEnds = () ->
|
||||
myTest.done() if --semaphore is 0
|
||||
( err, obj ) =>
|
||||
myTest.strictEqual mod, obj,
|
||||
myTest.deepEqual mod, obj,
|
||||
"Invoker #{ modname } does not equal the expected one"
|
||||
@db.deleteEventPoller modname
|
||||
forkEnds()
|
||||
|
||||
@db.storeEventPoller event1name, event1
|
||||
@db.storeEventPoller event2name, event2
|
||||
@db.storeEventPoller @event1id, @event1
|
||||
@db.storeEventPoller @event2id, @event2
|
||||
@db.getEventPollerIds ( err, obj ) =>
|
||||
test.ok event1name in obj and event2name in obj,
|
||||
test.ok @event1id in obj and @event2id in obj,
|
||||
'Not all event poller Ids in set'
|
||||
@db.getEventPoller event1name, fCheckPoller event1name, event1
|
||||
@db.getEventPoller event2name, fCheckPoller event2name, event2
|
||||
@db.getEventPoller @event1id, fCheckInvoker @event1id, @event1
|
||||
@db.getEventPoller @event2id, fCheckInvoker @event2id, @event2
|
||||
|
||||
|
||||
###
|
||||
|
|
@ -420,18 +417,18 @@ exports.EventPollerParams =
|
|||
params = 'shouldn\'t this be an object?'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeEventParams eventId, userId, params
|
||||
@db.storeEventUserParams eventId, userId, params
|
||||
|
||||
# test that the ID shows up in the set
|
||||
@db.getEventParamsIds ( err, obj ) =>
|
||||
@db.getEventUserParamsIds ( err, obj ) =>
|
||||
test.ok eventId+':'+userId in obj,
|
||||
'Expected key not in event-params set'
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getEventParams eventId, userId, ( err, obj ) =>
|
||||
@db.getEventUserParams eventId, userId, ( err, obj ) =>
|
||||
test.strictEqual obj, params,
|
||||
'Retrieved event params is not what we expected'
|
||||
@db.deleteEventParams eventId, userId
|
||||
@db.deleteEventUserParams eventId, userId
|
||||
test.done()
|
||||
|
||||
testUpdate: ( test ) =>
|
||||
|
|
@ -443,14 +440,14 @@ exports.EventPollerParams =
|
|||
paramsNew = 'shouldn\'t this be a new object?'
|
||||
|
||||
# store an entry to start with
|
||||
@db.storeEventParams eventId, userId, params
|
||||
@db.storeEventParams eventId, userId, paramsNew
|
||||
@db.storeEventUserParams eventId, userId, params
|
||||
@db.storeEventUserParams eventId, userId, paramsNew
|
||||
|
||||
# the retrieved object really is the one we expected
|
||||
@db.getEventParams eventId, userId, ( err, obj ) =>
|
||||
@db.getEventUserParams eventId, userId, ( err, obj ) =>
|
||||
test.strictEqual obj, paramsNew,
|
||||
'Retrieved event params is not what we expected'
|
||||
@db.deleteEventParams eventId, userId
|
||||
@db.deleteEventUserParams eventId, userId
|
||||
test.done()
|
||||
|
||||
testDelete: ( test ) =>
|
||||
|
|
@ -461,15 +458,15 @@ exports.EventPollerParams =
|
|||
params = 'shouldn\'t this be an object?'
|
||||
|
||||
# store an entry to start with and delete it right away
|
||||
@db.storeEventParams eventId, userId, params
|
||||
@db.deleteEventParams eventId, userId
|
||||
@db.storeEventUserParams eventId, userId, params
|
||||
@db.deleteEventUserParams eventId, userId
|
||||
|
||||
# Ensure the event params have been deleted
|
||||
@db.getEventParams eventId, userId, ( err, obj ) =>
|
||||
@db.getEventUserParams eventId, userId, ( err, obj ) =>
|
||||
test.strictEqual obj, null,
|
||||
'Event params still exists'
|
||||
# Ensure the ID has been removed from the set
|
||||
@db.getEventParamsIds ( err, obj ) =>
|
||||
@db.getEventUserParamsIds ( err, obj ) =>
|
||||
test.ok eventId+':'+userId not in obj,
|
||||
'Event Params key still exists in set'
|
||||
test.done()
|
||||
|
|
|
|||
20
webpages/handlers/coffee/admin.coffee
Normal file
20
webpages/handlers/coffee/admin.coffee
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
fOnLoad = () ->
|
||||
document.title = 'Administrate'
|
||||
$( '#pagetitle' ).text 'Hi {{{user.username}}}, issue your commands please:'
|
||||
$( '#but_submit' ).click () ->
|
||||
data =
|
||||
command: $( '#inp_command' ).val()
|
||||
$.post( 'admincommand', data )
|
||||
.done ( data ) ->
|
||||
$( '#info' ).text data.message
|
||||
$( '#info' ).attr 'class', 'success'
|
||||
.fail ( err ) ->
|
||||
if err.responseText is ''
|
||||
err.responseText = 'No Response from Server!'
|
||||
$( '#info' ).text 'Error: ' + err.responseText
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
if err.status is 401
|
||||
window.location.href = 'admin'
|
||||
|
||||
window.addEventListener 'load', fOnLoad, true
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
fOnLoad = () ->
|
||||
document.title = 'Error!'
|
||||
$( '#pagetitle' ).text 'Error processing your request!'
|
||||
$( '#pagetitle' ).attr 'class', 'error'
|
||||
|
||||
window.addEventListener 'load', fOnLoad, true
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
|
||||
fOnLoad = () ->
|
||||
document.title = 'Forge Action Invoker'
|
||||
$( '#pagetitle' ).text "{{{user.username}}}, forge your custom action invoker!"
|
||||
|
||||
# Setup the ACE editor
|
||||
editor = ace.edit "editor"
|
||||
editor.setTheme "ace/theme/monokai"
|
||||
editor.getSession().setMode "ace/mode/coffee"
|
||||
editor.setShowPrintMargin false
|
||||
|
||||
$( '#editor_mode' ).change ( el ) ->
|
||||
if $( this ).val() is '0'
|
||||
editor.getSession().setMode "ace/mode/coffee"
|
||||
else
|
||||
editor.getSession().setMode "ace/mode/javascript"
|
||||
|
||||
# Add parameter list functionality
|
||||
fChangeCrosses = () ->
|
||||
$( '#tableParams img' ).each ( id ) ->
|
||||
par = $( this ).closest 'tr'
|
||||
if par.is ':last-child' or par.is ':only-child'
|
||||
$( this ).hide()
|
||||
else
|
||||
$( this ).show()
|
||||
|
||||
$( '#tableParams' ).on 'click', 'img', () ->
|
||||
par = $( this ).closest 'tr'
|
||||
if not par.is ':last-child'
|
||||
par.remove()
|
||||
fChangeCrosses()
|
||||
|
||||
$( '#tableParams' ).on 'keyup', 'input', () ->
|
||||
par = $( this ).closest( 'tr' )
|
||||
if par.is ':last-child'
|
||||
tr = $ '<tr>'
|
||||
img = $( '<img>' ).attr 'src', 'red_cross_small.png'
|
||||
inp = $( '<input>' ).attr 'type', 'text'
|
||||
tr.append( $( '<td>' ).append img )
|
||||
tr.append( $( '<td>' ).append inp )
|
||||
par.parent().append tr
|
||||
fChangeCrosses()
|
||||
else if $( this ).val() is '' and not par.is ':only-child'
|
||||
par.remove()
|
||||
fChangeCrosses()
|
||||
|
||||
# Add submit button logic
|
||||
$( '#but_submit' ).click () ->
|
||||
if $( '#input_id' ).val() is ''
|
||||
alert 'Please enter an action invoker name!'
|
||||
else
|
||||
listParams = []
|
||||
$( '#tableParams input' ).each () ->
|
||||
val = $( this ).val()
|
||||
if val isnt ""
|
||||
listParams.push val
|
||||
obj =
|
||||
id: $( '#input_id' ).val()
|
||||
command: 'forge_action_invoker'
|
||||
lang: $( '#editor_mode' ).val()
|
||||
public: $( '#is_public' ).is ':checked'
|
||||
data: editor.getValue()
|
||||
params: JSON.stringify listParams
|
||||
$.post( '/usercommand', obj )
|
||||
.done ( data ) ->
|
||||
$( '#info' ).text data.message
|
||||
$( '#info' ).attr 'class', 'success'
|
||||
.fail ( err ) ->
|
||||
if err.responseText is ''
|
||||
msg = 'No Response from Server!'
|
||||
else
|
||||
try
|
||||
oErr = JSON.parse err.responseText
|
||||
msg = oErr.message
|
||||
$( '#info' ).text 'Action Invoker not stored! ' + msg
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
if err.status is 401
|
||||
window.location.href = 'forge?page=forge_action_invoker'
|
||||
|
||||
window.addEventListener 'load', fOnLoad, true
|
||||
|
|
@ -8,16 +8,25 @@ fOnLoad = () ->
|
|||
editor.setTheme "ace/theme/monokai"
|
||||
editor.getSession().setMode "ace/mode/json"
|
||||
editor.setShowPrintMargin false
|
||||
$( '#editor' ).css 'height', '400px'
|
||||
$( '#editor' ).css 'width', '600px'
|
||||
|
||||
$('#but_submit').click () ->
|
||||
$( '#but_submit' ).click () ->
|
||||
try
|
||||
data = JSON.parse editor.getValue()
|
||||
$.post('/event', data)
|
||||
$.post( '/event', data )
|
||||
.done ( data ) ->
|
||||
alert data
|
||||
.fail (err) ->
|
||||
alert 'Posting of event failed: ' + err.responseText
|
||||
$( '#info' ).text data.message
|
||||
$( '#info' ).attr 'class', 'success'
|
||||
.fail ( err ) ->
|
||||
if err.responseText is ''
|
||||
err.responseText = 'No Response from Server!'
|
||||
$( '#info' ).text 'Error in upload: ' + err.responseText
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
if err.status is 401
|
||||
window.location.href = 'forge?page=forge_event'
|
||||
catch err
|
||||
alert 'You have errors in your JSON object!'
|
||||
$( '#info' ).text 'You have errors in your JSON object! ' + err
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
|
||||
window.addEventListener 'load', fOnLoad, true
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
|
||||
fOnLoad = () ->
|
||||
document.title = 'Forge Event Poller'
|
||||
$( '#pagetitle' ).text 'Forge your custom event poller!'
|
||||
$( '#pagetitle' ).text "{{{user.username}}}, forge your custom event poller!"
|
||||
|
||||
# Setup the ACE editor
|
||||
editor = ace.edit "editor"
|
||||
editor.setTheme "ace/theme/monokai"
|
||||
editor.getSession().setMode "ace/mode/coffee"
|
||||
|
|
@ -14,41 +14,67 @@ fOnLoad = () ->
|
|||
editor.getSession().setMode "ace/mode/coffee"
|
||||
else
|
||||
editor.getSession().setMode "ace/mode/javascript"
|
||||
|
||||
$( '#but_submit' ).click () ->
|
||||
try
|
||||
data = JSON.parse editor.getValue()
|
||||
$.post('/event', data)
|
||||
.done ( data ) ->
|
||||
alert data
|
||||
.fail (err) ->
|
||||
alert 'Posting of event failed: ' + err.responseText
|
||||
catch err
|
||||
alert 'You have errors in your JSON object!'
|
||||
|
||||
# Add parameter list functionality
|
||||
fChangeCrosses = () ->
|
||||
$( '#listParams img' ).each ( id ) ->
|
||||
par = $( this ).parent 'tr'
|
||||
$( '#tableParams img' ).each ( id ) ->
|
||||
par = $( this ).closest 'tr'
|
||||
if par.is ':last-child' or par.is ':only-child'
|
||||
$( this ).hide()
|
||||
else
|
||||
$( this ).show()
|
||||
|
||||
$( '#listParams' ).on 'click', 'img', () ->
|
||||
par = $( this ).parent 'tr'
|
||||
$( '#tableParams' ).on 'click', 'img', () ->
|
||||
par = $( this ).closest 'tr'
|
||||
if not par.is ':last-child'
|
||||
par.remove()
|
||||
fChangeCrosses()
|
||||
|
||||
$( '#listParams' ).on 'keyup', 'input', ->
|
||||
console.log 'weees'
|
||||
if $( this ).parent( 'tr' ).is ':last-child'
|
||||
$( '#tableParams' ).on 'keyup', 'input', () ->
|
||||
par = $( this ).closest( 'tr' )
|
||||
if par.is ':last-child'
|
||||
tr = $ '<tr>'
|
||||
td = tr.append 'td'
|
||||
td.append $( '<img>' ).attr 'src', 'red_cross_small.png'
|
||||
td.append $( '<input>' ).attr 'type', 'text'
|
||||
$( '#listParams' ).append tr
|
||||
img = $( '<img>' ).attr 'src', 'red_cross_small.png'
|
||||
inp = $( '<input>' ).attr 'type', 'text'
|
||||
tr.append( $( '<td>' ).append img )
|
||||
tr.append( $( '<td>' ).append inp )
|
||||
par.parent().append tr
|
||||
fChangeCrosses()
|
||||
else if $( this ).val() is '' and not par.is ':only-child'
|
||||
par.remove()
|
||||
fChangeCrosses()
|
||||
|
||||
# Add submit button logic
|
||||
$( '#but_submit' ).click () ->
|
||||
if $( '#input_id' ).val() is ''
|
||||
alert 'Please enter an event poller name!'
|
||||
else
|
||||
listParams = []
|
||||
$( '#tableParams input' ).each () ->
|
||||
val = $( this ).val()
|
||||
if val isnt ""
|
||||
listParams.push val
|
||||
obj =
|
||||
id: $( '#input_id' ).val()
|
||||
command: 'forge_event_poller'
|
||||
lang: $( '#editor_mode' ).val()
|
||||
public: $( '#is_public' ).is ':checked'
|
||||
data: editor.getValue()
|
||||
params: JSON.stringify listParams
|
||||
$.post( '/usercommand', obj )
|
||||
.done ( data ) ->
|
||||
$( '#info' ).text data.message
|
||||
$( '#info' ).attr 'class', 'success'
|
||||
.fail ( err ) ->
|
||||
if err.responseText is ''
|
||||
msg = 'No Response from Server!'
|
||||
else
|
||||
try
|
||||
oErr = JSON.parse err.responseText
|
||||
msg = oErr.message
|
||||
$( '#info' ).text 'Event Poller not stored! ' + msg
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
if err.status is 401
|
||||
window.location.href = 'forge?page=forge_event_poller'
|
||||
|
||||
window.addEventListener 'load', fOnLoad, true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,188 @@
|
|||
|
||||
|
||||
fOnLoad = () ->
|
||||
document.title = 'Rule Forge!'
|
||||
$( '#pagetitle' ).text '{{{user.username}}}, forge your custom rule!'
|
||||
|
||||
# Fetch Event Poller user-specific parameters
|
||||
fFetchEventParams = ( name ) ->
|
||||
arr = name.split ' -> '
|
||||
obj =
|
||||
command: 'get_event_poller_params'
|
||||
id: arr[0]
|
||||
$.post( '/usercommand', obj )
|
||||
.done ( data ) ->
|
||||
if data.message
|
||||
arrParams = JSON.parse data.message
|
||||
$( '#event_poller_params table' ).remove()
|
||||
if arrParams.length > 0
|
||||
$( '#event_poller_params' ).text 'Required user-specific params:'
|
||||
table = $ '<table>'
|
||||
$( '#event_poller_params' ).append table
|
||||
fAppendParam = ( name ) ->
|
||||
tr = $( '<tr>' )
|
||||
tr.append $( '<td>' ).css 'width', '20px'
|
||||
tr.append $( '<td>' ).text name
|
||||
inp = $( '<input>' ).attr( 'type', 'password' ).attr 'id', "#{ name }"
|
||||
tr.append $( '<td>' ).text( ' :' ).append inp
|
||||
table.append tr
|
||||
fAppendParam name for name in arrParams
|
||||
.fail ( err ) ->
|
||||
console.log err
|
||||
$( '#info' ).text 'Error fetching event poller params'
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
|
||||
|
||||
#FIXME Add possibility for custom event via text input
|
||||
#FIXME Add conditions
|
||||
|
||||
|
||||
# Init Event Pollers
|
||||
obj =
|
||||
command: 'get_event_pollers'
|
||||
$.post( '/usercommand', obj )
|
||||
.done ( data ) ->
|
||||
fAppendEvent = ( id, name ) ->
|
||||
$( '#select_event' ).append $( '<option>' ).text id + ' -> ' + name
|
||||
fAppendEvent id, name for id, name of data.message
|
||||
fFetchEventParams $( '#select_event option:selected' ).text()
|
||||
.fail ( err ) ->
|
||||
console.log err
|
||||
$( '#info' ).text 'Error fetching event poller'
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
|
||||
$( '#select_event' ).change () ->
|
||||
fFetchEventParams $( this ).val()
|
||||
|
||||
# Init Action Invoker
|
||||
arrActionInvoker = []
|
||||
obj =
|
||||
command: 'get_action_invokers'
|
||||
$.post( '/usercommand', obj )
|
||||
.done ( data ) ->
|
||||
i = 0
|
||||
fAppendAction = ( id, name ) ->
|
||||
$( '#select_actions' ).append $( '<option>' ).attr( 'id', i++ ).text id + ' -> ' + name
|
||||
arrActionInvoker.push id + ' -> ' + name
|
||||
fAppendAction id, name for id, name of data.message
|
||||
.fail ( err ) ->
|
||||
console.log err
|
||||
$( '#info' ).text 'Error fetching event poller'
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
|
||||
# Fetch Action Invoker user-specific parameters
|
||||
fFetchActionParams = ( div, name ) ->
|
||||
obj =
|
||||
command: 'get_action_invoker_params'
|
||||
id: name
|
||||
$.post( '/usercommand', obj )
|
||||
.done ( data ) ->
|
||||
if data.message
|
||||
arrParams = JSON.parse data.message
|
||||
if arrParams.length > 0
|
||||
table = $ '<table>'
|
||||
div.append table
|
||||
fAppendActionParam = ( name ) ->
|
||||
tr = $( '<tr>' )
|
||||
tr.append $( '<td>' ).css 'width', '20px'
|
||||
tr.append $( '<td>' ).attr( 'class', 'key').text name
|
||||
tr.append $( '<td>' ).text(' :').append $( '<input>' ).attr( 'type', 'password' )
|
||||
table.append tr
|
||||
fAppendActionParam name for name in arrParams
|
||||
.fail ( err ) ->
|
||||
console.log err
|
||||
$( '#info' ).text 'Error fetching action invoker params'
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
|
||||
$( '#select_actions' ).on 'change', () ->
|
||||
opt = $ 'option:selected', this
|
||||
arrAI = opt.val().split ' -> '
|
||||
|
||||
table = $( '#selected_actions' )
|
||||
tr = $( '<tr>' ).attr( 'id', 'title_' + opt.attr 'id')
|
||||
img = $( '<img>' ).attr 'src', 'red_cross_small.png'
|
||||
tr.append $( '<td>' ).css( 'width', '20px' ).append img
|
||||
tr.append $( '<td>' ).attr( 'class', 'title').text( opt.val() )
|
||||
table.append tr
|
||||
if $( '#ap_' + arrAI[0] ).length is 0
|
||||
div = $( '<div>' ).attr( 'id', 'ap_' + arrAI[0] ).html "<i>#{ arrAI[0] }</i>"
|
||||
$( '#action_params' ).append div
|
||||
fFetchActionParams div, arrAI[0]
|
||||
opt.remove()
|
||||
|
||||
$( '#selected_actions' ).on 'click', 'img', () ->
|
||||
id = $( this ).closest( 'tr' ).attr( 'id' ).substring 6
|
||||
name = arrActionInvoker[id]
|
||||
arrName = name.split ' -> '
|
||||
$( '#title_' + id ).remove()
|
||||
$( '#params_' + id ).remove()
|
||||
opt = $( '<option>' ).attr( 'id', id ).text name
|
||||
$( '#select_actions' ).append opt
|
||||
isSelected = false
|
||||
$( '#selected_actions td' ).each () ->
|
||||
if $( this ).text().indexOf( arrName[0] ) > -1
|
||||
isSelected = true
|
||||
if not isSelected
|
||||
$( '#ap_' + arrName[0] ).remove()
|
||||
|
||||
|
||||
$( '#but_submit' ).click () ->
|
||||
arrEP = $( '#select_event option:selected' ).val().split ' -> '
|
||||
try
|
||||
if $( '#input_id' ).val() is ''
|
||||
throw new Error 'Please enter a module name!'
|
||||
|
||||
ep = {}
|
||||
$( "#event_poller_params tr" ).each () ->
|
||||
val = $( 'input', this ).val()
|
||||
name = $( 'td:nth-child(2)', this ).text()
|
||||
if val is ''
|
||||
throw new Error "Please enter a value for '#{ name }' in the event module!"
|
||||
ep[name] = val
|
||||
|
||||
if $( '#selected_actions tr' ).length is 0
|
||||
throw new Error 'Please select at least one action or create one!'
|
||||
|
||||
ap = {}
|
||||
$( '#action_params div' ).each () ->
|
||||
id = $( this ).attr( 'id' ).substring 3
|
||||
params = {}
|
||||
$( 'tr', this ).each () ->
|
||||
key = $( '.key', this ).text()
|
||||
val = $( 'input', this ).val()
|
||||
if val is ''
|
||||
throw new Error "'#{ key }' missing for '#{ id }'"
|
||||
params[key] = val
|
||||
ap[id] = params
|
||||
acts = []
|
||||
$( '#selected_actions .title' ).each () ->
|
||||
acts.push $( this ).text()
|
||||
obj =
|
||||
command: 'forge_rule'
|
||||
id: $( '#input_id' ).val()
|
||||
event: JSON.stringify
|
||||
module: arrEP[0]
|
||||
function: arrEP[1]
|
||||
event_params: JSON.stringify ep
|
||||
conditions: JSON.stringify {} #TODO Add conditions!
|
||||
actions: JSON.stringify acts
|
||||
action_params: JSON.stringify ap
|
||||
$.post( '/usercommand', obj )
|
||||
.done ( data ) ->
|
||||
$( '#info' ).text data.message
|
||||
$( '#info' ).attr 'class', 'success'
|
||||
.fail ( err ) ->
|
||||
if err.responseText is ''
|
||||
msg = 'No Response from Server!'
|
||||
else
|
||||
try
|
||||
oErr = JSON.parse err.responseText
|
||||
msg = oErr.message
|
||||
$( '#info' ).text 'Error in upload: ' + msg
|
||||
$( '#info' ).attr 'class', 'error'
|
||||
if err.status is 401
|
||||
window.location.href = 'forge?page=forge_rule'
|
||||
catch err
|
||||
alert err.message
|
||||
|
||||
window.addEventListener 'load', fOnLoad, true
|
||||
31
webpages/handlers/js/admin.js
Normal file
31
webpages/handlers/js/admin.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
(function() {
|
||||
var fOnLoad;
|
||||
|
||||
fOnLoad = function() {
|
||||
document.title = 'Administrate';
|
||||
$('#pagetitle').text('Hi {{{user.username}}}, issue your commands please:');
|
||||
return $('#but_submit').click(function() {
|
||||
var data;
|
||||
data = {
|
||||
command: $('#inp_command').val()
|
||||
};
|
||||
return $.post('admincommand', data).done(function(data) {
|
||||
$('#info').text(data.message);
|
||||
return $('#info').attr('class', 'success');
|
||||
}).fail(function(err) {
|
||||
if (err.responseText === '') {
|
||||
err.responseText = 'No Response from Server!';
|
||||
}
|
||||
$('#info').text('Error: ' + err.responseText);
|
||||
$('#info').attr('class', 'error');
|
||||
if (err.status === 401) {
|
||||
return window.location.href = 'admin';
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener('load', fOnLoad, true);
|
||||
|
||||
}).call(this);
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
(function() {
|
||||
var fOnLoad;
|
||||
|
||||
fOnLoad = function() {
|
||||
document.title = 'Error!';
|
||||
$('#pagetitle').text('Error processing your request!');
|
||||
return $('#pagetitle').attr('class', 'error');
|
||||
};
|
||||
|
||||
window.addEventListener('load', fOnLoad, true);
|
||||
|
||||
}).call(this);
|
||||
|
|
@ -1,5 +1,101 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
(function() {
|
||||
var fOnLoad;
|
||||
|
||||
fOnLoad = function() {
|
||||
var editor, fChangeCrosses;
|
||||
document.title = 'Forge Action Invoker';
|
||||
$('#pagetitle').text("{{{user.username}}}, forge your custom action invoker!");
|
||||
editor = ace.edit("editor");
|
||||
editor.setTheme("ace/theme/monokai");
|
||||
editor.getSession().setMode("ace/mode/coffee");
|
||||
editor.setShowPrintMargin(false);
|
||||
$('#editor_mode').change(function(el) {
|
||||
if ($(this).val() === '0') {
|
||||
return editor.getSession().setMode("ace/mode/coffee");
|
||||
} else {
|
||||
return editor.getSession().setMode("ace/mode/javascript");
|
||||
}
|
||||
});
|
||||
fChangeCrosses = function() {
|
||||
return $('#tableParams img').each(function(id) {
|
||||
var par;
|
||||
par = $(this).closest('tr');
|
||||
if (par.is(':last-child' || par.is(':only-child'))) {
|
||||
return $(this).hide();
|
||||
} else {
|
||||
return $(this).show();
|
||||
}
|
||||
});
|
||||
};
|
||||
$('#tableParams').on('click', 'img', function() {
|
||||
var par;
|
||||
par = $(this).closest('tr');
|
||||
if (!par.is(':last-child')) {
|
||||
par.remove();
|
||||
}
|
||||
return fChangeCrosses();
|
||||
});
|
||||
$('#tableParams').on('keyup', 'input', function() {
|
||||
var img, inp, par, tr;
|
||||
par = $(this).closest('tr');
|
||||
if (par.is(':last-child')) {
|
||||
tr = $('<tr>');
|
||||
img = $('<img>').attr('src', 'red_cross_small.png');
|
||||
inp = $('<input>').attr('type', 'text');
|
||||
tr.append($('<td>').append(img));
|
||||
tr.append($('<td>').append(inp));
|
||||
par.parent().append(tr);
|
||||
return fChangeCrosses();
|
||||
} else if ($(this).val() === '' && !par.is(':only-child')) {
|
||||
return par.remove();
|
||||
}
|
||||
});
|
||||
fChangeCrosses();
|
||||
return $('#but_submit').click(function() {
|
||||
var listParams, obj;
|
||||
if ($('#input_id').val() === '') {
|
||||
return alert('Please enter an action invoker name!');
|
||||
} else {
|
||||
listParams = [];
|
||||
$('#tableParams input').each(function() {
|
||||
var val;
|
||||
val = $(this).val();
|
||||
if (val !== "") {
|
||||
return listParams.push(val);
|
||||
}
|
||||
});
|
||||
obj = {
|
||||
id: $('#input_id').val(),
|
||||
command: 'forge_action_invoker',
|
||||
lang: $('#editor_mode').val(),
|
||||
"public": $('#is_public').is(':checked'),
|
||||
data: editor.getValue(),
|
||||
params: JSON.stringify(listParams)
|
||||
};
|
||||
return $.post('/usercommand', obj).done(function(data) {
|
||||
$('#info').text(data.message);
|
||||
return $('#info').attr('class', 'success');
|
||||
}).fail(function(err) {
|
||||
var msg, oErr;
|
||||
if (err.responseText === '') {
|
||||
msg = 'No Response from Server!';
|
||||
} else {
|
||||
try {
|
||||
oErr = JSON.parse(err.responseText);
|
||||
msg = oErr.message;
|
||||
} catch (_error) {}
|
||||
}
|
||||
$('#info').text('Action Invoker not stored! ' + msg);
|
||||
$('#info').attr('class', 'error');
|
||||
if (err.status === 401) {
|
||||
return window.location.href = 'forge?page=forge_action_invoker';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener('load', fOnLoad, true);
|
||||
|
||||
}).call(this);
|
||||
|
|
|
|||
|
|
@ -10,18 +10,29 @@
|
|||
editor.setTheme("ace/theme/monokai");
|
||||
editor.getSession().setMode("ace/mode/json");
|
||||
editor.setShowPrintMargin(false);
|
||||
$('#editor').css('height', '400px');
|
||||
$('#editor').css('width', '600px');
|
||||
return $('#but_submit').click(function() {
|
||||
var data, err;
|
||||
try {
|
||||
data = JSON.parse(editor.getValue());
|
||||
return $.post('/event', data).done(function(data) {
|
||||
return alert(data);
|
||||
$('#info').text(data.message);
|
||||
return $('#info').attr('class', 'success');
|
||||
}).fail(function(err) {
|
||||
return alert('Posting of event failed: ' + err.responseText);
|
||||
if (err.responseText === '') {
|
||||
err.responseText = 'No Response from Server!';
|
||||
}
|
||||
$('#info').text('Error in upload: ' + err.responseText);
|
||||
$('#info').attr('class', 'error');
|
||||
if (err.status === 401) {
|
||||
return window.location.href = 'forge?page=forge_event';
|
||||
}
|
||||
});
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
return alert('You have errors in your JSON object!');
|
||||
$('#info').text('You have errors in your JSON object! ' + err);
|
||||
return $('#info').attr('class', 'error');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
fOnLoad = function() {
|
||||
var editor, fChangeCrosses;
|
||||
document.title = 'Forge Event Poller';
|
||||
$('#pagetitle').text('Forge your custom event poller!');
|
||||
$('#pagetitle').text("{{{user.username}}}, forge your custom event poller!");
|
||||
editor = ace.edit("editor");
|
||||
editor.setTheme("ace/theme/monokai");
|
||||
editor.getSession().setMode("ace/mode/coffee");
|
||||
|
|
@ -17,24 +17,10 @@
|
|||
return editor.getSession().setMode("ace/mode/javascript");
|
||||
}
|
||||
});
|
||||
$('#but_submit').click(function() {
|
||||
var data, err;
|
||||
try {
|
||||
data = JSON.parse(editor.getValue());
|
||||
return $.post('/event', data).done(function(data) {
|
||||
return alert(data);
|
||||
}).fail(function(err) {
|
||||
return alert('Posting of event failed: ' + err.responseText);
|
||||
});
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
return alert('You have errors in your JSON object!');
|
||||
}
|
||||
});
|
||||
fChangeCrosses = function() {
|
||||
return $('#listParams img').each(function(id) {
|
||||
return $('#tableParams img').each(function(id) {
|
||||
var par;
|
||||
par = $(this).parent('tr');
|
||||
par = $(this).closest('tr');
|
||||
if (par.is(':last-child' || par.is(':only-child'))) {
|
||||
return $(this).hide();
|
||||
} else {
|
||||
|
|
@ -42,27 +28,72 @@
|
|||
}
|
||||
});
|
||||
};
|
||||
$('#listParams').on('click', 'img', function() {
|
||||
$('#tableParams').on('click', 'img', function() {
|
||||
var par;
|
||||
par = $(this).parent('tr');
|
||||
par = $(this).closest('tr');
|
||||
if (!par.is(':last-child')) {
|
||||
par.remove();
|
||||
}
|
||||
return fChangeCrosses();
|
||||
});
|
||||
$('#listParams').on('keyup', 'input', function() {
|
||||
var td, tr;
|
||||
console.log('weees');
|
||||
if ($(this).parent('tr').is(':last-child')) {
|
||||
$('#tableParams').on('keyup', 'input', function() {
|
||||
var img, inp, par, tr;
|
||||
par = $(this).closest('tr');
|
||||
if (par.is(':last-child')) {
|
||||
tr = $('<tr>');
|
||||
td = tr.append('td');
|
||||
td.append($('<img>').attr('src', 'red_cross_small.png'));
|
||||
td.append($('<input>').attr('type', 'text'));
|
||||
$('#listParams').append(tr);
|
||||
img = $('<img>').attr('src', 'red_cross_small.png');
|
||||
inp = $('<input>').attr('type', 'text');
|
||||
tr.append($('<td>').append(img));
|
||||
tr.append($('<td>').append(inp));
|
||||
par.parent().append(tr);
|
||||
return fChangeCrosses();
|
||||
} else if ($(this).val() === '' && !par.is(':only-child')) {
|
||||
return par.remove();
|
||||
}
|
||||
});
|
||||
fChangeCrosses();
|
||||
return $('#but_submit').click(function() {
|
||||
var listParams, obj;
|
||||
if ($('#input_id').val() === '') {
|
||||
return alert('Please enter an event poller name!');
|
||||
} else {
|
||||
listParams = [];
|
||||
$('#tableParams input').each(function() {
|
||||
var val;
|
||||
val = $(this).val();
|
||||
if (val !== "") {
|
||||
return listParams.push(val);
|
||||
}
|
||||
});
|
||||
obj = {
|
||||
id: $('#input_id').val(),
|
||||
command: 'forge_event_poller',
|
||||
lang: $('#editor_mode').val(),
|
||||
"public": $('#is_public').is(':checked'),
|
||||
data: editor.getValue(),
|
||||
params: JSON.stringify(listParams)
|
||||
};
|
||||
return $.post('/usercommand', obj).done(function(data) {
|
||||
$('#info').text(data.message);
|
||||
return $('#info').attr('class', 'success');
|
||||
}).fail(function(err) {
|
||||
var msg, oErr;
|
||||
if (err.responseText === '') {
|
||||
msg = 'No Response from Server!';
|
||||
} else {
|
||||
try {
|
||||
oErr = JSON.parse(err.responseText);
|
||||
msg = oErr.message;
|
||||
} catch (_error) {}
|
||||
}
|
||||
$('#info').text('Event Poller not stored! ' + msg);
|
||||
$('#info').attr('class', 'error');
|
||||
if (err.status === 401) {
|
||||
return window.location.href = 'forge?page=forge_event_poller';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return fChangeCrosses();
|
||||
};
|
||||
|
||||
window.addEventListener('load', fOnLoad, true);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,243 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
(function() {
|
||||
var fOnLoad;
|
||||
|
||||
fOnLoad = function() {
|
||||
var arrActionInvoker, fFetchActionParams, fFetchEventParams, obj;
|
||||
document.title = 'Rule Forge!';
|
||||
$('#pagetitle').text('{{{user.username}}}, forge your custom rule!');
|
||||
fFetchEventParams = function(name) {
|
||||
var arr, obj;
|
||||
arr = name.split(' -> ');
|
||||
obj = {
|
||||
command: 'get_event_poller_params',
|
||||
id: arr[0]
|
||||
};
|
||||
return $.post('/usercommand', obj).done(function(data) {
|
||||
var arrParams, fAppendParam, table, _i, _len, _results;
|
||||
if (data.message) {
|
||||
arrParams = JSON.parse(data.message);
|
||||
$('#event_poller_params table').remove();
|
||||
if (arrParams.length > 0) {
|
||||
$('#event_poller_params').text('Required user-specific params:');
|
||||
table = $('<table>');
|
||||
$('#event_poller_params').append(table);
|
||||
fAppendParam = function(name) {
|
||||
var inp, tr;
|
||||
tr = $('<tr>');
|
||||
tr.append($('<td>').css('width', '20px'));
|
||||
tr.append($('<td>').text(name));
|
||||
inp = $('<input>').attr('type', 'password').attr('id', "" + name);
|
||||
tr.append($('<td>').text(' :').append(inp));
|
||||
return table.append(tr);
|
||||
};
|
||||
_results = [];
|
||||
for (_i = 0, _len = arrParams.length; _i < _len; _i++) {
|
||||
name = arrParams[_i];
|
||||
_results.push(fAppendParam(name));
|
||||
}
|
||||
return _results;
|
||||
}
|
||||
}
|
||||
}).fail(function(err) {
|
||||
console.log(err);
|
||||
$('#info').text('Error fetching event poller params');
|
||||
return $('#info').attr('class', 'error');
|
||||
});
|
||||
};
|
||||
obj = {
|
||||
command: 'get_event_pollers'
|
||||
};
|
||||
$.post('/usercommand', obj).done(function(data) {
|
||||
var fAppendEvent, id, name, _ref;
|
||||
fAppendEvent = function(id, name) {
|
||||
return $('#select_event').append($('<option>').text(id + ' -> ' + name));
|
||||
};
|
||||
_ref = data.message;
|
||||
for (id in _ref) {
|
||||
name = _ref[id];
|
||||
fAppendEvent(id, name);
|
||||
}
|
||||
return fFetchEventParams($('#select_event option:selected').text());
|
||||
}).fail(function(err) {
|
||||
console.log(err);
|
||||
$('#info').text('Error fetching event poller');
|
||||
return $('#info').attr('class', 'error');
|
||||
});
|
||||
$('#select_event').change(function() {
|
||||
return fFetchEventParams($(this).val());
|
||||
});
|
||||
arrActionInvoker = [];
|
||||
obj = {
|
||||
command: 'get_action_invokers'
|
||||
};
|
||||
$.post('/usercommand', obj).done(function(data) {
|
||||
var fAppendAction, i, id, name, _ref, _results;
|
||||
i = 0;
|
||||
fAppendAction = function(id, name) {
|
||||
$('#select_actions').append($('<option>').attr('id', i++).text(id + ' -> ' + name));
|
||||
return arrActionInvoker.push(id + ' -> ' + name);
|
||||
};
|
||||
_ref = data.message;
|
||||
_results = [];
|
||||
for (id in _ref) {
|
||||
name = _ref[id];
|
||||
_results.push(fAppendAction(id, name));
|
||||
}
|
||||
return _results;
|
||||
}).fail(function(err) {
|
||||
console.log(err);
|
||||
$('#info').text('Error fetching event poller');
|
||||
return $('#info').attr('class', 'error');
|
||||
});
|
||||
fFetchActionParams = function(div, name) {
|
||||
obj = {
|
||||
command: 'get_action_invoker_params',
|
||||
id: name
|
||||
};
|
||||
return $.post('/usercommand', obj).done(function(data) {
|
||||
var arrParams, fAppendActionParam, table, _i, _len, _results;
|
||||
if (data.message) {
|
||||
arrParams = JSON.parse(data.message);
|
||||
if (arrParams.length > 0) {
|
||||
table = $('<table>');
|
||||
div.append(table);
|
||||
fAppendActionParam = function(name) {
|
||||
var tr;
|
||||
tr = $('<tr>');
|
||||
tr.append($('<td>').css('width', '20px'));
|
||||
tr.append($('<td>').attr('class', 'key').text(name));
|
||||
tr.append($('<td>').text(' :').append($('<input>').attr('type', 'password')));
|
||||
return table.append(tr);
|
||||
};
|
||||
_results = [];
|
||||
for (_i = 0, _len = arrParams.length; _i < _len; _i++) {
|
||||
name = arrParams[_i];
|
||||
_results.push(fAppendActionParam(name));
|
||||
}
|
||||
return _results;
|
||||
}
|
||||
}
|
||||
}).fail(function(err) {
|
||||
console.log(err);
|
||||
$('#info').text('Error fetching action invoker params');
|
||||
return $('#info').attr('class', 'error');
|
||||
});
|
||||
};
|
||||
$('#select_actions').on('change', function() {
|
||||
var arrAI, div, img, opt, table, tr;
|
||||
opt = $('option:selected', this);
|
||||
arrAI = opt.val().split(' -> ');
|
||||
table = $('#selected_actions');
|
||||
tr = $('<tr>').attr('id', 'title_' + opt.attr('id'));
|
||||
img = $('<img>').attr('src', 'red_cross_small.png');
|
||||
tr.append($('<td>').css('width', '20px').append(img));
|
||||
tr.append($('<td>').attr('class', 'title').text(opt.val()));
|
||||
table.append(tr);
|
||||
if ($('#ap_' + arrAI[0]).length === 0) {
|
||||
div = $('<div>').attr('id', 'ap_' + arrAI[0]).html("<i>" + arrAI[0] + "</i>");
|
||||
$('#action_params').append(div);
|
||||
fFetchActionParams(div, arrAI[0]);
|
||||
}
|
||||
return opt.remove();
|
||||
});
|
||||
$('#selected_actions').on('click', 'img', function() {
|
||||
var arrName, id, isSelected, name, opt;
|
||||
id = $(this).closest('tr').attr('id').substring(6);
|
||||
name = arrActionInvoker[id];
|
||||
arrName = name.split(' -> ');
|
||||
$('#title_' + id).remove();
|
||||
$('#params_' + id).remove();
|
||||
opt = $('<option>').attr('id', id).text(name);
|
||||
$('#select_actions').append(opt);
|
||||
isSelected = false;
|
||||
$('#selected_actions td').each(function() {
|
||||
if ($(this).text().indexOf(arrName[0]) > -1) {
|
||||
return isSelected = true;
|
||||
}
|
||||
});
|
||||
if (!isSelected) {
|
||||
return $('#ap_' + arrName[0]).remove();
|
||||
}
|
||||
});
|
||||
return $('#but_submit').click(function() {
|
||||
var acts, ap, arrEP, ep, err;
|
||||
arrEP = $('#select_event option:selected').val().split(' -> ');
|
||||
try {
|
||||
if ($('#input_id').val() === '') {
|
||||
throw new Error('Please enter a module name!');
|
||||
}
|
||||
ep = {};
|
||||
$("#event_poller_params tr").each(function() {
|
||||
var name, val;
|
||||
val = $('input', this).val();
|
||||
name = $('td:nth-child(2)', this).text();
|
||||
if (val === '') {
|
||||
throw new Error("Please enter a value for '" + name + "' in the event module!");
|
||||
}
|
||||
return ep[name] = val;
|
||||
});
|
||||
if ($('#selected_actions tr').length === 0) {
|
||||
throw new Error('Please select at least one action or create one!');
|
||||
}
|
||||
ap = {};
|
||||
$('#action_params div').each(function() {
|
||||
var id, params;
|
||||
id = $(this).attr('id').substring(3);
|
||||
params = {};
|
||||
$('tr', this).each(function() {
|
||||
var key, val;
|
||||
key = $('.key', this).text();
|
||||
val = $('input', this).val();
|
||||
if (val === '') {
|
||||
throw new Error("'" + key + "' missing for '" + id + "'");
|
||||
}
|
||||
return params[key] = val;
|
||||
});
|
||||
return ap[id] = params;
|
||||
});
|
||||
acts = [];
|
||||
$('#selected_actions .title').each(function() {
|
||||
return acts.push($(this).text());
|
||||
});
|
||||
obj = {
|
||||
command: 'forge_rule',
|
||||
id: $('#input_id').val(),
|
||||
event: JSON.stringify({
|
||||
module: arrEP[0],
|
||||
"function": arrEP[1]
|
||||
}),
|
||||
event_params: JSON.stringify(ep),
|
||||
conditions: JSON.stringify({}),
|
||||
actions: JSON.stringify(acts),
|
||||
action_params: JSON.stringify(ap)
|
||||
};
|
||||
return $.post('/usercommand', obj).done(function(data) {
|
||||
$('#info').text(data.message);
|
||||
return $('#info').attr('class', 'success');
|
||||
}).fail(function(err) {
|
||||
var msg, oErr;
|
||||
if (err.responseText === '') {
|
||||
msg = 'No Response from Server!';
|
||||
} else {
|
||||
try {
|
||||
oErr = JSON.parse(err.responseText);
|
||||
msg = oErr.message;
|
||||
} catch (_error) {}
|
||||
}
|
||||
$('#info').text('Error in upload: ' + msg);
|
||||
$('#info').attr('class', 'error');
|
||||
if (err.status === 401) {
|
||||
return window.location.href = 'forge?page=forge_rule';
|
||||
}
|
||||
});
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
return alert(err.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener('load', fOnLoad, true);
|
||||
|
||||
}).call(this);
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
admin page yay
|
||||
<input type="text" id="inp_command" style="width:300px" />
|
||||
<button type="button" id="but_submit">command</button>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<div class="error">Error: {{{message}}}</div>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
Action Invoker Name: <input id="input_id" type="text" />
|
||||
<select id="editor_mode">
|
||||
<option value="0">CoffeeScript</option>
|
||||
<option value="1">JavaScript</option>
|
||||
</select> is public: <input type="checkbox" id="is_public" />
|
||||
<table id="editor_table">
|
||||
<tr>
|
||||
<td id="editor_col" valign="top">
|
||||
<div id="editor">
|
||||
#
|
||||
# ProBinder Action Invoker
|
||||
#
|
||||
# Action Invoker requires user params:
|
||||
# - username: The ProBinder login username
|
||||
# - password: The ProBinder login password
|
||||
#
|
||||
|
||||
#
|
||||
# createBinderEntry function requires arguments:
|
||||
#
|
||||
# - company: The ProBidner company of the binder
|
||||
# - context: The ProBinder context (the binder ID)
|
||||
#
|
||||
exports.createBinderEntry = ( args ) ->
|
||||
url = 'https://probinder.com/service/27/save'
|
||||
|
||||
credentials =
|
||||
username: params.username
|
||||
password: params.password
|
||||
|
||||
data =
|
||||
companyId: args.company
|
||||
context: args.context
|
||||
text: args.content
|
||||
|
||||
needle.post url, data, credentials, ( err, resp, body ) ->
|
||||
if err
|
||||
log err
|
||||
if resp.statusCode isnt 200
|
||||
log "Request not successful: #{ body }"
|
||||
</div>
|
||||
<button id="but_submit">save</button>
|
||||
</td>
|
||||
<td id="params_col" valign="top">
|
||||
This action invoker requires user-specific properties:
|
||||
<table id="tableParams">
|
||||
<tr>
|
||||
<td><img src="red_cross_small.png"></td>
|
||||
<td><input type="text" value="username" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="red_cross_small.png"></td>
|
||||
<td><input type="text" value="password" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="red_cross_small.png"></td>
|
||||
<td><input type="text" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
<p>
|
||||
<div id="editor">
|
||||
|
||||
<div style="width:100%;float:left;">
|
||||
<div id="editor">
|
||||
{
|
||||
"event": "mail",
|
||||
"eventid": "mail_0",
|
||||
"payload": {
|
||||
"subject": "hello"
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
<p>
|
||||
<button id="but_submit">invoke</button>
|
||||
</p>
|
||||
<button id="but_submit">invoke</button>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
|
||||
Event Poller Name: <input id="input_id" type="text" />
|
||||
<select id="editor_mode">
|
||||
<option value="0">CoffeeScript</option>
|
||||
<option value="1">JavaScript</option>
|
||||
</select>
|
||||
</select> is public: <input type="checkbox" id="is_public" />
|
||||
<table id="editor_table">
|
||||
<tr>
|
||||
<td id="editor_col" valign="top">
|
||||
<p>
|
||||
<div id="editor">
|
||||
#
|
||||
# EmailYak EVENT POLLER
|
||||
#
|
||||
url = 'https://api.emailyak.com/v1/' + credentials.key + '/json/get/new/email/'
|
||||
# Requires user params:
|
||||
# - apikey: The user's EmailYak API key
|
||||
#
|
||||
|
||||
url = 'https://api.emailyak.com/v1/' + params.apikey + '/json/get/new/email/'
|
||||
|
||||
exports.newMail = ( pushEvent ) ->
|
||||
needle.get url, ( err, resp, body ) ->
|
||||
|
|
@ -22,14 +25,15 @@ exports.newMail = ( pushEvent ) ->
|
|||
log.error 'Error in EmailYak EM newMail: ' + err.message
|
||||
|
||||
</div>
|
||||
</p>
|
||||
<p>
|
||||
<button id="but_submit">save</button>
|
||||
</p>
|
||||
</td>
|
||||
<td id="params_col" valign="top">
|
||||
This event poller requires user-specific properties:
|
||||
<table id="tableParams">
|
||||
<tr>
|
||||
<td><img src="red_cross_small.png"></td>
|
||||
<td><input type="text" value="apikey" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="red_cross_small.png"></td>
|
||||
<td><input type="text" /></td>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<b>Rule Name: </b><input id="input_id" type="text" /><br><br>
|
||||
<b>Event: </b><select id="select_event"></select>
|
||||
<div id="event_poller_params"></div>
|
||||
<br><br>
|
||||
<b>Actions: </b><select id="select_actions"><option></option></select>
|
||||
<br><br>
|
||||
<b>Selected Actions:</b>
|
||||
<table id="selected_actions"></table>
|
||||
<br><br>
|
||||
<b>Required Params:</b>
|
||||
<br><br>
|
||||
<div id="action_params"></div>
|
||||
<br><br>
|
||||
<button id="but_submit">save</button>
|
||||
|
|
@ -1,26 +1,35 @@
|
|||
<div id="menubar">
|
||||
<div id="menubar_event">invoke events</div>
|
||||
<div id="menubar_events">forge event poller</div>
|
||||
<div id="menubar_actions">forge action invoker</div>
|
||||
<div id="menubar_rules">forge rules</div>
|
||||
<div id="menubar_logout">logout</div>
|
||||
<script>
|
||||
$( '#menubar_event' ).click( function() {
|
||||
window.location.href = 'forge?page=forge_event';
|
||||
});
|
||||
$( '#menubar_events' ).click( function() {
|
||||
window.location.href = 'forge?page=forge_event_poller';
|
||||
});
|
||||
$( '#menubar_actions' ).click( function() {
|
||||
window.location.href = 'forge?page=forge_action_invoker';
|
||||
});
|
||||
$( '#menubar_rules' ).click( function() {
|
||||
window.location.href = 'forge?page=forge_rule';
|
||||
});
|
||||
$( '#menubar_logout' ).click( function() {
|
||||
$.post( '/logout' ).done( function() {
|
||||
window.location.href = document.URL;
|
||||
});
|
||||
var menubar = $( '#menubar' );
|
||||
|
||||
var fRedirect = function( url ) {
|
||||
return function() {
|
||||
window.location.href = url;
|
||||
}
|
||||
};
|
||||
|
||||
var fCreateLink = function( text, fAction ) {
|
||||
var link = $( '<div>' ).text( text );
|
||||
link.click( fAction );
|
||||
menubar.append(link);
|
||||
};
|
||||
|
||||
fCreateLink( 'invoke event',
|
||||
fRedirect( 'forge?page=forge_event' )
|
||||
);
|
||||
fCreateLink( 'forge event poller',
|
||||
fRedirect( 'forge?page=forge_event_poller' )
|
||||
);
|
||||
fCreateLink( 'forge action invoker',
|
||||
fRedirect( 'forge?page=forge_action_invoker' )
|
||||
);
|
||||
fCreateLink( 'forge rule',
|
||||
fRedirect( 'forge?page=forge_rule' )
|
||||
);
|
||||
fCreateLink( 'admin', fRedirect( 'admin' ) );
|
||||
|
||||
fCreateLink( 'logout', function() {
|
||||
$.post( '/logout' ).done( fRedirect( document.URL ) );
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Forge A Module</title>
|
||||
{{{head_requires}}}
|
||||
|
||||
<script type = "text/template" id="templ_action">
|
||||
exports.myOwnActionFunction = function( args ) {
|
||||
var data = {
|
||||
companyId: '961',
|
||||
context: '17936',
|
||||
text: 'Binder entry based on event: ' + args.info
|
||||
};
|
||||
needle.post('https://probinder.com/service/27/save', data);
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type = "text/template" id="templ_event">
|
||||
exports.myOwnEventFunction = function( callback ) {
|
||||
var myEvent = {
|
||||
event: 'mail',
|
||||
eventid: 'mail_0',
|
||||
payload: {
|
||||
subject: 'My mail event subject',
|
||||
body: 'Complex text body'
|
||||
}
|
||||
};
|
||||
callback( myEvent );
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type = "text/template" id="templ_params">
|
||||
{
|
||||
"username": {
|
||||
"description": "The username for the Web API"
|
||||
},
|
||||
"password": {
|
||||
"description": "The password for the Web API"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
{{{div_menubar}}}
|
||||
<div id="mainbody">
|
||||
<div id="pagetitle">Hi {{user.username}}, forge your own modules!</div>
|
||||
<p>
|
||||
<select id="select_type">
|
||||
<option value="0">Action Invoker</option>
|
||||
<option value="1">Event Poller</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
Module name: <input type="text" id="input_id" />
|
||||
</p>
|
||||
<p>
|
||||
<textarea id="textarea_module" rows="20" cols="100"> </textarea>
|
||||
</p>
|
||||
<!-- <p>
|
||||
Description of module:<br />
|
||||
<textarea id="textarea_description" rows="2" cols="100">This module does...</textarea>
|
||||
</p> -->
|
||||
<p>
|
||||
<!-- <input id="checkbox_public" type="checkbox"> Module is public, reusable for everybody<br />-->
|
||||
<input id="checkbox_params" type="checkbox"> Module requires user-specific parameters
|
||||
</p>
|
||||
<p>
|
||||
<textarea id="textarea_params" rows="10" cols="40">
|
||||
</textarea>
|
||||
</p>
|
||||
<p>
|
||||
<button id="but_submit">save</button>
|
||||
</p>
|
||||
</div>
|
||||
<div id="info"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('#select_type').change(function(e) {
|
||||
if($(this).val() === '0') {
|
||||
$('#textarea_module').val($('#templ_action').html());
|
||||
} else {
|
||||
$('#textarea_module').val($('#templ_event').html());
|
||||
}
|
||||
});
|
||||
$('#but_submit').click(function() {
|
||||
if($('#input_id').val() === '') alert('Please enter a module name!');
|
||||
else {
|
||||
var obj = {
|
||||
id: $('#input_id').val(),
|
||||
data: $('#textarea_module').val()
|
||||
// description: $('#textarea_description').val(),
|
||||
// ispublic: $('#checkbox_public').is(':checked')
|
||||
};
|
||||
try {
|
||||
if($('#checkbox_params').is(':checked')) {
|
||||
//TODO if syntax error we should make better info's
|
||||
JSON.parse($('#textarea_params').val());
|
||||
obj.params = $('#textarea_params').val();
|
||||
}
|
||||
if($('#select_type').val() === '0') obj.command = 'store_action';
|
||||
else obj.command = 'store_event';
|
||||
$.post('/usercommand', obj)
|
||||
.done(function(data) {
|
||||
console.log(data);
|
||||
})
|
||||
.fail(function(err) {
|
||||
console.error(err);
|
||||
alert('Posting of module failed: ' + err.responseText);
|
||||
});
|
||||
} catch(err) {
|
||||
alert(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
$('#checkbox_params').click(function() {
|
||||
$('#textarea_params').toggle();
|
||||
});
|
||||
$('#textarea_module').val($('#templ_action').html());
|
||||
$('#textarea_params').val($('#templ_params').html());
|
||||
$('#textarea_params').hide();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -3,6 +3,7 @@ body {
|
|||
font-family: sans-serif, "Times New Roman", Georgia, Serif;
|
||||
font-size: 80%;
|
||||
margin: 0px;
|
||||
background-color: #EEF;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
|
|
@ -25,7 +26,6 @@ input[type=text]:focus {
|
|||
|
||||
#menubar {
|
||||
font-size: 0.75em;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
height: 1em;
|
||||
background-color: #DDD;
|
||||
|
|
@ -50,10 +50,21 @@ input[type=text]:focus {
|
|||
}
|
||||
|
||||
#info {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
line-height: 2em;
|
||||
font-family: Tahoma, sans-serif;
|
||||
font-size: 0.75em;
|
||||
color: #F33;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: #CFC;
|
||||
color: #050;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: #FCC;
|
||||
color: #800;
|
||||
}
|
||||
|
||||
#mainbody {
|
||||
|
|
@ -64,6 +75,12 @@ input[type=text]:focus {
|
|||
#pagetitle {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#editor_mode {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
#editor_table {
|
||||
|
|
@ -71,7 +88,7 @@ input[type=text]:focus {
|
|||
}
|
||||
|
||||
#editor_col {
|
||||
width: 80%;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
#editor {
|
||||
|
|
@ -93,14 +110,7 @@ input[type=text]:focus {
|
|||
}
|
||||
|
||||
#tableParams input {
|
||||
width: 100px;
|
||||
width: 150px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.error {
|
||||
padding: 10px;
|
||||
font-family: Tahoma, sans-serif;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
color: #F33;
|
||||
}
|
||||
Loading…
Reference in a new issue