mirror of
https://github.com/Hopiu/webapi-eca.git
synced 2026-03-16 22:10:31 +00:00
Documentation and private vars update
This commit is contained in:
parent
eba1357e9e
commit
a778cbcde5
15 changed files with 791 additions and 555 deletions
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
Config
|
||||
======
|
||||
> Loads the configuration file and acts as an interface to it.
|
||||
|
||||
Loads the configuration file and acts as an interface to it.
|
||||
###
|
||||
'use strict'
|
||||
|
||||
path = require 'path'
|
||||
log = require './logging'
|
||||
fs = require 'fs'
|
||||
config = null
|
||||
path = require 'path'
|
||||
# Requires:
|
||||
|
||||
# - The [Logging](logging.html) module
|
||||
log = require './logging'
|
||||
|
||||
###
|
||||
##Module call
|
||||
|
|
@ -19,7 +20,7 @@ Calling the module as a function will make it look for the `relPath` property in
|
|||
args object and then try to load a config file from that relative path.
|
||||
@param {Object} args
|
||||
###
|
||||
exports = module.exports = (args) ->
|
||||
exports = module.exports = ( args ) ->
|
||||
args = args ? {}
|
||||
log args
|
||||
if typeof args.relPath is 'string'
|
||||
|
|
@ -33,11 +34,11 @@ Reads the config file synchronously from the file system and try to parse it.
|
|||
@private loadConfigFile
|
||||
@param {String} relPath
|
||||
###
|
||||
loadConfigFile = (relPath) ->
|
||||
loadConfigFile = ( relPath ) =>
|
||||
try
|
||||
config = JSON.parse fs.readFileSync path.resolve __dirname, '..', relPath
|
||||
if config and config.http_port and config.db_port and
|
||||
config.crypto_key and config.session_secret
|
||||
@config = JSON.parse fs.readFileSync path.resolve __dirname, '..', relPath
|
||||
if @config and @config.http_port and @config.db_port and
|
||||
@config.crypto_key and @config.session_secret
|
||||
log.print 'CF', 'config file loaded successfully'
|
||||
else
|
||||
log.error 'CF', new Error("""Missing property in config file, requires:
|
||||
|
|
@ -57,14 +58,14 @@ Fetch a property from the configuration
|
|||
@private fetchProp( *prop* )
|
||||
@param {String} prop
|
||||
###
|
||||
fetchProp = (prop) -> config?[prop]
|
||||
fetchProp = ( prop ) => @config?[prop]
|
||||
|
||||
###
|
||||
Answer true if the config file is ready, else false
|
||||
|
||||
@public isReady()
|
||||
###
|
||||
exports.isReady = -> config?
|
||||
exports.isReady = => @config?
|
||||
|
||||
###
|
||||
Returns the HTTP port
|
||||
|
|
|
|||
|
|
@ -2,48 +2,48 @@
|
|||
|
||||
DB Interface
|
||||
============
|
||||
>Handles the connection to the database and provides functionalities for
|
||||
>event/action modules, rules and the encrypted storing of authentication tokens.
|
||||
>General functionality as a wrapper for the module holds initialization,
|
||||
>encryption/decryption, the retrieval of modules and shut down.
|
||||
>
|
||||
>The general structure for linked data is that the key is stored in a set.
|
||||
>By fetching all set entries we can then fetch all elements, which is
|
||||
>automated in this function.
|
||||
>For example modules of the same group, e.g. action modules are registered in an
|
||||
>unordered set in the database, from where they can be retrieved again. For example
|
||||
>a new action module has its ID (e.g 'probinder') first registered in the set
|
||||
>'action_modules' and then stored in the db with the key 'action\_module\_' + ID
|
||||
>(e.g. action\_module\_probinder).
|
||||
> Handles the connection to the database and provides functionalities for
|
||||
> event/action modules, rules and the encrypted storing of authentication tokens.
|
||||
> General functionality as a wrapper for the module holds initialization,
|
||||
> encryption/decryption, the retrieval of modules and shut down.
|
||||
>
|
||||
> The general structure for linked data is that the key is stored in a set.
|
||||
> By fetching all set entries we can then fetch all elements, which is
|
||||
> automated in this function.
|
||||
> For example modules of the same group, e.g. action modules are registered in an
|
||||
> unordered set in the database, from where they can be retrieved again. For example
|
||||
> a new action module has its ID (e.g 'probinder') first registered in the set
|
||||
> 'action_modules' and then stored in the db with the key 'action\_module\_' + ID
|
||||
> (e.g. action\_module\_probinder).
|
||||
>
|
||||
|
||||
###
|
||||
|
||||
'use strict'
|
||||
### Grab all required modules ###
|
||||
redis = require 'redis'
|
||||
crypto = require 'crypto' # TODO change to Google's "crypto-js""
|
||||
log = require './logging'
|
||||
crypto_key = null
|
||||
db = null
|
||||
|
||||
# Requires:
|
||||
|
||||
# - The [Logging](logging.html) module
|
||||
log = require './logging'
|
||||
|
||||
|
||||
###
|
||||
##Module call
|
||||
|
||||
Module call
|
||||
-----------
|
||||
Initializes the DB connection. Requires a valid configuration file which contains
|
||||
a db port and a crypto key.
|
||||
|
||||
@param {Object} args
|
||||
###
|
||||
exports = module.exports = (args) ->
|
||||
exports = module.exports = ( args ) =>
|
||||
args = args ? {}
|
||||
log args
|
||||
config = require './config'
|
||||
config args
|
||||
crypto_key = config.getCryptoKey()
|
||||
db = redis.createClient config.getDBPort(), 'localhost', { connect_timeout: 2000 }
|
||||
db.on "error", (err) ->
|
||||
@crypto_key = config.getCryptoKey()
|
||||
@db = redis.createClient config.getDBPort(), 'localhost', { connect_timeout: 2000 }
|
||||
@db.on "error", ( err ) ->
|
||||
err.addInfo = 'message from DB'
|
||||
log.error 'DB', err
|
||||
|
||||
|
|
@ -55,12 +55,12 @@ ten attempts within five seconds, or nothing on success to the callback(err).
|
|||
@param {function} cb
|
||||
###
|
||||
#}TODO check if timeout works with func in func
|
||||
exports.isConnected = (cb) ->
|
||||
if db.connected then cb()
|
||||
exports.isConnected = ( cb ) =>
|
||||
if @db.connected then cb()
|
||||
else
|
||||
numAttempts = 0
|
||||
fCheckConnection = ->
|
||||
if db.connected
|
||||
fCheckConnection = =>
|
||||
if @db.connected
|
||||
log.print 'DB', 'Successfully connected to DB!'
|
||||
cb()
|
||||
else if numAttempts++ < 10
|
||||
|
|
@ -78,10 +78,10 @@ Encrypts a string using the crypto key from the config file, based on aes-256-cb
|
|||
@private encrypt( *plainText* )
|
||||
@param {String} plainText
|
||||
###
|
||||
encrypt = (plainText) ->
|
||||
encrypt = ( plainText ) =>
|
||||
if !plainText? then return null
|
||||
try
|
||||
enciph = crypto.createCipher 'aes-256-cbc', crypto_key
|
||||
enciph = crypto.createCipher 'aes-256-cbc', @crypto_key
|
||||
et = enciph.update plainText, 'utf8', 'base64'
|
||||
et + enciph.final 'base64'
|
||||
catch err
|
||||
|
|
@ -95,10 +95,10 @@ Decrypts an encrypted string and hands it back on success or null.
|
|||
@private decrypt( *crypticText* )
|
||||
@param {String} crypticText
|
||||
###
|
||||
decrypt = (crypticText) ->
|
||||
decrypt = ( crypticText ) =>
|
||||
if !crypticText? then return null;
|
||||
try
|
||||
deciph = crypto.createDecipher 'aes-256-cbc', crypto_key
|
||||
deciph = crypto.createDecipher 'aes-256-cbc', @crypto_key
|
||||
dt = deciph.update crypticText, 'base64', 'utf8'
|
||||
dt + deciph.final 'utf8'
|
||||
catch err
|
||||
|
|
@ -112,8 +112,8 @@ Abstracts logging for simple action replies from the DB.
|
|||
@private replyHandler( *action* )
|
||||
@param {String} action
|
||||
###
|
||||
replyHandler = (action) ->
|
||||
(err, reply) ->
|
||||
replyHandler = ( action ) ->
|
||||
( err, reply ) ->
|
||||
if err
|
||||
err.addInfo = 'during "' + action + '"'
|
||||
log.error 'DB', err
|
||||
|
|
@ -129,9 +129,9 @@ via the provided function and returns the results to the callback(err, obj) func
|
|||
@param {function} fSingle a function to retrieve a single data element per set entry
|
||||
@param {function} cb the callback(err, obj) function that receives all the retrieved data or an error
|
||||
###
|
||||
getSetRecords = (set, fSingle, cb) ->
|
||||
getSetRecords = ( set, fSingle, cb ) =>
|
||||
log.print 'DB', 'Fetching set records: ' + set
|
||||
db?.smembers set, (err, arrReply) ->
|
||||
@db.smembers set, ( err, arrReply ) ->
|
||||
if err
|
||||
err.addInfo = 'fetching ' + set
|
||||
log.error 'DB', err
|
||||
|
|
@ -145,8 +145,8 @@ getSetRecords = (set, fSingle, cb) ->
|
|||
if semaphore > 0
|
||||
cb new Error('Timeout fetching ' + set)
|
||||
, 2000
|
||||
fCallback = (prop) ->
|
||||
(err, data) ->
|
||||
fCallback = ( prop ) ->
|
||||
( err, data ) ->
|
||||
--semaphore
|
||||
if err
|
||||
err.addInfo = 'fetching single element: ' + prop
|
||||
|
|
@ -171,10 +171,10 @@ Store a string representation of an action module in the DB.
|
|||
@param {String} data
|
||||
###
|
||||
# FIXME can the data be an object?
|
||||
exports.storeActionModule = (id, data) ->
|
||||
exports.storeActionModule = ( id, data ) =>
|
||||
log.print 'DB', 'storeActionModule: ' + id
|
||||
db?.sadd 'action-modules', id, replyHandler 'storing action module key ' + id
|
||||
db?.set 'action-module:' + id, data, replyHandler 'storing action module ' + id
|
||||
@db.sadd 'action-modules', id, replyHandler 'storing action module key ' + id
|
||||
@db.set 'action-module:' + id, data, replyHandler 'storing action module ' + id
|
||||
|
||||
###
|
||||
Query the DB for an action module and pass it to the callback(err, obj) function.
|
||||
|
|
@ -183,9 +183,9 @@ Query the DB for an action module and pass it to the callback(err, obj) function
|
|||
@param {String} id
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getActionModule = (id, cb) ->
|
||||
exports.getActionModule = ( id, cb ) =>
|
||||
log.print 'DB', 'getActionModule: ' + id
|
||||
db?.get 'action-module:' + id, cb
|
||||
@db.get 'action-module:' + id, cb
|
||||
|
||||
###
|
||||
Fetch all action modules and hand them to the callback(err, obj) function.
|
||||
|
|
@ -193,7 +193,7 @@ Fetch all action modules and hand them to the callback(err, obj) function.
|
|||
@public getActionModules( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getActionModules = (cb) ->
|
||||
exports.getActionModules = ( cb ) ->
|
||||
getSetRecords 'action-modules', exports.getActionModule, cb
|
||||
|
||||
###
|
||||
|
|
@ -204,9 +204,9 @@ Store a string representation of the authentication parameters for an action mod
|
|||
@param {String} moduleId
|
||||
@param {String} data
|
||||
###
|
||||
exports.storeActionAuth = (userId, moduleId, data) ->
|
||||
exports.storeActionAuth = ( userId, moduleId, data ) =>
|
||||
log.print 'DB', 'storeActionAuth: ' + userId + ':' + moduleId
|
||||
db?.set 'action-auth:' + userId + ':' + moduleId, encrypt(data),
|
||||
@db.set 'action-auth:' + userId + ':' + moduleId, encrypt(data),
|
||||
replyHandler 'storing action auth ' + userId + ':' + moduleId
|
||||
|
||||
###
|
||||
|
|
@ -218,9 +218,9 @@ and pass it to the callback(err, obj) function.
|
|||
@param {String} moduleId
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getActionAuth = (userId, moduleId, cb) ->
|
||||
exports.getActionAuth = ( userId, moduleId, cb ) =>
|
||||
log.print 'DB', 'getActionAuth: ' + userId + ':' + moduleId
|
||||
db?.get 'action-auth:' + userId + ':' + moduleId, (err, data) ->
|
||||
@db.get 'action-auth:' + userId + ':' + moduleId, ( err, data ) ->
|
||||
cb err, decrypt data
|
||||
|
||||
|
||||
|
|
@ -235,10 +235,10 @@ Store a string representation of an event module in the DB.
|
|||
@param {String} id
|
||||
@param {String} data
|
||||
###
|
||||
exports.storeEventModule = (id, data) ->
|
||||
exports.storeEventModule = ( id, data ) =>
|
||||
log.print 'DB', 'storeEventModule: ' + id
|
||||
db?.sadd 'event-modules', id, replyHandler 'storing event module key ' + id
|
||||
db?.set 'event-module:' + id, data, replyHandler 'storing event module ' + id
|
||||
@db.sadd 'event-modules', id, replyHandler 'storing event module key ' + id
|
||||
@db.set 'event-module:' + id, data, replyHandler 'storing event module ' + id
|
||||
|
||||
###
|
||||
Query the DB for an event module and pass it to the callback(err, obj) function.
|
||||
|
|
@ -247,9 +247,9 @@ Query the DB for an event module and pass it to the callback(err, obj) function.
|
|||
@param {String} id
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getEventModule = (id, cb) ->
|
||||
exports.getEventModule = ( id, cb ) =>
|
||||
log.print 'DB', 'getEventModule: ' + id
|
||||
db?.get 'event_module:' + id, cb
|
||||
@db.get 'event_module:' + id, cb
|
||||
|
||||
###
|
||||
Fetch all event modules and pass them to the callback(err, obj) function.
|
||||
|
|
@ -257,31 +257,33 @@ Fetch all event modules and pass them to the callback(err, obj) function.
|
|||
@public getEventModules( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getEventModules = (cb) ->
|
||||
exports.getEventModules = ( cb ) ->
|
||||
getSetRecords 'event_modules', exports.getEventModule, cb
|
||||
|
||||
###
|
||||
Store a string representation of he authentication parameters for an event module.
|
||||
|
||||
@public storeEventAuth( *userId, moduleId, data* )
|
||||
@param {String} id
|
||||
@param {String} data
|
||||
@param {String} userId
|
||||
@param {String} moduleId
|
||||
@param {Object} data
|
||||
###
|
||||
exports.storeEventAuth = (userId, moduleId, data) ->
|
||||
exports.storeEventAuth = ( userId, moduleId, data ) =>
|
||||
log.print 'DB', 'storeEventAuth: ' + userId + ':' + moduleId
|
||||
db?.set 'event-auth:' + userId + ':' + moduleId, encrypt(data),
|
||||
@db.set 'event-auth:' + userId + ':' + moduleId, encrypt(data),
|
||||
replyHandler 'storing event auth ' + userId + ':' + moduleId
|
||||
|
||||
###
|
||||
Query the DB for an action module authentication token, associated with a user.
|
||||
|
||||
@public getEventAuth( *id, cb* )
|
||||
@param {String} id
|
||||
@public getEventAuth( *userId, moduleId, data* )
|
||||
@param {String} userId
|
||||
@param {String} moduleId
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getEventAuth = (userId, moduleId, cb) ->
|
||||
exports.getEventAuth = ( userId, moduleId, cb ) =>
|
||||
log.print 'DB', 'getEventAuth: ' + userId + ':' + moduleId
|
||||
db?.get 'event-auth:' + userId + ':' + moduleId, (err, data) ->
|
||||
@db.get 'event-auth:' + userId + ':' + moduleId, ( err, data ) ->
|
||||
cb err, decrypt data
|
||||
|
||||
|
||||
|
|
@ -296,10 +298,10 @@ Store a string representation of a rule in the DB.
|
|||
@param {String} id
|
||||
@param {String} data
|
||||
###
|
||||
exports.storeRule = (id, data) ->
|
||||
exports.storeRule = ( id, data ) =>
|
||||
log.print 'DB', 'storeRule: ' + id
|
||||
db?.sadd 'rules', id, replyHandler 'storing rule key ' + id
|
||||
db?.set 'rule:' + id, data, replyHandler 'storing rule ' + id
|
||||
@db.sadd 'rules', id, replyHandler 'storing rule key ' + id
|
||||
@db.set 'rule:' + id, data, replyHandler 'storing rule ' + id
|
||||
|
||||
###
|
||||
Query the DB for a rule and pass it to the callback(err, obj) function.
|
||||
|
|
@ -308,9 +310,9 @@ Query the DB for a rule and pass it to the callback(err, obj) function.
|
|||
@param {String} id
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getRule = (id, cb) ->
|
||||
exports.getRule = ( id, cb ) =>
|
||||
log.print 'DB', 'getRule: ' + id
|
||||
db?.get 'rule:' + id, cb
|
||||
@db.get 'rule:' + id, cb
|
||||
|
||||
###
|
||||
Fetch all rules from the database and pass them to the callback function.
|
||||
|
|
@ -318,7 +320,7 @@ Fetch all rules from the database and pass them to the callback function.
|
|||
@public getRules( *cb* )
|
||||
@param {function} cb
|
||||
###
|
||||
exports.getRules = (cb) ->
|
||||
exports.getRules = ( cb ) ->
|
||||
log.print 'DB', 'Fetching all Rules'
|
||||
getSetRecords 'rules', exports.getRule, cb
|
||||
|
||||
|
|
@ -328,12 +330,14 @@ Store a user object (needs to be a flat structure).
|
|||
@public storeUser( *objUser* )
|
||||
@param {Object} objUser
|
||||
###
|
||||
exports.storeUser = (objUser) ->
|
||||
exports.storeUser = ( objUser ) =>
|
||||
# TODO Only store user if not already existing, or at least only then add a private key
|
||||
# for his encryption. we would want to have one private key per user, right?
|
||||
log.print 'DB', 'storeUser: ' + objUser.username
|
||||
if objUser and objUser.username and objUser.password
|
||||
db?.sadd 'users', objUser.username, replyHandler 'storing user key ' + objUser.username
|
||||
@db.sadd 'users', objUser.username, replyHandler 'storing user key ' + objUser.username
|
||||
objUser.password = encrypt objUser.password
|
||||
db?.hmset 'user:' + objUser.username, objUser, replyHandler 'storing user properties ' + objUser.username
|
||||
@db.hmset 'user:' + objUser.username, objUser, replyHandler 'storing user properties ' + objUser.username
|
||||
else
|
||||
log.error 'DB', new Error 'username or password was missing'
|
||||
|
||||
|
|
@ -344,10 +348,10 @@ Associate a role with a user.
|
|||
@param {String} username
|
||||
@param {String} role
|
||||
###
|
||||
exports.storeUserRole = (username, role) ->
|
||||
exports.storeUserRole = ( username, role ) =>
|
||||
log.print 'DB', 'storeUserRole: ' + username + ':' + role
|
||||
db?.sadd 'user-roles:' + username, role, replyHandler 'adding role ' + role + ' to user ' + username
|
||||
db?.sadd 'role-users:' + role, username, replyHandler 'adding user ' + username + ' to role ' + role
|
||||
@db.sadd 'user-roles:' + username, role, replyHandler 'adding role ' + role + ' to user ' + username
|
||||
@db.sadd 'role-users:' + role, username, replyHandler 'adding user ' + username + ' to role ' + role
|
||||
|
||||
###
|
||||
Fetch all roles of a user and pass them to the callback(err, obj)
|
||||
|
|
@ -355,9 +359,9 @@ Fetch all roles of a user and pass them to the callback(err, obj)
|
|||
@public getUserRoles( *username* )
|
||||
@param {String} username
|
||||
###
|
||||
exports.getUserRoles = (username) ->
|
||||
exports.getUserRoles = ( username ) =>
|
||||
log.print 'DB', 'getUserRole: ' + username
|
||||
db?.get 'user-roles:' + username, cb
|
||||
@db.get 'user-roles:' + username, cb
|
||||
|
||||
###
|
||||
Fetch all users of a role and pass them to the callback(err, obj)
|
||||
|
|
@ -365,9 +369,9 @@ Fetch all users of a role and pass them to the callback(err, obj)
|
|||
@public getUserRoles( *role* )
|
||||
@param {String} role
|
||||
###
|
||||
exports.getRoleUsers = (role) ->
|
||||
exports.getRoleUsers = ( role ) =>
|
||||
log.print 'DB', 'getRoleUsers: ' + role
|
||||
db?.get 'role-users:' + role, cb
|
||||
@db.get 'role-users:' + role, cb
|
||||
|
||||
###
|
||||
Checks the credentials and on success returns the user object to the callback(err, obj) function.
|
||||
|
|
@ -378,10 +382,10 @@ Checks the credentials and on success returns the user object to the callback(er
|
|||
@param {function} cb
|
||||
###
|
||||
# TODO verify and test whole function
|
||||
exports.loginUser = (username, password, cb) ->
|
||||
exports.loginUser = ( username, password, cb ) =>
|
||||
log.print 'DB', 'User "' + username + '" tries to log in'
|
||||
fCheck = (pw) ->
|
||||
(err, obj) ->
|
||||
fCheck = ( pw ) ->
|
||||
( err, obj ) ->
|
||||
if err
|
||||
cb err
|
||||
else if obj and obj.password
|
||||
|
|
@ -392,7 +396,7 @@ exports.loginUser = (username, password, cb) ->
|
|||
cb new Error 'Wrong credentials!'
|
||||
else
|
||||
cb new Error 'Empty arguments!'
|
||||
db?.hgetall 'user:' + username, fCheck password
|
||||
@db.hgetall 'user:' + username, fCheck password
|
||||
|
||||
# TODO implement functions required for user sessions and the rule activation
|
||||
|
||||
|
|
@ -401,4 +405,4 @@ Shuts down the db link.
|
|||
|
||||
@public shutDown()
|
||||
###
|
||||
exports.shutDown = -> db?.quit()
|
||||
exports.shutDown = => @db.quit()
|
||||
|
|
|
|||
85
coffee/http_listener.coffee
Normal file
85
coffee/http_listener.coffee
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
###
|
||||
|
||||
HTTP Listener
|
||||
=============
|
||||
> Handles the HTTP requests to the server at the port specified by the
|
||||
> [config](config.html) file.
|
||||
|
||||
###
|
||||
|
||||
path = require 'path'
|
||||
express = require 'express'
|
||||
app = express()
|
||||
# } RedisStore = require('connect-redis')(express), # TODO use RedisStore for persistent sessions
|
||||
qs = require 'querystring'
|
||||
|
||||
# Requires:
|
||||
|
||||
# - The [Logging](logging.html) module
|
||||
log = require './logging'
|
||||
# - The [Config](config.html) module
|
||||
config = require './config'
|
||||
# - The [User Handler](user_handler.html) module
|
||||
userHandler = require './user_handler'
|
||||
sess_sec = '#C[>;j`@".TXm2TA;A2Tg)'
|
||||
|
||||
|
||||
# The module needs to be called as a function to initialize it.
|
||||
# After that it fetches the http\_port, db\_port & sess\_sec properties
|
||||
# from the configuration file.
|
||||
exports = module.exports = ( args ) ->
|
||||
args = args ? {}
|
||||
log args
|
||||
config args
|
||||
userHandler args
|
||||
# TODO check whether this really does what it's supposed to do (fetch wrong sess property)
|
||||
sess_sec = config.getSessionSecret() || sess_sec
|
||||
module.exports
|
||||
|
||||
exports.addHandlers = ( fEvtHandler, fShutDown ) =>
|
||||
userHandler.addShutdownHandler fShutDown
|
||||
@eventHandler = fEvtHandler
|
||||
# Add cookie support for session handling.
|
||||
app.use express.cookieParser()
|
||||
app.use express.session { secret: sess_sec }
|
||||
log.print 'HL', 'no session backbone'
|
||||
|
||||
# Redirect the requests to the appropriate handler.
|
||||
app.use '/', express.static path.resolve __dirname, '..', 'webpages'
|
||||
app.get '/rulesforge', userHandler.handleRequest
|
||||
app.get '/admin', userHandler.handleRequest
|
||||
app.post '/login', userHandler.handleLogin
|
||||
app.post '/push_event', onPushEvent
|
||||
try
|
||||
http_port = config.getHttpPort()
|
||||
if http_port
|
||||
app.listen http_port # inbound event channel
|
||||
else
|
||||
log.error 'HL', new Error 'No HTTP port found!? Nothing to listen on!...'
|
||||
catch e
|
||||
e.addInfo = 'opening port'
|
||||
log.error e
|
||||
|
||||
#
|
||||
# If a post request reaches the server, this function handles it and treats the request as a possible event.
|
||||
#
|
||||
onPushEvent = ( req, resp ) =>
|
||||
body = ''
|
||||
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.write 'Thank you for the event (' + obj.event + '[' + obj.eventid + '])!'
|
||||
@eventHandler obj
|
||||
else
|
||||
resp.writeHead 400, { "Content-Type": "text/plain" }
|
||||
resp.write 'Your event was missing important parameters!'
|
||||
resp.end()
|
||||
|
||||
|
||||
exports.shutDown = () ->
|
||||
log.print 'HL', 'Shutting down HTTP listener'
|
||||
process.exit() # This is a bit brute force...
|
||||
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
###
|
||||
|
||||
Rules Server
|
||||
============
|
||||
|
||||
>This is the main module that is used to run the whole server:
|
||||
>
|
||||
> node server [log_type http_port]
|
||||
|
|
@ -14,46 +16,38 @@ Rules Server
|
|||
>`http_port` can be set to use another port, than defined in the
|
||||
>[config](config.html) file, to listen to, e.g. used by the test suite.
|
||||
>
|
||||
>---
|
||||
>
|
||||
|
||||
###
|
||||
|
||||
'use strict'
|
||||
### Grab all required modules ###
|
||||
path = require 'path'
|
||||
# Requires:
|
||||
|
||||
# - The [Logging](logging.html) module
|
||||
log = require './logging'
|
||||
# - The [Config](config.html) module
|
||||
conf = require './config'
|
||||
# - The [DB Interface](db_interface.html) module
|
||||
db = require './db_interface'
|
||||
# - The [Engine](engine.html) module
|
||||
engine = require './engine'
|
||||
# - The [HTTP Listener](http_listener.html) module
|
||||
http_listener = require './http_listener'
|
||||
mm = require './module_manager'
|
||||
args = {}
|
||||
procCmds = {}
|
||||
|
||||
### Prepare the admin commands that are issued via HTTP requests. ###
|
||||
adminCmds =
|
||||
'loadrules': mm.loadRulesFromFS,
|
||||
'loadaction': mm.loadActionModuleFromFS,
|
||||
'loadactions': mm.loadActionModulesFromFS,
|
||||
'loadevent': mm.loadEventModuleFromFS,
|
||||
'loadevents': mm.loadEventModulesFromFS,
|
||||
'loadusers': http_listener.loadUsers,
|
||||
'shutdown': shutDown
|
||||
|
||||
|
||||
###
|
||||
Error handling of the express port listener requires special attention,
|
||||
thus we have to catch the process error, which is issued if
|
||||
the port is already in use.
|
||||
###
|
||||
process.on 'uncaughtException', (err) ->
|
||||
process.on 'uncaughtException', ( err ) ->
|
||||
switch err.errno
|
||||
when 'EADDRINUSE'
|
||||
err.addInfo = 'http_port already in use, shutting down!'
|
||||
log.error 'RS', err
|
||||
shutDown()
|
||||
else log.error err
|
||||
null
|
||||
else throw err
|
||||
|
||||
###
|
||||
This function is invoked right after the module is loaded and starts the server.
|
||||
|
|
@ -85,9 +79,10 @@ init = ->
|
|||
if process.argv.length > 3 then args.http_port = parseInt process.argv[3]
|
||||
else log.print 'RS', 'No HTTP port passed, using standard port from config file'
|
||||
|
||||
log.print 'RS', 'Initialzing DB'
|
||||
db args
|
||||
### We only proceed with the initialization if the DB is ready ###
|
||||
db.isConnected (err, result) ->
|
||||
db.isConnected ( err, result ) ->
|
||||
if !err
|
||||
|
||||
### Initialize all required modules with the args object.###
|
||||
|
|
@ -95,57 +90,23 @@ init = ->
|
|||
engine args
|
||||
log.print 'RS', 'Initialzing http listener'
|
||||
http_listener args
|
||||
log.print 'RS', 'Initialzing module manager'
|
||||
mm args
|
||||
log.print 'RS', 'Initialzing DB'
|
||||
|
||||
### Distribute handlers between modules to link the application. ###
|
||||
log.print 'RS', 'Passing handlers to engine'
|
||||
engine.addDBLinkAndLoadActionsAndRules db
|
||||
log.print 'RS', 'Passing handlers to http listener'
|
||||
http_listener.addHandlers db, fAdminCommands, engine.pushEvent
|
||||
log.print 'RS', 'Passing handlers to module manager'
|
||||
mm.addHandlers db, engine.loadActionModule, engine.addRule
|
||||
|
||||
###
|
||||
admin commands handler receives all command arguments and an answerHandler
|
||||
object that eases response handling to the HTTP request issuer.
|
||||
|
||||
@private fAdminCommands( *args, answHandler* )
|
||||
###
|
||||
fAdminCommands = (args, answHandler) ->
|
||||
if args and args.cmd
|
||||
adminCmds[args.cmd]? args, answHandler
|
||||
else
|
||||
log.print 'RS', 'No command in request'
|
||||
|
||||
###
|
||||
The fAnsw function receives an answerHandler object as an argument when called
|
||||
and returns an anonymous function
|
||||
###
|
||||
fAnsw = (ah) ->
|
||||
###
|
||||
The anonymous function checks whether the answerHandler was already used to
|
||||
issue an answer, if no answer was provided we answer with an error message
|
||||
###
|
||||
() ->
|
||||
if not ah.isAnswered()
|
||||
ah.answerError 'Not handled...'
|
||||
|
||||
###
|
||||
Delayed function call of the anonymous function that checks the answer handler
|
||||
###
|
||||
setTimeout fAnsw(answHandler), 2000
|
||||
# TODO engine pushEvent needs to go into redis queue
|
||||
http_listener.addHandlers db, engine.pushEvent, shutDown
|
||||
# log.print 'RS', 'Passing handlers to module manager'
|
||||
# TODO loadAction and addRule will be removed
|
||||
# mm.addHandlers db, engine.loadActionModule, engine.addRule
|
||||
|
||||
###
|
||||
Shuts down the server.
|
||||
|
||||
@private shutDown( *args, answHandler* )
|
||||
@param {Object} args
|
||||
@param {Object} answHandler
|
||||
@private shutDown()
|
||||
###
|
||||
shutDown = (args, answHandler) ->
|
||||
answHandler?.answerSuccess 'Goodbye!'
|
||||
shutDown = ->
|
||||
log.print 'RS', 'Received shut down command!'
|
||||
engine?.shutDown()
|
||||
http_listener?.shutDown()
|
||||
|
|
@ -157,7 +118,7 @@ When the server is run as a child process, this function handles messages
|
|||
from the parent process (e.g. the testing suite)
|
||||
###
|
||||
|
||||
process.on 'message', (cmd) -> procCmds[cmd]?()
|
||||
process.on 'message', ( cmd ) -> procCmds[cmd]?()
|
||||
|
||||
###
|
||||
The die command redirects to the shutDown function.
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
efew = require 'fs'
|
||||
|
||||
###
|
||||
root = exports ? this
|
||||
root.foo = -> 'Hello World'
|
||||
console.log root.foo()
|
||||
|
||||
My comments will show up here
|
||||
|
||||
###
|
||||
138
coffee/user_handler.coffee
Normal file
138
coffee/user_handler.coffee
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
###
|
||||
|
||||
User Handler
|
||||
============
|
||||
> TODO Add documentation
|
||||
|
||||
###
|
||||
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
qs = require 'querystring'
|
||||
|
||||
# Requires:
|
||||
|
||||
# - The [Logging](logging.html) module
|
||||
log = require './logging'
|
||||
# - The [DB Interface](db_interface.html) module
|
||||
db = require './db_interface'
|
||||
# - The [Module Manager](module_manager.html) module
|
||||
mm = require './module_manager'
|
||||
|
||||
### Prepare the admin command handlers that are issued via HTTP requests. ###
|
||||
objAdminCmds =
|
||||
'loadrules': mm.loadRulesFromFS,
|
||||
'loadaction': mm.loadActionModuleFromFS,
|
||||
'loadactions': mm.loadActionModulesFromFS,
|
||||
'loadevent': mm.loadEventModuleFromFS,
|
||||
'loadevents': mm.loadEventModulesFromFS
|
||||
|
||||
|
||||
exports = module.exports = ( args ) ->
|
||||
args = args ? {}
|
||||
log args
|
||||
db args
|
||||
mm args
|
||||
mm.addDBLink db
|
||||
users = JSON.parse fs.readFileSync path.resolve __dirname, '..', 'config', 'users.json'
|
||||
db.storeUser user for user in users
|
||||
module.exports
|
||||
|
||||
|
||||
exports.addShutdownHandler = ( fShutdown ) ->
|
||||
objAdminCmds.shutdown = fShutdown
|
||||
|
||||
|
||||
exports.handleRequest = ( req, resp ) ->
|
||||
req.on 'end', -> resp.end()
|
||||
if req.session and req.session.user
|
||||
resp.send 'You\'re logged in'
|
||||
else
|
||||
resp.sendfile path.resolve __dirname, '..', 'webpages', 'handlers', 'login.html'
|
||||
req.session.lastPage = req.originalUrl
|
||||
|
||||
|
||||
exports.handleLogin = ( req, resp ) ->
|
||||
body = ''
|
||||
req.on 'data', ( data ) -> body += data
|
||||
req.on 'end', ->
|
||||
if not req.session or not req.session.user
|
||||
obj = qs.parse body
|
||||
db.loginUser obj.username, obj.password, ( err, obj ) ->
|
||||
if not err
|
||||
req.session.user = obj
|
||||
if req.session.user
|
||||
resp.write 'Welcome ' + req.session.user.name + '!'
|
||||
else
|
||||
resp.writeHead 401, { "Content-Type": "text/plain" }
|
||||
resp.write 'Login failed!'
|
||||
resp.end()
|
||||
else
|
||||
resp.write 'Welcome ' + req.session.user.name + '!'
|
||||
resp.end()
|
||||
|
||||
|
||||
answerHandler = ( resp ) ->
|
||||
hasBeenAnswered = false
|
||||
postAnswer( msg ) ->
|
||||
if not hasBeenAnswered
|
||||
resp.write msg
|
||||
resp.end()
|
||||
hasBeenAnswered = true
|
||||
{
|
||||
answerSuccess: ( msg ) ->
|
||||
if not hasBeenAnswered
|
||||
postAnswer msg,
|
||||
answerError: ( msg ) ->
|
||||
if not hasBeenAnswered
|
||||
resp.writeHead 400, { "Content-Type": "text/plain" }
|
||||
postAnswer msg,
|
||||
isAnswered: -> hasBeenAnswered
|
||||
}
|
||||
|
||||
# TODO add loadUsers as directive to admin commands
|
||||
# exports.loadUsers = ->
|
||||
# var users = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', 'users.json')));
|
||||
# for(var name in users) {
|
||||
# db.storeUser(users[name]);
|
||||
# }
|
||||
# };
|
||||
|
||||
onAdminCommand = ( req, response ) ->
|
||||
q = req.query;
|
||||
log.print 'HL', 'Received admin request: ' + req.originalUrl
|
||||
if q.cmd
|
||||
fAdminCommands q, answerHandler response
|
||||
#answerSuccess(response, 'Thank you, we try our best!');
|
||||
else answerError response, 'I\'m not sure about what you want from me...'
|
||||
|
||||
|
||||
###
|
||||
admin commands handler receives all command arguments and an answerHandler
|
||||
object that eases response handling to the HTTP request issuer.
|
||||
|
||||
@private fAdminCommands( *args, answHandler* )
|
||||
###
|
||||
fAdminCommands = ( args, answHandler ) ->
|
||||
if args and args.cmd
|
||||
adminCmds[args.cmd]? args, answHandler
|
||||
else
|
||||
log.print 'RS', 'No command in request'
|
||||
|
||||
###
|
||||
The fAnsw function receives an answerHandler object as an argument when called
|
||||
and returns an anonymous function
|
||||
###
|
||||
fAnsw = ( ah ) ->
|
||||
###
|
||||
The anonymous function checks whether the answerHandler was already used to
|
||||
issue an answer, if no answer was provided we answer with an error message
|
||||
###
|
||||
() ->
|
||||
if not ah.isAnswered()
|
||||
ah.answerError 'Not handled...'
|
||||
|
||||
###
|
||||
Delayed function call of the anonymous function that checks the answer handler
|
||||
###
|
||||
setTimeout fAnsw(answHandler), 2000
|
||||
|
|
@ -3,23 +3,20 @@
|
|||
|
||||
Config
|
||||
======
|
||||
|
||||
Loads the configuration file and acts as an interface to it.
|
||||
> Loads the configuration file and acts as an interface to it.
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
var config, exports, fetchProp, fs, loadConfigFile, log, path;
|
||||
var exports, fetchProp, fs, loadConfigFile, log, path,
|
||||
_this = this;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
path = require('path');
|
||||
|
||||
log = require('./logging');
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
config = null;
|
||||
|
||||
/*
|
||||
##Module call
|
||||
|
||||
|
|
@ -50,8 +47,8 @@ Loads the configuration file and acts as an interface to it.
|
|||
loadConfigFile = function(relPath) {
|
||||
var e;
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', relPath)));
|
||||
if (config && config.http_port && config.db_port && config.crypto_key && config.session_secret) {
|
||||
_this.config = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', relPath)));
|
||||
if (_this.config && _this.config.http_port && _this.config.db_port && _this.config.crypto_key && _this.config.session_secret) {
|
||||
return log.print('CF', 'config file loaded successfully');
|
||||
} else {
|
||||
return log.error('CF', new Error("Missing property in config file, requires:\n- http_port\n- db_port\n- crypto_key\n- session_secret"));
|
||||
|
|
@ -74,7 +71,8 @@ Loads the configuration file and acts as an interface to it.
|
|||
|
||||
|
||||
fetchProp = function(prop) {
|
||||
return config != null ? config[prop] : void 0;
|
||||
var _ref;
|
||||
return (_ref = _this.config) != null ? _ref[prop] : void 0;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -85,7 +83,7 @@ Loads the configuration file and acts as an interface to it.
|
|||
|
||||
|
||||
exports.isReady = function() {
|
||||
return config != null;
|
||||
return _this.config != null;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -3,28 +3,26 @@
|
|||
|
||||
DB Interface
|
||||
============
|
||||
>Handles the connection to the database and provides functionalities for
|
||||
>event/action modules, rules and the encrypted storing of authentication tokens.
|
||||
>General functionality as a wrapper for the module holds initialization,
|
||||
>encryption/decryption, the retrieval of modules and shut down.
|
||||
>
|
||||
>The general structure for linked data is that the key is stored in a set.
|
||||
>By fetching all set entries we can then fetch all elements, which is
|
||||
>automated in this function.
|
||||
>For example modules of the same group, e.g. action modules are registered in an
|
||||
>unordered set in the database, from where they can be retrieved again. For example
|
||||
>a new action module has its ID (e.g 'probinder') first registered in the set
|
||||
>'action_modules' and then stored in the db with the key 'action\_module\_' + ID
|
||||
>(e.g. action\_module\_probinder).
|
||||
> Handles the connection to the database and provides functionalities for
|
||||
> event/action modules, rules and the encrypted storing of authentication tokens.
|
||||
> General functionality as a wrapper for the module holds initialization,
|
||||
> encryption/decryption, the retrieval of modules and shut down.
|
||||
>
|
||||
> The general structure for linked data is that the key is stored in a set.
|
||||
> By fetching all set entries we can then fetch all elements, which is
|
||||
> automated in this function.
|
||||
> For example modules of the same group, e.g. action modules are registered in an
|
||||
> unordered set in the database, from where they can be retrieved again. For example
|
||||
> a new action module has its ID (e.g 'probinder') first registered in the set
|
||||
> 'action_modules' and then stored in the db with the key 'action\_module\_' + ID
|
||||
> (e.g. action\_module\_probinder).
|
||||
>
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
/* Grab all required modules*/
|
||||
|
||||
var crypto, crypto_key, db, decrypt, encrypt, exports, getSetRecords, log, redis, replyHandler;
|
||||
var crypto, decrypt, encrypt, exports, getSetRecords, log, redis, replyHandler,
|
||||
_this = this;
|
||||
|
||||
redis = require('redis');
|
||||
|
||||
|
|
@ -32,15 +30,12 @@ DB Interface
|
|||
|
||||
log = require('./logging');
|
||||
|
||||
crypto_key = null;
|
||||
|
||||
db = null;
|
||||
|
||||
/*
|
||||
##Module call
|
||||
|
||||
Module call
|
||||
-----------
|
||||
Initializes the DB connection. Requires a valid configuration file which contains
|
||||
a db port and a crypto key.
|
||||
|
||||
@param {Object} args
|
||||
*/
|
||||
|
||||
|
|
@ -51,11 +46,11 @@ DB Interface
|
|||
log(args);
|
||||
config = require('./config');
|
||||
config(args);
|
||||
crypto_key = config.getCryptoKey();
|
||||
db = redis.createClient(config.getDBPort(), 'localhost', {
|
||||
_this.crypto_key = config.getCryptoKey();
|
||||
_this.db = redis.createClient(config.getDBPort(), 'localhost', {
|
||||
connect_timeout: 2000
|
||||
});
|
||||
return db.on("error", function(err) {
|
||||
return _this.db.on("error", function(err) {
|
||||
err.addInfo = 'message from DB';
|
||||
return log.error('DB', err);
|
||||
});
|
||||
|
|
@ -72,13 +67,13 @@ DB Interface
|
|||
|
||||
exports.isConnected = function(cb) {
|
||||
var fCheckConnection, numAttempts;
|
||||
if (db.connected) {
|
||||
if (_this.db.connected) {
|
||||
return cb();
|
||||
} else {
|
||||
numAttempts = 0;
|
||||
fCheckConnection = function() {
|
||||
var e;
|
||||
if (db.connected) {
|
||||
if (_this.db.connected) {
|
||||
log.print('DB', 'Successfully connected to DB!');
|
||||
return cb();
|
||||
} else if (numAttempts++ < 10) {
|
||||
|
|
@ -107,7 +102,7 @@ DB Interface
|
|||
return null;
|
||||
}
|
||||
try {
|
||||
enciph = crypto.createCipher('aes-256-cbc', crypto_key);
|
||||
enciph = crypto.createCipher('aes-256-cbc', _this.crypto_key);
|
||||
et = enciph.update(plainText, 'utf8', 'base64');
|
||||
return et + enciph.final('base64');
|
||||
} catch (_error) {
|
||||
|
|
@ -132,7 +127,7 @@ DB Interface
|
|||
return null;
|
||||
}
|
||||
try {
|
||||
deciph = crypto.createDecipher('aes-256-cbc', crypto_key);
|
||||
deciph = crypto.createDecipher('aes-256-cbc', _this.crypto_key);
|
||||
dt = deciph.update(crypticText, 'base64', 'utf8');
|
||||
return dt + deciph.final('utf8');
|
||||
} catch (_error) {
|
||||
|
|
@ -175,7 +170,7 @@ DB Interface
|
|||
|
||||
getSetRecords = function(set, fSingle, cb) {
|
||||
log.print('DB', 'Fetching set records: ' + set);
|
||||
return db != null ? db.smembers(set, function(err, arrReply) {
|
||||
return _this.db.smembers(set, function(err, arrReply) {
|
||||
var fCallback, objReplies, reply, semaphore, _i, _len, _results;
|
||||
if (err) {
|
||||
err.addInfo = 'fetching ' + set;
|
||||
|
|
@ -213,7 +208,7 @@ DB Interface
|
|||
}
|
||||
return _results;
|
||||
}
|
||||
}) : void 0;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -232,10 +227,8 @@ DB Interface
|
|||
|
||||
exports.storeActionModule = function(id, data) {
|
||||
log.print('DB', 'storeActionModule: ' + id);
|
||||
if (db != null) {
|
||||
db.sadd('action-modules', id, replyHandler('storing action module key ' + id));
|
||||
}
|
||||
return db != null ? db.set('action-module:' + id, data, replyHandler('storing action module ' + id)) : void 0;
|
||||
_this.db.sadd('action-modules', id, replyHandler('storing action module key ' + id));
|
||||
return _this.db.set('action-module:' + id, data, replyHandler('storing action module ' + id));
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -249,7 +242,7 @@ DB Interface
|
|||
|
||||
exports.getActionModule = function(id, cb) {
|
||||
log.print('DB', 'getActionModule: ' + id);
|
||||
return db != null ? db.get('action-module:' + id, cb) : void 0;
|
||||
return _this.db.get('action-module:' + id, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -276,7 +269,7 @@ DB Interface
|
|||
|
||||
exports.storeActionAuth = function(userId, moduleId, data) {
|
||||
log.print('DB', 'storeActionAuth: ' + userId + ':' + moduleId);
|
||||
return db != null ? db.set('action-auth:' + userId + ':' + moduleId, encrypt(data), replyHandler('storing action auth ' + userId + ':' + moduleId)) : void 0;
|
||||
return _this.db.set('action-auth:' + userId + ':' + moduleId, encrypt(data), replyHandler('storing action auth ' + userId + ':' + moduleId));
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -292,9 +285,9 @@ DB Interface
|
|||
|
||||
exports.getActionAuth = function(userId, moduleId, cb) {
|
||||
log.print('DB', 'getActionAuth: ' + userId + ':' + moduleId);
|
||||
return db != null ? db.get('action-auth:' + userId + ':' + moduleId, function(err, data) {
|
||||
return _this.db.get('action-auth:' + userId + ':' + moduleId, function(err, data) {
|
||||
return cb(err, decrypt(data));
|
||||
}) : void 0;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -313,10 +306,8 @@ DB Interface
|
|||
|
||||
exports.storeEventModule = function(id, data) {
|
||||
log.print('DB', 'storeEventModule: ' + id);
|
||||
if (db != null) {
|
||||
db.sadd('event-modules', id, replyHandler('storing event module key ' + id));
|
||||
}
|
||||
return db != null ? db.set('event-module:' + id, data, replyHandler('storing event module ' + id)) : void 0;
|
||||
_this.db.sadd('event-modules', id, replyHandler('storing event module key ' + id));
|
||||
return _this.db.set('event-module:' + id, data, replyHandler('storing event module ' + id));
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -330,7 +321,7 @@ DB Interface
|
|||
|
||||
exports.getEventModule = function(id, cb) {
|
||||
log.print('DB', 'getEventModule: ' + id);
|
||||
return db != null ? db.get('event_module:' + id, cb) : void 0;
|
||||
return _this.db.get('event_module:' + id, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -349,30 +340,32 @@ DB Interface
|
|||
Store a string representation of he authentication parameters for an event module.
|
||||
|
||||
@public storeEventAuth( *userId, moduleId, data* )
|
||||
@param {String} id
|
||||
@param {String} data
|
||||
@param {String} userId
|
||||
@param {String} moduleId
|
||||
@param {Object} data
|
||||
*/
|
||||
|
||||
|
||||
exports.storeEventAuth = function(userId, moduleId, data) {
|
||||
log.print('DB', 'storeEventAuth: ' + userId + ':' + moduleId);
|
||||
return db != null ? db.set('event-auth:' + userId + ':' + moduleId, encrypt(data), replyHandler('storing event auth ' + userId + ':' + moduleId)) : void 0;
|
||||
return _this.db.set('event-auth:' + userId + ':' + moduleId, encrypt(data), replyHandler('storing event auth ' + userId + ':' + moduleId));
|
||||
};
|
||||
|
||||
/*
|
||||
Query the DB for an action module authentication token, associated with a user.
|
||||
|
||||
@public getEventAuth( *id, cb* )
|
||||
@param {String} id
|
||||
@public getEventAuth( *userId, moduleId, data* )
|
||||
@param {String} userId
|
||||
@param {String} moduleId
|
||||
@param {function} cb
|
||||
*/
|
||||
|
||||
|
||||
exports.getEventAuth = function(userId, moduleId, cb) {
|
||||
log.print('DB', 'getEventAuth: ' + userId + ':' + moduleId);
|
||||
return db != null ? db.get('event-auth:' + userId + ':' + moduleId, function(err, data) {
|
||||
return _this.db.get('event-auth:' + userId + ':' + moduleId, function(err, data) {
|
||||
return cb(err, decrypt(data));
|
||||
}) : void 0;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -391,10 +384,8 @@ DB Interface
|
|||
|
||||
exports.storeRule = function(id, data) {
|
||||
log.print('DB', 'storeRule: ' + id);
|
||||
if (db != null) {
|
||||
db.sadd('rules', id, replyHandler('storing rule key ' + id));
|
||||
}
|
||||
return db != null ? db.set('rule:' + id, data, replyHandler('storing rule ' + id)) : void 0;
|
||||
_this.db.sadd('rules', id, replyHandler('storing rule key ' + id));
|
||||
return _this.db.set('rule:' + id, data, replyHandler('storing rule ' + id));
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -408,7 +399,7 @@ DB Interface
|
|||
|
||||
exports.getRule = function(id, cb) {
|
||||
log.print('DB', 'getRule: ' + id);
|
||||
return db != null ? db.get('rule:' + id, cb) : void 0;
|
||||
return _this.db.get('rule:' + id, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -435,11 +426,9 @@ DB Interface
|
|||
exports.storeUser = function(objUser) {
|
||||
log.print('DB', 'storeUser: ' + objUser.username);
|
||||
if (objUser && objUser.username && objUser.password) {
|
||||
if (db != null) {
|
||||
db.sadd('users', objUser.username, replyHandler('storing user key ' + objUser.username));
|
||||
}
|
||||
_this.db.sadd('users', objUser.username, replyHandler('storing user key ' + objUser.username));
|
||||
objUser.password = encrypt(objUser.password);
|
||||
return db != null ? db.hmset('user:' + objUser.username, objUser, replyHandler('storing user properties ' + objUser.username)) : void 0;
|
||||
return _this.db.hmset('user:' + objUser.username, objUser, replyHandler('storing user properties ' + objUser.username));
|
||||
} else {
|
||||
return log.error('DB', new Error('username or password was missing'));
|
||||
}
|
||||
|
|
@ -456,10 +445,8 @@ DB Interface
|
|||
|
||||
exports.storeUserRole = function(username, role) {
|
||||
log.print('DB', 'storeUserRole: ' + username + ':' + role);
|
||||
if (db != null) {
|
||||
db.sadd('user-roles:' + username, role, replyHandler('adding role ' + role + ' to user ' + username));
|
||||
}
|
||||
return db != null ? db.sadd('role-users:' + role, username, replyHandler('adding user ' + username + ' to role ' + role)) : void 0;
|
||||
_this.db.sadd('user-roles:' + username, role, replyHandler('adding role ' + role + ' to user ' + username));
|
||||
return _this.db.sadd('role-users:' + role, username, replyHandler('adding user ' + username + ' to role ' + role));
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -472,7 +459,7 @@ DB Interface
|
|||
|
||||
exports.getUserRoles = function(username) {
|
||||
log.print('DB', 'getUserRole: ' + username);
|
||||
return db != null ? db.get('user-roles:' + username, cb) : void 0;
|
||||
return _this.db.get('user-roles:' + username, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -485,7 +472,7 @@ DB Interface
|
|||
|
||||
exports.getRoleUsers = function(role) {
|
||||
log.print('DB', 'getRoleUsers: ' + role);
|
||||
return db != null ? db.get('role-users:' + role, cb) : void 0;
|
||||
return _this.db.get('role-users:' + role, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -517,7 +504,7 @@ DB Interface
|
|||
}
|
||||
};
|
||||
};
|
||||
return db != null ? db.hgetall('user:' + username, fCheck(password)) : void 0;
|
||||
return _this.db.hgetall('user:' + username, fCheck(password));
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -528,7 +515,7 @@ DB Interface
|
|||
|
||||
|
||||
exports.shutDown = function() {
|
||||
return db != null ? db.quit() : void 0;
|
||||
return _this.db.quit();
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
|
|
|||
|
|
@ -1,116 +1,95 @@
|
|||
// HTTP Listener
|
||||
// =============
|
||||
//
|
||||
// Handles the HTTP requests to the server at the port specified by the [config](config.html) file.
|
||||
|
||||
'use strict';
|
||||
|
||||
var path = require('path'),
|
||||
express = require('express'),
|
||||
app = express(),
|
||||
RedisStore = require('connect-redis')(express),
|
||||
qs = require('querystring'),
|
||||
log = require('./logging'),
|
||||
sess_sec = '#C[>;j`@".TXm2TA;A2Tg)',
|
||||
db_port, http_port, server,
|
||||
eventHandler, userHandler;
|
||||
|
||||
// Generated by CoffeeScript 1.6.3
|
||||
/*
|
||||
* The module needs to be called as a function to initialize it.
|
||||
* After that it fetches the http\_port, db\_port & sess\_sec properties
|
||||
* from the configuration file.
|
||||
*/
|
||||
exports = module.exports = function(args) {
|
||||
args = args || {};
|
||||
log(args);
|
||||
var config = require('./config')(args);
|
||||
userHandler = require('./user_handler')(args);
|
||||
db_port = config.getDBPort(),
|
||||
sess_sec = config.getSessionSecret(),
|
||||
http_port = config.getHttpPort();
|
||||
return module.exports;
|
||||
};
|
||||
|
||||
exports.addHandlers = function(funcAdminHandler, funcEvtHandler) {
|
||||
if(!funcAdminHandler || !funcEvtHandler) {
|
||||
log.error('HL', 'ERROR: either adminHandler or eventHandler function not defined!');
|
||||
return;
|
||||
}
|
||||
userHandler.addHandler(funcAdminHandler);
|
||||
eventHandler = funcEvtHandler;
|
||||
// Add cookie support for session handling.
|
||||
app.use(express.cookieParser());
|
||||
app.use(express.session({secret: sess_sec}));
|
||||
log.print('HL', 'no session backbone');
|
||||
|
||||
// ^ TODO figure out why redis backbone doesn't work. eventually the db pass has to be set in the DB?
|
||||
// } session information seems to be stored in DB but not retrieved correctly
|
||||
// } if(db_port) {
|
||||
// } app.use(express.session({
|
||||
// } store: new RedisStore({
|
||||
// } host: 'localhost',
|
||||
// } port: db_port,
|
||||
// } db: 2
|
||||
// } ,
|
||||
// } pass: null
|
||||
// } }),
|
||||
// } secret: sess_sec
|
||||
// } }));
|
||||
// } log.print('HL', 'Added redis DB as session backbone');
|
||||
// } } else {
|
||||
// } app.use(express.session({secret: sess_sec}));
|
||||
// } log.print('HL', 'no session backbone');
|
||||
// } }
|
||||
HTTP Listener
|
||||
=============
|
||||
> Handles the HTTP requests to the server at the port specified by the
|
||||
> [config](config.html) file.
|
||||
*/
|
||||
|
||||
// Redirect the requests to the appropriate handler.
|
||||
app.use('/', express.static(path.resolve(__dirname, '..', 'webpages')));
|
||||
// app.use('/doc/', express.static(path.resolve(__dirname, '..', 'webpages', 'doc')));
|
||||
// app.get('/mobile', userHandler.handleRequest);
|
||||
app.get('/rulesforge', userHandler.handleRequest);
|
||||
// app.use('/mobile', express.static(path.resolve(__dirname, '..', 'webpages', 'mobile')));
|
||||
// } app.use('/rulesforge/', express.static(path.resolve(__dirname, '..', 'webpages', 'rulesforge')));
|
||||
app.get('/admin', userHandler.handleRequest);
|
||||
app.post('/login', userHandler.handleLogin);
|
||||
app.post('/push_event', onPushEvent);
|
||||
try {
|
||||
if(http_port) server = app.listen(http_port); // inbound event channel
|
||||
else log.error('HL', new Error('No HTTP port found!? Nothing to listen on!...'));
|
||||
} catch(e) {
|
||||
e.addInfo = 'port unavailable';
|
||||
log.error(e);
|
||||
funcAdminHandler({cmd: 'shutdown'});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If a post request reaches the server, this function handles it and treats the request as a possible event.
|
||||
*/
|
||||
function onPushEvent(req, resp) {
|
||||
var body = '';
|
||||
req.on('data', function (data) { body += data; });
|
||||
req.on('end', function () {
|
||||
var obj = qs.parse(body);
|
||||
/* If required event properties are present we process the event */
|
||||
if(obj && obj.event && obj.eventid){
|
||||
resp.writeHead(200, { "Content-Type": "text/plain" });
|
||||
resp.write('Thank you for the event (' + obj.event + '[' + obj.eventid + '])!');
|
||||
eventHandler(obj);
|
||||
} else {
|
||||
resp.writeHead(400, { "Content-Type": "text/plain" });
|
||||
resp.write('Your event was missing important parameters!');
|
||||
(function() {
|
||||
var app, config, exports, express, log, onPushEvent, path, qs, sess_sec, userHandler,
|
||||
_this = this;
|
||||
|
||||
path = require('path');
|
||||
|
||||
express = require('express');
|
||||
|
||||
app = express();
|
||||
|
||||
qs = require('querystring');
|
||||
|
||||
log = require('./logging');
|
||||
|
||||
config = require('./config');
|
||||
|
||||
userHandler = require('./user_handler');
|
||||
|
||||
sess_sec = '#C[>;j`@".TXm2TA;A2Tg)';
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
args = args != null ? args : {};
|
||||
log(args);
|
||||
config(args);
|
||||
userHandler(args);
|
||||
sess_sec = config.getSessionSecret() || sess_sec;
|
||||
return module.exports;
|
||||
};
|
||||
|
||||
exports.addHandlers = function(fEvtHandler, fShutDown) {
|
||||
var e, http_port;
|
||||
userHandler.addShutdownHandler(fShutDown);
|
||||
_this.eventHandler = fEvtHandler;
|
||||
app.use(express.cookieParser());
|
||||
app.use(express.session({
|
||||
secret: sess_sec
|
||||
}));
|
||||
log.print('HL', 'no session backbone');
|
||||
app.use('/', express["static"](path.resolve(__dirname, '..', 'webpages')));
|
||||
app.get('/rulesforge', userHandler.handleRequest);
|
||||
app.get('/admin', userHandler.handleRequest);
|
||||
app.post('/login', userHandler.handleLogin);
|
||||
app.post('/push_event', onPushEvent);
|
||||
try {
|
||||
http_port = config.getHttpPort();
|
||||
if (http_port) {
|
||||
return app.listen(http_port);
|
||||
} else {
|
||||
return log.error('HL', new Error('No HTTP port found!? Nothing to listen on!...'));
|
||||
}
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
e.addInfo = 'opening port';
|
||||
return log.error(e);
|
||||
}
|
||||
resp.end();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.loadUsers = function() {
|
||||
var users = JSON.parse(require('fs').readFileSync(path.resolve(__dirname, '..', relPath)));
|
||||
for(var name in users) {
|
||||
|
||||
}
|
||||
};
|
||||
onPushEvent = function(req, resp) {
|
||||
var body;
|
||||
body = '';
|
||||
req.on('data', function(data) {
|
||||
return body += data;
|
||||
});
|
||||
return req.on('end', function() {
|
||||
var obj;
|
||||
obj = qs.parse(body);
|
||||
if (obj && obj.event && obj.eventid) {
|
||||
resp.write('Thank you for the event (' + obj.event + '[' + obj.eventid + '])!');
|
||||
_this.eventHandler(obj);
|
||||
} else {
|
||||
resp.writeHead(400, {
|
||||
"Content-Type": "text/plain"
|
||||
});
|
||||
resp.write('Your event was missing important parameters!');
|
||||
}
|
||||
return resp.end();
|
||||
});
|
||||
};
|
||||
|
||||
exports.shutDown = function() {
|
||||
log.print('HL', 'Shutting down HTTP listener');
|
||||
process.exit(); // This is a bit brute force...
|
||||
};
|
||||
exports.shutDown = function() {
|
||||
log.print('HL', 'Shutting down HTTP listener');
|
||||
return process.exit();
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ exports = module.exports = function(args) {
|
|||
return module.exports;
|
||||
};
|
||||
|
||||
exports.addHandlers = function(db_link, fLoadAction, fLoadRule) {
|
||||
exports.addDBLink = function(db_link) {
|
||||
db = db_link;
|
||||
funcLoadAction = fLoadAction;
|
||||
funcLoadRule = fLoadRule;
|
||||
// funcLoadAction = fLoadAction;
|
||||
// funcLoadRule = fLoadRule;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -47,7 +47,7 @@ exports.loadRulesFromFS = function(args, answHandler) {
|
|||
for(var i = 0; i < arr.length; i++) {
|
||||
txt += arr[i].id + ', ';
|
||||
db.storeRule(arr[i].id, JSON.stringify(arr[i]));
|
||||
funcLoadRule(arr[i]);
|
||||
// funcLoadRule(arr[i]);
|
||||
}
|
||||
answHandler.answerSuccess('Yep, loaded rules: ' + txt);
|
||||
} catch (e) {
|
||||
|
|
@ -71,7 +71,7 @@ exports.loadRulesFromFS = function(args, answHandler) {
|
|||
*/
|
||||
function loadActionCallback(name, data, mod, auth) {
|
||||
db.storeActionModule(name, data); // store module in db
|
||||
funcLoadAction(name, mod); // hand back compiled module
|
||||
// funcLoadAction(name, mod); // hand back compiled module
|
||||
if(auth) db.storeActionModuleAuth(name, auth);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
/*
|
||||
|
||||
Rules Server
|
||||
============
|
||||
|
||||
>This is the main module that is used to run the whole server:
|
||||
>
|
||||
> node server [log_type http_port]
|
||||
|
|
@ -15,17 +17,12 @@ Rules Server
|
|||
>`http_port` can be set to use another port, than defined in the
|
||||
>[config](config.html) file, to listen to, e.g. used by the test suite.
|
||||
>
|
||||
>---
|
||||
>
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
/* Grab all required modules*/
|
||||
|
||||
var adminCmds, args, conf, db, engine, fAdminCommands, http_listener, init, log, mm, path, procCmds, shutDown;
|
||||
|
||||
path = require('path');
|
||||
var args, conf, db, engine, http_listener, init, log, procCmds, shutDown;
|
||||
|
||||
log = require('./logging');
|
||||
|
||||
|
|
@ -37,25 +34,10 @@ Rules Server
|
|||
|
||||
http_listener = require('./http_listener');
|
||||
|
||||
mm = require('./module_manager');
|
||||
|
||||
args = {};
|
||||
|
||||
procCmds = {};
|
||||
|
||||
/* Prepare the admin commands that are issued via HTTP requests.*/
|
||||
|
||||
|
||||
adminCmds = {
|
||||
'loadrules': mm.loadRulesFromFS,
|
||||
'loadaction': mm.loadActionModuleFromFS,
|
||||
'loadactions': mm.loadActionModulesFromFS,
|
||||
'loadevent': mm.loadEventModuleFromFS,
|
||||
'loadevents': mm.loadEventModulesFromFS,
|
||||
'loadusers': http_listener.loadUsers,
|
||||
'shutdown': shutDown
|
||||
};
|
||||
|
||||
/*
|
||||
Error handling of the express port listener requires special attention,
|
||||
thus we have to catch the process error, which is issued if
|
||||
|
|
@ -68,12 +50,10 @@ Rules Server
|
|||
case 'EADDRINUSE':
|
||||
err.addInfo = 'http_port already in use, shutting down!';
|
||||
log.error('RS', err);
|
||||
shutDown();
|
||||
break;
|
||||
return shutDown();
|
||||
default:
|
||||
log.error(err);
|
||||
throw err;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
@ -119,6 +99,7 @@ Rules Server
|
|||
} else {
|
||||
log.print('RS', 'No HTTP port passed, using standard port from config file');
|
||||
}
|
||||
log.print('RS', 'Initialzing DB');
|
||||
db(args);
|
||||
/* We only proceed with the initialization if the DB is ready*/
|
||||
|
||||
|
|
@ -130,75 +111,24 @@ Rules Server
|
|||
engine(args);
|
||||
log.print('RS', 'Initialzing http listener');
|
||||
http_listener(args);
|
||||
log.print('RS', 'Initialzing module manager');
|
||||
mm(args);
|
||||
log.print('RS', 'Initialzing DB');
|
||||
/* Distribute handlers between modules to link the application.*/
|
||||
|
||||
log.print('RS', 'Passing handlers to engine');
|
||||
engine.addDBLinkAndLoadActionsAndRules(db);
|
||||
log.print('RS', 'Passing handlers to http listener');
|
||||
http_listener.addHandlers(db, fAdminCommands, engine.pushEvent);
|
||||
log.print('RS', 'Passing handlers to module manager');
|
||||
return mm.addHandlers(db, engine.loadActionModule, engine.addRule);
|
||||
return http_listener.addHandlers(db, engine.pushEvent, shutDown);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
admin commands handler receives all command arguments and an answerHandler
|
||||
object that eases response handling to the HTTP request issuer.
|
||||
|
||||
@private fAdminCommands( *args, answHandler* )
|
||||
*/
|
||||
|
||||
|
||||
fAdminCommands = function(args, answHandler) {
|
||||
var fAnsw, _name;
|
||||
if (args && args.cmd) {
|
||||
if (typeof adminCmds[_name = args.cmd] === "function") {
|
||||
adminCmds[_name](args, answHandler);
|
||||
}
|
||||
} else {
|
||||
log.print('RS', 'No command in request');
|
||||
}
|
||||
/*
|
||||
The fAnsw function receives an answerHandler object as an argument when called
|
||||
and returns an anonymous function
|
||||
*/
|
||||
|
||||
fAnsw = function(ah) {
|
||||
/*
|
||||
The anonymous function checks whether the answerHandler was already used to
|
||||
issue an answer, if no answer was provided we answer with an error message
|
||||
*/
|
||||
|
||||
return function() {
|
||||
if (!ah.isAnswered()) {
|
||||
return ah.answerError('Not handled...');
|
||||
}
|
||||
};
|
||||
};
|
||||
/*
|
||||
Delayed function call of the anonymous function that checks the answer handler
|
||||
*/
|
||||
|
||||
return setTimeout(fAnsw(answHandler), 2000);
|
||||
};
|
||||
|
||||
/*
|
||||
Shuts down the server.
|
||||
|
||||
@private shutDown( *args, answHandler* )
|
||||
@param {Object} args
|
||||
@param {Object} answHandler
|
||||
@private shutDown()
|
||||
*/
|
||||
|
||||
|
||||
shutDown = function(args, answHandler) {
|
||||
if (answHandler != null) {
|
||||
answHandler.answerSuccess('Goodbye!');
|
||||
}
|
||||
shutDown = function() {
|
||||
log.print('RS', 'Received shut down command!');
|
||||
if (engine != null) {
|
||||
engine.shutDown();
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
// Generated by CoffeeScript 1.6.3
|
||||
(function() {
|
||||
var efew;
|
||||
|
||||
efew = require('fs');
|
||||
|
||||
/*
|
||||
root = exports ? this
|
||||
root.foo = -> 'Hello World'
|
||||
console.log root.foo()
|
||||
|
||||
My comments will show up here
|
||||
*/
|
||||
|
||||
|
||||
}).call(this);
|
||||
|
|
@ -1,96 +1,180 @@
|
|||
var path = require('path'),
|
||||
qs = require('querystring'),
|
||||
log = require('./logging'),
|
||||
db = require('./db_interface'),
|
||||
adminHandler;
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
args = args || {};
|
||||
log(args);
|
||||
db(args);
|
||||
var users = JSON.parse(require('fs').readFileSync(path.resolve(__dirname, '..', 'config', 'users.json')));
|
||||
for(var i = 0; i < users.length; i++) {
|
||||
log.print('UH', 'Found user ' + users[i].username + ' in user file, storing him in the DB');
|
||||
db.storeUser(users[i]);
|
||||
}
|
||||
|
||||
return module.exports;
|
||||
};
|
||||
// Generated by CoffeeScript 1.6.3
|
||||
/*
|
||||
|
||||
exports.addHandler = function(adminHandl) {
|
||||
adminHandler = adminHandl;
|
||||
};
|
||||
User Handler
|
||||
============
|
||||
> TODO Add documentation
|
||||
*/
|
||||
|
||||
exports.handleRequest = function(req, resp) {
|
||||
req.on('end', function () {
|
||||
resp.end();
|
||||
});
|
||||
if(req.session && req.session.user) {
|
||||
resp.send('You\'re logged in');
|
||||
} else resp.sendfile(path.resolve(__dirname, '..', 'webpages', 'handlers', 'login.html'));
|
||||
// resp.end();
|
||||
log.print('UH', 'last: '+ req.session.lastPage);
|
||||
req.session.lastPage = req.originalUrl;
|
||||
log.print('UH', 'last: '+ req.session.lastPage);
|
||||
log.print('UH', 'retrieved req: '+ req.originalUrl);
|
||||
// console.log(req);
|
||||
};
|
||||
|
||||
exports.handleLogin = function(req, resp) {
|
||||
var body = '';
|
||||
req.on('data', function (data) { body += data; });
|
||||
req.on('end', function () {
|
||||
if(!req.session || !req.session.user) {
|
||||
var obj = qs.parse(body);
|
||||
db.loginUser(obj.username, obj.password, function(err, obj) {
|
||||
if(err) {
|
||||
log.error('UH', err);
|
||||
resp.writeHead(401, { "Content-Type": "text/plain" });
|
||||
resp.write('Login failed!');
|
||||
}
|
||||
else {
|
||||
req.session.user = obj;
|
||||
if(req.session.user) {
|
||||
(function() {
|
||||
var answerHandler, db, exports, fAdminCommands, fs, log, mm, objAdminCmds, onAdminCommand, path, qs;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
path = require('path');
|
||||
|
||||
qs = require('querystring');
|
||||
|
||||
log = require('./logging');
|
||||
|
||||
db = require('./db_interface');
|
||||
|
||||
mm = require('./module_manager');
|
||||
|
||||
/* Prepare the admin command handlers that are issued via HTTP requests.*/
|
||||
|
||||
|
||||
objAdminCmds = {
|
||||
'loadrules': mm.loadRulesFromFS,
|
||||
'loadaction': mm.loadActionModuleFromFS,
|
||||
'loadactions': mm.loadActionModulesFromFS,
|
||||
'loadevent': mm.loadEventModuleFromFS,
|
||||
'loadevents': mm.loadEventModulesFromFS
|
||||
};
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
var user, users, _i, _len;
|
||||
args = args != null ? args : {};
|
||||
log(args);
|
||||
db(args);
|
||||
mm(args);
|
||||
mm.addDBLink(db);
|
||||
users = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', 'config', 'users.json')));
|
||||
for (_i = 0, _len = users.length; _i < _len; _i++) {
|
||||
user = users[_i];
|
||||
db.storeUser(user);
|
||||
}
|
||||
return module.exports;
|
||||
};
|
||||
|
||||
exports.addShutdownHandler = function(fShutdown) {
|
||||
return objAdminCmds.shutdown = fShutdown;
|
||||
};
|
||||
|
||||
exports.handleRequest = function(req, resp) {
|
||||
req.on('end', function() {
|
||||
return resp.end();
|
||||
});
|
||||
if (req.session && req.session.user) {
|
||||
resp.send('You\'re logged in');
|
||||
} else {
|
||||
resp.sendfile(path.resolve(__dirname, '..', 'webpages', 'handlers', 'login.html'));
|
||||
}
|
||||
return req.session.lastPage = req.originalUrl;
|
||||
};
|
||||
|
||||
exports.handleLogin = function(req, resp) {
|
||||
var body;
|
||||
body = '';
|
||||
req.on('data', function(data) {
|
||||
return body += data;
|
||||
});
|
||||
return req.on('end', function() {
|
||||
var obj;
|
||||
if (!req.session || !req.session.user) {
|
||||
obj = qs.parse(body);
|
||||
return db.loginUser(obj.username, obj.password, function(err, obj) {
|
||||
if (!err) {
|
||||
req.session.user = obj;
|
||||
}
|
||||
if (req.session.user) {
|
||||
resp.write('Welcome ' + req.session.user.name + '!');
|
||||
} else {
|
||||
resp.writeHead(401, { "Content-Type": "text/plain" });
|
||||
resp.writeHead(401, {
|
||||
"Content-Type": "text/plain"
|
||||
});
|
||||
resp.write('Login failed!');
|
||||
}
|
||||
}
|
||||
resp.end();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function answerHandler(r) {
|
||||
var response = r, hasBeenAnswered = false;
|
||||
function postAnswer(msg) {
|
||||
if(!hasBeenAnswered) {
|
||||
response.write(msg);
|
||||
response.end();
|
||||
hasBeenAnswered = true;
|
||||
}
|
||||
}
|
||||
return {
|
||||
answerSuccess: function(msg) {
|
||||
if(!hasBeenAnswered) response.writeHead(200, { "Content-Type": "text/plain" });
|
||||
postAnswer(msg);
|
||||
},
|
||||
answerError: function(msg) {
|
||||
if(!hasBeenAnswered) response.writeHead(400, { "Content-Type": "text/plain" });
|
||||
postAnswer(msg);
|
||||
},
|
||||
isAnswered: function() { return hasBeenAnswered; }
|
||||
return resp.end();
|
||||
});
|
||||
} else {
|
||||
resp.write('Welcome ' + req.session.user.name + '!');
|
||||
return resp.end();
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
function onAdminCommand(request, response) {
|
||||
var q = request.query;
|
||||
log.print('HL', 'Received admin request: ' + request.originalUrl);
|
||||
if(q.cmd) {
|
||||
adminHandler(q, answerHandler(response));
|
||||
// answerSuccess(response, 'Thank you, we try our best!');
|
||||
} else answerError(response, 'I\'m not sure about what you want from me...');
|
||||
}
|
||||
answerHandler = function(resp) {
|
||||
var hasBeenAnswered;
|
||||
hasBeenAnswered = false;
|
||||
postAnswer(msg)(function() {
|
||||
if (!hasBeenAnswered) {
|
||||
resp.write(msg);
|
||||
resp.end();
|
||||
return hasBeenAnswered = true;
|
||||
}
|
||||
});
|
||||
return {
|
||||
answerSuccess: function(msg) {
|
||||
if (!hasBeenAnswered) {
|
||||
return postAnswer(msg);
|
||||
}
|
||||
},
|
||||
answerError: function(msg) {
|
||||
if (!hasBeenAnswered) {
|
||||
resp.writeHead(400, {
|
||||
"Content-Type": "text/plain"
|
||||
});
|
||||
}
|
||||
return postAnswer(msg);
|
||||
},
|
||||
isAnswered: function() {
|
||||
return hasBeenAnswered;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
onAdminCommand = function(req, response) {
|
||||
var q;
|
||||
q = req.query;
|
||||
log.print('HL', 'Received admin request: ' + req.originalUrl);
|
||||
if (q.cmd) {
|
||||
return fAdminCommands(q, answerHandler(response));
|
||||
} else {
|
||||
return answerError(response, 'I\'m not sure about what you want from me...');
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
admin commands handler receives all command arguments and an answerHandler
|
||||
object that eases response handling to the HTTP request issuer.
|
||||
|
||||
@private fAdminCommands( *args, answHandler* )
|
||||
*/
|
||||
|
||||
|
||||
fAdminCommands = function(args, answHandler) {
|
||||
var fAnsw, _name;
|
||||
if (args && args.cmd) {
|
||||
if (typeof adminCmds[_name = args.cmd] === "function") {
|
||||
adminCmds[_name](args, answHandler);
|
||||
}
|
||||
} else {
|
||||
log.print('RS', 'No command in request');
|
||||
}
|
||||
/*
|
||||
The fAnsw function receives an answerHandler object as an argument when called
|
||||
and returns an anonymous function
|
||||
*/
|
||||
|
||||
fAnsw = function(ah) {
|
||||
/*
|
||||
The anonymous function checks whether the answerHandler was already used to
|
||||
issue an answer, if no answer was provided we answer with an error message
|
||||
*/
|
||||
|
||||
return function() {
|
||||
if (!ah.isAnswered()) {
|
||||
return ah.answerError('Not handled...');
|
||||
}
|
||||
};
|
||||
};
|
||||
/*
|
||||
Delayed function call of the anonymous function that checks the answer handler
|
||||
*/
|
||||
|
||||
return setTimeout(fAnsw(answHandler), 2000);
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ exports = module.exports = function(args) {
|
|||
return module.exports;
|
||||
};
|
||||
|
||||
exports.addHandlers = function(db_link, fLoadAction, fLoadRule) {
|
||||
exports.addDBLink = function(db_link) {
|
||||
db = db_link;
|
||||
funcLoadAction = fLoadAction;
|
||||
funcLoadRule = fLoadRule;
|
||||
//TODO Remove fLoadAction and fLoadRule and replace them with user commands
|
||||
// funcLoadAction = fLoadAction;
|
||||
// funcLoadRule = fLoadRule;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -34,8 +35,8 @@ exports.addHandlers = function(db_link, fLoadAction, fLoadRule) {
|
|||
exports.loadRulesFromFS = function(args, answHandler) {
|
||||
if(!args) args = {};
|
||||
if(!args.name) args.name = 'rules';
|
||||
if(!funcLoadRule) log.error('ML', 'no rule loader function available');
|
||||
else {
|
||||
// if(!funcLoadRule) log.error('ML', 'no rule loader function available');
|
||||
// else {
|
||||
fs.readFile(path.resolve(__dirname, '..', 'rules', args.name + '.json'), 'utf8', function (err, data) {
|
||||
if (err) {
|
||||
log.error('ML', 'Loading rules file: ' + args.name + '.json');
|
||||
|
|
@ -47,14 +48,14 @@ exports.loadRulesFromFS = function(args, answHandler) {
|
|||
for(var i = 0; i < arr.length; i++) {
|
||||
txt += arr[i].id + ', ';
|
||||
db.storeRule(arr[i].id, JSON.stringify(arr[i]));
|
||||
funcLoadRule(arr[i]);
|
||||
// funcLoadRule(arr[i]);
|
||||
}
|
||||
answHandler.answerSuccess('Yep, loaded rules: ' + txt);
|
||||
} catch (e) {
|
||||
log.error('ML', 'rules file was corrupt! (' + args.name + '.json)');
|
||||
}
|
||||
});
|
||||
}
|
||||
// }
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -71,7 +72,7 @@ exports.loadRulesFromFS = function(args, answHandler) {
|
|||
*/
|
||||
function loadActionCallback(name, data, mod, auth) {
|
||||
db.storeActionModule(name, data); // store module in db
|
||||
funcLoadAction(name, mod); // hand back compiled module
|
||||
// funcLoadAction(name, mod); // hand back compiled module
|
||||
if(auth) db.storeActionModuleAuth(name, auth);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,22 +2,33 @@ var path = require('path'),
|
|||
qs = require('querystring'),
|
||||
log = require('./logging'),
|
||||
db = require('./db_interface'),
|
||||
adminHandler;
|
||||
mm = require('./module_manager'),
|
||||
// ### Prepare the admin command handlers that are issued via HTTP requests. ###
|
||||
objAdminCmds = {
|
||||
'loadrules': mm.loadRulesFromFS,
|
||||
'loadaction': mm.loadActionModuleFromFS,
|
||||
'loadactions': mm.loadActionModulesFromFS,
|
||||
'loadevent': mm.loadEventModuleFromFS,
|
||||
'loadevents': mm.loadEventModulesFromFS
|
||||
};
|
||||
|
||||
exports = module.exports = function(args) {
|
||||
args = args || {};
|
||||
log(args);
|
||||
db(args);
|
||||
mm(args);
|
||||
mm.addDBLink(db);
|
||||
var users = JSON.parse(require('fs').readFileSync(path.resolve(__dirname, '..', 'config', 'users.json')));
|
||||
for(var name in users) {
|
||||
db.storeUser(users[name]);
|
||||
}
|
||||
log.print('RS', 'Initialzing module manager');
|
||||
|
||||
return module.exports;
|
||||
};
|
||||
|
||||
exports.addHandler = function(adminHandl) {
|
||||
adminHandler = adminHandl;
|
||||
exports.addHandler = function(fShutdown) {
|
||||
objAdminCmds.shutdown = fShutdown;
|
||||
};
|
||||
|
||||
exports.handleRequest = function(req, resp) {
|
||||
|
|
@ -77,12 +88,95 @@ function answerHandler(r) {
|
|||
};
|
||||
};
|
||||
|
||||
//TODO add loadUsers as directive to admin commands
|
||||
exports.loadUsers = function () {
|
||||
var users = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', 'users.json')));
|
||||
for(var name in users) {
|
||||
db.storeUser(users[name]);
|
||||
}
|
||||
};
|
||||
|
||||
function onAdminCommand(request, response) {
|
||||
var q = request.query;
|
||||
log.print('HL', 'Received admin request: ' + request.originalUrl);
|
||||
if(q.cmd) {
|
||||
adminHandler(q, answerHandler(response));
|
||||
fAdminCommands(q, answerHandler(response));
|
||||
// answerSuccess(response, 'Thank you, we try our best!');
|
||||
} else answerError(response, 'I\'m not sure about what you want from me...');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
admin commands handler receives all command arguments and an answerHandler
|
||||
object that eases response handling to the HTTP request issuer.
|
||||
|
||||
@private fAdminCommands( *args, answHandler* )
|
||||
*/
|
||||
|
||||
|
||||
function fAdminCommands(args, answHandler) {
|
||||
var fAnsw, _name;
|
||||
if (args && args.cmd) {
|
||||
if (typeof objAdminCmds[_name = args.cmd] === "function") {
|
||||
objAdminCmds[_name](args, answHandler);
|
||||
}
|
||||
} else {
|
||||
log.print('RS', 'No command in request');
|
||||
}
|
||||
/*
|
||||
The fAnsw function receives an answerHandler object as an argument when called
|
||||
and returns an anonymous function
|
||||
*/
|
||||
|
||||
fAnsw = function(ah) {
|
||||
/*
|
||||
The anonymous function checks whether the answerHandler was already used to
|
||||
issue an answer, if no answer was provided we answer with an error message
|
||||
*/
|
||||
|
||||
return function() {
|
||||
if (!ah.isAnswered()) {
|
||||
return ah.answerError('Not handled...');
|
||||
}
|
||||
};
|
||||
};
|
||||
/*
|
||||
Delayed function call of the anonymous function that checks the answer handler
|
||||
*/
|
||||
|
||||
return setTimeout(fAnsw(answHandler), 2000);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
###
|
||||
admin commands handler receives all command arguments and an answerHandler
|
||||
object that eases response handling to the HTTP request issuer.
|
||||
|
||||
@private fAdminCommands( *args, answHandler* )
|
||||
###
|
||||
fAdminCommands = (args, answHandler) ->
|
||||
if args and args.cmd
|
||||
adminCmds[args.cmd]? args, answHandler
|
||||
else
|
||||
log.print 'RS', 'No command in request'
|
||||
|
||||
###
|
||||
The fAnsw function receives an answerHandler object as an argument when called
|
||||
and returns an anonymous function
|
||||
###
|
||||
fAnsw = (ah) ->
|
||||
###
|
||||
The anonymous function checks whether the answerHandler was already used to
|
||||
issue an answer, if no answer was provided we answer with an error message
|
||||
###
|
||||
() ->
|
||||
if not ah.isAnswered()
|
||||
ah.answerError 'Not handled...'
|
||||
|
||||
###
|
||||
Delayed function call of the anonymous function that checks the answer handler
|
||||
###
|
||||
setTimeout fAnsw(answHandler), 2000
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue