From 0727570e1fbee729fe2327e0764722c368c89718 Mon Sep 17 00:00:00 2001 From: underscope Date: Thu, 25 Nov 2021 13:42:46 +0100 Subject: [PATCH 1/3] Updated request limiter - Fixed issue with store due to missing ttl - Create new store for different ttl --- server/shared/request/mw.js | 31 +++++++++++++++++++++---------- server/user/mw.js | 1 + 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/server/shared/request/mw.js b/server/shared/request/mw.js index fd49538f1..1aab815d9 100644 --- a/server/shared/request/mw.js +++ b/server/shared/request/mw.js @@ -4,16 +4,19 @@ const rateLimit = require('express-rate-limit'); const Tapster = require('@extensionengine/tapster'); const { provider, ...options } = require('../../../config/server').store; -const DEFAULT_WINDOW_MS = 15 * 60 * 1000; // every 15 minutes +const DEFAULT_STORE_NAMESPACE = 'default-request-limiter'; +const DEFAULT_WINDOW_MINUTES = 5; +const DEFAULT_WINDOW_MS = DEFAULT_WINDOW_MINUTES * 60 * 1000; // Store must be implemented using the following interface: // https://github.com/nfriedly/express-rate-limit/blob/master/README.md#store class Store { - constructor() { + constructor(namespace, ttlMs) { this.cache = new Tapster({ ...options[provider], store: provider, - namespace: 'request-limiter' + namespace, + ttl: ttlMs / 1000 // Tapster expects input in seconds }); } @@ -37,14 +40,22 @@ class Store { } } -const defaultStore = new Store(); +const defaultStore = new Store(DEFAULT_STORE_NAMESPACE, DEFAULT_WINDOW_MS); + +function requestLimiter({ max = 10, namespace, windowMs, ...opts } = {}) { + let store; + // If namespace and windowMs are not provided, use the default store + if (!namespace && !windowMs) { + store = defaultStore; + windowMs = DEFAULT_WINDOW_MS; + } else if (namespace && windowMs) { + store = new Store(namespace, windowMs); + } else { + throw new Error(` + Namespace and windowMs are required to create a custom store. + Omit both for default store with ${DEFAULT_WINDOW_MINUTES}min window.`); + } -function requestLimiter({ - max = 10, - windowMs = DEFAULT_WINDOW_MS, - store = defaultStore, - ...opts -} = {}) { return rateLimit({ max, windowMs, store, ...opts }); } diff --git a/server/user/mw.js b/server/user/mw.js index 9c9dc3fff..a17a97797 100644 --- a/server/user/mw.js +++ b/server/user/mw.js @@ -6,6 +6,7 @@ const { requestLimiter } = require('../shared/request/mw'); const ONE_HOUR_IN_MS = 60 * 60 * 1000; const loginRequestLimiter = requestLimiter({ + namespace: 'login-request-limiter', windowMs: ONE_HOUR_IN_MS, keyGenerator: req => req.userKey }); From 36ffeb484b65eb255303ab7ebde71a265076e9f6 Mon Sep 17 00:00:00 2001 From: underscope Date: Thu, 25 Nov 2021 14:04:12 +0100 Subject: [PATCH 2/3] Added JSDoc for store constructor --- server/shared/request/mw.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/shared/request/mw.js b/server/shared/request/mw.js index 1aab815d9..097c12893 100644 --- a/server/shared/request/mw.js +++ b/server/shared/request/mw.js @@ -11,12 +11,16 @@ const DEFAULT_WINDOW_MS = DEFAULT_WINDOW_MINUTES * 60 * 1000; // Store must be implemented using the following interface: // https://github.com/nfriedly/express-rate-limit/blob/master/README.md#store class Store { - constructor(namespace, ttlMs) { + /** + * @param {string} namespace namespace for the keys that need to be stored + * @param {number} windowMs ttl in milliseconds + */ + constructor(namespace, windowMs) { this.cache = new Tapster({ ...options[provider], store: provider, namespace, - ttl: ttlMs / 1000 // Tapster expects input in seconds + ttl: windowMs / 1000 // Tapster expects input in seconds }); } From a908675348a100850e1cfb0d08a754968d35d87b Mon Sep 17 00:00:00 2001 From: underscope Date: Thu, 25 Nov 2021 14:14:38 +0100 Subject: [PATCH 3/3] :lipstick: --- server/shared/request/mw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/shared/request/mw.js b/server/shared/request/mw.js index 097c12893..ba093ed51 100644 --- a/server/shared/request/mw.js +++ b/server/shared/request/mw.js @@ -56,7 +56,7 @@ function requestLimiter({ max = 10, namespace, windowMs, ...opts } = {}) { store = new Store(namespace, windowMs); } else { throw new Error(` - Namespace and windowMs are required to create a custom store. + namespace and windowMs are required to create a custom store. Omit both for default store with ${DEFAULT_WINDOW_MINUTES}min window.`); }