diff --git a/src/meta/themes.js b/src/meta/themes.js index a0c42f4708..d757cfb9ec 100644 --- a/src/meta/themes.js +++ b/src/meta/themes.js @@ -108,7 +108,7 @@ Themes.set = async (data) => { await db.sortedSetAdd('plugins:active', numPlugins, data.id); } else if (!activePluginsConfig.includes(data.id)) { // This prevents changing theme when configuration doesn't include it, but allows it otherwise - winston.error('When defining active plugins in configuration, changing themes requires adding the new theme to the list of active plugins before updating it in the ACP'); + winston.error(`When defining active plugins in configuration, changing themes requires adding the theme '${data.id}' to the list of active plugins before updating it in the ACP`); throw new Error('[[error:theme-not-set-in-configuration]]'); } diff --git a/src/middleware/index.js b/src/middleware/index.js index e174febe51..a92501a7b9 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -104,11 +104,20 @@ middleware.pluginHooks = helpers.try(async (req, res, next) => { }); middleware.validateFiles = function validateFiles(req, res, next) { - if (!Array.isArray(req.files.files) || !req.files.files.length) { + if (!req.files.files) { return next(new Error(['[[error:invalid-files]]'])); } - next(); + if (Array.isArray(req.files.files) && req.files.files.length) { + return next(); + } + + if (typeof req.files.files === 'object') { + req.files.files = [req.files.files]; + return next(); + } + + return next(new Error(['[[error:invalid-files]]'])); }; middleware.prepareAPI = function prepareAPI(req, res, next) { diff --git a/test/helpers/index.js b/test/helpers/index.js index 7ca8462006..b79bf66e2d 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -122,7 +122,6 @@ helpers.uploadFile = function (uploadEndPoint, filePath, body, jar, csrf_token, let formData = { files: [ fs.createReadStream(filePath), - fs.createReadStream(filePath), // see https://github.com/request/request/issues/2445 ], }; formData = utils.merge(formData, body); diff --git a/test/uploads.js b/test/uploads.js index 5be0818b5e..11aea1bedd 100644 --- a/test/uploads.js +++ b/test/uploads.js @@ -88,7 +88,7 @@ describe('Upload Controllers', () => { meta.config.allowedFileExtensions = 'png,jpg,bmp,html'; require('../src/middleware/uploads').clearCache(); // why / 2? see: helpers.uploadFile for a weird quirk where we actually upload 2 files per upload in our tests. - const times = (meta.config.uploadRateLimitThreshold / 2) + 1; + const times = (meta.config.uploadRateLimitThreshold) + 1; async.timesSeries(times, (i, next) => { helpers.uploadFile(`${nconf.get('url')}/api/post/upload`, path.join(__dirname, '../test/files/503.html'), {}, jar, csrf_token, (err, res, body) => { if (i + 1 >= times) { @@ -522,7 +522,7 @@ describe('Upload Controllers', () => { it('should return files with no post associated with them', async () => { const orphans = await posts.uploads.getOrphans(); - assert.strictEqual(orphans.length, 2); + assert.strictEqual(orphans.length, 1); orphans.forEach((relPath) => { assert(relPath.startsWith('files/')); assert(relPath.endsWith('test.png')); @@ -553,7 +553,7 @@ describe('Upload Controllers', () => { await posts.uploads.cleanOrphans(); const orphans = await posts.uploads.getOrphans(); - assert.strictEqual(orphans.length, 2); + assert.strictEqual(orphans.length, 1); }); it('should not touch orphans if they are newer than the configured expiry', async () => { @@ -561,7 +561,7 @@ describe('Upload Controllers', () => { await posts.uploads.cleanOrphans(); const orphans = await posts.uploads.getOrphans(); - assert.strictEqual(orphans.length, 2); + assert.strictEqual(orphans.length, 1); }); it('should delete orphans older than the configured number of days', async () => {