summaryrefslogtreecommitdiff
path: root/src/node/hooks/express
diff options
context:
space:
mode:
Diffstat (limited to 'src/node/hooks/express')
-rw-r--r--src/node/hooks/express/adminplugins.js77
-rw-r--r--src/node/hooks/express/apicalls.js12
-rw-r--r--src/node/hooks/express/errorhandling.js7
-rw-r--r--src/node/hooks/express/importexport.js2
-rw-r--r--src/node/hooks/express/padreadonly.js56
-rw-r--r--src/node/hooks/express/padurlsanitize.js22
-rw-r--r--src/node/hooks/express/specialpages.js32
-rw-r--r--src/node/hooks/express/swagger.js5
-rw-r--r--src/node/hooks/express/webaccess.js20
9 files changed, 153 insertions, 80 deletions
diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js
index 7e221cf1..d8f19bba 100644
--- a/src/node/hooks/express/adminplugins.js
+++ b/src/node/hooks/express/adminplugins.js
@@ -27,49 +27,84 @@ exports.socketio = function (hook_name, args, cb) {
io.on('connection', function (socket) {
if (!socket.handshake.session.user || !socket.handshake.session.user.is_admin) return;
- socket.on("load", function (query) {
+ socket.on("getInstalled", function (query) {
// send currently installed plugins
- socket.emit("installed-results", {results: plugins.plugins});
- socket.emit("progress", {progress:1});
+ var installed = Object.keys(plugins.plugins).map(function(plugin) {
+ return plugins.plugins[plugin].package
+ })
+ socket.emit("results:installed", {installed: installed});
});
socket.on("checkUpdates", function() {
- socket.emit("progress", {progress:0, message:'Checking for plugin updates...'});
// Check plugins for updates
- installer.search({offset: 0, pattern: '', limit: 500}, /*useCache:*/true, function(data) { // hacky
- if (!data.results) return;
+ installer.getAvailablePlugins(/*maxCacheAge:*/60*10, function(er, results) {
+ if(er) {
+ console.warn(er);
+ socket.emit("results:updatable", {updatable: {}});
+ return;
+ }
var updatable = _(plugins.plugins).keys().filter(function(plugin) {
- if(!data.results[plugin]) return false;
- var latestVersion = data.results[plugin]['dist-tags'].latest
+ if(!results[plugin]) return false;
+ var latestVersion = results[plugin].version
var currentVersion = plugins.plugins[plugin].package.version
return semver.gt(latestVersion, currentVersion)
});
- socket.emit("updatable", {updatable: updatable});
- socket.emit("progress", {progress:1});
+ socket.emit("results:updatable", {updatable: updatable});
});
})
+
+ socket.on("getAvailable", function (query) {
+ installer.getAvailablePlugins(/*maxCacheAge:*/false, function (er, results) {
+ if(er) {
+ console.error(er)
+ results = {}
+ }
+ socket.emit("results:available", results);
+ });
+ });
socket.on("search", function (query) {
- socket.emit("progress", {progress:0, message:'Fetching results...'});
- installer.search(query, true, function (progress) {
- if (progress.results)
- socket.emit("search-result", progress);
- socket.emit("progress", progress);
+ installer.search(query.searchTerm, /*maxCacheAge:*/60*10, function (er, results) {
+ if(er) {
+ console.error(er)
+ results = {}
+ }
+ var res = Object.keys(results)
+ .map(function(pluginName) {
+ return results[pluginName]
+ })
+ .filter(function(plugin) {
+ return !plugins.plugins[plugin.name]
+ });
+ res = sortPluginList(res, query.sortBy, query.sortDir)
+ .slice(query.offset, query.offset+query.limit);
+ socket.emit("results:search", {results: res, query: query});
});
});
socket.on("install", function (plugin_name) {
- socket.emit("progress", {progress:0, message:'Downloading and installing ' + plugin_name + "..."});
- installer.install(plugin_name, function (progress) {
- socket.emit("progress", progress);
+ installer.install(plugin_name, function (er) {
+ if(er) console.warn(er)
+ socket.emit("finished:install", {plugin: plugin_name, error: er? er.message : null});
});
});
socket.on("uninstall", function (plugin_name) {
- socket.emit("progress", {progress:0, message:'Uninstalling ' + plugin_name + "..."});
- installer.uninstall(plugin_name, function (progress) {
- socket.emit("progress", progress);
+ installer.uninstall(plugin_name, function (er) {
+ if(er) console.warn(er)
+ socket.emit("finished:uninstall", {plugin: plugin_name, error: er? er.message : null});
});
});
});
}
+
+function sortPluginList(plugins, property, /*ASC?*/dir) {
+ return plugins.sort(function(a, b) {
+ if (a[property] < b[property])
+ return dir? -1 : 1;
+ if (a[property] > b[property])
+ return dir? 1 : -1;
+ // a must be equal to b
+ return 0;
+ })
+} \ No newline at end of file
diff --git a/src/node/hooks/express/apicalls.js b/src/node/hooks/express/apicalls.js
index 0971a877..db0fc81f 100644
--- a/src/node/hooks/express/apicalls.js
+++ b/src/node/hooks/express/apicalls.js
@@ -1,5 +1,6 @@
var log4js = require('log4js');
var apiLogger = log4js.getLogger("API");
+var clientLogger = log4js.getLogger("client");
var formidable = require('formidable');
var apiHandler = require('../../handler/APIHandler');
@@ -42,10 +43,10 @@ exports.expressCreateServer = function (hook_name, args, cb) {
});
});
- //The Etherpad client side sends information about how a disconnect happen
+ //The Etherpad client side sends information about how a disconnect happened
args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) {
new formidable.IncomingForm().parse(req, function(err, fields, files) {
- console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
+ clientLogger.info("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
res.end("OK");
});
});
@@ -53,7 +54,12 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//The Etherpad client side sends information about client side javscript errors
args.app.post('/jserror', function(req, res) {
new formidable.IncomingForm().parse(req, function(err, fields, files) {
- console.error("CLIENT SIDE JAVASCRIPT ERROR: " + fields.errorInfo);
+ try {
+ var data = JSON.parse(fields.errorInfo)
+ }catch(e){
+ return res.end()
+ }
+ clientLogger.warn(data.msg+' --', data);
res.end("OK");
});
});
diff --git a/src/node/hooks/express/errorhandling.js b/src/node/hooks/express/errorhandling.js
index 3c595683..087dd50e 100644
--- a/src/node/hooks/express/errorhandling.js
+++ b/src/node/hooks/express/errorhandling.js
@@ -1,5 +1,6 @@
var os = require("os");
var db = require('../../db/DB');
+var stats = require('ep_etherpad-lite/node/stats')
exports.onShutdown = false;
@@ -28,6 +29,7 @@ exports.gracefulShutdown = function(err) {
}, 3000);
}
+process.on('uncaughtException', exports.gracefulShutdown);
exports.expressCreateServer = function (hook_name, args, cb) {
exports.app = args.app;
@@ -39,6 +41,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
// allowing you to respond however you like
res.send(500, { error: 'Sorry, something bad happened!' });
console.error(err.stack? err.stack : err.toString());
+ stats.meter('http500').mark()
})
//connect graceful shutdown with sigint and uncaughtexception
@@ -47,6 +50,4 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//https://github.com/joyent/node/issues/1553
process.on('SIGINT', exports.gracefulShutdown);
}
-
- process.on('uncaughtException', exports.gracefulShutdown);
-}
+} \ No newline at end of file
diff --git a/src/node/hooks/express/importexport.js b/src/node/hooks/express/importexport.js
index 9754ffa6..f5a3e5a1 100644
--- a/src/node/hooks/express/importexport.js
+++ b/src/node/hooks/express/importexport.js
@@ -15,7 +15,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//if abiword is disabled, and this is a format we only support with abiword, output a message
if (settings.abiword == null &&
["odt", "pdf", "doc"].indexOf(req.params.type) !== -1) {
- res.send("Abiword is not enabled at this Etherpad Lite instance. Set the path to Abiword in settings.json to enable this feature");
+ res.send("Abiword is not enabled at this Etherpad instance. Set the path to Abiword in settings.json to enable this feature");
return;
}
diff --git a/src/node/hooks/express/padreadonly.js b/src/node/hooks/express/padreadonly.js
index af5cbed3..9a0a52bf 100644
--- a/src/node/hooks/express/padreadonly.js
+++ b/src/node/hooks/express/padreadonly.js
@@ -16,50 +16,50 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//translate the read only pad to a padId
function(callback)
{
- readOnlyManager.getPadId(req.params.id, function(err, _padId)
- {
- if(ERR(err, callback)) return;
+ readOnlyManager.getPadId(req.params.id, function(err, _padId)
+ {
+ if(ERR(err, callback)) return;
- padId = _padId;
+ padId = _padId;
- //we need that to tell hasPadAcess about the pad
- req.params.pad = padId;
+ //we need that to tell hasPadAcess about the pad
+ req.params.pad = padId;
- callback();
- });
+ callback();
+ });
},
//render the html document
function(callback)
{
- //return if the there is no padId
- if(padId == null)
- {
- callback("notfound");
- return;
- }
+ //return if the there is no padId
+ if(padId == null)
+ {
+ callback("notfound");
+ return;
+ }
- hasPadAccess(req, res, function()
- {
- //render the html document
- exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
- {
- if(ERR(err, callback)) return;
- html = _html;
- callback();
- });
- });
+ hasPadAccess(req, res, function()
+ {
+ //render the html document
+ exporthtml.getPadHTMLDocument(padId, null, false, function(err, _html)
+ {
+ if(ERR(err, callback)) return;
+ html = _html;
+ callback();
+ });
+ });
}
], function(err)
{
//throw any unexpected error
if(err && err != "notfound")
- ERR(err);
+ ERR(err);
if(err == "notfound")
- res.send(404, '404 - Not Found');
+ res.send(404, '404 - Not Found');
else
- res.send(html);
+ res.send(html);
});
});
-} \ No newline at end of file
+}
diff --git a/src/node/hooks/express/padurlsanitize.js b/src/node/hooks/express/padurlsanitize.js
index 29782b69..2aadccdc 100644
--- a/src/node/hooks/express/padurlsanitize.js
+++ b/src/node/hooks/express/padurlsanitize.js
@@ -12,20 +12,20 @@ exports.expressCreateServer = function (hook_name, args, cb) {
else
{
padManager.sanitizePadId(padId, function(sanitizedPadId) {
- //the pad id was sanitized, so we redirect to the sanitized version
- if(sanitizedPadId != padId)
- {
+ //the pad id was sanitized, so we redirect to the sanitized version
+ if(sanitizedPadId != padId)
+ {
var real_url = sanitizedPadId;
var query = url.parse(req.url).query;
if ( query ) real_url += '?' + query;
- res.header('Location', real_url);
- res.send(302, 'You should be redirected to <a href="' + real_url + '">' + real_url + '</a>');
- }
- //the pad id was fine, so just render it
- else
- {
- next();
- }
+ res.header('Location', real_url);
+ res.send(302, 'You should be redirected to <a href="' + real_url + '">' + real_url + '</a>');
+ }
+ //the pad id was fine, so just render it
+ else
+ {
+ next();
+ }
});
}
});
diff --git a/src/node/hooks/express/specialpages.js b/src/node/hooks/express/specialpages.js
index 44002461..063328fb 100644
--- a/src/node/hooks/express/specialpages.js
+++ b/src/node/hooks/express/specialpages.js
@@ -1,7 +1,13 @@
var path = require('path');
var eejs = require('ep_etherpad-lite/node/eejs');
+var toolbar = require("ep_etherpad-lite/node/utils/toolbar");
+var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
exports.expressCreateServer = function (hook_name, args, cb) {
+ // expose current stats
+ args.app.get('/stats', function(req, res) {
+ res.json(require('ep_etherpad-lite/node/stats').toJSON())
+ })
//serve index.html under /
args.app.get('/', function(req, res)
@@ -26,14 +32,28 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//serve pad.html under /p
args.app.get('/p/:pad', function(req, res, next)
- {
- res.send(eejs.require("ep_etherpad-lite/templates/pad.html", {req: req}));
+ {
+ hooks.callAll("padInitToolbar", {
+ toolbar: toolbar
+ });
+
+ res.send(eejs.require("ep_etherpad-lite/templates/pad.html", {
+ req: req,
+ toolbar: toolbar
+ }));
});
//serve timeslider.html under /p/$padname/timeslider
args.app.get('/p/:pad/timeslider', function(req, res, next)
{
- res.send(eejs.require("ep_etherpad-lite/templates/timeslider.html", {req: req}));
+ hooks.callAll("padInitToolbar", {
+ toolbar: toolbar
+ });
+
+ res.send(eejs.require("ep_etherpad-lite/templates/timeslider.html", {
+ req: req,
+ toolbar: toolbar
+ }));
});
//serve favicon.ico from all path levels except as a pad name
@@ -45,11 +65,11 @@ exports.expressCreateServer = function (hook_name, args, cb) {
//there is no custom favicon, send the default favicon
if(err)
{
- filePath = path.normalize(__dirname + "/../../../static/favicon.ico");
- res.sendfile(filePath);
+ filePath = path.normalize(__dirname + "/../../../static/favicon.ico");
+ res.sendfile(filePath);
}
});
});
-} \ No newline at end of file
+}
diff --git a/src/node/hooks/express/swagger.js b/src/node/hooks/express/swagger.js
index f4fc5cff..e8daa61c 100644
--- a/src/node/hooks/express/swagger.js
+++ b/src/node/hooks/express/swagger.js
@@ -86,7 +86,7 @@ var API = {
},
"createIfNotExistsFor" : {
"func": "createGroupIfNotExistsFor",
- "description": "this functions helps you to map your application group ids to etherpad lite group ids",
+ "description": "this functions helps you to map your application group ids to Etherpad group ids",
"response": {"groupID":{"type":"string"}}
},
"delete" : {
@@ -124,7 +124,7 @@ var API = {
},
"createIfNotExistsFor": {
"func": "createAuthorIfNotExistsFor",
- "description": "this functions helps you to map your application author ids to etherpad lite author ids",
+ "description": "this functions helps you to map your application author ids to Etherpad author ids",
"response": {"authorID":{"type":"string"}}
},
"listPads": {
@@ -354,7 +354,6 @@ exports.expressCreateServer = function (hook_name, args, cb) {
// Let's put this under /rest for now
var subpath = express();
- args.app.use(express.bodyParser());
args.app.use(basePath, subpath);
swagger.setAppHandler(subpath);
diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js
index c39f91da..6998853f 100644
--- a/src/node/hooks/express/webaccess.js
+++ b/src/node/hooks/express/webaccess.js
@@ -5,6 +5,7 @@ var settings = require('../../utils/Settings');
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
var ueberStore = require('../../db/SessionStore');
+var stats = require('ep_etherpad-lite/node/stats')
//checks for basic http auth
exports.basicAuth = function (req, res, next) {
@@ -32,15 +33,15 @@ exports.basicAuth = function (req, res, next) {
// If auth headers are present use them to authenticate...
if (req.headers.authorization && req.headers.authorization.search('Basic ') === 0) {
var userpass = new Buffer(req.headers.authorization.split(' ')[1], 'base64').toString().split(":")
- var username = userpass[0];
- var password = userpass[1];
+ var username = userpass.shift();
+ var password = userpass.join(':');
if (settings.users[username] != undefined && settings.users[username].password == password) {
settings.users[username].username = username;
req.session.user = settings.users[username];
return cb(true);
}
- return hooks.aCallFirst("authenticate", {req: req, res:res, next:next, username: username, password: password}, hookResultMangle(cb));
+ return hooks.aCallFirst("authenticate", {req: req, res:res, next:next, username: username, password: password}, hookResultMangle(cb));
}
hooks.aCallFirst("authenticate", {req: req, res:res, next:next}, hookResultMangle(cb));
}
@@ -91,10 +92,21 @@ exports.basicAuth = function (req, res, next) {
exports.secret = null;
exports.expressConfigure = function (hook_name, args, cb) {
+ // Measure response time
+ args.app.use(function(req, res, next) {
+ var stopWatch = stats.timer('httpRequests').start();
+ var sendFn = res.send
+ res.send = function() {
+ stopWatch.end()
+ sendFn.apply(res, arguments)
+ }
+ next()
+ })
+
// If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158.
// Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway.
if (!(settings.loglevel === "WARN" || settings.loglevel == "ERROR"))
- args.app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'}));
+ args.app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.DEBUG, format: ':status, :method :url'}));
/* Do not let express create the session, so that we can retain a
* reference to it for socket.io to use. Also, set the key (cookie