diff --git a/Notesnook.Inbox.API/bun.lock b/Notesnook.Inbox.API/bun.lock index 39da6f3..22dbdc6 100644 --- a/Notesnook.Inbox.API/bun.lock +++ b/Notesnook.Inbox.API/bun.lock @@ -5,6 +5,7 @@ "name": "notesnook-inbox-api", "dependencies": { "express": "^5.1.0", + "express-rate-limit": "^8.1.0", "libsodium-wrappers-sumo": "^0.7.15", "zod": "^4.1.9", }, @@ -83,6 +84,8 @@ "express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="], + "express-rate-limit": ["express-rate-limit@8.1.0", "", { "dependencies": { "ip-address": "10.0.1" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-4nLnATuKupnmwqiJc27b4dCFmB/T60ExgmtDD7waf4LdrbJ8CPZzZRHYErDYNhoz+ql8fUdYwM/opf90PoPAQA=="], + "finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="], "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], @@ -107,6 +110,8 @@ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + "ip-address": ["ip-address@10.0.1", "", {}, "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA=="], + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], diff --git a/Notesnook.Inbox.API/package.json b/Notesnook.Inbox.API/package.json index 054fc18..2195ffa 100644 --- a/Notesnook.Inbox.API/package.json +++ b/Notesnook.Inbox.API/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "express": "^5.1.0", + "express-rate-limit": "^8.1.0", "libsodium-wrappers-sumo": "^0.7.15", "zod": "^4.1.9" }, diff --git a/Notesnook.Inbox.API/src/index.ts b/Notesnook.Inbox.API/src/index.ts index bd58ddf..ec6a626 100644 --- a/Notesnook.Inbox.API/src/index.ts +++ b/Notesnook.Inbox.API/src/index.ts @@ -1,6 +1,7 @@ import express from "express"; import _sodium, { base64_variants } from "libsodium-wrappers-sumo"; import { z } from "zod"; +import { rateLimit } from "express-rate-limit"; const NOTESNOOK_API_SERVER_URL = process.env.NOTESNOOK_API_SERVER_URL; if (!NOTESNOOK_API_SERVER_URL) { @@ -126,6 +127,12 @@ async function postEncryptedInboxItem( const app = express(); app.use(express.json({ limit: "10mb" })); +app.use( + rateLimit({ + windowMs: 1 * 60 * 1000, // 1 minute + limit: 60, + }) +); app.post("/inbox", async (req, res) => { try { const apiKey = req.headers["authorization"];