mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-05-05 22:57:11 -04:00
Fixed docker build.
This commit is contained in:
parent
4d97c3c48f
commit
fa5aed489f
36 changed files with 243 additions and 967 deletions
|
@ -5,8 +5,6 @@ require('eslint-config-etherpad/patch/modern-module-resolution');
|
|||
|
||||
module.exports = {
|
||||
ignorePatterns: [
|
||||
'/static/js/admin/jquery.autosize.js',
|
||||
'/static/js/admin/minify.json.js',
|
||||
'/static/js/vendors/browser.js',
|
||||
'/static/js/vendors/farbtastic.js',
|
||||
'/static/js/vendors/gritter.js',
|
||||
|
|
|
@ -92,14 +92,12 @@
|
|||
{
|
||||
"name": "adminplugins",
|
||||
"hooks": {
|
||||
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminplugins",
|
||||
"socketio": "ep_etherpad-lite/node/hooks/express/adminplugins"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "adminsettings",
|
||||
"hooks": {
|
||||
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminsettings",
|
||||
"socketio": "ep_etherpad-lite/node/hooks/express/adminsettings"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
'use strict';
|
||||
import {ArgsExpressType} from "../../types/ArgsExpressType";
|
||||
import path from "path";
|
||||
const settings = require('ep_etherpad-lite/node/utils/Settings');
|
||||
|
||||
const eejs = require('../../eejs');
|
||||
const ADMIN_PATH = path.join(settings.root, 'src', 'templates', 'admin');
|
||||
|
||||
/**
|
||||
* Add the admin navigation link
|
||||
|
@ -11,9 +13,19 @@ const eejs = require('../../eejs');
|
|||
* @return {*}
|
||||
*/
|
||||
exports.expressCreateServer = (hookName:string, args: ArgsExpressType, cb:Function): any => {
|
||||
args.app.get('/admin', (req:any, res:any) => {
|
||||
if ('/' !== req.path[req.path.length - 1]) return res.redirect('./admin/');
|
||||
res.send(eejs.require('ep_etherpad-lite/templates/admin/index.html', {req}));
|
||||
});
|
||||
args.app.get('/admin/*', (req:any, res:any, next:Function) => {
|
||||
if (req.path.includes('.')) {
|
||||
const relativPath = req.path.split('/admin/')[1];
|
||||
res.sendFile(path.join(ADMIN_PATH, relativPath));
|
||||
} else {
|
||||
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
|
||||
res.header('Expires', '-1');
|
||||
res.header('Pragma', 'no-cache');
|
||||
res.sendFile(path.join(ADMIN_PATH, 'index.html'));
|
||||
}
|
||||
});
|
||||
args.app.get('/admin', (req:any, res:any, next:Function) => {
|
||||
if ('/' !== req.path[req.path.length - 1]) return res.redirect('./admin/');
|
||||
})
|
||||
return cb();
|
||||
};
|
||||
|
|
|
@ -12,35 +12,7 @@ const installer = require('../../../static/js/pluginfw/installer');
|
|||
const pluginDefs = require('../../../static/js/pluginfw/plugin_defs');
|
||||
const plugins = require('../../../static/js/pluginfw/plugins');
|
||||
const semver = require('semver');
|
||||
const UpdateCheck = require('../../utils/UpdateCheck');
|
||||
|
||||
exports.expressCreateServer = (hookName:string, args: ArgsExpressType, cb:Function) => {
|
||||
args.app.get('/admin/plugins', (req:any, res:any) => {
|
||||
res.send(eejs.require('ep_etherpad-lite/templates/admin/plugins.html', {
|
||||
plugins: pluginDefs.plugins,
|
||||
req,
|
||||
errors: [],
|
||||
}));
|
||||
});
|
||||
|
||||
args.app.get('/admin/plugins/info', (req:any, res:any) => {
|
||||
const gitCommit = settings.getGitCommit();
|
||||
const epVersion = settings.getEpVersion();
|
||||
|
||||
res.send(eejs.require('ep_etherpad-lite/templates/admin/plugins-info.html', {
|
||||
gitCommit,
|
||||
epVersion,
|
||||
installedPlugins: `<pre>${plugins.formatPlugins().replace(/, /g, '\n')}</pre>`,
|
||||
installedParts: `<pre>${plugins.formatParts()}</pre>`,
|
||||
installedServerHooks: `<div>${plugins.formatHooks('hooks', true)}</div>`,
|
||||
installedClientHooks: `<div>${plugins.formatHooks('client_hooks', true)}</div>`,
|
||||
latestVersion: UpdateCheck.getLatestVersion(),
|
||||
req,
|
||||
}));
|
||||
});
|
||||
|
||||
return cb();
|
||||
};
|
||||
|
||||
exports.socketio = (hookName:string, args:ArgsExpressType, cb:Function) => {
|
||||
const io = args.io.of('/pluginfw/installer');
|
||||
|
|
|
@ -13,16 +13,6 @@ const UpdateCheck = require('../../utils/UpdateCheck');
|
|||
const padManager = require('../../db/PadManager');
|
||||
const api = require('../../db/API');
|
||||
|
||||
exports.expressCreateServer = (hookName:string, {app}:any) => {
|
||||
app.get('/admin/settings', (req:any, res:any) => {
|
||||
res.send(eejs.require('ep_etherpad-lite/templates/admin/settings.html', {
|
||||
req,
|
||||
settings: '',
|
||||
errors: [],
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const queryPadLimit = 12;
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ exports.userCanModify = (padId: string, req: SocketClientRequest) => {
|
|||
exports.authnFailureDelayMs = 1000;
|
||||
|
||||
const checkAccess = async (req:any, res:any, next: Function) => {
|
||||
const requireAdmin = req.path.toLowerCase().startsWith('/admin');
|
||||
const requireAdmin = req.path.toLowerCase().startsWith('/admin-auth');
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 1: Check the preAuthorize hook for early permit/deny (permit is only allowed for non-admin
|
||||
|
@ -126,7 +126,13 @@ const checkAccess = async (req:any, res:any, next: Function) => {
|
|||
// completed, or maybe different credentials are required), go to the next step.
|
||||
// ///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (await authorize()) return next();
|
||||
if (await authorize()) {
|
||||
if(requireAdmin) {
|
||||
res.status(200).send('Authorized')
|
||||
return
|
||||
}
|
||||
return next();
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 3: Authenticate the user. (Or, if already logged in, reauthenticate with different
|
||||
|
@ -163,7 +169,7 @@ const checkAccess = async (req:any, res:any, next: Function) => {
|
|||
if (await aCallFirst0('authnFailure', {req, res})) return;
|
||||
if (await aCallFirst0('authFailure', {req, res, next})) return;
|
||||
// No plugin handled the authentication failure. Fall back to basic authentication.
|
||||
res.header('WWW-Authenticate', 'Basic realm="Protected Area"');
|
||||
//res.header('WWW-Authenticate', 'Basic realm="Protected Area"');
|
||||
// Delay the error response for 1s to slow down brute force attacks.
|
||||
await new Promise((resolve) => setTimeout(resolve, exports.authnFailureDelayMs));
|
||||
res.status(401).send('Authentication Required');
|
||||
|
@ -188,7 +194,13 @@ const checkAccess = async (req:any, res:any, next: Function) => {
|
|||
// a login page).
|
||||
// ///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (await authorize()) return next();
|
||||
const auth = await authorize()
|
||||
if (auth && !requireAdmin) return next();
|
||||
if(auth && requireAdmin) {
|
||||
res.status(200).send('Authorized')
|
||||
return
|
||||
}
|
||||
|
||||
if (await aCallFirst0('authzFailure', {req, res})) return;
|
||||
if (await aCallFirst0('authFailure', {req, res, next})) return;
|
||||
// No plugin handled the authorization failure.
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
// Autosize 1.13 - jQuery plugin for textareas
|
||||
// (c) 2012 Jack Moore - jacklmoore.com
|
||||
// license: www.opensource.org/licenses/mit-license.php
|
||||
|
||||
(function ($) {
|
||||
var
|
||||
defaults = {
|
||||
className: 'autosizejs',
|
||||
append: "",
|
||||
callback: false
|
||||
},
|
||||
hidden = 'hidden',
|
||||
borderBox = 'border-box',
|
||||
lineHeight = 'lineHeight',
|
||||
copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
|
||||
// line-height is omitted because IE7/IE8 doesn't return the correct value.
|
||||
copyStyle = [
|
||||
'fontFamily',
|
||||
'fontSize',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'letterSpacing',
|
||||
'textTransform',
|
||||
'wordSpacing',
|
||||
'textIndent'
|
||||
],
|
||||
oninput = 'oninput',
|
||||
onpropertychange = 'onpropertychange',
|
||||
test = $(copy)[0];
|
||||
|
||||
// For testing support in old FireFox
|
||||
test.setAttribute(oninput, "return");
|
||||
|
||||
if ($.isFunction(test[oninput]) || onpropertychange in test) {
|
||||
|
||||
// test that line-height can be accurately copied to avoid
|
||||
// incorrect value reporting in old IE and old Opera
|
||||
$(test).css(lineHeight, '99px');
|
||||
if ($(test).css(lineHeight) === '99px') {
|
||||
copyStyle.push(lineHeight);
|
||||
}
|
||||
|
||||
$.fn.autosize = function (options) {
|
||||
options = $.extend({}, defaults, options || {});
|
||||
|
||||
return this.each(function () {
|
||||
var
|
||||
ta = this,
|
||||
$ta = $(ta),
|
||||
mirror,
|
||||
minHeight = $ta.height(),
|
||||
maxHeight = parseInt($ta.css('maxHeight'), 10),
|
||||
active,
|
||||
i = copyStyle.length,
|
||||
resize,
|
||||
boxOffset = 0,
|
||||
value = ta.value,
|
||||
callback = $.isFunction(options.callback);
|
||||
|
||||
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox){
|
||||
boxOffset = $ta.outerHeight() - $ta.height();
|
||||
}
|
||||
|
||||
if ($ta.data('mirror') || $ta.data('ismirror')) {
|
||||
// if autosize has already been applied, exit.
|
||||
// if autosize is being applied to a mirror element, exit.
|
||||
return;
|
||||
} else {
|
||||
mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
|
||||
|
||||
resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
|
||||
|
||||
$ta.data('mirror', $(mirror)).css({
|
||||
overflow: hidden,
|
||||
overflowY: hidden,
|
||||
wordWrap: 'break-word',
|
||||
resize: resize
|
||||
});
|
||||
}
|
||||
|
||||
// Opera returns '-1px' when max-height is set to 'none'.
|
||||
maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
|
||||
|
||||
// Using mainly bare JS in this function because it is going
|
||||
// to fire very often while typing, and needs to very efficient.
|
||||
function adjust() {
|
||||
var height, overflow, original;
|
||||
|
||||
// the active flag keeps IE from tripping all over itself. Otherwise
|
||||
// actions in the adjust function will cause IE to call adjust again.
|
||||
if (!active) {
|
||||
active = true;
|
||||
mirror.value = ta.value + options.append;
|
||||
mirror.style.overflowY = ta.style.overflowY;
|
||||
original = parseInt(ta.style.height,10);
|
||||
|
||||
// Update the width in case the original textarea width has changed
|
||||
mirror.style.width = $ta.css('width');
|
||||
|
||||
// Needed for IE to reliably return the correct scrollHeight
|
||||
mirror.scrollTop = 0;
|
||||
|
||||
// Set a very high value for scrollTop to be sure the
|
||||
// mirror is scrolled all the way to the bottom.
|
||||
mirror.scrollTop = 9e4;
|
||||
|
||||
height = mirror.scrollTop;
|
||||
overflow = hidden;
|
||||
if (height > maxHeight) {
|
||||
height = maxHeight;
|
||||
overflow = 'scroll';
|
||||
} else if (height < minHeight) {
|
||||
height = minHeight;
|
||||
}
|
||||
height += boxOffset;
|
||||
ta.style.overflowY = overflow;
|
||||
|
||||
if (original !== height) {
|
||||
ta.style.height = height + 'px';
|
||||
if (callback) {
|
||||
options.callback.call(ta);
|
||||
}
|
||||
}
|
||||
|
||||
// This small timeout gives IE a chance to draw it's scrollbar
|
||||
// before adjust can be run again (prevents an infinite loop).
|
||||
setTimeout(function () {
|
||||
active = false;
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// mirror is a duplicate textarea located off-screen that
|
||||
// is automatically updated to contain the same text as the
|
||||
// original textarea. mirror always has a height of 0.
|
||||
// This gives a cross-browser supported way getting the actual
|
||||
// height of the text, through the scrollTop property.
|
||||
while (i--) {
|
||||
mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
|
||||
}
|
||||
|
||||
$('body').append(mirror);
|
||||
|
||||
if (onpropertychange in ta) {
|
||||
if (oninput in ta) {
|
||||
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
||||
// so binding to onkeyup to catch most of those occassions. There is no way that I
|
||||
// know of to detect something like 'cut' in IE9.
|
||||
ta[oninput] = ta.onkeyup = adjust;
|
||||
} else {
|
||||
// IE7 / IE8
|
||||
ta[onpropertychange] = adjust;
|
||||
}
|
||||
} else {
|
||||
// Modern Browsers
|
||||
ta[oninput] = adjust;
|
||||
|
||||
// The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
|
||||
// This is a hack to get Chrome to reflow it's text.
|
||||
ta.value = '';
|
||||
ta.value = value;
|
||||
}
|
||||
|
||||
$(window).resize(adjust);
|
||||
|
||||
// Allow for manual triggering if needed.
|
||||
$ta.on('autosize', adjust);
|
||||
|
||||
// Call adjust in case the textarea already contains text.
|
||||
adjust();
|
||||
});
|
||||
};
|
||||
} else {
|
||||
// Makes no changes for older browsers (FireFox3- and Safari4-)
|
||||
$.fn.autosize = function (callback) {
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
}(jQuery));
|
|
@ -1,61 +0,0 @@
|
|||
/*! JSON.minify()
|
||||
v0.1 (c) Kyle Simpson
|
||||
MIT License
|
||||
*/
|
||||
|
||||
(function(global){
|
||||
if (typeof global.JSON == "undefined" || !global.JSON) {
|
||||
global.JSON = {};
|
||||
}
|
||||
|
||||
global.JSON.minify = function(json) {
|
||||
|
||||
var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g,
|
||||
in_string = false,
|
||||
in_multiline_comment = false,
|
||||
in_singleline_comment = false,
|
||||
tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc
|
||||
;
|
||||
|
||||
tokenizer.lastIndex = 0;
|
||||
|
||||
while (tmp = tokenizer.exec(json)) {
|
||||
lc = RegExp.leftContext;
|
||||
rc = RegExp.rightContext;
|
||||
if (!in_multiline_comment && !in_singleline_comment) {
|
||||
tmp2 = lc.substring(from);
|
||||
if (!in_string) {
|
||||
tmp2 = tmp2.replace(/(\n|\r|\s)*/g,"");
|
||||
}
|
||||
new_str[ns++] = tmp2;
|
||||
}
|
||||
from = tokenizer.lastIndex;
|
||||
|
||||
if (tmp[0] == "\"" && !in_multiline_comment && !in_singleline_comment) {
|
||||
tmp2 = lc.match(/(\\)*$/);
|
||||
if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) { // start of string with ", or unescaped " character found to end string
|
||||
in_string = !in_string;
|
||||
}
|
||||
from--; // include " character in next catch
|
||||
rc = json.substring(from);
|
||||
}
|
||||
else if (tmp[0] == "/*" && !in_string && !in_multiline_comment && !in_singleline_comment) {
|
||||
in_multiline_comment = true;
|
||||
}
|
||||
else if (tmp[0] == "*/" && !in_string && in_multiline_comment && !in_singleline_comment) {
|
||||
in_multiline_comment = false;
|
||||
}
|
||||
else if (tmp[0] == "//" && !in_string && !in_multiline_comment && !in_singleline_comment) {
|
||||
in_singleline_comment = true;
|
||||
}
|
||||
else if ((tmp[0] == "\n" || tmp[0] == "\r") && !in_string && !in_multiline_comment && in_singleline_comment) {
|
||||
in_singleline_comment = false;
|
||||
}
|
||||
else if (!in_multiline_comment && !in_singleline_comment && !(/\n|\r|\s/.test(tmp[0]))) {
|
||||
new_str[ns++] = tmp[0];
|
||||
}
|
||||
}
|
||||
new_str[ns++] = rc;
|
||||
return new_str.join("");
|
||||
};
|
||||
})(this);
|
|
@ -1,273 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/* global socketio */
|
||||
|
||||
$(document).ready(() => {
|
||||
const socket = socketio.connect('..', '/pluginfw/installer');
|
||||
socket.on('disconnect', (reason) => {
|
||||
// The socket.io client will automatically try to reconnect for all reasons other than "io
|
||||
// server disconnect".
|
||||
if (reason === 'io server disconnect') socket.connect();
|
||||
});
|
||||
|
||||
const search = (searchTerm, limit) => {
|
||||
if (search.searchTerm !== searchTerm) {
|
||||
search.offset = 0;
|
||||
search.results = [];
|
||||
search.end = false;
|
||||
}
|
||||
limit = limit ? limit : search.limit;
|
||||
search.searchTerm = searchTerm;
|
||||
socket.emit('search', {
|
||||
searchTerm,
|
||||
offset: search.offset,
|
||||
limit,
|
||||
sortBy: search.sortBy,
|
||||
sortDir: search.sortDir,
|
||||
});
|
||||
search.offset += limit;
|
||||
|
||||
$('#search-progress').show();
|
||||
search.messages.show('fetching');
|
||||
search.searching = true;
|
||||
};
|
||||
search.searching = false;
|
||||
search.offset = 0;
|
||||
search.limit = 999;
|
||||
search.results = [];
|
||||
search.sortBy = 'name';
|
||||
search.sortDir = /* DESC?*/true;
|
||||
search.end = true;// have we received all results already?
|
||||
search.messages = {
|
||||
show: (msg) => {
|
||||
// $('.search-results .messages').show()
|
||||
$(`.search-results .messages .${msg}`).show();
|
||||
$(`.search-results .messages .${msg} *`).show();
|
||||
},
|
||||
hide: (msg) => {
|
||||
$('.search-results .messages').hide();
|
||||
$(`.search-results .messages .${msg}`).hide();
|
||||
$(`.search-results .messages .${msg} *`).hide();
|
||||
},
|
||||
};
|
||||
|
||||
const installed = {
|
||||
progress: {
|
||||
show: (plugin, msg) => {
|
||||
$(`.installed-results .${plugin} .progress`).show();
|
||||
$(`.installed-results .${plugin} .progress .message`).text(msg);
|
||||
if ($(window).scrollTop() > $(`.${plugin}`).offset().top) {
|
||||
$(window).scrollTop($(`.${plugin}`).offset().top - 100);
|
||||
}
|
||||
},
|
||||
hide: (plugin) => {
|
||||
$(`.installed-results .${plugin} .progress`).hide();
|
||||
$(`.installed-results .${plugin} .progress .message`).text('');
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
show: (msg) => {
|
||||
$('.installed-results .messages').show();
|
||||
$(`.installed-results .messages .${msg}`).show();
|
||||
},
|
||||
hide: (msg) => {
|
||||
$('.installed-results .messages').hide();
|
||||
$(`.installed-results .messages .${msg}`).hide();
|
||||
},
|
||||
},
|
||||
list: [],
|
||||
};
|
||||
|
||||
const displayPluginList = (plugins, container, template) => {
|
||||
plugins.forEach((plugin) => {
|
||||
const row = template.clone();
|
||||
|
||||
for (const attr in plugin) {
|
||||
if (attr === 'name') { // Hack to rewrite URLS into name
|
||||
const link = $('<a>')
|
||||
.attr('href', `https://npmjs.org/package/${plugin.name}`)
|
||||
.attr('plugin', 'Plugin details')
|
||||
.attr('rel', 'noopener noreferrer')
|
||||
.attr('target', '_blank')
|
||||
.text(plugin.name.substr(3));
|
||||
row.find('.name').append(link);
|
||||
} else {
|
||||
row.find(`.${attr}`).text(plugin[attr]);
|
||||
}
|
||||
}
|
||||
row.find('.version').text(plugin.version);
|
||||
row.addClass(plugin.name);
|
||||
row.data('plugin', plugin.name);
|
||||
container.append(row);
|
||||
});
|
||||
updateHandlers();
|
||||
};
|
||||
|
||||
const sortPluginList = (plugins, property, /* ASC?*/dir) => plugins.sort((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;
|
||||
});
|
||||
|
||||
const updateHandlers = () => {
|
||||
// Search
|
||||
$('#search-query').off('keyup').on('keyup', () => {
|
||||
search($('#search-query').val());
|
||||
});
|
||||
|
||||
// Prevent form submit
|
||||
$('#search-query').parent().on('submit', () => false);
|
||||
|
||||
// update & install
|
||||
$('.do-install, .do-update').off('click').on('click', function (e) {
|
||||
const $row = $(e.target).closest('tr');
|
||||
const plugin = $row.data('plugin');
|
||||
if ($(this).hasClass('do-install')) {
|
||||
$row.remove().appendTo('#installed-plugins');
|
||||
installed.progress.show(plugin, 'Installing');
|
||||
} else {
|
||||
installed.progress.show(plugin, 'Updating');
|
||||
}
|
||||
socket.emit('install', plugin);
|
||||
installed.messages.hide('nothing-installed');
|
||||
});
|
||||
|
||||
// uninstall
|
||||
$('.do-uninstall').off('click').on('click', (e) => {
|
||||
const $row = $(e.target).closest('tr');
|
||||
const pluginName = $row.data('plugin');
|
||||
socket.emit('uninstall', pluginName);
|
||||
installed.progress.show(pluginName, 'Uninstalling');
|
||||
installed.list = installed.list.filter((plugin) => plugin.name !== pluginName);
|
||||
});
|
||||
|
||||
// Sort
|
||||
$('.sort.up').off('click').on('click', function () {
|
||||
search.sortBy = $(this).attr('data-label').toLowerCase();
|
||||
search.sortDir = false;
|
||||
search.offset = 0;
|
||||
search(search.searchTerm, search.results.length);
|
||||
search.results = [];
|
||||
});
|
||||
$('.sort.down, .sort.none').off('click').on('click', function () {
|
||||
search.sortBy = $(this).attr('data-label').toLowerCase();
|
||||
search.sortDir = true;
|
||||
search.offset = 0;
|
||||
search(search.searchTerm, search.results.length);
|
||||
search.results = [];
|
||||
});
|
||||
};
|
||||
|
||||
socket.on('results:search', (data) => {
|
||||
if (!data.results.length) search.end = true;
|
||||
if (data.query.offset === 0) search.results = [];
|
||||
search.messages.hide('nothing-found');
|
||||
search.messages.hide('fetching');
|
||||
$('#search-query').prop('disabled', false);
|
||||
|
||||
console.log('got search results', data);
|
||||
|
||||
// add to results
|
||||
search.results = search.results.concat(data.results);
|
||||
|
||||
// Update sorting head
|
||||
$('.sort')
|
||||
.removeClass('up down')
|
||||
.addClass('none');
|
||||
$(`.search-results thead th[data-label=${data.query.sortBy}]`)
|
||||
.removeClass('none')
|
||||
.addClass(data.query.sortDir ? 'up' : 'down');
|
||||
|
||||
// re-render search results
|
||||
const searchWidget = $('.search-results');
|
||||
searchWidget.find('.results *').remove();
|
||||
if (search.results.length > 0) {
|
||||
displayPluginList(
|
||||
search.results, searchWidget.find('.results'), searchWidget.find('.template tr'));
|
||||
} else {
|
||||
search.messages.show('nothing-found');
|
||||
}
|
||||
search.messages.hide('fetching');
|
||||
$('#search-progress').hide();
|
||||
search.searching = false;
|
||||
});
|
||||
|
||||
socket.on('results:installed', (data) => {
|
||||
installed.messages.hide('fetching');
|
||||
installed.messages.hide('nothing-installed');
|
||||
|
||||
installed.list = data.installed;
|
||||
sortPluginList(installed.list, 'name', /* ASC?*/true);
|
||||
|
||||
// filter out epl
|
||||
installed.list = installed.list.filter((plugin) => plugin.name !== 'ep_etherpad-lite');
|
||||
|
||||
// remove all installed plugins (leave plugins that are still being installed)
|
||||
installed.list.forEach((plugin) => {
|
||||
$(`#installed-plugins .${plugin.name}`).remove();
|
||||
});
|
||||
|
||||
if (installed.list.length > 0) {
|
||||
displayPluginList(installed.list, $('#installed-plugins'), $('#installed-plugin-template'));
|
||||
socket.emit('checkUpdates');
|
||||
} else {
|
||||
installed.messages.show('nothing-installed');
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('results:updatable', (data) => {
|
||||
data.updatable.forEach((pluginName) => {
|
||||
const actions = $(`#installed-plugins > tr.${pluginName} .actions`);
|
||||
actions.find('.do-update').remove();
|
||||
actions.append(
|
||||
$('<input>').addClass('do-update').attr('type', 'button').attr('value', 'Update'));
|
||||
});
|
||||
updateHandlers();
|
||||
});
|
||||
|
||||
socket.on('finished:install', (data) => {
|
||||
if (data.error) {
|
||||
if (data.code === 'EPEERINVALID') {
|
||||
alert("This plugin requires that you update Etherpad so it can operate in it's true glory");
|
||||
}
|
||||
alert(`An error occurred while installing ${data.plugin} \n${data.error}`);
|
||||
$(`#installed-plugins .${data.plugin}`).remove();
|
||||
}
|
||||
|
||||
socket.emit('getInstalled');
|
||||
|
||||
// update search results
|
||||
search.offset = 0;
|
||||
search(search.searchTerm, search.results.length);
|
||||
search.results = [];
|
||||
});
|
||||
|
||||
socket.on('finished:uninstall', (data) => {
|
||||
if (data.error) {
|
||||
alert(`An error occurred while uninstalling the ${data.plugin} \n${data.error}`);
|
||||
}
|
||||
|
||||
// remove plugin from installed list
|
||||
$(`#installed-plugins .${data.plugin}`).remove();
|
||||
|
||||
socket.emit('getInstalled');
|
||||
|
||||
// update search results
|
||||
search.offset = 0;
|
||||
search(search.searchTerm, search.results.length);
|
||||
search.results = [];
|
||||
});
|
||||
|
||||
socket.on('connect', () => {
|
||||
updateHandlers();
|
||||
socket.emit('getInstalled');
|
||||
search.searchTerm = null;
|
||||
search($('#search-query').val());
|
||||
});
|
||||
|
||||
// check for updates every 5mins
|
||||
setInterval(() => {
|
||||
socket.emit('checkUpdates');
|
||||
}, 1000 * 60 * 5);
|
||||
});
|
|
@ -1,69 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
$(document).ready(() => {
|
||||
const socket = window.socketio.connect('..', '/settings');
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.emit('load');
|
||||
});
|
||||
|
||||
socket.on('disconnect', (reason) => {
|
||||
// The socket.io client will automatically try to reconnect for all reasons other than "io
|
||||
// server disconnect".
|
||||
if (reason === 'io server disconnect') socket.connect();
|
||||
});
|
||||
|
||||
socket.on('settings', (settings) => {
|
||||
/* Check whether the settings.json is authorized to be viewed */
|
||||
if (settings.results === 'NOT_ALLOWED') {
|
||||
$('.innerwrapper').hide();
|
||||
$('.innerwrapper-err').show();
|
||||
$('.err-message').html('Settings json is not authorized to be viewed in Admin page!!');
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check to make sure the JSON is clean before proceeding */
|
||||
if (isJSONClean(settings.results)) {
|
||||
$('.settings').append(settings.results);
|
||||
$('.settings').trigger('focus');
|
||||
$('.settings').autosize();
|
||||
} else {
|
||||
alert('Invalid JSON');
|
||||
}
|
||||
});
|
||||
|
||||
/* When the admin clicks save Settings check the JSON then send the JSON back to the server */
|
||||
$('#saveSettings').on('click', () => {
|
||||
const editedSettings = $('.settings').val();
|
||||
if (isJSONClean(editedSettings)) {
|
||||
// JSON is clean so emit it to the server
|
||||
socket.emit('saveSettings', $('.settings').val());
|
||||
} else {
|
||||
alert('Invalid JSON');
|
||||
$('.settings').trigger('focus');
|
||||
}
|
||||
});
|
||||
|
||||
/* Tell Etherpad Server to restart */
|
||||
$('#restartEtherpad').on('click', () => {
|
||||
socket.emit('restartServer');
|
||||
});
|
||||
|
||||
socket.on('saveprogress', (progress) => {
|
||||
$('#response').show();
|
||||
$('#response').text(progress);
|
||||
$('#response').fadeOut('slow');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const isJSONClean = (data) => {
|
||||
let cleanSettings = JSON.minify(data);
|
||||
// this is a bit naive. In theory some key/value might contain the sequences ',]' or ',}'
|
||||
cleanSettings = cleanSettings.replace(',]', ']').replace(',}', '}');
|
||||
try {
|
||||
return typeof JSON.parse(cleanSettings) === 'object';
|
||||
} catch (e) {
|
||||
return false; // the JSON failed to be parsed
|
||||
}
|
||||
};
|
|
@ -1,28 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title data-l10n-id="admin.page-title">Admin Dashboard - Etherpad</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="stylesheet" href="../static/css/admin.css">
|
||||
<script src="../static/js/vendors/jquery.js"></script>
|
||||
<script src="../socket.io/socket.io.js"></script>
|
||||
<link rel="localizations" type="application/l10n+json" href="../locales.json" />
|
||||
<script src="../static/js/vendors/html10n.js"></script>
|
||||
<script src="../static/js/l10n.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<div class="menu">
|
||||
<h1><a href="../">Etherpad</a></h1>
|
||||
<ul>
|
||||
<% e.begin_block("adminMenu"); %>
|
||||
<li><a href="plugins" data-l10n-id="admin_plugins">Plugin manager</a></li>
|
||||
<li><a href="settings" data-l10n-id="admin_settings">Settings</a></li>
|
||||
<li><a href="plugins/info" data-l10n-id="admin_plugins_info">Troubleshooting information</a></li>
|
||||
<% e.end_block(); %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:none"><a href="/javascript" data-jslicense="1">JavaScript license information</a></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,47 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title data-l10n-id="admin_plugins_info.page-title">Plugin information - Etherpad</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="stylesheet" href="../../static/css/admin.css">
|
||||
<link rel="localizations" type="application/l10n+json" href="../../locales.json" />
|
||||
<script src="../../static/js/vendors/html10n.js"></script>
|
||||
<script src="../../static/js/l10n.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<div class="menu">
|
||||
<h1><a href="../../">Etherpad</a></h1>
|
||||
<ul>
|
||||
<% e.begin_block("adminMenu"); %>
|
||||
<li><a href="../plugins" data-l10n-id="admin_plugins">Plugin manager</a></li>
|
||||
<li><a href="../settings" data-l10n-id="admin_settings">Settings</a></li>
|
||||
<li><a href="../plugins/info" data-l10n-id="admin_plugins_info">Troubleshooting information</a></li>
|
||||
<% e.end_block(); %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="innerwrapper">
|
||||
<h2 data-l10n-id="admin_plugins_info.version">Etherpad version</h2>
|
||||
<p><span data-l10n-id="admin_plugins_info.version_number">Version number</span>: <%= epVersion %></p>
|
||||
<p><span data-l10n-id="admin_plugins_info.version_latest">Latest available version</span>: <%= latestVersion %></p>
|
||||
<p>Git sha: <a href='https://github.com/ether/etherpad-lite/commit/<%= gitCommit %>'><%= gitCommit %></a></p>
|
||||
|
||||
<h2 data-l10n-id="admin_plugins_info.plugins">Installed plugins</h2>
|
||||
<%- installedPlugins %>
|
||||
|
||||
<h2 data-l10n-id="admin_plugins_info.parts">Installed parts</h2>
|
||||
<%- installedParts %>
|
||||
|
||||
<h2 data-l10n-id="admin_plugins_info.hooks">Installed hooks</h2>
|
||||
<h3 data-l10n-id="admin_plugins_info.hooks_server">Server-side hooks</h3>
|
||||
<%- installedServerHooks %>
|
||||
|
||||
<h3 data-l10n-id="admin_plugins_info.hooks_client">Client-side hooks</h3>
|
||||
<%- installedClientHooks %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:none"><a href="/javascript" data-jslicense="1">JavaScript license information</a></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,121 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title data-l10n-id="admin_plugins.page-title">Plugin manager - Etherpad</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="stylesheet" href="../static/css/admin.css">
|
||||
<script src="../static/js/vendors/jquery.js"></script>
|
||||
<script src="../socket.io/socket.io.js"></script>
|
||||
<script src="../static/js/socketio.js"></script>
|
||||
<script src="../static/js/admin/plugins.js"></script>
|
||||
<link rel="localizations" type="application/l10n+json" href="../locales.json" />
|
||||
<script src="../static/js/vendors/html10n.js"></script>
|
||||
<script src="../static/js/l10n.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
|
||||
<% if (errors.length) { %>
|
||||
<div class="errors">
|
||||
<% errors.forEach(function (item) { %>
|
||||
<div class="error"><%= item.toString() %></div>
|
||||
<% }) %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<div class="menu">
|
||||
<h1><a href="../">Etherpad</a></h1>
|
||||
<ul>
|
||||
<% e.begin_block("adminMenu"); %>
|
||||
<li><a href="plugins" data-l10n-id="admin_plugins">Plugin manager</a></li>
|
||||
<li><a href="settings" data-l10n-id="admin_settings">Settings</a></li>
|
||||
<li><a href="plugins/info" data-l10n-id="admin_plugins_info">Troubleshooting information</a></li>
|
||||
<% e.end_block(); %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="innerwrapper">
|
||||
<h2 data-l10n-id="admin_plugins.installed">Installed plugins</h2>
|
||||
<table class="installed-results">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-l10n-id="admin_plugins.name">Name</th>
|
||||
<th data-l10n-id="admin_plugins.description">Description</th>
|
||||
<th data-l10n-id="admin_plugins.version">Version</th>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="template">
|
||||
<tr id="installed-plugin-template">
|
||||
<td class="name" data-label="Name"></td>
|
||||
<td class="description" data-label="Description"></td>
|
||||
<td class="version" data-label="Version"></td>
|
||||
<td>
|
||||
<div class="actions">
|
||||
<input type="button" value="Uninstall" class="do-uninstall" data-l10n-id="admin_plugins.installed_uninstall.value">
|
||||
<div class="progress"><p class="loadingAnimation"></p><p><span class="message"></span></p></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody id="installed-plugins">
|
||||
</tbody>
|
||||
<tbody class="messages">
|
||||
<tr><td></td><td>
|
||||
<p class="nothing-installed" data-l10n-id="admin_plugins.installed_nothing">You haven't installed any plugins yet.</p>
|
||||
<p class="fetching"><p class="loadingAnimation"></p><br/><span data-l10n-id="admin_plugins.installed_fetching">Fetching installed plugins…</span></p>
|
||||
</td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="paged listing search-results">
|
||||
<div class="separator"></div>
|
||||
|
||||
<h2 data-l10n-id="admin_plugins.available">Available plugins</h2>
|
||||
<form>
|
||||
<input type="text" name="search" disabled placeholder="Search for plugins to install" id="search-query" data-l10n-id="admin_plugins.available_search.placeholder">
|
||||
</form>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort up" data-label="name" data-l10n-id="admin_plugins.name">Name</th>
|
||||
<th class="sort none" data-label="description" data-l10n-id="admin_plugins.description">Description</th>
|
||||
<th class="sort none" data-label="version" data-l10n-id="admin_plugins.version">Version</th>
|
||||
<th class="sort none" data-label="time" data-l10n-id="admin_plugins.last-update">Last update</th>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="template">
|
||||
<tr>
|
||||
<td class="name" data-label="Name"></td>
|
||||
<td class="description" data-label="Description"></td>
|
||||
<td class="version" data-label="Version"></td>
|
||||
<td class="time" data-label="Time"></td>
|
||||
<td>
|
||||
<div class="actions">
|
||||
<input type="button" value="Install" class="do-install" data-l10n-id="admin_plugins.available_install.value">
|
||||
<div class="progress"><p><p class="loadingAnimation"></p></p><p><span class="message"></span></p></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody class="results">
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr><td></td><td>
|
||||
<div class="messages">
|
||||
<div id="search-progress" class="progress"><p> </p></div>
|
||||
<p class="nothing-found" data-l10n-id="admin_plugins.available_not-found">No plugins found.</p>
|
||||
<p class="fetching"><p class="loadingAnimation"></p><br/><span data-l10n-id="admin_plugins.available_fetching">Fetching…</span></p>
|
||||
</div>
|
||||
</td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:none"><a href="/javascript" data-jslicense="1">JavaScript license information</a></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,58 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title data-l10n-id="admin_settings.page-title">Settings - Etherpad</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="stylesheet" href="../static/css/admin.css">
|
||||
<script src="../static/js/vendors/jquery.js"></script>
|
||||
<script src="../socket.io/socket.io.js"></script>
|
||||
<script src="../static/js/socketio.js"></script>
|
||||
<script src="../static/js/admin/minify.json.js"></script>
|
||||
<script src="../static/js/admin/settings.js"></script>
|
||||
<script src="../static/js/admin/jquery.autosize.js"></script>
|
||||
<link rel="localizations" type="application/l10n+json" href="../locales.json" />
|
||||
<script src="../static/js/vendors/html10n.js"></script>
|
||||
<script src="../static/js/l10n.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
|
||||
<% if (errors.length) { %>
|
||||
<div class="errors">
|
||||
<% errors.forEach(function (item) { %>
|
||||
<div class="error"><%= item.toString() %></div>
|
||||
<% }) %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
|
||||
<div class="menu">
|
||||
<h1><a href="../">Etherpad</a></h1>
|
||||
<ul>
|
||||
<% e.begin_block("adminMenu"); %>
|
||||
<li><a href="plugins" data-l10n-id="admin_plugins">Plugin manager</a></li>
|
||||
<li><a href="settings" data-l10n-id="admin_settings">Settings</a></li>
|
||||
<li><a href="plugins/info" data-l10n-id="admin_plugins_info">Troubleshooting information</a></li>
|
||||
<% e.end_block(); %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="innerwrapper">
|
||||
<h2 data-l10n-id="admin_settings.current">Current configuration</h2>
|
||||
<textarea class="settings"></textarea>
|
||||
<input type="button" class="settingsButton" id="saveSettings" value="Save Settings" data-l10n-id="admin_settings.current_save.value">
|
||||
<input type="button" class="settingsButton" id="restartEtherpad" value="Restart Etherpad" data-l10n-id="admin_settings.current_restart.value">
|
||||
<div id="response"></div>
|
||||
<div class="separator"></div>
|
||||
<a href='https://github.com/ether/etherpad-lite/wiki/Example-Production-Settings.JSON' data-l10n-id="admin_settings.current_example-prod">Example production settings template</a>
|
||||
<a href='https://github.com/ether/etherpad-lite/wiki/Example-Development-Settings.JSON' data-l10n-id="admin_settings.current_example-devel">Example development settings template</a>
|
||||
</div>
|
||||
|
||||
<div class="innerwrapper-err" >
|
||||
<h2 class="err-message"></h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="display:none"><a href="/javascript" data-jslicense="1">JavaScript license information</a></div>
|
||||
</body>
|
||||
</html>
|
|
@ -34,24 +34,16 @@
|
|||
<td><a href="/static/js/require-kernel.js">require-kernel.js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/static/js/admin/plugins.js">plugins.js</a></td>
|
||||
<td><a href="http://www.apache.org/licenses/LICENSE-2.0">Apache-2.0-only</a></td>
|
||||
<td><a href="/static/js/admin/plugins.js">plugins.js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/static/js/admin/minify.json.js">minify.json.js</a></td>
|
||||
<td><a href="http://www.jclark.com/xml/copying.txt">Expat</a></td>
|
||||
<td><a href="/static/js/admin/minify.json.js">minify.json.js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/static/js/admin/settings.js">settings.js</a></td>
|
||||
<td><a href="http://www.apache.org/licenses/LICENSE-2.0">Apache-2.0-only</a></td>
|
||||
<td><a href="/static/js/admin/settings.js">settings.js</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/static/js/admin/jquery.autosize.js">jquery.autosize.js</a></td>
|
||||
<td><a href="http://www.jclark.com/xml/copying.txt">Expat</a></td>
|
||||
<td><a href="/static/js/admin/jquery.autosize.js">jquery.autosize.js</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
|
|
@ -54,10 +54,10 @@ describe(__filename, function () {
|
|||
await agent.get('/').expect(200);
|
||||
});
|
||||
|
||||
it('!authn !authz anonymous /admin/ -> 401', async function () {
|
||||
it('!authn !authz anonymous /admin-auth// -> 401', async function () {
|
||||
settings.requireAuthentication = false;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').expect(401);
|
||||
await agent.get('/admin-auth/').expect(401);
|
||||
});
|
||||
|
||||
it('authn !authz anonymous / -> 401', async function () {
|
||||
|
@ -72,10 +72,10 @@ describe(__filename, function () {
|
|||
await agent.get('/').auth('user', 'user-password').expect(200);
|
||||
});
|
||||
|
||||
it('authn !authz user /admin/ -> 403', async function () {
|
||||
it('authn !authz user //admin-auth// -> 403', async function () {
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').auth('user', 'user-password').expect(403);
|
||||
await agent.get('/admin-auth//').auth('user', 'user-password').expect(403);
|
||||
});
|
||||
|
||||
it('authn !authz admin / -> 200', async function () {
|
||||
|
@ -84,10 +84,10 @@ describe(__filename, function () {
|
|||
await agent.get('/').auth('admin', 'admin-password').expect(200);
|
||||
});
|
||||
|
||||
it('authn !authz admin /admin/ -> 200', async function () {
|
||||
it('authn !authz admin /admin-auth/ -> 200', async function () {
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
|
||||
await agent.get('/admin-auth/').auth('admin', 'admin-password').expect(200);
|
||||
});
|
||||
|
||||
it('authn authz anonymous /robots.txt -> 200', async function () {
|
||||
|
@ -102,10 +102,10 @@ describe(__filename, function () {
|
|||
await agent.get('/').auth('user', 'user-password').expect(403);
|
||||
});
|
||||
|
||||
it('authn authz user /admin/ -> 403', async function () {
|
||||
it('authn authz user //admin-auth// -> 403', async function () {
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
await agent.get('/admin/').auth('user', 'user-password').expect(403);
|
||||
await agent.get('/admin-auth//').auth('user', 'user-password').expect(403);
|
||||
});
|
||||
|
||||
it('authn authz admin / -> 200', async function () {
|
||||
|
@ -114,10 +114,10 @@ describe(__filename, function () {
|
|||
await agent.get('/').auth('admin', 'admin-password').expect(200);
|
||||
});
|
||||
|
||||
it('authn authz admin /admin/ -> 200', async function () {
|
||||
it('authn authz admin /admin-auth/ -> 200', async function () {
|
||||
settings.requireAuthentication = true;
|
||||
settings.requireAuthorization = true;
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
|
||||
await agent.get('/admin-auth/').auth('admin', 'admin-password').expect(200);
|
||||
});
|
||||
|
||||
describe('login fails if password is nullish', function () {
|
||||
|
@ -130,7 +130,7 @@ describe(__filename, function () {
|
|||
it(`admin password: ${adminPassword} credentials: ${creds}`, async function () {
|
||||
settings.users.admin.password = adminPassword;
|
||||
const encCreds = Buffer.from(creds).toString('base64');
|
||||
await agent.get('/admin/').set('Authorization', `Basic ${encCreds}`).expect(401);
|
||||
await agent.get('/admin-auth/').set('Authorization', `Basic ${encCreds}`).expect(401);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -228,11 +228,11 @@ describe(__filename, function () {
|
|||
|
||||
it('cannot grant access to /admin', async function () {
|
||||
handlers.preAuthorize[0].innerHandle = () => [true];
|
||||
await agent.get('/admin/').expect(401);
|
||||
await agent.get('/admin-auth/').expect(401);
|
||||
// Notes:
|
||||
// * preAuthorize[1] is called despite preAuthorize[0] returning a non-empty list because
|
||||
// 'true' entries are ignored for /admin/* requests.
|
||||
// * The authenticate hook always runs for /admin/* requests even if
|
||||
// 'true' entries are ignored for /admin-auth//* requests.
|
||||
// * The authenticate hook always runs for /admin-auth//* requests even if
|
||||
// settings.requireAuthentication is false.
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
'preAuthorize_1',
|
||||
|
@ -240,9 +240,9 @@ describe(__filename, function () {
|
|||
'authenticate_1']);
|
||||
});
|
||||
|
||||
it('can deny access to /admin', async function () {
|
||||
it('can deny access to /admin-auth/', async function () {
|
||||
handlers.preAuthorize[0].innerHandle = () => [false];
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(403);
|
||||
await agent.get('/admin-auth/').auth('admin', 'admin-password').expect(403);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0']);
|
||||
});
|
||||
|
||||
|
@ -258,7 +258,7 @@ describe(__filename, function () {
|
|||
res.status(200).send('injected');
|
||||
return cb([true]);
|
||||
})];
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(200, 'injected');
|
||||
await agent.get('/admin-auth//').auth('admin', 'admin-password').expect(200, 'injected');
|
||||
assert(called);
|
||||
});
|
||||
|
||||
|
@ -274,15 +274,15 @@ describe(__filename, function () {
|
|||
settings.requireAuthorization = false;
|
||||
});
|
||||
|
||||
it('is not called if !requireAuthentication and not /admin/*', async function () {
|
||||
it('is not called if !requireAuthentication and not /admin-auth/*', async function () {
|
||||
settings.requireAuthentication = false;
|
||||
await agent.get('/').expect(200);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0', 'preAuthorize_1']);
|
||||
});
|
||||
|
||||
it('is called if !requireAuthentication and /admin/*', async function () {
|
||||
it('is called if !requireAuthentication and /admin-auth//*', async function () {
|
||||
settings.requireAuthentication = false;
|
||||
await agent.get('/admin/').expect(401);
|
||||
await agent.get('/admin-auth/').expect(401);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
'preAuthorize_1',
|
||||
'authenticate_0',
|
||||
|
@ -393,7 +393,7 @@ describe(__filename, function () {
|
|||
|
||||
it('is not called if !requireAuthorization (/admin)', async function () {
|
||||
settings.requireAuthorization = false;
|
||||
await agent.get('/admin/').auth('admin', 'admin-password').expect(200);
|
||||
await agent.get('/admin-auth/').auth('admin', 'admin-password').expect(200);
|
||||
assert.deepEqual(callOrder, ['preAuthorize_0',
|
||||
'preAuthorize_1',
|
||||
'authenticate_0',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue