webapi-eca/coffee/components-manager.coffee

347 lines
10 KiB
CoffeeScript
Raw Normal View History

###
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)
2014-04-03 15:41:51 +00:00
dynmod = require './dynamic-modules'
# - Node.js Modules: [fs](http://nodejs.org/api/fs.html),
2014-04-03 15:41:51 +00:00
# [path](http://nodejs.org/api/path.html) and
# [events](http://nodejs.org/api/events.html)
fs = require 'fs'
path = require 'path'
events = require 'events'
2014-04-03 15:41:51 +00:00
eventEmitter = new events.EventEmitter()
###
Module call
-----------
Initializes the Components Manager and constructs a new Event Emitter.
@param {Object} args
###
exports = module.exports = ( args ) =>
@log = args.logger
db args
dynmod args
module.exports
###
2014-04-03 15:41:51 +00:00
Add an event handler (eh) that listens for rules.
2014-04-03 15:41:51 +00:00
@public addRuleListener ( *eh* )
@param {function} eh
###
2014-04-03 15:41:51 +00:00
exports.addRuleListener = ( eh ) =>
eventEmitter.addListener 'rule', eh
# Fetch all active rules per user
db.getAllActivatedRuleIdsPerUser ( err, objUsers ) ->
# Go through all rules of each user
fGoThroughUsers = ( user, rules ) ->
# Fetch the rules object for each rule in each user
fFetchRule = ( userName ) ->
( rule ) ->
db.getRule rule, ( err, strRule ) =>
try
oRule = JSON.parse strRule
db.resetLog userName, oRule.id
db.appendLog userName, oRule.id, "INIT", "Rule '#{ oRule.id }' initialized"
eventEmitter.emit 'rule',
event: 'init'
user: userName
rule: oRule
catch err
@log.warn "CM | There's an invalid rule in the system: #{ strRule }"
2014-04-03 15:41:51 +00:00
# Go through all rules for each user
fFetchRule( user ) rule for rule in rules
2014-04-03 15:41:51 +00:00
# Go through each user
fGoThroughUsers user, rules for user, rules of objUsers
2014-04-01 21:31:54 +00:00
###
Processes a user request coming through the request-handler.
2014-04-05 01:09:40 +00:00
2014-04-01 21:31:54 +00:00
- `user` is the user object as it comes from the DB.
- `oReq` is the request object that contains:
2014-04-05 01:09:40 +00:00
2014-04-01 21:31:54 +00:00
- `command` as a string
- `payload` an optional stringified JSON object
2014-04-01 21:47:54 +00:00
The callback function `callback( obj )` will receive an object
containing the HTTP response code and a corresponding message.
2014-04-01 21:31:54 +00:00
2014-04-01 21:47:54 +00:00
@public processRequest ( *user, oReq, callback* )
2014-04-01 21:31:54 +00:00
###
exports.processRequest = ( user, oReq, callback ) ->
2014-04-01 21:31:54 +00:00
if not oReq.payload
oReq.payload = '{}'
try
dat = JSON.parse oReq.payload
catch err
2014-04-01 21:47:54 +00:00
return callback
2014-04-01 21:31:54 +00:00
code: 404
message: 'You had a strange payload in your request!'
if commandFunctions[oReq.command]
2014-04-05 01:09:40 +00:00
# If the command function was registered we invoke it
2014-04-01 21:47:54 +00:00
commandFunctions[oReq.command] user, dat, callback
else
2014-03-27 10:41:30 +00:00
callback
code: 404
2014-03-27 10:41:30 +00:00
message: 'What do you want from me?'
2014-04-05 01:09:40 +00:00
###
Checks whether all required parameters are present in the payload.
@private hasRequiredParams ( *arrParams, oPayload* )
@param {Array} arrParams
@param {Object} oPayload
###
hasRequiredParams = ( arrParams, oPayload ) ->
2014-04-01 21:31:54 +00:00
answ =
code: 400
2014-04-03 15:41:51 +00:00
message: "Your request didn't contain all necessary fields! Requires: #{ arrParams.join() }"
return answ for param in arrParams when not oPayload[param]
2014-04-01 21:31:54 +00:00
answ.code = 200
answ.message = 'All required properties found'
answ
2014-04-05 01:09:40 +00:00
###
Fetches all available modules and return them together with the available functions.
@private getModules ( *user, oPayload, dbMod, callback* )
@param {Object} user
@param {Object} oPayload
@param {Object} dbMod
@param {function} callback
###
getModules = ( user, oPayload, dbMod, callback ) ->
dbMod.getAvailableModuleIds user.username, ( err, arrNames ) ->
oRes = {}
answReq = () ->
callback
code: 200
message: JSON.stringify oRes
sem = arrNames.length
if sem is 0
answReq()
2014-04-01 21:31:54 +00:00
else
fGetFunctions = ( id ) =>
dbMod.getModule id, ( err, oModule ) =>
if oModule
oRes[id] = JSON.parse oModule.functions
if --sem is 0
answReq()
fGetFunctions id for id in arrNames
getModuleParams = ( user, oPayload, dbMod, callback ) ->
answ = hasRequiredParams [ 'id' ], oPayload
if answ.code isnt 200
callback answ
else
dbMod.getModuleParams oPayload.id, ( err, oPayload ) ->
answ.message = oPayload
callback answ
2014-04-03 15:41:51 +00:00
2014-04-02 21:08:05 +00:00
forgeModule = ( user, oPayload, dbMod, callback ) =>
answ = hasRequiredParams [ 'id', 'params', 'lang', 'data' ], oPayload
if answ.code isnt 200
callback answ
else
dbMod.getModule oPayload.id, ( err, mod ) =>
if mod
answ.code = 409
answ.message = 'Module name already existing: ' + oPayload.id
callback answ
2014-04-01 21:31:54 +00:00
else
src = oPayload.data
dynmod.compileString src, user.username, 'dummyRule', oPayload.id, oPayload.lang, null, ( cm ) =>
answ = cm.answ
if answ.code is 200
funcs = []
funcs.push name for name, id of cm.module
@log.info "CM | Storing new module with functions #{ funcs.join( ', ' ) }"
answ.message =
" Module #{ oPayload.id } successfully stored! Found following function(s): #{ funcs }"
oPayload.functions = JSON.stringify funcs
2014-04-09 14:07:31 +00:00
oPayload.functionParameters = JSON.stringify cm.funcParams
dbMod.storeModule user.username, oPayload
if oPayload.public is 'true'
dbMod.publish oPayload.id
callback answ
commandFunctions =
2014-04-03 15:41:51 +00:00
get_public_key: ( user, oPayload, callback ) ->
callback
code: 200
message: dynmod.getPublicKey()
# EVENT POLLERS
# -------------
get_event_pollers: ( user, oPayload, callback ) ->
getModules user, oPayload, db.eventPollers, callback
get_full_event_poller: ( user, oPayload, callback ) ->
db.eventPollers.getModule oPayload.id, ( err, obj ) ->
callback
code: 200
message: JSON.stringify obj
get_event_poller_params: ( user, oPayload, callback ) ->
getModuleParams user, oPayload, db.eventPollers, callback
forge_event_poller: ( user, oPayload, callback ) ->
forgeModule user, oPayload, db.eventPollers, callback
delete_event_poller: ( user, oPayload, callback ) ->
answ = hasRequiredParams [ 'id' ], oPayload
if answ.code isnt 200
callback answ
else
db.eventPollers.deleteModule oPayload.id
callback
code: 200
message: 'OK!'
# ACTION INVOKERS
# ---------------
get_action_invokers: ( user, oPayload, callback ) ->
getModules user, oPayload, db.actionInvokers, callback
get_full_action_invoker: ( user, oPayload, callback ) ->
2014-04-09 14:07:31 +00:00
answ = hasRequiredParams [ 'id' ], oPayload
if answ.code isnt 200
callback answ
else
db.actionInvokers.getModule oPayload.id, ( err, obj ) ->
callback
code: 200
message: JSON.stringify obj
get_action_invoker_params: ( user, oPayload, callback ) ->
getModuleParams user, oPayload, db.actionInvokers, callback
2014-04-09 14:07:31 +00:00
get_action_invoker_function_params: ( user, oPayload, callback ) ->
answ = hasRequiredParams [ 'id' ], oPayload
if answ.code isnt 200
callback answ
else
db.actionInvokers.getModuleField oPayload.id, 'functionParameters', ( err, obj ) ->
callback
code: 200
message: obj
forge_action_invoker: ( user, oPayload, callback ) ->
forgeModule user, oPayload, db.actionInvokers, callback
2014-04-01 21:31:54 +00:00
delete_action_invoker: ( user, oPayload, callback ) ->
answ = hasRequiredParams [ 'id' ], oPayload
if answ.code isnt 200
callback answ
else
db.actionInvokers.deleteModule oPayload.id
callback
code: 200
message: 'OK!'
# RULES
# -----
get_rules: ( user, oPayload, callback ) ->
db.getUserLinkedRules user.username, ( err, obj ) ->
callback
code: 200
message: obj
get_rule_log: ( user, oPayload, callback ) ->
answ = hasRequiredParams [ 'id' ], oPayload
if answ.code isnt 200
callback answ
else
db.getLog user.username, oPayload.id, ( err, obj ) ->
callback
code: 200
message: obj
# A rule needs to be in following format:
2014-04-05 01:09:40 +00:00
# - id
# - event
# - conditions
# - actions
2014-04-03 15:41:51 +00:00
forge_rule: ( user, oPayload, callback ) ->
answ = hasRequiredParams [ 'id', 'event', 'conditions', 'actions' ], oPayload
if answ.code isnt 200
callback answ
else
2014-04-03 15:41:51 +00:00
db.getRule oPayload.id, ( err, oExisting ) ->
if oExisting isnt null
answ =
code: 409
message: 'Rule name already existing!'
else
2014-04-09 14:07:31 +00:00
console.log 'new ruke'
rule =
id: oPayload.id
event: oPayload.event
conditions: oPayload.conditions
actions: oPayload.actions
strRule = JSON.stringify rule
2014-04-09 14:07:31 +00:00
console.log 'stringified'
db.storeRule rule.id, strRule
2014-04-09 14:07:31 +00:00
console.log 'stored'
db.linkRule rule.id, user.username
2014-04-09 14:07:31 +00:00
console.log 'linked'
db.activateRule rule.id, user.username
2014-04-09 14:07:31 +00:00
console.log 'activated'
if oPayload.event_params
2014-04-03 15:41:51 +00:00
epModId = rule.event.split( ' -> ' )[0]
db.eventPollers.storeUserParams epModId, user.username, oPayload.event_params
2014-04-09 14:07:31 +00:00
console.log 'event params loaded'
arrParams = oPayload.action_params
2014-04-09 14:07:31 +00:00
console.log 'arractionparams'
db.actionInvokers.storeUserParams id, user.username, JSON.stringify params for id, params of arrParams
2014-04-09 14:07:31 +00:00
console.log 'action aprams stored'
db.resetLog user.username, rule.id
db.appendLog user.username, rule.id, "INIT", "Rule '#{ rule.id }' initialized"
2014-04-03 15:41:51 +00:00
eventEmitter.emit 'rule',
event: 'new'
user: user.username
rule: rule
answ =
code: 200
message: "Rule '#{ rule.id }' stored and activated!"
2014-04-09 14:07:31 +00:00
console.log 'done'
callback answ
delete_rule: ( user, oPayload, callback ) ->
answ = hasRequiredParams [ 'id' ], oPayload
if answ.code isnt 200
callback answ
else
db.deleteRule oPayload.id
eventEmitter.emit 'rule',
event: 'del'
user: user.username
rule: null
ruleId: oPayload.id
callback
code: 200
message: 'OK!'