Index: Dev/trunk/src/server/app.js
===================================================================
--- Dev/trunk/src/server/app.js	(revision 478)
+++ Dev/trunk/src/server/app.js	(revision 481)
@@ -8,4 +8,5 @@
   , CouchDB = require('./util/couch').CouchDB
   , _ = require("underscore")
+  , tv4 = require("tv4")
   ;
 
@@ -24,4 +25,17 @@
     var couch = new CouchDB(settings.couchDbURL);
     
+    var schema = require("./config/couchdb-schema.json");
+    return couch.get("schemaInfo").then(function(schemaInfo){
+        if (schemaInfo.version !== schema.version) {
+            var msg =  "Database has version "+schemaInfo.version+" but we expect version "+schema.version;
+            throw new Error(msg);
+        }
+        return configureApp(settings,couch,schema);
+    });
+
+};
+
+function configureApp(settings,couch,schema) {
+
     function clientPath(relativePath) {
         return path.resolve(__dirname+'/../client/'+relativePath);
@@ -77,8 +91,4 @@
     });
 
-    // data is proxied to couch
-    app.use('/data', ensureAuthenticated);
-    app.use('/data', proxy(settings.couchDbURL));
-
     // post to this url to login
     app.post(
@@ -102,55 +112,46 @@
         });
 
-    app.get(
-        '/api/surveyRuns/:id',
-        function(req,res){
+    function makeDocsGet(type) {
+        return function(req,res) {
+            var url = '_design/default/_view/by_type?key='+JSON.stringify(type);
+            couch.get(url).then(function(result){
+                var items = _.map(result.rows, function(item) { return item.value; });
+                res.send(200, items);
+            }, function(error){
+                res.send(404, {error: "Cannot find collection"});
+            });
+        };
+    }
+    function makeDocGet_id(type) {
+        return function(req,res) {
             var id = req.params.id;
             couch.get(id).then(function(result){
-                if ( result.type === 'SurveyRun') {
+                if ( result.type === type ) {
                     res.send(200, result);
                 } else {
-                    res.send(404, {error: "Cannot find survey run "+id});
+                    res.send(404, {error: "Document "+id+" is not a "+type});
                 }
             }, function(error){
                 res.send(404, {error: "Cannot find survey run "+id});
             });
-        });
-    app.get(
-        '/api/responses/:id',
-        function(req,res){
-            var id = req.params.id;
-            couch.get(id).then(function(result){
-                if ( result.type === 'Response') {
+        };
+    }
+    function makeDocPut_id(type) {
+        return function(req,res) {
+            var id = req.params.id;
+            var doc = req.body;
+            if ( doc.type === type && tv4.validateResult(doc, schema) ) {
+                couch.put(id,doc).then(function(result){
                     res.send(200, result);
-                } else {
-                    res.send(404, {error: "Cannot find response "+id});
-                }
-            }, function(error){
-                res.send(404, {error: "Cannot find response "+id});
-            });
-        });
-    app.post(
-        '/api/responses',
-        function(req,res){
-            console.log(req.body);
-            couch.post(req.body).then(function(result){
-                res.send(200, result);
-            }, function(error){
-                res.send(500, error);
-            });
-        });
-    app.put(
-        '/api/responses/:id',
-        function(req,res){
-            var id = req.params.id;
-            couch.put(id,req.body).then(function(result){
-                res.send(200, result);
-            }, function(error){
-                res.send(500, error);
-            });
-        });
-    app.delete(
-        '/api/responses/:id',
-        function(req,res){
+                }, function(error){
+                    res.send(500, error);
+                });
+            } else {
+                res.send(400,{error: "Document failed schema verification."});
+            }
+        };
+    }
+    function makeDocDel_id(type) {
+        return function(req,res) {
             var id = req.params.id;
             var rev = req.query.rev;
@@ -160,9 +161,69 @@
                 res.send(500, error);
             });
-        });
-    
-    // generate CSV download of responses
-    app.get(
-        '/api/surveyRuns/:id/responses.csv',
+        };
+    }
+    function makeDocPost(type) {
+        return function(req,res) {
+            var doc = req.body;
+            if ( doc.type === type && tv4.validateResult(doc, schema) ) {
+                couch.post(req.body).then(function(result){
+                    res.send(200, result);
+                }, function(error){
+                    res.send(500, error);
+                });
+            } else {
+                res.send(400,{error: "Document failed schema verification."});
+            }
+        };
+    }
+    function notImplemented(req,res) {
+        res.send(501,{error:"API not implemented yet."});
+    }
+
+    // Questions
+    app.get('/api/questions',
+        ensureAuthenticated,
+        makeDocsGet('Question'));
+    app.get('/api/questions/:id',
+        ensureAuthenticated,
+        makeDocGet_id('Question'));
+    app.post('/api/questions',
+        ensureAuthenticated,
+        makeDocPost('Question'));
+    app.put('/api/questions/:id',
+        ensureAuthenticated,
+        makeDocPut_id('Question'));
+    app.delete('/api/questions/:id',
+        ensureAuthenticated,
+        makeDocDel_id('Question'));
+    app.get('/api/questions/categories',
+        ensureAuthenticated,
+        notImplemented);
+
+    // Surveys
+    app.get('/api/surveys',
+        ensureAuthenticated,
+        makeDocsGet('Survey'));
+    app.get('/api/surveys/:id',
+        ensureAuthenticated,
+        makeDocGet_id('Survey'));
+    app.post('/api/surveys',
+        ensureAuthenticated,
+        makeDocPost('Survey'));
+    app.put('/api/surveys/:id',
+        ensureAuthenticated,
+        makeDocPut_id('Survey'));
+    app.delete('/api/surveys/:id',
+        ensureAuthenticated,
+        makeDocDel_id('Survey'));
+
+    // SurveyRuns
+    app.get('/api/surveyRuns',
+        ensureAuthenticated,
+        makeDocsGet('SurveyRun'));
+    app.get('/api/surveyRuns/:id',
+        ensureAuthenticated,
+        makeDocGet_id('SurveyRun'));
+    app.get('/api/surveyRuns/:id/responses.csv',
         ensureAuthenticated,
         function(req, res) {
@@ -183,8 +244,37 @@
             });
         });
+    app.get('/api/surveyRuns/:id/responses',
+        ensureAuthenticated,
+        function(req,res) {
+            var id = req.params.id;
+            var url = '_design/responses/_view/by_surveyrun?key='+JSON.stringify(id);
+            couch.get(url).then(function(result){
+                var responses = _.map(result.rows, function(item) { return item.value; });
+                res.send(200, responses);
+            }, function(error){
+                res.send(404, {error: "Cannot find responses for survey run "+id});
+            });
+        });
     
+    // Responses
+    app.get('/api/responses',
+        ensureAuthenticated,
+        makeDocsGet('Response'));
+    app.get('/api/responses/:id',
+        ensureAuthenticated,
+        makeDocGet_id('Response'));
+    app.post('/api/responses',
+        ensureAuthenticated,
+        makeDocPost('Response'));
+    app.put('/api/responses/:id',
+        ensureAuthenticated,
+        makeDocPut_id('Response'));
+    app.delete('/api/responses/:id',
+        ensureAuthenticated,
+        makeDocDel_id('Response'));
+
     return app;
 
-};
+}
 
 function responsesToVariables(responses) {
