From f503e61748e3e12cadcb76c67f975ca0d4800f06 Mon Sep 17 00:00:00 2001 From: Sam Poder Date: Tue, 24 Oct 2023 14:23:03 -0700 Subject: [PATCH] Add Protection on Organiser API Routes --- .../hackathons/[slug]/check-in/[attendee].ts | 5 ++-- .../hackathons/[slug]/data/create.ts | 5 ++-- .../hackathons/[slug]/data/delete.ts | 5 ++-- .../organizer/hackathons/[slug]/data/form.ts | 14 ++------- .../organizer/hackathons/[slug]/data/save.ts | 13 +++----- .../hackathons/[slug]/data/schema.ts | 5 ++-- .../hackathons/[slug]/features/leads.ts | 5 ++-- .../hackathons/[slug]/features/sponsors.ts | 5 ++-- .../api/organizer/hackathons/[slug]/index.ts | 30 ++++++++++++++++--- pages/api/organizer/hackathons/create.ts | 2 -- 10 files changed, 51 insertions(+), 38 deletions(-) diff --git a/pages/api/organizer/hackathons/[slug]/check-in/[attendee].ts b/pages/api/organizer/hackathons/[slug]/check-in/[attendee].ts index baef79b..ac81e2f 100644 --- a/pages/api/organizer/hackathons/[slug]/check-in/[attendee].ts +++ b/pages/api/organizer/hackathons/[slug]/check-in/[attendee].ts @@ -1,13 +1,14 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import { NextApiRequest, NextApiResponse } from "next"; +import { getHackathon } from ".."; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); + const hackathon = await getHackathon(req, res) + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); const { attendee, slug } = req.query; diff --git a/pages/api/organizer/hackathons/[slug]/data/create.ts b/pages/api/organizer/hackathons/[slug]/data/create.ts index 4239499..3a3940d 100644 --- a/pages/api/organizer/hackathons/[slug]/data/create.ts +++ b/pages/api/organizer/hackathons/[slug]/data/create.ts @@ -2,13 +2,14 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import type { Attendee } from "@prisma/client"; import { NextApiRequest, NextApiResponse } from "next"; +import { getHackathon } from ".."; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); + const hackathon = await getHackathon(req, res) + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); let attendee: Attendee = await prisma.attendee.create({ data: { email: req.body.email, diff --git a/pages/api/organizer/hackathons/[slug]/data/delete.ts b/pages/api/organizer/hackathons/[slug]/data/delete.ts index e71a9fe..449a65b 100644 --- a/pages/api/organizer/hackathons/[slug]/data/delete.ts +++ b/pages/api/organizer/hackathons/[slug]/data/delete.ts @@ -1,13 +1,14 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import { NextApiRequest, NextApiResponse } from "next"; +import { getHackathon } from ".."; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); + const hackathon = await getHackathon(req, res) + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); const { ids } = req.body; diff --git a/pages/api/organizer/hackathons/[slug]/data/form.ts b/pages/api/organizer/hackathons/[slug]/data/form.ts index 35a0421..f458e92 100644 --- a/pages/api/organizer/hackathons/[slug]/data/form.ts +++ b/pages/api/organizer/hackathons/[slug]/data/form.ts @@ -1,7 +1,7 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import { NextApiRequest, NextApiResponse } from "next"; - +import { getHackathon } from ".."; import type { AttendeeAttribute, Hackathon } from "@prisma/client"; type HackathonWithAttributes = Hackathon & { @@ -12,16 +12,8 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); - let hackathon = (await prisma.hackathon.findUnique({ - where: { - slug: req.query.slug as string - }, - include: { - attendeeAttributes: true - } - })) as HackathonWithAttributes; + const hackathon = await getHackathon(req, res, {attendeeAttributes: true}) as HackathonWithAttributes | null + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); let newData: any = {}; Object.keys(req.body).map((x) => { let id = x.split("_")[0]; diff --git a/pages/api/organizer/hackathons/[slug]/data/save.ts b/pages/api/organizer/hackathons/[slug]/data/save.ts index 5a9fef8..c036af5 100644 --- a/pages/api/organizer/hackathons/[slug]/data/save.ts +++ b/pages/api/organizer/hackathons/[slug]/data/save.ts @@ -6,6 +6,7 @@ import { getAuth } from "@clerk/nextjs/server"; import type { AttendeeAttributeValue } from "@prisma/client"; import { NextApiRequest, NextApiResponse } from "next"; import { v4 as uuidv4 } from "uuid"; +import { getHackathon } from ".."; function c(x: T): T { console.log(x); @@ -16,8 +17,8 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); + const hackathon = await getHackathon(req, res, {attendeeAttributes: true}) as HackathonWithAttributes | null + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); try { let newData = req.body as { shape: Column[]; content: string[][] }; @@ -31,13 +32,7 @@ export default async function handler( if (hackathon == null) throw new Error("no hackathon!"); - const attendeeAttributes = await prisma.attendeeAttribute.findMany({ - where: { - hackathon: { - slug: slug as string - } - } - }); + const attendeeAttributes = hackathon.attendeeAttributes const toCreateAttributes = newData.shape .map((column, i) => ({ diff --git a/pages/api/organizer/hackathons/[slug]/data/schema.ts b/pages/api/organizer/hackathons/[slug]/data/schema.ts index 2ba8c77..49f4ec5 100644 --- a/pages/api/organizer/hackathons/[slug]/data/schema.ts +++ b/pages/api/organizer/hackathons/[slug]/data/schema.ts @@ -1,13 +1,14 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import { NextApiRequest, NextApiResponse } from "next"; +import { getHackathon } from ".."; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); + const hackathon = await getHackathon(req, res) + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); let attributes: { [key: string]: { name?: string; type?: string; options?: string[] }; } = {}; diff --git a/pages/api/organizer/hackathons/[slug]/features/leads.ts b/pages/api/organizer/hackathons/[slug]/features/leads.ts index d978ea5..a30a109 100644 --- a/pages/api/organizer/hackathons/[slug]/features/leads.ts +++ b/pages/api/organizer/hackathons/[slug]/features/leads.ts @@ -1,13 +1,14 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import { NextApiRequest, NextApiResponse } from "next"; +import { getHackathon } from ".."; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); + const hackathon = await getHackathon(req, res) + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); try { switch (req.method) { case "GET": diff --git a/pages/api/organizer/hackathons/[slug]/features/sponsors.ts b/pages/api/organizer/hackathons/[slug]/features/sponsors.ts index 7e43422..d589775 100644 --- a/pages/api/organizer/hackathons/[slug]/features/sponsors.ts +++ b/pages/api/organizer/hackathons/[slug]/features/sponsors.ts @@ -1,13 +1,14 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import { NextApiRequest, NextApiResponse } from "next"; +import { getHackathon } from ".."; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); + const hackathon = await getHackathon(req, res) + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); try { switch (req.method) { case "GET": diff --git a/pages/api/organizer/hackathons/[slug]/index.ts b/pages/api/organizer/hackathons/[slug]/index.ts index 90ee7d7..545037b 100644 --- a/pages/api/organizer/hackathons/[slug]/index.ts +++ b/pages/api/organizer/hackathons/[slug]/index.ts @@ -1,18 +1,40 @@ import prisma from "@/lib/prisma"; import { getAuth } from "@clerk/nextjs/server"; import { NextApiRequest, NextApiResponse } from "next"; +import { HackathonPolicy } from "@/lib/permissions"; + +export async function getHackathon(req: NextApiRequest, res: NextApiResponse, include?: any) { + const { userId } = getAuth(req); + if (!userId) return null; + const { slug } = req.query; + const hackathon = await prisma.hackathon.delete({ + where: { + slug: slug as string + }, + include: { + attendees: true + } + }); + if ( + hackathon == null || + userId == null || + !new HackathonPolicy(hackathon).canOrganizerAccess({ id: userId }) + ) { + return null; + } + return hackathon; +} export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const { userId } = getAuth(req); - if (!userId) return res.status(401).json({ error: "Unauthorized" }); - + const hackathon = await getHackathon(req, res) + if (!hackathon) return res.status(401).json({ error: "Unauthorized" }); switch (req.method) { case "DELETE": { const { slug } = req.query; - const hackathon = await prisma.hackathon.delete({ + await prisma.hackathon.delete({ where: { slug: slug as string } diff --git a/pages/api/organizer/hackathons/create.ts b/pages/api/organizer/hackathons/create.ts index 8cd113e..7620a2e 100644 --- a/pages/api/organizer/hackathons/create.ts +++ b/pages/api/organizer/hackathons/create.ts @@ -27,8 +27,6 @@ export default async function handler( } }); - console.log({ hackathon }); - res.redirect(`/${hackathon.slug}`); } catch (error) { console.error(error);