webapi-eca/coffee/request_handler.coffee

303 lines
8.2 KiB
CoffeeScript
Raw Normal View History

2013-11-26 22:24:15 +00:00
###
Request Handler
2013-11-26 22:24:15 +00:00
============
> TODO Add documentation
###
# **Requires:**
2013-11-26 22:24:15 +00:00
# - [Logging](logging.html)
2013-11-26 22:24:15 +00:00
log = require './logging'
# - [DB Interface](db_interface.html)
2013-11-26 22:24:15 +00:00
db = require './db_interface'
# - [Module Manager](module_manager.html)
2013-11-26 22:24:15 +00:00
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 which are invoked via HTTP requests.
2013-11-26 22:24:15 +00:00
objAdminCmds =
'loadrules': mm.loadRulesFromFS,
'loadaction': mm.loadActionModuleFromFS,
'loadactions': mm.loadActionModulesFromFS,
'loadevent': mm.loadEventModuleFromFS,
'loadevents': mm.loadEventModulesFromFS
# Prepare the user command handlers which are invoked via HTTP requests.
objUserCmds =
'store_action': mm.storeActionModule
'store_event': mm.storeEventModule
'store_rule': mm.storeRule
2013-11-26 22:24:15 +00:00
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.
2013-11-26 22:24:15 +00:00
@public addHandlers( *fShutdown* )
@param {function} fShutdown
###
exports.addHandlers = ( fShutdown ) =>
2013-11-26 22:24:15 +00:00
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!'
2013-11-26 22:24:15 +00:00
###
*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.*
2013-11-26 22:24:15 +00:00
@public handleLogin( *req, resp* )
###
2013-11-26 22:24:15 +00:00
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
2013-11-26 22:24:15 +00:00
if req.session.user
resp.send 'OK!'
2013-11-26 22:24:15 +00:00
else
resp.send 401, 'NO!'
2013-11-26 22:24:15 +00:00
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'
###
Renders a page depending on the user session and returns it.
@private renderPage( *name, sess* )
@param {String} name
@param {Object} sess
###
renderPage = ( name, sess ) ->
template = getHandlerFileAsString name
menubar = getHandlerFileAsString 'menubar'
view =
user: sess.user,
div_menubar: menubar
mustache.render template, view
###
Sends the desired page or the login to the user.
*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 renderPageOrLogin( *req, resp, pagename* )
@param {String} pagename
###
sendLoginOrPage = ( pagename, req, resp ) ->
if req.session and req.session.user
resp.send renderPage pagename, req.session
else
resp.sendfile getHandlerPath 'login'
###
Handles the user command requests.
*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.handleUserCommand = ( req, resp ) ->
if not req.session or not req.session.user
resp.send 401, 'Login first!'
else
body = ''
req.on 'data', ( data ) ->
body += data
req.on 'end', ->
obj = qs.parse body
if objUserCmds[obj.command] is 'function'
resp.send 'Command accepted!'
objUserCmds[obj.command] req.session.user, obj
else
resp.send 404, 'Command unknown!'
###
Present the module forge to the user.
*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 handleForgeModules( *req, resp* )
###
exports.handleForgeModules = ( req, resp ) ->
sendLoginOrPage 'forge_modules', req, resp
###
Present the event invoke page to the user.
*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 handleInvokeEvent( *req, resp* )
###
exports.handleInvokeEvent = ( req, resp ) ->
sendLoginOrPage 'push_event', req, resp
###
Handles the admin command requests.
*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"
resp.send renderPage 'welcome', req.session
else
resp.send renderPage 'unauthorized', req.session
else
resp.sendfile getHandlerPath 'login'
2013-11-26 22:24:15 +00:00
onAdminCommand = ( req, response ) ->
q = req.query
log.print 'RH', 'Received admin request: ' + q
2013-11-26 22:24:15 +00:00
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'
2013-11-26 22:24:15 +00:00
###
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