diff options
Diffstat (limited to 'src/node/hooks/express')
-rw-r--r-- | src/node/hooks/express/adminplugins.js | 77 | ||||
-rw-r--r-- | src/node/hooks/express/apicalls.js | 12 | ||||
-rw-r--r-- | src/node/hooks/express/errorhandling.js | 7 | ||||
-rw-r--r-- | src/node/hooks/express/importexport.js | 2 | ||||
-rw-r--r-- | src/node/hooks/express/padreadonly.js | 56 | ||||
-rw-r--r-- | src/node/hooks/express/padurlsanitize.js | 22 | ||||
-rw-r--r-- | src/node/hooks/express/specialpages.js | 32 | ||||
-rw-r--r-- | src/node/hooks/express/swagger.js | 5 | ||||
-rw-r--r-- | src/node/hooks/express/webaccess.js | 20 |
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 |