diff --git a/settings.json.template b/settings.json.template index f89fcd8ed..8700de052 100644 --- a/settings.json.template +++ b/settings.json.template @@ -51,8 +51,6 @@ Note: /admin always requires authentication. */ "requireAuthentication": false, - /* Require authorization by a module, or a user with is_admin set, see below. */ - "requireAuthorization": false, /* Users for basic authentication. is_admin = true gives access to /admin. If you do not uncomment this, /admin will not be available! */ diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 028d8ab1b..3f1c91cca 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -8,19 +8,24 @@ var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); //checks for basic http auth exports.basicAuth = function (req, res, next) { + var hookResultMangle = function (cb) { return function (err, data) { - return cb(!err && data.length && data[0]); + // If data has 1 or more element, use the first one to decide if a user + // is authenticated, if its empty or undefined, no plugin gave its 'ok' + return cb(!err && data !== undefined && data.length < 1 && data[0]); } } var authorize = function (cb) { // Do not require auth for static paths...this could be a bit brittle if (req.path.match(/^\/(static|javascripts|pluginfw)/)) return cb(true); + + var requirePluginAuthorization = hooks.registeredCallbacks('authorize').length > 0; if (req.path.indexOf('/admin') != 0) { if (!settings.requireAuthentication) return cb(true); - if (!settings.requireAuthorization && req.session && req.session.user) return cb(true); + if (!requirePluginAuthorization && req.session && req.session.user) return cb(true); } if (req.session && req.session.user && req.session.user.is_admin) return cb(true); @@ -40,7 +45,7 @@ exports.basicAuth = function (req, res, next) { 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)); } diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index cb6a64033..5d5432710 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -80,11 +80,11 @@ exports.abiword = null; */ exports.loglevel = "INFO"; -/* This setting is used if you need authentication and/or - * authorization. Note: /admin always requires authentication, and - * either authorization by a module, or a user with is_admin set */ +/* This setting is used if you need authentication. + * Note: /admin always requires authentication, and + * either authorization by a module, or a user with is_admin set. + * Plugins may override this behavior */ exports.requireAuthentication = false; -exports.requireAuthorization = false; exports.users = {}; //checks if abiword is avaiable diff --git a/src/static/js/pluginfw/hooks.js b/src/static/js/pluginfw/hooks.js index 49e46c608..3d999493c 100644 --- a/src/static/js/pluginfw/hooks.js +++ b/src/static/js/pluginfw/hooks.js @@ -62,35 +62,33 @@ exports.mapFirst = function (lst, fn, cb) { } -/* Don't use Array.concat as it flatterns arrays within the array */ -exports.flatten = function (lst) { - var res = []; - if (lst != undefined && lst != null) { - for (var i = 0; i < lst.length; i++) { - if (lst[i] != undefined && lst[i] != null) { - for (var j = 0; j < lst[i].length; j++) { - res.push(lst[i][j]); - } - } - } - } - return res; +/* + Returns all registered callbacks of a hook + @param string hook_name the hook to retrieve the callbacks for. + @return an array of callback functions, an empty array if no callbacks are registered +*/ +exports.registeredCallbacks = function (hook_name){ + console.log(plugins.hooks[hook_name]) + return (plugins.hooks[hook_name] !== undefined) ? plugins.hooks[hook_name] : []; } exports.callAll = function (hook_name, args) { if (!args) args = {}; - if (plugins.hooks[hook_name] === undefined) return []; - return _.flatten(_.map(plugins.hooks[hook_name], function (hook) { - return hookCallWrapper(hook, hook_name, args); - }), true); + var callbacks = exports.registeredCallbacks(hook_name); + + return _.flatten( + _.map(callbacks, function (hook) { + return hookCallWrapper(hook, hook_name, args); + }), true); } exports.aCallAll = function (hook_name, args, cb) { if (!args) args = {}; if (!cb) cb = function () {}; - if (plugins.hooks[hook_name] === undefined) return cb(null, []); + var callbacks = exports.registeredCallbacks(hook_name); + async.map( - plugins.hooks[hook_name], + callbacks, function (hook, cb) { hookCallWrapper(hook, hook_name, args, function (res) { cb(null, res); }); }, @@ -102,18 +100,21 @@ exports.aCallAll = function (hook_name, args, cb) { exports.callFirst = function (hook_name, args) { if (!args) args = {}; - if (plugins.hooks[hook_name][0] === undefined) return []; - return exports.syncMapFirst(plugins.hooks[hook_name], function (hook) { - return hookCallWrapper(hook, hook_name, args); + var callbacks = exports.registeredCallbacks(hook_name); + + return exports.syncMapFirst(callbacks, function (hook) { + var res = hookCallWrapper(hook, hook_name, args); + return res !== undefined ? res : []; }); } exports.aCallFirst = function (hook_name, args, cb) { if (!args) args = {}; if (!cb) cb = function () {}; - if (plugins.hooks[hook_name] === undefined) return cb(null, []); + var callbacks = exports.registeredCallbacks(hook_name); + exports.mapFirst( - plugins.hooks[hook_name], + callbacks, function (hook, cb) { hookCallWrapper(hook, hook_name, args, function (res) { cb(null, res); }); },