diff --git a/app/[id]+api.ts b/app/[id]+api.ts index 4a83d46..289f5ed 100644 --- a/app/[id]+api.ts +++ b/app/[id]+api.ts @@ -1,5 +1,5 @@ import { deleteGuestInsecure, getGuestInsecure } from '../database/guests'; -import { Guest } from '../migrations/00000-createTableGuests'; +import { guestsSchema } from '../migrations/00000-createTableGuests'; export async function GET( request: Request, @@ -30,31 +30,15 @@ export async function PUT( request: Request, { id }: { id: string }, ): Promise { - const body = await request.json(); - const allowedKeys: Record = { - id: false, - firstName: true, - lastName: true, - attending: true, - }; - const difference = Object.keys(body).filter( - (key) => !allowedKeys[key as keyof Guest], - ); + const requestBody = await request.json(); - if (difference.length > 0) { + const result = guestsSchema.safeParse(requestBody); + + if (!result.success) { return Response.json( { - errors: [ - { - message: `Request body contains more than allowed properties (${Object.keys( - allowedKeys, - ).join( - ', ', - )}). The request also contains these extra keys that are not allowed: ${difference.join( - ', ', - )}`, - }, - ], + error: 'Request does not contain guest object', + errorIssues: result.error.issues, }, { status: 400, diff --git a/app/guests+api.ts b/app/guests+api.ts index 53512df..f077342 100644 --- a/app/guests+api.ts +++ b/app/guests+api.ts @@ -1,4 +1,5 @@ import { addGuestInsecure, getGuestsInsecure } from '../database/guests'; +import { guestsSchema } from '../migrations/00000-createTableGuests'; export async function GET(request: Request): Promise { const cookie = request.headers.get('cookie'); @@ -16,20 +17,18 @@ export async function GET(request: Request): Promise { } export async function POST(request: Request): Promise { - const body = await request.json(); + const requestBody = await request.json(); - if (!body.firstName || !body.lastName) { + const result = guestsSchema.safeParse(requestBody); + + console.log(result); + + if (!result.success) { return Response.json( - 'Request body missing a firstName or lastName property', { - status: 400, + error: 'Request does not contain guest object', + errorIssues: result.error.issues, }, - ); - } - - if (Object.keys(body).length > 3) { - return Response.json( - 'Request body contains more than firstName, lastName and deadline properties', { status: 400, }, @@ -37,12 +36,21 @@ export async function POST(request: Request): Promise { } const newGuest = { - firstName: body.firstName, - lastName: body.lastName, + firstName: result.data.firstName, + lastName: result.data.lastName, attending: false, }; const guest = await addGuestInsecure(newGuest); + if (!guest) { + return Response.json( + { error: 'Guest not created' }, + { + status: 500, + }, + ); + } + return Response.json({ guest: guest }); } diff --git a/migrations/00000-createTableGuests.ts b/migrations/00000-createTableGuests.ts index acf8806..b0574b5 100644 --- a/migrations/00000-createTableGuests.ts +++ b/migrations/00000-createTableGuests.ts @@ -1,4 +1,5 @@ import { Sql } from 'postgres'; +import { z } from 'zod'; export type Guest = { id: number; @@ -7,6 +8,11 @@ export type Guest = { attending: boolean; }; +export const guestsSchema = z.object({ + firstName: z.string().min(1).max(30), + lastName: z.string().min(1).max(30), +}); + export async function up(sql: Sql) { await sql` CREATE TABLE guests ( diff --git a/package.json b/package.json index 9c7ad58..c7d9b86 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "react-native": "0.74.2", "react-native-safe-area-context": "^4.10.5", "react-native-screens": "^3.32.0", - "tsx": "^4.12.0" + "tsx": "^4.12.0", + "zod": "^3.23.8" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c95413..34019d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: tsx: specifier: ^4.12.0 version: 4.16.0 + zod: + specifier: ^3.23.8 + version: 3.23.8 devDependencies: '@babel/core': specifier: ^7.20.0