Showing with 320 additions and 476 deletions.
  1. +32 −26 app.js
  2. +11 −12 mdb.js
  3. +37 −9 routes/api.js
  4. +237 −426 routes/course.js
  5. +3 −3 views/activity.jade
58 app.js
@@ -212,6 +212,8 @@ function addDatabaseMiddleware(req, res, next) {

app.put( '/repos/:owner/:repo/git/commits/:sha', api.verifyCollaborator );
app.put( '/repos/:owner/:repo/git/commits/:sha', api.putCommit );

app.put( '/commits/:sha', api.putBareCommit );

//app.put( '/activity/:commit/:path(*.tex)', api.authenticateViaHMAC);
//app.put( '/activity/:commit/:path(*.tex)', api.putTex );
@@ -263,34 +265,35 @@ function addDatabaseMiddleware(req, res, next) {
app.get( '/course/multivariable/', function( req, res ) { res.redirect('/about/m2o2c2'); });
app.get( '/course/multivariable', function( req, res ) { res.redirect('/about/m2o2c2'); });

app.get('/course/', course.index );
//app.get('/course/', course.index );
app.get( '/course', function( req, res ) { res.redirect(req.url + '/'); });
app.get( '/courses', function( req, res ) { res.redirect('/course/'); });
app.get( '/courses/', function( req, res ) { res.redirect('/course/'); });

app.get( '/course/:username/:repository/', course.tableOfContents );
app.get( '/course/:username/:repository$', function( req, res ) { res.redirect(req.url + '/'); });
app.get( '/course/:username/:repository/:branch/', course.tableOfContents );
app.get( '/course/:username/:repository/:branch$', function( req, res ) { res.redirect(req.url + '/'); });

app.get( '/course/:username/:repository/:branch/:path(*.tex)', course.source );
app.get( '/course/:username/:repository/:branch/:path(*.png)', course.image );
app.get( '/course/:username/:repository/:branch/:path(*.jpg)', course.image );
app.get( '/course/:username/:repository/:branch/:path(*.pdf)', course.image );
app.get( '/course/:username/:repository/:branch/:path(*.svg)', course.image );
app.get( '/course/:username/:repository/:branch/:path(*)', course.activity );

app.get( '/activity/:commit/:path(*.css)', course.stylesheet );
app.get( '/activity/:commit/:path(*.js)', course.javascript );

app.get( '/activity/:commit/:path(*.tex)', course.source );
app.get( '/course/:commit([0-9a-fA-F]+)$', function( req, res ) { res.redirect(req.url + '/'); });

app.get( '/activity/:commit/:path(*.png)', course.image );
app.get( '/activity/:commit/:path(*.jpg)', course.image );
app.get( '/activity/:commit/:path(*.pdf)', course.image );
app.get( '/activity/:commit/:path(*.svg)', course.image );
app.get( '/activity/:commit/:path(*)', course.activityByHash );

app.get( '/course/:commit([0-9a-fA-F]+)/', course.xourseFromCommit, course.tableOfContents );
app.get( '/course/:username/:repository/', course.xourseFromUserAndRepo, course.tableOfContents );
app.get( '/course/:username/:repository/:branch/', course.xourseFromUserAndRepo, course.tableOfContents );

var appXimera = function( regexp, callback ) {
app.get( '/:noun(course|activity)/:commit([0-9a-fA-F]+)/:path(' + regexp + ')', course.objectFromCommit, callback );
app.get( '/:noun(course|activity)/:username/:repository/:path(' + regexp + ')', course.objectFromUserAndRepo, callback );
app.get( '/:noun(course|activity)/:username/:repository/:branch/:path(' + regexp + ')', course.objectFromUserAndRepo, callback );
};

appXimera( '*.tex', course.source );

// SVG files will only be rendered if they are sent with content type image/svg+xml
appXimera( '*.svg', course.file('image/svg+xml') );
appXimera( '*.png', course.file('image/png') );
appXimera( '*.pdf', course.file('image/pdf') );
appXimera( '*.jpg', course.file('image/jpeg') );
appXimera( '*.js', course.file('text/javascript') );
appXimera( '*.css', course.file('text/css') );

appXimera( '*', course.activity );

app.get( '/statistics/:commit/:hash/answers', course.answers );
app.get( '/statistics/:commit/:hash/successes', course.successes );

@@ -444,9 +447,12 @@ function addDatabaseMiddleware(req, res, next) {
app.delete('/forum/:post', forum.delete);
*/

server.listen(app.get('port'), function(stream){
console.log('Express server listening on port ' + app.get('port'));
});
if(!module.parent){
server.listen(app.get('port'), function(stream){
console.log('Express server listening on port ' + app.get('port'));
});
}


io.on('connection', function (socket) {
// join to room and save the room name
23 mdb.js
@@ -59,18 +59,17 @@ exports.initialize = function initialize(callback) {
});

exports.Commit = mongoose.model("Commit",
{
owner: {type: String, index: true},
repository: {type: String, index: true},
sha: {type: String, index: true},
author: Mixed,
url: String,
committer: Mixed,
message: String,
tree: Mixed,
parents: Mixed,
});

{
owner: {type: String, index: true},
repository: {type: String, index: true},
sha: {type: String, index: true},
author: Mixed,
url: String,
committer: Mixed,
message: String,
tree: Mixed,
parents: Mixed,
});

// These records are designed to conform to the TinCan API 1.0.0
exports.LearningRecord = mongoose.model("LearningRecord",
@@ -117,24 +117,24 @@ exports.putFile = function(req, res){
var path = req.params.path;

if (!(req.user.isAuthor)) {
res.status(500).send('You must be an instructor to PUT files.');
res.status(500).send('You must be an author to PUT files.');
return;
}

saveToContentAddressableFilesystem( req.rawBody, function(err, hash) {
var gitFile = {};
;

gitFile.commit = commit;
gitFile.path = path;
gitFile.hash = hash;

mdb.GitFile.findOneAndUpdate({commit: gitFile.commit, hash: gitFile.hash, path: gitFile.path},
gitFile, {upsert:true}, function(err, doc){
if (err)
res.status(500).send();
else
res.status(200).send();
});
gitFile, {upsert:true}, function(err, doc){
if (err)
res.status(500).send();
else
res.status(200).send();
});
});
};

@@ -226,6 +226,7 @@ exports.putCommit = function(req, res){
var commitData = data[0];

var commit = {};

commit.owner = owner;
commit.repository = repo;
commit.sha = sha;
@@ -245,6 +246,32 @@ exports.putCommit = function(req, res){
});
};

exports.putBareCommit = function(req, res){
if (!(req.user.isAuthor)) {
res.status(500).send('You must have permission to PUT commits.');
return;
}

var sha = req.params.sha;
var head = JSON.parse(req.rawBody);

var commit = {};

commit.owner = undefined;
commit.repository = undefined;
commit.sha = sha;
commit.author = head.author;
commit.committer = head.committer;
commit.message = head.message;
commit.parents = head.parents;

mdb.Commit.findOneAndUpdate({sha: commit.sha},
commit, {upsert:true},
function(err, doc){
res.status(200).send();
});
}

function findRelatedCommits( commit, callback ) {
mdb.Branch.findOne( { commit: commit }, function( err, branch ) {
if (err)
@@ -258,7 +285,8 @@ function findRelatedCommits( commit, callback ) {
callback(err, branches.map( function(branch) { return branch.commit; } ) );
});
} else {
callback("Missing branch");
// This could have been callback("Missing branch"); but instead I'm just going to fake it
callback(err, [ commit ] );
}
}
});