diff --git a/src/pages/api/external/ping.ts b/src/pages/api/external/ping.ts index 1f495da..e0d8100 100644 --- a/src/pages/api/external/ping.ts +++ b/src/pages/api/external/ping.ts @@ -6,9 +6,9 @@ export default async function handler( req: NextApiRequest, res: NextApiResponse ) { - const success = await validateRequest(req, res); + const isValid = await validateRequest(req, res); - if (success) { + if (isValid) { await db.query.votes.findFirst(); res.status(200).json({ result: "Pong!" }); } diff --git a/src/pages/api/webhooks/index.ts b/src/pages/api/webhooks/index.ts index 7b712ab..b699ab2 100644 --- a/src/pages/api/webhooks/index.ts +++ b/src/pages/api/webhooks/index.ts @@ -4,7 +4,7 @@ import { onUserCreatedHandler, onUserDeletedHandler, } from "~/server/webhookHelpers"; -import { type WebhookEvent, WebhookEvents } from "~/utils/types"; +import { WebhookEventBodySchema, WebhookEvents } from "~/utils/types"; export default async function handler( req: NextApiRequest, @@ -16,36 +16,24 @@ export default async function handler( return; } - const requestBody = req.body as { - data: { - id: string; - email_addresses: - | [ - { - email_address: string; - id: string; - verification: { - status: string; - strategy: string; - }; - } - ] - | null; - }; - type: WebhookEvent; - }; + try { + const requestBody = WebhookEventBodySchema.parse(req.body); - switch (requestBody.type) { - case WebhookEvents.USER_CREATED: - await onUserCreatedHandler(requestBody.data.id, res); - return; + switch (requestBody.type) { + case WebhookEvents.USER_CREATED: + await onUserCreatedHandler(requestBody.data.id, res); + return; - case WebhookEvents.USER_DELETED: - await onUserDeletedHandler(requestBody.data.id, res); - return; + case WebhookEvents.USER_DELETED: + await onUserDeletedHandler(requestBody.data.id, res); + return; - default: - res.status(400).json({ error: "INVALID WEBHOOK EVENT" }); - return; + default: + res.status(400).json({ error: "INVALID WEBHOOK EVENT TYPE" }); + return; + } + } catch { + res.status(400).json({ error: "INVALID WEBHOOK EVENT BODY" }); + return; } } diff --git a/src/utils/types.ts b/src/utils/types.ts index 883414e..a41fb24 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,3 +1,5 @@ +import { z } from "zod"; + type BetterEnum = T[keyof T]; export const EventTypes = { @@ -14,6 +16,27 @@ export const WebhookEvents = { } as const; export type WebhookEvent = BetterEnum; +export const WebhookEventBodySchema = z.object({ + data: z.object({ + id: z.string(), + email_addresses: z + .array( + z.object({ + email_address: z.string().email(), + id: z.string(), + verification: z.object({ + status: z.string(), + strategy: z.string(), + }), + }) + ) + .optional(), + }), + type: z.string(), +}); + +export type WebhookEventBody = z.infer; + export interface PresenceItem { name: string; image: string;