Adafruit-WebIDE/editor/server.js
2012-09-15 10:14:34 -05:00

302 lines
10 KiB
JavaScript

var express = require('express'),
tty = require('tty.js'),
app = express(),
util = require('util'),
io = require('socket.io'),
passport = require('passport'),
util = require('util'),
BitbucketStrategy = require('passport-bitbucket').Strategy,
site = require('./controllers/site'),
editor = require('./controllers/editor'),
user = require('./controllers/user'),
jsDAV = require("jsDAV/lib/jsdav"),
fs = require('fs'),
path = require('path'),
updater = require('./helpers/updater'),
git_helper = require('./helpers/git_helper'),
fs_helper = require('./helpers/fs_helper'),
request_helper = require('./helpers/request_helper'),
exec_helper = require('./helpers/exec_helper'),
RedisStore = require('connect-redis')(express),
redis = require("redis"),
client = redis.createClient(),
config = require('./config/config');
var davServer;
var REPOSITORY_PATH = path.resolve(__dirname + "/../repositories");
console.log(__dirname);
console.log("REPOSITORY_PATH", REPOSITORY_PATH);
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing. However, since this example does not
// have a database of user records, the complete Bitbucket profile is
// serialized and deserialized.
// Use the BitbucketStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a token, tokenSecret, and Bitbucket profile),
// and invoke a callback with a user object.
function setup_passport(consumer_key, consumer_secret) {
passport.serializeUser(function(user, done) {
//console.log("serializeUser");
//console.log(user);
client.set(user.username, JSON.stringify(user));
done(null, user.username);
});
passport.deserializeUser(function(obj, done) {
//console.log("deserializeUser");
//console.log(obj);
client.get(obj, function(err, reply) {
//console.log(JSON.parse(reply));
done(null, JSON.parse(reply));
});
});
passport.use(new BitbucketStrategy({
consumerKey: consumer_key,
consumerSecret: consumer_secret,
callbackURL: "http://raspberrypi.local:3000/auth/bitbucket/callback"
//callbackURL: "http://76.17.224.82:3000/auth/bitbucket/callback"
//callbackURL: "http://127.0.0.1:3000/auth/bitbucket/callback"
},
function(token, tokenSecret, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
profile.token = token;
profile.token_secret = tokenSecret;
profile.consumer_key = consumer_key;
profile.consumer_secret = consumer_secret;
var project_repository = 'git@bitbucket.org:' + profile.username + '/my-pi-projects.git';
//TODO REFACTOR THIS MESS - it shouldn't even be here...
git_helper.set_config(function() {
request_helper.list_repositories(profile, function(err, list) {
var exists = list.some(function(repository) {
return (repository.name.toLowerCase() === config.defaults.repository.toLowerCase());
});
git_helper.clone_adafruit_libraries(config.adafruit.repository, config.adafruit.remote, function() {
if (!exists) {
request_helper.create_repository(profile, config.defaults.repository, function(err, response) {
git_helper.clone_repository(profile, project_repository, function(err, response) {
console.log("created personal repository in bitbucket");
fs_helper.create_project_readme(function(err, file) {
if (err) console.log(err);
console.log(file);
git_helper.commit_push_and_save(file, function(err, response) {
return done(null, profile);
});
});
});
});
} else {
git_helper.clone_repository(profile, project_repository, function(err, response) {
console.log(err, response);
fs_helper.create_project_readme(function(err, file) {
console.log(file);
if (err) console.log(err);
git_helper.commit_push_and_save(file, function(err, response) {
return done(null, profile);
});
});
});
}
});
});
});
});
}
));
}
//need to setup passport on server startup, if the bitbucket oauth is already setup
client.hgetall('bitbucket_oauth', function (err, bitbucket) {
if (bitbucket) {
setup_passport(bitbucket.consumer_key, bitbucket.consumer_secret);
}
});
//redirect anything with /filesystem in the url to the WebDav server.
app.use(function(req, res, next) {
if (req.path.indexOf("/filesystem") != -1) {
davServer.exec(req, res);
} else {
next();
}
});
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.use(express.logger());
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/node_modules/tty.js/static'));
app.use(express.cookieParser());
app.use(express.session({
store: new RedisStore(),
key: 'sid',
secret: 'cat nap'
}));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.get('/', ensureAuthenticated, site.index);
//app.get('/editor/filesystem', editor.filesystem);
//app.get('/editor/file', editor.file);
app.get('/editor', ensureAuthenticated, editor.index);
app.post('/create/repository', ensureAuthenticated, editor.create_repository);
app.get('/setup', user.setup);
app.post('/setup', user.submit_setup);
app.get('/login', ensureOauth, user.login);
app.get('/logout', user.logout);
// GET /auth/bitbucket
// Use passport.authenticate() as route middleware to authenticate the
// request. The first step in Bitbucket authentication will involve redirecting
// the user to bitbucket.org. After authorization, Bitbucket will redirect the user
// back to this application at /auth/bitbucket/callback
app.get('/auth/bitbucket',
passport.authenticate('bitbucket'),
function(req, res){
// The request will be redirected to Bitbucket for authentication, so this
// function will not be called.
});
// GET /auth/bitbucket/callback
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be calsled,
// which, in this example, will redirect the user to the home page.
app.get('/auth/bitbucket/callback',
passport.authenticate('bitbucket', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/editor');
});
serverInitialization(app);
// Simple route middleware to ensure user is authenticated.
// Use this route middleware on any resource that needs to be protected. If
// the request is authenticated (typically via a persistent login session),
// the request will proceed. Otherwise, the user will be redirected to the
// login page.
function ensureAuthenticated(req, res, next) {
console.log(req.session);
console.log(req.isAuthenticated());
if (req.isAuthenticated()) {
return next();
}
client.hgetall('bitbucket_oauth', function (err, bitbucket) {
if (!bitbucket) {
res.redirect('/setup');
} else {
res.redirect('/login');
}
});
}
function ensureOauth(req, res, next) {
client.hgetall('bitbucket_oauth', function (err, bitbucket) {
if (!bitbucket) {
res.redirect('/setup');
} else {
setup_passport(bitbucket.consumer_key, bitbucket.consumer_secret);
return next();
}
});
}
function serverInitialization(app) {
var exists = path.existsSync(REPOSITORY_PATH);
if (!exists) {
fs.mkdirSync(REPOSITORY_PATH, 0777);
console.log('created repositories folder');
}
var server = start_server();
socket_listeners();
mount_dav(server);
}
function start_server() {
console.log('listening on port 3000');
server = require('http').createServer(app);
io = io.listen(server);
new tty.Server(config.term, app, server, io);
return server.listen(3000);
}
function socket_listeners() {
io.sockets.on('connection', function (socket) {
socket.emit('cwd-init', {dirname: __dirname + '/../repositories'});
socket.on('git-delete', function(data) {
git_helper.remove_commit_push(data.file, function(err, status) {
socket.emit('git-delete-complete', {message: ""});
});
});
socket.on('commit-file', function (data) {
//TODO...clean this up, and check for errors
//console.log(data.file.path);
//console.log(repository);
git_helper.commit_push_and_save(data.file, function(err, status) {
socket.emit('commit-file-complete', {message: "Save was successful"});
});
});
socket.on('run-file', function(data) {
exec_helper.execute_program(data.file, socket);
//git_helper.commit_push_and_save(data.file, function(err, status) {
// socket.emit('commit-file-complete', {message: "Save was successful"});
//});
});
socket.on('editor-check-updates', function() {
updater.check_for_updates(socket);
});
socket.on('editor-update', function() {
updater.update(socket);
});
});
}
function mount_dav(server) {
var jsDAV_Tree_Filesystem = require("jsDAV/lib/DAV/tree/filesystem").jsDAV_Tree_Filesystem;
//jsDAV.debugMode = true;
davServer = jsDAV.mount({
path: REPOSITORY_PATH,
mount: '/filesystem',
plugins: ["codesearch", "tree", "filelist", "filesearch", "locks", "mount", "temporaryfilefilter"],
server: server,
standalone: false,
tree: new jsDAV_Tree_Filesystem(REPOSITORY_PATH)
});
console.log('webdav filesystem mounted');
}