272 lines
7.2 KiB
JavaScript
272 lines
7.2 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),
|
|
multer = require('multer'),
|
|
upload = multer({ dest: './uploads' }),
|
|
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'),
|
|
scheduler = require('./helpers/scheduler'),
|
|
fs_helper = require('./helpers/fs_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 = {};
|
|
|
|
//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', upload.single('obj'), 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),
|
|
cwd = req.query.cwd;
|
|
|
|
var term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
|
|
name: 'xterm-color',
|
|
cols: cols || 80,
|
|
rows: rows || 24,
|
|
cwd: path.resolve(cwd),
|
|
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) {
|
|
try {
|
|
msg = JSON.parse(msg);
|
|
} catch (e) {
|
|
//not json, just a string...
|
|
}
|
|
|
|
if (msg.type === 'input') {
|
|
term.write(msg.data.toString() + '\r');
|
|
} else {
|
|
term.write(msg.toString());
|
|
}
|
|
});
|
|
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 if (process.env.PORT) {
|
|
port = process.env.PORT
|
|
} else {
|
|
port = config.editor.port;
|
|
}
|
|
|
|
|
|
|
|
winston.info('listening on port ' + port);
|
|
cb(app.listen(port));
|
|
});
|
|
}
|
|
|
|
function mount_dav(server) {
|
|
var jsDAV_FS_Tree = require("jsDAV/lib/DAV/backends/fs/tree");
|
|
//jsDAV.debugMode = true;
|
|
davServer = jsDAV.mount({
|
|
path: REPOSITORY_PATH,
|
|
mount: '/filesystem',
|
|
plugins: ["codesearch", "tree", "filelist", "filesearch", "locks", "mount", "temporaryfilefilter"],
|
|
server: server,
|
|
standalone: false,
|
|
tree: jsDAV_FS_Tree.new(REPOSITORY_PATH)
|
|
});
|
|
winston.info('webdav filesystem mounted');
|
|
}
|
|
|
|
function cleanup() {
|
|
winston.info("process and worker cleanup");
|
|
Object.keys(terminals).forEach(function (pid) {
|
|
var term = terminals[pid];
|
|
console.log('Closed terminal ' + term.pid);
|
|
term.kill();
|
|
});
|
|
|
|
debug_helper.kill_debug(false, function() {
|
|
//no need to wait for this
|
|
});
|
|
}
|
|
|
|
process.on('SIGINT', function() {
|
|
winston.info("Shutting down from SIGINT");
|
|
cleanup();
|
|
process.exit();
|
|
});
|
|
|
|
process.on('uncaughtException', function(err) {
|
|
winston.error("Shutting down from uncaughtException");
|
|
winston.error(err.stack);
|
|
cleanup();
|
|
process.exit();
|
|
});
|