webapi-eca/coffee/request_handler.coffee
Dominic Bosch 1342d0b2de Events can now be pushed into the engine via webpage.
The events are now queued through the DB.
2013-11-28 19:14:05 +01:00

240 lines
6.6 KiB
CoffeeScript

###
Request Handler
============
> TODO Add documentation
###
# **Requires:**
# - [Logging](logging.html)
log = require './logging'
# - [DB Interface](db_interface.html)
db = require './db_interface'
# - [Module Manager](module_manager.html)
mm = require './module_manager'
# - Node.js Modules: [fs](http://nodejs.org/api/fs.html),
# [path](http://nodejs.org/api/path.html) and
# [querystring](http://nodejs.org/api/querystring.html)
fs = require 'fs'
path = require 'path'
qs = require 'querystring'
# - External Modules: [mustache](https://github.com/janl/mustache.js) and
# [crypto-js](https://github.com/evanvosberg/crypto-js)
mustache = require 'mustache'
crypto = require 'crypto-js'
# Prepare the admin command handlers that are invoked 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
###
This allows the parent to add handlers. The event handler will receive
the events that were received. The shutdown function will be called if the
admin command shutdown is issued.
@public addHandlers( *fShutdown* )
@param {function} fShutdown
###
exports.addHandlers = ( fShutdown ) =>
objAdminCmds.shutdown = fShutdown
###
Handles possible events that were posted to this server and pushes them into the
event queue.
*Requires
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
objects.*
@public handleEvent( *req, resp* )
###
exports.handleEvent = ( 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.send 'Thank you for the event (' + obj.event + '[' + obj.eventid + '])!'
db.pushEvent obj
else
resp.writeHead 400, { "Content-Type": "text/plain" }
resp.send 'Your event was missing important parameters!'
###
*Requires
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
objects.*
@public handleLogin( *req, resp* )
###
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, usr ) ->
if(err)
# Tapping on fingers, at least in log...
log.print 'RH', "AUTH-UH-OH (#{obj.username}): " + err.message
else
# no error, so we can associate the user object from the DB to the session
req.session.user = usr
if req.session.user
resp.send 'OK!'
else
resp.send 401, 'NO!'
else
resp.send 'Welcome ' + req.session.user.name + '!'
###
A post request retrieved on this handler causes the user object to be
purged from the session, thus the user will be logged out.
*Requires
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
objects.*
@public handleLogout( *req, resp* )
###
exports.handleLogout = ( req, resp ) ->
if req.session
req.session.user = null
resp.send 'Bye!'
###
Resolves the path to a handler webpage.
@private getHandlerPath( *name* )
@param {String} name
###
getHandlerPath = ( name ) ->
path.resolve __dirname, '..', 'webpages', 'handlers', name + '.html'
###
Resolves the path to a handler webpage and returns it as a string.
@private getHandlerFileAsString( *name* )
@param {String} name
###
getHandlerFileAsString = ( name ) ->
fs.readFileSync getHandlerPath( name ), 'utf8'
###
*Requires
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
objects.*
@public handleUser( *req, resp* )
###
exports.handleUser = ( req, resp ) ->
if req.session and req.session.user
welcome = getHandlerFileAsString 'welcome'
menubar = getHandlerFileAsString 'menubar'
view = {
user: req.session.user,
div_menubar: menubar
}
resp.send mustache.render welcome, view
else
resp.sendfile getHandlerPath 'login'
###
*Requires
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
objects.*
@public handleAdmin( *req, resp* )
###
exports.handleAdmin = ( req, resp ) ->
if req.session and req.session.user
if req.session.user.isAdmin is "true"
welcome = getHandlerFileAsString 'welcome'
menubar = getHandlerFileAsString 'menubar'
view =
user: req.session.user,
div_menubar: menubar
resp.send mustache.render welcome, view
else
unauthorized = getHandlerFileAsString 'unauthorized'
menubar = getHandlerFileAsString 'menubar'
view =
user: req.session.user,
div_menubar: menubar
resp.send mustache.render unauthorized, view
else
resp.sendfile getHandlerPath 'login'
onAdminCommand = ( req, response ) ->
q = req.query
log.print 'RH', 'Received admin request: ' + q
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 'RH', '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