From 2ea468daa317b5a83632b6bbd2f7538c674826fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sun, 18 Apr 2021 21:38:47 -0400 Subject: [PATCH] test: clear cache between runs, require middleware later in helpers --- src/controllers/helpers.js | 4 ++-- src/middleware/index.js | 2 +- src/middleware/uploads.js | 34 +++++++++++++++++++--------------- src/routes/api.js | 2 +- src/routes/write/topics.js | 2 +- test/mocks/databasemock.js | 2 ++ test/uploads.js | 2 +- 7 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/controllers/helpers.js b/src/controllers/helpers.js index f33952f0a8..c28cc25d57 100644 --- a/src/controllers/helpers.js +++ b/src/controllers/helpers.js @@ -11,7 +11,6 @@ const privileges = require('../privileges'); const categories = require('../categories'); const plugins = require('../plugins'); const meta = require('../meta'); -const middleware = require('../middleware'); const helpers = module.exports; @@ -22,7 +21,7 @@ helpers.noScriptErrors = async function (req, res, error, httpStatus) { if (req.body.noscript !== 'true') { return res.status(httpStatus).send(error); } - + const middleware = require('../middleware'); const httpStatusString = httpStatus.toString(); await middleware.buildHeaderAsync(req, res); res.status(httpStatus).render(httpStatusString, { @@ -127,6 +126,7 @@ helpers.notAllowed = async function (req, res, error) { if (res.locals.isAPI) { helpers.formatApiResponse(403, res, error); } else { + const middleware = require('../middleware'); await middleware.buildHeaderAsync(req, res); res.status(403).render('403', { path: req.path, diff --git a/src/middleware/index.js b/src/middleware/index.js index 9de7a70a98..ea22f285af 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -66,7 +66,7 @@ Object.assign(middleware, { require('./render')(middleware); require('./maintenance')(middleware); require('./user')(middleware); -require('./uploads')(middleware); +middleware.uploads = require('./uploads'); require('./headers')(middleware); require('./expose')(middleware); middleware.assert = require('./assert'); diff --git a/src/middleware/uploads.js b/src/middleware/uploads.js index 92db36b990..32c012619d 100644 --- a/src/middleware/uploads.js +++ b/src/middleware/uploads.js @@ -5,24 +5,28 @@ const meta = require('../meta'); const helpers = require('./helpers'); const user = require('../user'); +console.log('----cooldown', meta.config.uploadRateLimitCooldown * 1000, new Error('a').stack); const cache = new LRU({ maxAge: meta.config.uploadRateLimitCooldown * 1000, }); -module.exports = function (middleware) { - middleware.ratelimitUploads = helpers.try(async (req, res, next) => { - const { uid } = req; - if (!meta.config.uploadRateLimitThreshold || (uid && await user.isAdminOrGlobalMod(uid))) { - return next(); - } +exports.clearCache = function () { + cache.reset(); +}; - const count = (cache.peek(`${req.ip}:uploaded_file_count`) || 0) + req.files.files.length; - console.log('req.ip', req.ip, count, req.files.files.length, meta.config.uploadRateLimitThreshold); - if (count > meta.config.uploadRateLimitThreshold) { - return next(new Error(['[[error:upload-ratelimit-reached]]'])); - } +exports.ratelimit = helpers.try(async (req, res, next) => { + const { uid } = req; + if (!meta.config.uploadRateLimitThreshold || (uid && await user.isAdminOrGlobalMod(uid))) { + return next(); + } + + const count = (cache.peek(`${req.ip}:uploaded_file_count`) || 0) + req.files.files.length; + console.log('req.ip', req.ip, count, req.files.files.length, meta.config.uploadRateLimitThreshold); + if (count > meta.config.uploadRateLimitThreshold) { + return next(new Error(['[[error:upload-ratelimit-reached]]'])); + } + + cache.set(`${req.ip}:uploaded_file_count`, count); + next(); +}); - cache.set(`${req.ip}:uploaded_file_count`, count); - next(); - }); -}; diff --git a/src/routes/api.js b/src/routes/api.js index 9e78f03705..2ac922308a 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -31,7 +31,7 @@ module.exports = function (app, middleware, controllers) { middleware.maintenanceMode, multipartMiddleware, middleware.validateFiles, - middleware.ratelimitUploads, + middleware.uploads.ratelimit, middleware.applyCSRF, ]; diff --git a/src/routes/write/topics.js b/src/routes/write/topics.js index 2e6e3bcbbe..9f7f009cef 100644 --- a/src/routes/write/topics.js +++ b/src/routes/write/topics.js @@ -36,7 +36,7 @@ module.exports = function () { setupApiRoute(router, 'delete', '/:tid/tags', [...middlewares, middleware.assert.topic], controllers.write.topics.deleteTags); setupApiRoute(router, 'get', '/:tid/thumbs', [], controllers.write.topics.getThumbs); - setupApiRoute(router, 'post', '/:tid/thumbs', [multipartMiddleware, middleware.validateFiles, middleware.ratelimitUploads, ...middlewares], controllers.write.topics.addThumb); + setupApiRoute(router, 'post', '/:tid/thumbs', [multipartMiddleware, middleware.validateFiles, middleware.uploads.ratelimit, ...middlewares], controllers.write.topics.addThumb); setupApiRoute(router, 'put', '/:tid/thumbs', [...middlewares, middleware.checkRequired.bind(null, ['tid'])], controllers.write.topics.migrateThumbs); setupApiRoute(router, 'delete', '/:tid/thumbs', [...middlewares, middleware.checkRequired.bind(null, ['path'])], controllers.write.topics.deleteThumb); setupApiRoute(router, 'put', '/:tid/thumbs/order', [...middlewares, middleware.checkRequired.bind(null, ['path', 'order'])], controllers.write.topics.reorderThumbs); diff --git a/test/mocks/databasemock.js b/test/mocks/databasemock.js index 0b001996b5..0b66306b2f 100644 --- a/test/mocks/databasemock.js +++ b/test/mocks/databasemock.js @@ -176,6 +176,7 @@ async function setupMockDefaults() { require('../../src/groups').cache.reset(); require('../../src/posts/cache').reset(); require('../../src/cache').reset(); + require('../../src/middleware/uploads').clearCache(); winston.info('test_database flushed'); await setupDefaultConfigs(meta); @@ -185,6 +186,7 @@ async function setupMockDefaults() { meta.config.initialPostDelay = 0; meta.config.newbiePostDelay = 0; meta.config.autoDetectLang = 0; + // meta.config.uploadRateLimitCooldown = 1; await enableDefaultPlugins(); diff --git a/test/uploads.js b/test/uploads.js index 8938f95897..0b57c0f139 100644 --- a/test/uploads.js +++ b/test/uploads.js @@ -79,7 +79,7 @@ describe('Upload Controllers', () => { it('should fail if the user exceeds the upload rate limit threshold', (done) => { const oldValue = meta.config.allowedFileExtensions; 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. console.log('times', (meta.config.uploadRateLimitThreshold / 2) + 1); const times = (meta.config.uploadRateLimitThreshold / 2) + 1;