Skip to content

Commit

Permalink
Fixing Rate Limiting #8
Browse files Browse the repository at this point in the history
  • Loading branch information
david emioma committed Mar 31, 2024
1 parent 574a29d commit 65a63b0
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 28 deletions.
29 changes: 12 additions & 17 deletions actions/login.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use server";

import { signIn } from "@/auth";
import redis from "@/lib/redis";
import { redis } from "@/lib/redis";
import prismadb from "@/lib/prisma";
import { AuthError } from "next-auth";
import { headers } from "next/headers";
Expand All @@ -16,13 +16,21 @@ import { getTwoFactorConfirmationByUserId } from "@/data/two-factor-confirmation

const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(5, "60s"),
limiter: Ratelimit.slidingWindow(5, "5 m"),
});

export const login = async (
values: LoginValidator,
callbackUrl?: string | null
) => {
const ip = headers().get("x-forwarded-for") ?? "127.0.0.1";

const { success } = await ratelimit.limit(ip);

if (!success && process.env.VERCEL_ENV === "production") {
return { error: "Too Many Requests! try again in 5 min" };
}

const validatedFields = LoginSchema.safeParse(values);

if (!validatedFields.success) {
Expand Down Expand Up @@ -112,21 +120,8 @@ export const login = async (
}

try {
if (process.env.VERCEL_ENV === "production") {
const forwardedIps = headers()
.get("x-forwarded-for")
?.split(",")
.map((ip) => ip.trim());

const ip =
forwardedIps && forwardedIps?.length > 0 ? forwardedIps[0] : "";

const { success } = await ratelimit.limit(ip);

if (!success) {
return { error: "Too Many Requests! try again in 1 min" };
}
}
// if (process.env.VERCEL_ENV === "production") {
// }

await signIn("credentials", {
email,
Expand Down
16 changes: 16 additions & 0 deletions actions/register.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
"use server";

import bcrypt from "bcryptjs";
import { redis } from "@/lib/redis";
import prismadb from "@/lib/prisma";
import { headers } from "next/headers";
import { getUserByEmail } from "@/data/user";
import { Ratelimit } from "@upstash/ratelimit";
import { sendVerificationEmail } from "@/lib/mail";
import { generateVerificationToken } from "@/lib/token";
import { RegisterValidator, RegisterSchema } from "@/lib/validators/register";

const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(5, "5 m"),
});

export const register = async (values: RegisterValidator) => {
const ip = headers().get("x-forwarded-for") ?? "127.0.0.1";

const { success } = await ratelimit.limit(ip);

if (!success && process.env.VERCEL_ENV === "production") {
return { error: "Too Many Requests! try again in 5 min" };
}

const validatedFields = RegisterSchema.safeParse(values);

if (!validatedFields.success) {
Expand Down
29 changes: 22 additions & 7 deletions app/api/stores/[storeId]/products/[productId]/route.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
import prismadb from "@/lib/prisma";
import { redis } from "@/lib/redis";
import { NextResponse } from "next/server";
import { getCurrentPrice } from "@/lib/utils";
import { Ratelimit } from "@upstash/ratelimit";
import { UserRole, storeStatus } from "@prisma/client";
import { currentRole, currentUser } from "@/lib/auth";
import { ProductSchema } from "@/lib/validators/product";

const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(5, "60 s"),
});

export async function PATCH(
request: Request,
{ params }: { params: { storeId: string; productId: string } }
) {
try {
//Check if there is a current user
const { user } = await currentUser();

if (!user) {
return new NextResponse("Unauthorized", { status: 401 });
}

const { success } = await ratelimit.limit(user.id);

if (!success && process.env.VERCEL_ENV === "production") {
return new NextResponse("Too Many Requests! try again in 1 min", {
status: 429,
});
}

const { storeId, productId } = params;

if (!storeId) {
Expand All @@ -20,13 +42,6 @@ export async function PATCH(
return new NextResponse("Product Id is required", { status: 400 });
}

//Check if there is a current user
const { user } = await currentUser();

if (!user) {
return new NextResponse("Unauthorized", { status: 401 });
}

//Check if user is a seller
const { role } = await currentRole();

Expand Down
17 changes: 16 additions & 1 deletion app/api/stores/[storeId]/products/new/route.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import prismadb from "@/lib/prisma";
import { redis } from "@/lib/redis";
import { NextResponse } from "next/server";
import { UserRole, storeStatus } from "@prisma/client";
import { getCurrentPrice } from "@/lib/utils";
import { Ratelimit } from "@upstash/ratelimit";
import { UserRole, storeStatus } from "@prisma/client";
import { currentRole, currentUser } from "@/lib/auth";
import { ProductSchema } from "@/lib/validators/product";

const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(5, "60 s"),
});

export async function POST(
request: Request,
{ params }: { params: { storeId: string } }
Expand All @@ -23,6 +30,14 @@ export async function POST(
return new NextResponse("Unauthorized", { status: 401 });
}

const { success } = await ratelimit.limit(user.id);

if (!success && process.env.VERCEL_ENV === "production") {
return new NextResponse("Too Many Requests! try again in 1 min", {
status: 429,
});
}

//Check if user is a seller
const { role } = await currentRole();

Expand Down
5 changes: 2 additions & 3 deletions lib/redis.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Redis } from "@upstash/redis";
import { Ratelimit } from "@upstash/ratelimit";

const redis = new Redis({
export const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL as string,
token: process.env.UPSTASH_REDIS_REST_TOKEN as string,
});

export default redis;

0 comments on commit 65a63b0

Please sign in to comment.