diff --git a/settings.json.docker b/settings.json.docker index 725af9f31..ea25bba42 100644 --- a/settings.json.docker +++ b/settings.json.docker @@ -634,5 +634,10 @@ "customLocaleStrings": {}, /* Disable Admin UI tests */ - "enableAdminUITests": false + "enableAdminUITests": false, + + /* + * Enable/Disable case-insensitive pad names. + */ + "enforceLowerCasePadIds": "${ENFORCE_LOWER_CASE_PAD_IDS:false}" } diff --git a/settings.json.template b/settings.json.template index b2cb9555a..13124fcfa 100644 --- a/settings.json.template +++ b/settings.json.template @@ -635,5 +635,10 @@ "customLocaleStrings": {}, /* Disable Admin UI tests */ - "enableAdminUITests": false + "enableAdminUITests": false, + + /* + * Enable/Disable case-insensitive pad names. + */ + "enforceLowerCasePadIds": false } diff --git a/src/node/db/PadManager.js b/src/node/db/PadManager.js index e419e8392..bbd227bd1 100644 --- a/src/node/db/PadManager.js +++ b/src/node/db/PadManager.js @@ -22,6 +22,7 @@ const CustomError = require('../utils/customError'); const Pad = require('../db/Pad'); const db = require('./DB'); +const settings = require('../utils/Settings'); /** * A cache of all loaded Pads. @@ -170,6 +171,8 @@ exports.sanitizePadId = async (padId) => { padId = padId.replace(from, to); } + if (settings.enforceLowerCasePadIds) padId = padId.toLowerCase(); + // we're out of possible transformations, so just return it return padId; }; diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index 51f48237a..67b6e1028 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -430,6 +430,11 @@ exports.importMaxFileSize = 50 * 1024 * 1024; */ exports.enableAdminUITests = false; +/* + * Enable auto conversion of pad Ids to lowercase. + * e.g. /p/EtHeRpAd to /p/ehtherpad + */ +exports.enforceLowerCasePadIds = false; // checks if abiword is avaiable exports.abiwordAvailable = () => { diff --git a/src/tests/backend/specs/enforceLowerCasePadIds.js b/src/tests/backend/specs/enforceLowerCasePadIds.js new file mode 100644 index 000000000..458e380f9 --- /dev/null +++ b/src/tests/backend/specs/enforceLowerCasePadIds.js @@ -0,0 +1,69 @@ +'use strict'; + +const assert = require('assert').strict; +const common = require('../common'); +const padManager = require('../../../node/db/PadManager'); +const settings = require('../../../node/utils/Settings'); + +describe(__filename, function () { + this.timeout(30000); + let agent; + const cleanUpPads = async () => { + const padIds = ['UPPERCASEpad', 'uppercasepad', 'ALREADYexistingPad', 'alreadyexistingpad']; + await Promise.all(padIds.map(async (padId) => { + if (await padManager.doesPadExist(padId)) { + const pad = await padManager.getPad(padId); + await pad.remove(); + } + })); + }; + + before(async function () { agent = await common.init(); }); + beforeEach(async function () { + await cleanUpPads(); + }); + afterEach(async function () { + await cleanUpPads(); + }); + + describe('not activated', function () { + Object.assign(settings, { + enforceLowerCasePadIds: false, + }); + it('- do nothing', async function () { + const res = await agent.get('/p/UPPERCASEpad'); + assert.equal(res.status, 200); + }); + + it('- do nothingg', async function () { + await agent.get('/p/UPPERCASEpad') + .expect(200); + }); + }); + + describe('activated', function () { + it('- lowercase pad ids', async function () { + Object.assign(settings, { + enforceLowerCasePadIds: true, + }); + await agent.get('/p/UPPERCASEpad') + .expect(302) + .expect('location', 'uppercasepad'); + }); + + it('- keeps old pads accessible', async function () { + Object.assign(settings, { + enforceLowerCasePadIds: false, + }); + const pad = await padManager.getPad('ALREADYexistingPad', 'alreadyexistingpad'); + await padManager.getPad('ALREADYexistingPad', 'bla'); + assert.equal(pad.text(), 'alreadyexistingpad\n'); + Object.assign(settings, { + enforceLowerCasePadIds: true, + }); + + const newpad = await padManager.getPad('alreadyexistingpad', 'testcontent'); + assert.equal(newpad.text(), 'testcontent\n'); + }); + }); +});