diff options
| author | Mohamed Bassem <me@mbassem.com> | 2025-07-10 21:22:54 +0000 |
|---|---|---|
| committer | Mohamed Bassem <me@mbassem.com> | 2025-07-10 22:03:30 +0000 |
| commit | 613137ff99442885c5fe679b2cc1172adfc5a283 (patch) | |
| tree | 97f2b940448357870090364c6f73b780d6f473d9 /packages/trpc/routers | |
| parent | 333d1610fad10e70759545f223959503288a02c6 (diff) | |
| download | karakeep-613137ff99442885c5fe679b2cc1172adfc5a283.tar.zst | |
feat: Add API ratelimits
Diffstat (limited to 'packages/trpc/routers')
| -rw-r--r-- | packages/trpc/routers/apiKeys.ts | 21 | ||||
| -rw-r--r-- | packages/trpc/routers/invites.ts | 21 | ||||
| -rw-r--r-- | packages/trpc/routers/users.ts | 22 |
3 files changed, 62 insertions, 2 deletions
diff --git a/packages/trpc/routers/apiKeys.ts b/packages/trpc/routers/apiKeys.ts index eb52189b..d4e01aa5 100644 --- a/packages/trpc/routers/apiKeys.ts +++ b/packages/trpc/routers/apiKeys.ts @@ -11,7 +11,12 @@ import { logAuthenticationError, validatePassword, } from "../auth"; -import { authedProcedure, publicProcedure, router } from "../index"; +import { + authedProcedure, + createRateLimitMiddleware, + publicProcedure, + router, +} from "../index"; const zApiKeySchema = z.object({ id: z.string(), @@ -70,6 +75,13 @@ export const apiKeysAppRouter = router({ // Exchange the username and password with an API key. // Homemade oAuth. This is used by the extension. exchange: publicProcedure + .use( + createRateLimitMiddleware({ + name: "apiKey.exchange", + windowMs: 15 * 60 * 1000, + maxRequests: 10, + }), + ) // 10 requests per 15 minutes .input( z.object({ keyName: z.string(), @@ -97,6 +109,13 @@ export const apiKeysAppRouter = router({ return await generateApiKey(input.keyName, user.id); }), validate: publicProcedure + .use( + createRateLimitMiddleware({ + name: "apiKey.validate", + windowMs: 60 * 1000, + maxRequests: 30, + }), + ) // 30 requests per minute .input(z.object({ apiKey: z.string() })) .output(z.object({ success: z.boolean() })) .mutation(async ({ input, ctx }) => { diff --git a/packages/trpc/routers/invites.ts b/packages/trpc/routers/invites.ts index 5f7897c5..0a98f36a 100644 --- a/packages/trpc/routers/invites.ts +++ b/packages/trpc/routers/invites.ts @@ -7,7 +7,12 @@ import { invites, users } from "@karakeep/db/schema"; import { generatePasswordSalt, hashPassword } from "../auth"; import { sendInviteEmail } from "../email"; -import { adminProcedure, publicProcedure, router } from "../index"; +import { + adminProcedure, + createRateLimitMiddleware, + publicProcedure, + router, +} from "../index"; import { createUserRaw } from "./users"; export const invitesAppRouter = router({ @@ -113,6 +118,13 @@ export const invitesAppRouter = router({ }), get: publicProcedure + .use( + createRateLimitMiddleware({ + name: "invites.get", + windowMs: 60 * 1000, + maxRequests: 10, + }), + ) .input( z.object({ token: z.string(), @@ -153,6 +165,13 @@ export const invitesAppRouter = router({ }), accept: publicProcedure + .use( + createRateLimitMiddleware({ + name: "invites.accept", + windowMs: 60 * 1000, + maxRequests: 10, + }), + ) .input( z.object({ token: z.string(), diff --git a/packages/trpc/routers/users.ts b/packages/trpc/routers/users.ts index 58093b42..ebe7d96f 100644 --- a/packages/trpc/routers/users.ts +++ b/packages/trpc/routers/users.ts @@ -31,6 +31,7 @@ import { adminProcedure, authedProcedure, Context, + createRateLimitMiddleware, publicProcedure, router, } from "../index"; @@ -124,6 +125,13 @@ export async function createUser( export const usersAppRouter = router({ create: publicProcedure + .use( + createRateLimitMiddleware({ + name: "users.create", + windowMs: 60 * 1000, + maxRequests: 3, + }), + ) .input(zSignUpSchema) .output( z.object({ @@ -541,6 +549,13 @@ export const usersAppRouter = router({ .where(eq(userSettings.userId, ctx.user.id)); }), verifyEmail: publicProcedure + .use( + createRateLimitMiddleware({ + name: "users.verifyEmail", + windowMs: 5 * 60 * 1000, + maxRequests: 10, + }), + ) // 10 requests per 5 minutes .input( z.object({ email: z.string().email(), @@ -572,6 +587,13 @@ export const usersAppRouter = router({ return { success: true }; }), resendVerificationEmail: publicProcedure + .use( + createRateLimitMiddleware({ + name: "users.resendVerificationEmail", + windowMs: 5 * 60 * 1000, + maxRequests: 3, + }), + ) // 3 requests per 5 minutes .input( z.object({ email: z.string().email(), |
