From ee47f99f8a2ef162feaf49788241fbc786f6f175 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Tue, 4 Jul 2023 23:27:01 -0400 Subject: [PATCH] Update: add update brewery post --- src/pages/api/breweries/[id]/index.ts | 91 +++++++++++++++++++ src/pages/beers/[id]/edit.tsx | 4 +- src/pages/breweries/[id]/edit.tsx | 55 +++++++++++ .../types/EditBreweryPostValidationSchema.ts | 13 +++ 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 src/pages/api/breweries/[id]/index.ts create mode 100644 src/pages/breweries/[id]/edit.tsx create mode 100644 src/services/BreweryPost/types/EditBreweryPostValidationSchema.ts diff --git a/src/pages/api/breweries/[id]/index.ts b/src/pages/api/breweries/[id]/index.ts new file mode 100644 index 0000000..00b694a --- /dev/null +++ b/src/pages/api/breweries/[id]/index.ts @@ -0,0 +1,91 @@ +import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser'; +import { UserExtendedNextApiRequest } from '@/config/auth/types'; +import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; +import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; +import { NextApiResponse } from 'next'; +import { createRouter, NextHandler } from 'next-connect'; +import { z } from 'zod'; +import ServerError from '@/config/util/ServerError'; +import DBClient from '@/prisma/DBClient'; +import getBreweryPostById from '@/services/BreweryPost/getBreweryPostById'; +import EditBreweryPostValidationSchema from '@/services/BreweryPost/types/EditBreweryPostValidationSchema'; + +interface BreweryPostRequest extends UserExtendedNextApiRequest { + query: { id: string }; +} + +interface EditBreweryPostRequest extends BreweryPostRequest { + body: z.infer; +} + +const checkIfBreweryPostOwner = async ( + req: BreweryPostRequest, + res: NextApiResponse, + next: NextHandler, +) => { + const user = req.user!; + const { id } = req.query; + + const breweryPost = await getBreweryPostById(id); + if (!breweryPost) { + throw new ServerError('Brewery post not found', 404); + } + + if (breweryPost.postedBy.id !== user.id) { + throw new ServerError('You are not the owner of this brewery post', 403); + } + + next(); +}; + +const editBreweryPost = async ( + req: EditBreweryPostRequest, + res: NextApiResponse>, +) => { + const { + body, + query: { id }, + } = req; + + await DBClient.instance.breweryPost.update({ + where: { id }, + data: body, + }); + + res.status(200).json({ + message: 'Brewery post updated successfully', + success: true, + statusCode: 200, + }); +}; + +const deleteBreweryPost = async (req: BreweryPostRequest, res: NextApiResponse) => { + const { + query: { id }, + } = req; + + const deleted = await DBClient.instance.beerPost.delete({ + where: { id }, + }); + + if (!deleted) { + throw new ServerError('Brewery post not found', 404); + } + + res.status(200).json({ + message: 'Brewery post deleted successfully', + success: true, + statusCode: 200, + }); +}; +const router = createRouter< + EditBreweryPostRequest, + NextApiResponse> +>(); + +router.put(getCurrentUser, checkIfBreweryPostOwner, editBreweryPost); +router.delete(getCurrentUser, checkIfBreweryPostOwner, deleteBreweryPost); + +const handler = router.handler(NextConnectOptions); + +export default handler; diff --git a/src/pages/beers/[id]/edit.tsx b/src/pages/beers/[id]/edit.tsx index a55e933..83321c3 100644 --- a/src/pages/beers/[id]/edit.tsx +++ b/src/pages/beers/[id]/edit.tsx @@ -14,7 +14,7 @@ interface EditPageProps { beerPost: z.infer; } -const EditPage: NextPage = ({ beerPost }) => { +const EditBeerPostPage: NextPage = ({ beerPost }) => { const pageTitle = `Edit \u201c${beerPost.name}\u201d`; return ( @@ -44,7 +44,7 @@ const EditPage: NextPage = ({ beerPost }) => { ); }; -export default EditPage; +export default EditBeerPostPage; export const getServerSideProps = withPageAuthRequired( async (context, session) => { diff --git a/src/pages/breweries/[id]/edit.tsx b/src/pages/breweries/[id]/edit.tsx new file mode 100644 index 0000000..9fc0b36 --- /dev/null +++ b/src/pages/breweries/[id]/edit.tsx @@ -0,0 +1,55 @@ +import FormPageLayout from '@/components/ui/forms/FormPageLayout'; +import getBreweryPostById from '@/services/BreweryPost/getBreweryPostById'; +import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult'; +import withPageAuthRequired from '@/util/withPageAuthRequired'; +import { NextPage } from 'next'; +import Head from 'next/head'; +import { BiBeer } from 'react-icons/bi'; +import { z } from 'zod'; + +interface EditPageProps { + breweryPost: z.infer; +} + +const EditBreweryPostPage: NextPage = ({ breweryPost }) => { + const pageTitle = `Edit \u201c${breweryPost.name}\u201d`; + + return ( + <> + + {pageTitle} + + + + + <> + + + ); +}; + +export default EditBreweryPostPage; + +export const getServerSideProps = withPageAuthRequired( + async (context, session) => { + const breweryPostId = context.params?.id as string; + const breweryPost = await getBreweryPostById(breweryPostId); + + const { id: userId } = session; + + if (!breweryPost) { + return { notFound: true }; + } + + const isBreweryPostOwner = breweryPost.postedBy.id === userId; + + return isBreweryPostOwner + ? { props: { breweryPost: JSON.parse(JSON.stringify(breweryPost)) } } + : { redirect: { destination: `/breweries/${breweryPostId}`, permanent: false } }; + }, +); diff --git a/src/services/BreweryPost/types/EditBreweryPostValidationSchema.ts b/src/services/BreweryPost/types/EditBreweryPostValidationSchema.ts new file mode 100644 index 0000000..705fe97 --- /dev/null +++ b/src/services/BreweryPost/types/EditBreweryPostValidationSchema.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; +import CreateBreweryPostSchema from './CreateBreweryPostSchema'; + +const EditBreweryPostValidationSchema = CreateBreweryPostSchema.extend({ + id: z.string().cuid(), +}).omit({ + address: true, + city: true, + region: true, + country: true, +}); + +export default EditBreweryPostValidationSchema;