summaryrefslogtreecommitdiffstats
path: root/server/rate-limiter.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/rate-limiter.js')
-rw-r--r--server/rate-limiter.js75
1 files changed, 75 insertions, 0 deletions
diff --git a/server/rate-limiter.js b/server/rate-limiter.js
new file mode 100644
index 0000000..3c269b6
--- /dev/null
+++ b/server/rate-limiter.js
@@ -0,0 +1,75 @@
+const { RateLimiter } = require("limiter");
+const { log } = require("../src/util");
+
+class KumaRateLimiter {
+ /**
+ * @param {object} config Rate limiter configuration object
+ */
+ constructor(config) {
+ this.errorMessage = config.errorMessage;
+ this.rateLimiter = new RateLimiter(config);
+ }
+
+ /**
+ * Callback for pass
+ * @callback passCB
+ * @param {object} err Too many requests
+ */
+
+ /**
+ * Should the request be passed through
+ * @param {passCB} callback Callback function to call with decision
+ * @param {number} num Number of tokens to remove
+ * @returns {Promise<boolean>} Should the request be allowed?
+ */
+ async pass(callback, num = 1) {
+ const remainingRequests = await this.removeTokens(num);
+ log.info("rate-limit", "remaining requests: " + remainingRequests);
+ if (remainingRequests < 0) {
+ if (callback) {
+ callback({
+ ok: false,
+ msg: this.errorMessage,
+ });
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Remove a given number of tokens
+ * @param {number} num Number of tokens to remove
+ * @returns {Promise<number>} Number of remaining tokens
+ */
+ async removeTokens(num = 1) {
+ return await this.rateLimiter.removeTokens(num);
+ }
+}
+
+const loginRateLimiter = new KumaRateLimiter({
+ tokensPerInterval: 20,
+ interval: "minute",
+ fireImmediately: true,
+ errorMessage: "Too frequently, try again later."
+});
+
+const apiRateLimiter = new KumaRateLimiter({
+ tokensPerInterval: 60,
+ interval: "minute",
+ fireImmediately: true,
+ errorMessage: "Too frequently, try again later."
+});
+
+const twoFaRateLimiter = new KumaRateLimiter({
+ tokensPerInterval: 30,
+ interval: "minute",
+ fireImmediately: true,
+ errorMessage: "Too frequently, try again later."
+});
+
+module.exports = {
+ loginRateLimiter,
+ apiRateLimiter,
+ twoFaRateLimiter,
+};