[475] | 1 | var express = require("express") |
---|
| 2 | , passport = require("passport") |
---|
| 3 | , passportLocal = require("passport-local") |
---|
| 4 | , fs = require("fs") |
---|
| 5 | , path = require("path") |
---|
| 6 | , proxy = require("./util/simple-http-proxy") |
---|
[525] | 7 | , CouchDB = require('./util/couch') |
---|
| 8 | , HTTPResult = require('./util/http-result') |
---|
[475] | 9 | , _ = require("underscore") |
---|
| 10 | ; |
---|
[443] | 11 | |
---|
[525] | 12 | exports.app = function(env) { |
---|
[443] | 13 | |
---|
[519] | 14 | assertSetting("couchServerURL", env, _.isString); |
---|
| 15 | assertSetting("dbName", env, _.isString); |
---|
| 16 | assertSetting("mode", env, _.isString); |
---|
| 17 | var couch = new CouchDB(env.couchServerURL,env.dbName); |
---|
[463] | 18 | |
---|
[481] | 19 | var schema = require("./config/couchdb-schema.json"); |
---|
[523] | 20 | var views = require("./config/couchdb-design-docs.js"); |
---|
| 21 | return couch.get("schemaInfo") |
---|
| 22 | .then(function(schemaInfo){ |
---|
| 23 | if ( schemaInfo.version !== schema.version ) { |
---|
[525] | 24 | return HTTPResult.fail( |
---|
| 25 | new Error("Found schema version "+schemaInfo.version+ |
---|
| 26 | ", expected "+schema.version)); |
---|
[523] | 27 | } else if ( schemaInfo.viewsVersion !== views.schemaInfo.viewsVersion ) { |
---|
[525] | 28 | return HTTPResult.fail( |
---|
| 29 | new Error("Found views version "+schemaInfo.viewsVersion+ |
---|
| 30 | ", expected "+views.schemaInfo.viewsVersion)); |
---|
[523] | 31 | } else { |
---|
| 32 | return configureApp(env,couch,schema); |
---|
[481] | 33 | } |
---|
| 34 | }); |
---|
| 35 | |
---|
| 36 | }; |
---|
| 37 | |
---|
[519] | 38 | function configureApp(env,couch,schema) { |
---|
[481] | 39 | |
---|
[525] | 40 | var apiUtil = require('./api/util')(couch,schema); |
---|
| 41 | |
---|
[463] | 42 | function clientPath(relativePath) { |
---|
| 43 | return path.resolve(__dirname+'/../client/'+relativePath); |
---|
| 44 | } |
---|
[451] | 45 | |
---|
[519] | 46 | passport.use( |
---|
| 47 | new passportLocal.Strategy( |
---|
| 48 | function(username, password, done){ |
---|
| 49 | if ( username === "igor" && password === "mayer" ) { |
---|
| 50 | done(null,{ username: "igor" }); |
---|
| 51 | } else { |
---|
| 52 | done(null,false,{ message: 'Invalid credentials.' }); |
---|
| 53 | } |
---|
| 54 | })); |
---|
[466] | 55 | passport.serializeUser(function(user, done) { |
---|
| 56 | done(null, user.username); |
---|
| 57 | }); |
---|
| 58 | passport.deserializeUser(function(id, done) { |
---|
| 59 | done(null, {username: id}); |
---|
| 60 | }); |
---|
[451] | 61 | |
---|
[463] | 62 | var app = express(); |
---|
| 63 | app.use(express.logger()); |
---|
| 64 | app.use(express.compress()); |
---|
| 65 | app.use(express.favicon()); |
---|
| 66 | |
---|
[470] | 67 | // cookies and session |
---|
[463] | 68 | app.use(express.cookieParser()); |
---|
| 69 | app.use(express.session({ secret: "quasi experimental design" })); |
---|
[478] | 70 | app.use('/api',express.bodyParser()); |
---|
[463] | 71 | |
---|
[470] | 72 | // passport |
---|
[463] | 73 | app.use(passport.initialize()); |
---|
| 74 | app.use(passport.session()); |
---|
[487] | 75 | |
---|
| 76 | // various middlewares |
---|
[470] | 77 | function ensureAuthenticated(req,res,next){ |
---|
| 78 | if (!req.user) { |
---|
| 79 | return res.send(401,{error:"Login before accessing API."}); |
---|
| 80 | } else { |
---|
| 81 | return next(); |
---|
| 82 | } |
---|
| 83 | } |
---|
| 84 | function returnUser(req,res) { |
---|
| 85 | res.send(200, req.user); |
---|
| 86 | } |
---|
[487] | 87 | function notImplemented(req,res) { |
---|
| 88 | res.send(501,{error:"API not implemented yet."}); |
---|
| 89 | } |
---|
[463] | 90 | |
---|
| 91 | // static resources |
---|
[525] | 92 | app.get('/', function(req, res){ |
---|
| 93 | res.sendfile(clientPath('index.html')); |
---|
[463] | 94 | }); |
---|
[525] | 95 | app.get('/*.html', function(req, res) { |
---|
| 96 | res.sendfile(clientPath(req.path)); |
---|
[463] | 97 | }); |
---|
| 98 | _.each(['/dojo', '/dijit', '/dojox', '/qed', '/qed-client'], function(dir){ |
---|
| 99 | app.use(dir, express.static(clientPath(dir))); |
---|
| 100 | }); |
---|
| 101 | |
---|
[470] | 102 | // post to this url to login |
---|
[466] | 103 | app.post( |
---|
| 104 | '/api/login', |
---|
| 105 | passport.authenticate('local'), |
---|
| 106 | returnUser); |
---|
[463] | 107 | |
---|
[470] | 108 | // return the info for the current logged in user |
---|
[466] | 109 | app.get( |
---|
| 110 | '/api/login', |
---|
[467] | 111 | ensureAuthenticated, |
---|
[466] | 112 | returnUser); |
---|
| 113 | |
---|
[470] | 114 | // explicitly logout this user |
---|
[466] | 115 | app.post( |
---|
[467] | 116 | '/api/logout', |
---|
| 117 | ensureAuthenticated, |
---|
| 118 | function(req,res){ |
---|
[466] | 119 | req.logout(); |
---|
| 120 | res.send(200,{}); |
---|
| 121 | }); |
---|
| 122 | |
---|
[525] | 123 | app.use('/api/questions', ensureAuthenticated); |
---|
| 124 | app.use('/api/questions', |
---|
| 125 | require('./api/questions')(couch,schema).app); |
---|
[487] | 126 | |
---|
[525] | 127 | app.use('/api/categories', ensureAuthenticated); |
---|
| 128 | app.use('/api/categories', |
---|
| 129 | require('./api/categories')(couch,schema).app); |
---|
[487] | 130 | |
---|
[525] | 131 | app.use('/api/topics', ensureAuthenticated); |
---|
| 132 | app.use('/api/topics', |
---|
| 133 | require('./api/topics')(couch,schema).app); |
---|
[487] | 134 | |
---|
[525] | 135 | app.use('/api/surveys', ensureAuthenticated); |
---|
| 136 | app.use('/api/surveys', |
---|
| 137 | require('./api/surveys')(couch,schema).app); |
---|
[481] | 138 | |
---|
[525] | 139 | app.use('/api/surveyRuns', ensureAuthenticated); |
---|
| 140 | app.use('/api/surveyRuns', |
---|
| 141 | require('./api/surveyRuns')(couch,schema).app); |
---|
[487] | 142 | |
---|
[525] | 143 | app.use('/api/responses', ensureAuthenticated); |
---|
| 144 | app.use('/api/responses', |
---|
| 145 | require('./api/responses')(couch,schema).app); |
---|
[481] | 146 | |
---|
[525] | 147 | app.use('/api/open', |
---|
| 148 | require('./api/open')(couch,schema).app); |
---|
[481] | 149 | |
---|
[519] | 150 | app.get('/api/mode', |
---|
[525] | 151 | apiUtil.ensureMIME(apiUtil.JSON_MIME), |
---|
[519] | 152 | function(req,res){ |
---|
| 153 | res.send({mode:env.mode}); |
---|
| 154 | }); |
---|
| 155 | |
---|
[534] | 156 | // anything not handled before is redirected |
---|
| 157 | // as if it was a client URL |
---|
| 158 | app.use('/',function(req,res){ |
---|
| 159 | res.redirect('#!'+req.path); |
---|
| 160 | }); |
---|
[519] | 161 | |
---|
[463] | 162 | return app; |
---|
[481] | 163 | } |
---|
[475] | 164 | |
---|
[519] | 165 | function assertSetting(name, settings, validate) { |
---|
| 166 | if ( typeof settings[name] === 'undefined' ) { |
---|
| 167 | throw new Error("Required setting '"+name+"' undefined."); |
---|
| 168 | } |
---|
| 169 | if ( _.isFunction(validate) && !validate(settings[name]) ) { |
---|
| 170 | throw new Error("Setting '"+name+"' with value '"+settings[name]+"' is invalid."); |
---|
| 171 | } |
---|
| 172 | } |
---|