webapi-eca/coffee/request_handler.coffee

317 lines
8.5 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
2013-11-26 22:24:15 +00:00
'loadevents': mm.loadEventModulesFromFS
# Prepare the user command handlers which are invoked via HTTP requests.
objUserCmds =
'store_action': mm.storeActionModule
'get_actionmodules': mm.getAllActionModules
'store_event': mm.storeEventModule
'get_eventmodules': mm.getAllEventModules
'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 ) =>
objAdminCmds.shutdown = ( args, answerHandler ) ->
answerHandler.answerSuccess 'Shutting down... BYE!'
setTimeout fShutdown, 500
2013-11-26 22:24:15 +00:00
###
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.send 400, '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, msg ) ->
template = getHandlerFileAsString name
menubar = getHandlerFileAsString 'part_menubar'
requires = getHandlerFileAsString 'part_requires'
view =
user: sess.user,
head_requires: requires,
div_menubar: menubar,
message: msg
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'
###
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 rules 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 handleForgeRules( *req, resp* )
###
exports.handleForgeRules = ( req, resp ) ->
sendLoginOrPage 'forge_rules', 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 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
2013-12-10 22:44:28 +00:00
console.log obj
if typeof objUserCmds[obj.command] is 'function'
objUserCmds[obj.command] req.session.user, obj, answerHandler req, resp
else
resp.send 404, 'Command unknown!'
###
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"
q = req.query
log.print 'RH', 'Received admin request: ' + req.originalUrl
if q.cmd
objAdminCmds[q.cmd]? q, answerHandler req, resp, true
else
resp.send 404, 'Command unknown!'
else
resp.send renderPage 'unauthorized', req.session
else
resp.sendfile getHandlerPath 'login'
2013-11-26 22:24:15 +00:00
answerHandler = (req, resp, ntbr) ->
request = req
response = resp
needsToBeRendered = ntbr
hasBeenAnswered = false
ret =
answerSuccess: (msg) ->
if not hasBeenAnswered
if needsToBeRendered
response.send renderPage 'command_answer', request.session, msg
else
response.send msg
hasBeenAnswered = true
,
answerError: (msg) ->
if not hasBeenAnswered
if needsToBeRendered
response.send 400, renderPage 'error', request.session, msg
else
response.send 400, msg
hasBeenAnswered = true
,
isAnswered: -> hasBeenAnswered
setTimeout(() ->
ret.answerError 'Strange... maybe try again?'
, 5000)
ret
2013-11-26 22:24:15 +00:00