Adafruit-WebIDE/server.js
2018-02-02 15:06:34 -06:00

253 lines
7 KiB
JavaScript

var express = require('express'),
session = require('express-session'),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
cookieParser = require('cookie-parser'),
serveStatic = require('serve-static'),
morgan = require('morgan'),
app = express(),
expressWs = require('express-ws')(app),
util = require('util'),
util = require('util'),
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'),
scheduler = require('./helpers/scheduler'),
exec_helper = require('./helpers/exec_helper'),
fs_helper = require('./helpers/fs_helper'),
exec_helper = require('./helpers/exec_helper'),
request_helper = require('./helpers/request_helper'),
debug_helper = require('./helpers/python/debug_helper'),
config = require('./config/config'),
winston = require('winston'),
db = require('./models/webideModel'),
pty = require('node-pty');
var davServer,
HOSTNAME,
REPOSITORY_PATH = path.resolve(__dirname + "/repositories");
var terminals = {}, logs = {};
//exec_helper.spawn_ipython();
//check for the existence of the logs directory, if it doesn't
//exist, create it prior to starting the child process.
var exists = fs.existsSync(__dirname + '/logs');
if (!exists) {
fs.mkdirSync(__dirname + '/logs', 0755);
winston.info('created logs folder');
}
//winston.add(winston.transports.File, { filename: __dirname + '/logs/output.log', json: false });
//winston.handleExceptions(new winston.transports.File({ filename: __dirname + '/logs/errors.log', json: false }));
//winston.remove(winston.transports.Console);
winston.info("REPOSITORY_PATH", REPOSITORY_PATH);
//redirect anything with /filesystem in the url to the WebDav server.
app.use(function(req, res, next) {
//res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
if (req.path.indexOf("/filesystem") != -1) {
davServer.exec(req, res);
} else {
next();
}
});
app.set('view engine', 'pug');
app.set('views', __dirname + '/views');
//logging
app.use(morgan('tiny'));
app.use(serveStatic(__dirname + '/public'));
app.use(serveStatic(__dirname + '/node_modules/xterm/dist'));
app.use(cookieParser());
var sessionMiddleware = session({
key: 'sid',
secret: 'cat nap',
resave: true,
saveUninitialized: true
});
app.use(sessionMiddleware);
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(methodOverride());
app.use(function(req, res, next) {
res.locals.session = req.session;
next();
});
app.get('/', site.index);
app.get('/editor', editor.index);
app.get('/editor/image', editor.image);
app.post('/editor/upload', editor.upload_file);
app.post('/create/repository', editor.create_repository);
app.get('/setup', user.setup);
app.post('/setup', user.submit_setup);
app.get('/config', user.config);
app.post('/config', user.submit_config);
app.get('/set-datetime', user.set_datetime);
app.post('/terminals', function (req, res) {
var cols = parseInt(req.query.cols),
rows = parseInt(req.query.rows),
term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
name: 'xterm-color',
cols: cols || 80,
rows: rows || 24,
cwd: process.env.PWD,
env: process.env
});
console.log('Created terminal with PID: ' + term.pid);
terminals[term.pid] = term;
logs[term.pid] = '';
term.on('data', function(data) {
logs[term.pid] += data;
});
res.send(term.pid.toString());
res.end();
});
app.post('/terminals/:pid/size', function (req, res) {
var pid = parseInt(req.params.pid),
cols = parseInt(req.query.cols),
rows = parseInt(req.query.rows),
term = terminals[pid];
term.resize(cols, rows);
console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.');
res.end();
});
app.ws('/terminals/:pid', function (ws, req) {
var term = terminals[parseInt(req.params.pid)];
console.log('Connected to terminal ' + term.pid);
ws.send(logs[term.pid]);
term.on('data', function(data) {
try {
ws.send(data);
} catch (ex) {
// The WebSocket is not open, ignore
}
});
ws.on('message', function(msg) {
term.write(msg);
});
ws.on('close', function () {
term.kill();
console.log('Closed terminal ' + term.pid);
// Clean things up
delete terminals[term.pid];
delete logs[term.pid];
});
});
app.ws('/editor', editor.editor);
app.use(errorHandler);
serverInitialization(app);
function errorHandler(err, req, res, next) {
winston.error(err);
if (err.name === "InternalOAuthError") {
res.status(500);
res.render('oauth_error', { error: err });
} else {
res.status(500);
res.render('error', { error: err });
}
}
function setHostName(req) {
//set it each time, it's quick, and hostname may change (internal IP vs external IP).
HOSTNAME = req.headers.host;
}
function serverInitialization(app) {
//setup repositories path
var exists = fs.existsSync(REPOSITORY_PATH);
if (!exists) {
fs.mkdirSync(REPOSITORY_PATH, 0777);
winston.info('created repositories folder');
}
//setup symlink to webide home, if it exists:
var has_webide_path = fs.existsSync("/home/webide");
if (has_webide_path) {
//Creating symbolic link to repositories path
winston.info('Linked repository paths: /home/webide/repositories');
if (!fs.existsSync("/home/webide/repositories")) {
fs.symlinkSync(REPOSITORY_PATH, "/home/webide/repositories", 'dir');
}
}
scheduler.initialize_jobs();
start_server(function(server) {
mount_dav(server);
});
}
function start_server(cb) {
db.find('server', function (err, server_data) {
var port;
if (server_data && server_data.port) {
port = server_data.port;
} else {
port = config.editor.port;
}
winston.info('listening on port ' + port);
cb(app.listen(port));
});
}
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)
});
winston.info('webdav filesystem mounted');
}
exports.get_socket = function (username, cb) {
for (var socketId in io.sockets.sockets) {
io.sockets.sockets[socketId].get('username', function(err, sock_username) {
if (username === sock_username) {
cb(io.sockets.sockets[socketId]);
}
});
}
};
process.on('SIGINT', function() {
winston.info("\nShutting down from SIGINT");
// some other closing procedures go here
debug_helper.kill_debug(false, function() {
//no need to wait for this
});
process.exit();
});