source: Dev/trunk/src/server/app.js @ 532

Last change on this file since 532 was 525, checked in by hendrikvanantwerpen, 11 years ago
  • Allow empty subcodes.
  • Use HTTPResult exclusively on server (no more q).
  • Set readonly & disabled on ourselves as well in _ComplexValueMixin
  • Split server into several modules.
  • Check codes on the variable level, not question level.
  • We can add modules in design documents now.
File size: 5.0 KB
RevLine 
[475]1var 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]12exports.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]38function 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
156
[463]157    return app;
[481]158}
[475]159
[519]160function assertSetting(name, settings, validate) {
161    if ( typeof settings[name] === 'undefined' ) {
162        throw new Error("Required setting '"+name+"' undefined.");
163    }
164    if ( _.isFunction(validate) && !validate(settings[name]) ) {
165        throw new Error("Setting '"+name+"' with value '"+settings[name]+"' is invalid.");
166    }
167}
Note: See TracBrowser for help on using the repository browser.