Rate limits return!

This commit is contained in:
Atridad Lahiji 2023-07-24 23:09:02 -06:00 committed by atridadl
parent eddbcdf20a
commit d636f25bf7
No known key found for this signature in database
5 changed files with 314 additions and 273 deletions

View file

@ -5,6 +5,8 @@ DATABASE_URL=""
UPSTASH_REDIS_REST_URL="" UPSTASH_REDIS_REST_URL=""
UPSTASH_REDIS_REST_TOKEN="" UPSTASH_REDIS_REST_TOKEN=""
UPSTASH_REDIS_EXPIRY_SECONDS="" UPSTASH_REDIS_EXPIRY_SECONDS=""
UPSTASH_RATELIMIT_REQUESTS=""
UPSTASH_RATELIMIT_SECONDS=""
#Next Auth Core #Next Auth Core
NEXTAUTH_SECRET="" NEXTAUTH_SECRET=""

View file

@ -16,37 +16,38 @@
"@auth/prisma-adapter": "^1.0.1", "@auth/prisma-adapter": "^1.0.1",
"@prisma/client": "5.0.0", "@prisma/client": "5.0.0",
"@react-email/components": "^0.0.7", "@react-email/components": "^0.0.7",
"@tanstack/react-query": "^4.29.25", "@tanstack/react-query": "^4.32.0",
"@trpc/client": "10.34.0", "@trpc/client": "10.35.0",
"@trpc/next": "10.34.0", "@trpc/next": "10.35.0",
"@trpc/react-query": "10.34.0", "@trpc/react-query": "10.35.0",
"@trpc/server": "10.34.0", "@trpc/server": "10.35.0",
"@upstash/ratelimit": "^0.4.3",
"@upstash/redis": "^1.22.0", "@upstash/redis": "^1.22.0",
"ably": "^1.2.41", "ably": "^1.2.41",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
"json2csv": "6.0.0-alpha.2", "json2csv": "6.0.0-alpha.2",
"next": "^13.4.10", "next": "^13.4.12",
"next-auth": "^4.22.1", "next-auth": "^4.22.3",
"postcss": "^8.4.26", "postcss": "^8.4.27",
"preact": "^10.16.0", "preact": "^10.16.0",
"react": "18.2.0", "react": "18.2.0",
"react-email": "^1.9.4", "react-email": "^1.9.4",
"react-icons": "^4.10.1", "react-icons": "^4.10.1",
"resend": "^0.17.1", "resend": "^0.17.1",
"sharp": "^0.32.3", "sharp": "^0.32.4",
"superjson": "1.13.1", "superjson": "1.13.1",
"zod": "^3.21.4" "zod": "^3.21.4"
}, },
"devDependencies": { "devDependencies": {
"@types/eslint": "^8.44.0", "@types/eslint": "^8.44.0",
"@types/json2csv": "^5.0.3", "@types/json2csv": "^5.0.3",
"@types/node": "^20.4.2", "@types/node": "^20.4.4",
"@types/react": "^18.2.15", "@types/react": "^18.2.16",
"@typescript-eslint/eslint-plugin": "^6.1.0", "@typescript-eslint/eslint-plugin": "^6.2.0",
"@typescript-eslint/parser": "^6.1.0", "@typescript-eslint/parser": "^6.2.0",
"daisyui": "^3.2.1", "daisyui": "^3.4.0",
"eslint": "^8.45.0", "eslint": "^8.45.0",
"eslint-config-next": "^13.4.10", "eslint-config-next": "^13.4.12",
"prisma": "5.0.0", "prisma": "5.0.0",
"tailwindcss": "^3.3.3", "tailwindcss": "^3.3.3",
"typescript": "^5.1.6" "typescript": "^5.1.6"

516
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,8 @@ const server = z.object({
UPSTASH_REDIS_REST_URL: z.string().url(), UPSTASH_REDIS_REST_URL: z.string().url(),
UPSTASH_REDIS_REST_TOKEN: z.string(), UPSTASH_REDIS_REST_TOKEN: z.string(),
UPSTASH_REDIS_EXPIRY_SECONDS: z.string(), UPSTASH_REDIS_EXPIRY_SECONDS: z.string(),
UPSTASH_RATELIMIT_REQUESTS: z.string(),
UPSTASH_RATELIMIT_SECONDS: z.string(),
NODE_ENV: z.enum(["development", "test", "production"]), NODE_ENV: z.enum(["development", "test", "production"]),
NEXTAUTH_SECRET: NEXTAUTH_SECRET:
process.env.NODE_ENV === "production" process.env.NODE_ENV === "production"
@ -50,6 +52,8 @@ const processEnv = {
UPSTASH_REDIS_REST_URL: process.env.UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_URL: process.env.UPSTASH_REDIS_REST_URL,
UPSTASH_REDIS_REST_TOKEN: process.env.UPSTASH_REDIS_REST_TOKEN, UPSTASH_REDIS_REST_TOKEN: process.env.UPSTASH_REDIS_REST_TOKEN,
UPSTASH_REDIS_EXPIRY_SECONDS: process.env.UPSTASH_REDIS_EXPIRY_SECONDS, UPSTASH_REDIS_EXPIRY_SECONDS: process.env.UPSTASH_REDIS_EXPIRY_SECONDS,
UPSTASH_RATELIMIT_REQUESTS: process.env.UPSTASH_RATELIMIT_REQUESTS,
UPSTASH_RATELIMIT_SECONDS: process.env.UPSTASH_RATELIMIT_SECONDS,
NODE_ENV: process.env.NODE_ENV, NODE_ENV: process.env.NODE_ENV,
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL, NEXTAUTH_URL: process.env.NEXTAUTH_URL,

View file

@ -66,8 +66,10 @@ export const createTRPCContext = async (opts: CreateNextContextOptions) => {
* This is where the tRPC API is initialized, connecting the context and transformer. * This is where the tRPC API is initialized, connecting the context and transformer.
*/ */
import { initTRPC, TRPCError } from "@trpc/server"; import { initTRPC, TRPCError } from "@trpc/server";
import { Ratelimit } from "@upstash/ratelimit";
import superjson from "superjson"; import superjson from "superjson";
import { env } from "~/env.mjs"; import { env } from "~/env.mjs";
import { Redis } from "@upstash/redis";
const t = initTRPC.context<typeof createTRPCContext>().create({ const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson, transformer: superjson,
@ -106,11 +108,33 @@ const enforceRouteProtection = t.middleware(async ({ ctx, next }) => {
throw new TRPCError({ code: "UNAUTHORIZED" }); throw new TRPCError({ code: "UNAUTHORIZED" });
} }
return next({ try {
ctx: { const rateLimit = new Ratelimit({
session: { ...ctx.session, user: ctx.session.user }, redis: Redis.fromEnv(),
}, limiter: Ratelimit.slidingWindow(
}); Number(env.UPSTASH_RATELIMIT_REQUESTS),
`${Number(env.UPSTASH_RATELIMIT_SECONDS)}s`
),
analytics: true,
});
const { success } = await rateLimit.limit(
`${env.APP_ENV}_${ctx.session.user.id}`
);
if (!success) throw new TRPCError({ code: "TOO_MANY_REQUESTS" });
return next({
ctx: {
session: { ...ctx.session, user: ctx.session.user },
},
});
} catch {
return next({
ctx: {
session: { ...ctx.session, user: ctx.session.user },
},
});
}
}); });
/** /**