From d55703c6be40af2144e9072dc8878a6b4ac9cb2f Mon Sep 17 00:00:00 2001 From: hady Date: Thu, 25 Apr 2024 18:40:51 +0530 Subject: [PATCH] Added req input validation on API routes --- src/app/api/admin/course/route.ts | 23 ++++++++++++++++++- src/app/api/admin/discord/refresh/route.ts | 18 +++++++++++++-- src/app/api/admin/discord/route.ts | 18 +++++++++++++-- src/app/api/admin/drm/route.ts | 19 +++++++++++++-- src/app/api/admin/segments/route.ts | 16 ++++++++++++- .../videoProgress/markAsCompleted/route.ts | 15 +++++++++++- src/app/api/course/videoProgress/route.ts | 16 ++++++++++++- 7 files changed, 115 insertions(+), 10 deletions(-) diff --git a/src/app/api/admin/course/route.ts b/src/app/api/admin/course/route.ts index d57ffc428..4d6389616 100644 --- a/src/app/api/admin/course/route.ts +++ b/src/app/api/admin/course/route.ts @@ -1,7 +1,28 @@ import { NextRequest, NextResponse } from 'next/server'; import db from '@/db'; +import { z } from 'zod'; + +const requestBodySchema = z.object({ + adminSecret: z.string(), + title: z.string(), + description: z.string(), + imageUrl: z.string().url().or(z.string()), + id: z.string(), + slug: z.string(), + appxCourseId: z.string(), + discordRoleId: z.string(), +}); export async function POST(req: NextRequest) { + const parseResult = requestBodySchema.safeParse(await req.json()); + + if (!parseResult.success) { + return NextResponse.json( + { error: parseResult.error.message }, + { status: 400 }, + ); + } + const { adminSecret, title, @@ -11,7 +32,7 @@ export async function POST(req: NextRequest) { slug, appxCourseId, discordRoleId, - } = await req.json(); + } = parseResult.data; if (adminSecret !== process.env.ADMIN_SECRET) { return NextResponse.json({}, { status: 401 }); diff --git a/src/app/api/admin/discord/refresh/route.ts b/src/app/api/admin/discord/refresh/route.ts index f635eb0ce..3c1f87adc 100644 --- a/src/app/api/admin/discord/refresh/route.ts +++ b/src/app/api/admin/discord/refresh/route.ts @@ -1,8 +1,22 @@ import db from '@/db'; import { NextRequest, NextResponse } from 'next/server'; +import { z } from 'zod'; + +const requestBodySchema = z.object({ + adminSecret: z.string(), + email: z.string().email(), +}); export async function POST(req: NextRequest) { - const { adminSecret, email } = await req.json(); + const parseResult = requestBodySchema.safeParse(await req.json()); + + if (!parseResult.success) { + return NextResponse.json( + { error: parseResult.error.message }, + { status: 400 }, + ); + } + const { adminSecret, email } = parseResult.data; if (adminSecret !== process.env.ADMIN_SECRET) { return NextResponse.json({}, { status: 401 }); @@ -15,7 +29,7 @@ export async function POST(req: NextRequest) { }); if (!user) { - return NextResponse.json({ msg: 'User not found' }, { status: 440 }); + return NextResponse.json({ msg: 'User not found' }, { status: 404 }); } await db.discordConnect.delete({ diff --git a/src/app/api/admin/discord/route.ts b/src/app/api/admin/discord/route.ts index ad9320861..e71fca2c7 100644 --- a/src/app/api/admin/discord/route.ts +++ b/src/app/api/admin/discord/route.ts @@ -1,8 +1,22 @@ import db from '@/db'; import { NextRequest, NextResponse } from 'next/server'; +import { z } from 'zod'; + +const requestBodySchema = z.object({ + adminSecret: z.string(), + email: z.string().email(), +}); export async function POST(req: NextRequest) { - const { adminSecret, email } = await req.json(); + const parseResult = requestBodySchema.safeParse(await req.json()); + + if (!parseResult.success) { + return NextResponse.json( + { error: parseResult.error.message }, + { status: 400 }, + ); + } + const { adminSecret, email } = parseResult.data; if (adminSecret !== process.env.ADMIN_SECRET) { return NextResponse.json({}, { status: 401 }); @@ -15,7 +29,7 @@ export async function POST(req: NextRequest) { }); if (!user) { - return NextResponse.json({ msg: 'User not found' }, { status: 440 }); + return NextResponse.json({ msg: 'User not found' }, { status: 404 }); } const response = await db.discordConnect.findFirst({ diff --git a/src/app/api/admin/drm/route.ts b/src/app/api/admin/drm/route.ts index 17e6077a1..286d77632 100644 --- a/src/app/api/admin/drm/route.ts +++ b/src/app/api/admin/drm/route.ts @@ -1,8 +1,23 @@ import db from '@/db'; import { NextRequest, NextResponse } from 'next/server'; +import { z } from 'zod'; + +const requestBodySchema = z.object({ + adminSecret: z.string(), + email: z.string().email(), + disableDrm: z.boolean(), +}); export async function POST(req: NextRequest) { - const { adminSecret, email, disableDrm } = await req.json(); + const parseResult = requestBodySchema.safeParse(await req.json()); + + if (!parseResult.success) { + return NextResponse.json( + { error: parseResult.error.message }, + { status: 400 }, + ); + } + const { adminSecret, email, disableDrm } = parseResult.data; if (adminSecret !== process.env.ADMIN_SECRET) { return NextResponse.json({}, { status: 401 }); @@ -15,7 +30,7 @@ export async function POST(req: NextRequest) { }); if (!user) { - return NextResponse.json({ msg: 'User not found' }, { status: 440 }); + return NextResponse.json({ msg: 'User not found' }, { status: 404 }); } const response = await db.user.update({ diff --git a/src/app/api/admin/segments/route.ts b/src/app/api/admin/segments/route.ts index 8dd50e48c..b88746535 100644 --- a/src/app/api/admin/segments/route.ts +++ b/src/app/api/admin/segments/route.ts @@ -1,8 +1,22 @@ import db from '@/db'; import { NextRequest, NextResponse } from 'next/server'; +import { z } from 'zod'; + +const requestBodySchema = z.object({ + adminSecret: z.string(), + contentId: z.number(), + segmentsJson: z.unknown(), +}); export async function POST(req: NextRequest) { - const { adminSecret, contentId, segmentsJson } = await req.json(); + const parseResult = requestBodySchema.safeParse(await req.json()); + if (!parseResult.success) { + return NextResponse.json( + { error: parseResult.error.message }, + { status: 400 }, + ); + } + const { adminSecret, contentId, segmentsJson } = parseResult.data; if (adminSecret !== process.env.ADMIN_SECRET) { return NextResponse.json({}, { status: 401 }); diff --git a/src/app/api/course/videoProgress/markAsCompleted/route.ts b/src/app/api/course/videoProgress/markAsCompleted/route.ts index 43ec76b94..44ec17cac 100644 --- a/src/app/api/course/videoProgress/markAsCompleted/route.ts +++ b/src/app/api/course/videoProgress/markAsCompleted/route.ts @@ -2,9 +2,22 @@ import { NextRequest, NextResponse } from 'next/server'; import db from '@/db'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/lib/auth'; +import { z } from 'zod'; + +const requestBodySchema = z.object({ + contentId: z.number(), + markAsCompleted: z.boolean(), +}); export async function POST(req: NextRequest) { - const { contentId, markAsCompleted } = await req.json(); + const parseResult = requestBodySchema.safeParse(req.json()); + if (!parseResult.success) { + return NextResponse.json( + { error: parseResult.error.message }, + { status: 400 }, + ); + } + const { contentId, markAsCompleted } = parseResult.data; const session = await getServerSession(authOptions); if (!session || !session?.user) { return NextResponse.json({}, { status: 401 }); diff --git a/src/app/api/course/videoProgress/route.ts b/src/app/api/course/videoProgress/route.ts index 15f3ffb14..d06003ab1 100644 --- a/src/app/api/course/videoProgress/route.ts +++ b/src/app/api/course/videoProgress/route.ts @@ -3,6 +3,7 @@ import db from '@/db'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/lib/auth'; import { revalidatePath } from 'next/cache'; +import { z } from 'zod'; export async function GET(req: NextRequest) { const url = new URL(req.url); @@ -26,8 +27,21 @@ export async function GET(req: NextRequest) { }); } +const requestBodySchema = z.object({ + contentId: z.number(), + currentTimestamp: z.number(), +}); + export async function POST(req: NextRequest) { - const { contentId, currentTimestamp } = await req.json(); + const parseResult = requestBodySchema.safeParse(req.json()); + if (!parseResult.success) { + return NextResponse.json( + { error: parseResult.error.message }, + { status: 400 }, + ); + } + const { contentId, currentTimestamp } = parseResult.data; + const session = await getServerSession(authOptions); if (!session || !session?.user) { return NextResponse.json({}, { status: 401 });