mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
Update api routes and begin to extract controllers out of routing logic
This commit is contained in:
@@ -29,7 +29,7 @@ import FormTextInput from '../ui/forms/FormTextInput';
|
|||||||
import Button from '../ui/forms/Button';
|
import Button from '../ui/forms/Button';
|
||||||
|
|
||||||
const AddressAutofill = dynamic(
|
const AddressAutofill = dynamic(
|
||||||
// @ts-ignore
|
// @ts-expect-error
|
||||||
() => import('@mapbox/search-js-react').then((mod) => mod.AddressAutofill),
|
() => import('@mapbox/search-js-react').then((mod) => mod.AddressAutofill),
|
||||||
{ ssr: false },
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|||||||
66
src/controllers/beerComments/index.ts
Normal file
66
src/controllers/beerComments/index.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import ServerError from '@/config/util/ServerError';
|
||||||
|
import DBClient from '@/prisma/DBClient';
|
||||||
|
import editBeerCommentById from '@/services/BeerComment/editBeerCommentById';
|
||||||
|
import findBeerCommentById from '@/services/BeerComment/findBeerCommentById';
|
||||||
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
|
import { NextApiResponse } from 'next';
|
||||||
|
import { NextHandler } from 'next-connect';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { CommentRequest, EditCommentRequest } from '../requestTypes';
|
||||||
|
|
||||||
|
export const checkIfBeerCommentOwner = async <T extends CommentRequest>(
|
||||||
|
req: T,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
next: NextHandler,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
const user = req.user!;
|
||||||
|
const comment = await findBeerCommentById({ beerCommentId: id });
|
||||||
|
|
||||||
|
if (!comment) {
|
||||||
|
throw new ServerError('Comment not found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comment.postedBy.id !== user.id) {
|
||||||
|
throw new ServerError('You are not authorized to modify this comment', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editBeerPostComment = async (
|
||||||
|
req: EditCommentRequest,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
const updated = await editBeerCommentById({
|
||||||
|
content: req.body.content,
|
||||||
|
rating: req.body.rating,
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Comment updated successfully',
|
||||||
|
statusCode: 200,
|
||||||
|
payload: updated,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteBeerPostComment = async (
|
||||||
|
req: CommentRequest,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
await DBClient.instance.beerComment.delete({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Comment deleted successfully',
|
||||||
|
statusCode: 200,
|
||||||
|
});
|
||||||
|
};
|
||||||
67
src/controllers/beerStyleComments/index.ts
Normal file
67
src/controllers/beerStyleComments/index.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import ServerError from '@/config/util/ServerError';
|
||||||
|
import DBClient from '@/prisma/DBClient';
|
||||||
|
import updateBeerStyleCommentById from '@/services/BeerStyleComment/updateBeerStyleCommentById';
|
||||||
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
|
import { NextApiResponse } from 'next';
|
||||||
|
import { NextHandler } from 'next-connect';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { CommentRequest, EditCommentRequest } from '../requestTypes';
|
||||||
|
|
||||||
|
export const checkIfBeerStyleCommentOwner = async <
|
||||||
|
CommentRequestType extends CommentRequest,
|
||||||
|
>(
|
||||||
|
req: CommentRequestType,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
next: NextHandler,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
const user = req.user!;
|
||||||
|
const beerStyleComment = await DBClient.instance.beerStyleComment.findFirst({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!beerStyleComment) {
|
||||||
|
throw new ServerError('Beer style comment not found.', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (beerStyleComment.postedById !== user.id) {
|
||||||
|
throw new ServerError(
|
||||||
|
'You are not authorized to modify this beer style comment.',
|
||||||
|
403,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editBeerStyleComment = async (
|
||||||
|
req: EditCommentRequest,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
) => {
|
||||||
|
const updated = await updateBeerStyleCommentById({
|
||||||
|
id: req.query.id,
|
||||||
|
body: req.body,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Comment updated successfully',
|
||||||
|
statusCode: 200,
|
||||||
|
payload: updated,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteBeerStyleComment = async (
|
||||||
|
req: CommentRequest,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
await DBClient.instance.beerStyleComment.delete({ where: { id } });
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Comment deleted successfully',
|
||||||
|
statusCode: 200,
|
||||||
|
});
|
||||||
|
};
|
||||||
68
src/controllers/breweryComments/index.ts
Normal file
68
src/controllers/breweryComments/index.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import ServerError from '@/config/util/ServerError';
|
||||||
|
import DBClient from '@/prisma/DBClient';
|
||||||
|
import getBreweryCommentById from '@/services/BreweryComment/getBreweryCommentById';
|
||||||
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
|
import { NextApiResponse } from 'next';
|
||||||
|
import { NextHandler } from 'next-connect';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { CommentRequest, EditCommentRequest } from '../requestTypes';
|
||||||
|
|
||||||
|
export const checkIfBreweryCommentOwner = async <
|
||||||
|
CommentRequestType extends CommentRequest,
|
||||||
|
>(
|
||||||
|
req: CommentRequestType,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
next: NextHandler,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
const user = req.user!;
|
||||||
|
const comment = await getBreweryCommentById(id);
|
||||||
|
|
||||||
|
if (!comment) {
|
||||||
|
throw new ServerError('Comment not found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comment.postedById !== user.id) {
|
||||||
|
throw new ServerError('You are not authorized to modify this comment', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editBreweryPostComment = async (
|
||||||
|
req: EditCommentRequest,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
const updated = await DBClient.instance.breweryComment.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
content: req.body.content,
|
||||||
|
rating: req.body.rating,
|
||||||
|
updatedAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Comment updated successfully',
|
||||||
|
statusCode: 200,
|
||||||
|
payload: updated,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteBreweryPostComment = async (
|
||||||
|
req: CommentRequest,
|
||||||
|
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
||||||
|
) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
await DBClient.instance.breweryComment.delete({ where: { id } });
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: 'Comment deleted successfully',
|
||||||
|
statusCode: 200,
|
||||||
|
});
|
||||||
|
};
|
||||||
11
src/controllers/requestTypes/index.ts
Normal file
11
src/controllers/requestTypes/index.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { UserExtendedNextApiRequest } from '@/config/auth/types';
|
||||||
|
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export interface CommentRequest extends UserExtendedNextApiRequest {
|
||||||
|
query: { id: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EditCommentRequest extends CommentRequest {
|
||||||
|
body: z.infer<typeof CreateCommentValidationSchema>;
|
||||||
|
}
|
||||||
@@ -1,85 +1,22 @@
|
|||||||
import { UserExtendedNextApiRequest } from '@/config/auth/types';
|
|
||||||
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
||||||
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
||||||
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
||||||
import ServerError from '@/config/util/ServerError';
|
|
||||||
import DBClient from '@/prisma/DBClient';
|
|
||||||
import findBeerCommentById from '@/services/BeerComment/findBeerCommentById';
|
|
||||||
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
||||||
import editBeerCommentById from '@/services/BeerComment/editBeerCommentById';
|
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
import { NextApiResponse } from 'next';
|
import { NextApiResponse } from 'next';
|
||||||
import { createRouter, NextHandler } from 'next-connect';
|
import { createRouter } from 'next-connect';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface DeleteCommentRequest extends UserExtendedNextApiRequest {
|
import { CommentRequest } from '@/controllers/requestTypes';
|
||||||
query: { id: string };
|
import {
|
||||||
}
|
checkIfBeerCommentOwner,
|
||||||
|
deleteBeerPostComment,
|
||||||
interface EditCommentRequest extends UserExtendedNextApiRequest {
|
editBeerPostComment,
|
||||||
query: { id: string };
|
} from '@/controllers/beerComments';
|
||||||
body: z.infer<typeof CreateCommentValidationSchema>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkIfCommentOwner = async (
|
|
||||||
req: DeleteCommentRequest | EditCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
next: NextHandler,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
const user = req.user!;
|
|
||||||
const comment = await findBeerCommentById({ beerCommentId: id });
|
|
||||||
|
|
||||||
if (!comment) {
|
|
||||||
throw new ServerError('Comment not found', 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comment.postedBy.id !== user.id) {
|
|
||||||
throw new ServerError('You are not authorized to modify this comment', 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
};
|
|
||||||
|
|
||||||
const editComment = async (
|
|
||||||
req: EditCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
|
|
||||||
const updated = await editBeerCommentById({
|
|
||||||
content: req.body.content,
|
|
||||||
rating: req.body.rating,
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Comment updated successfully',
|
|
||||||
statusCode: 200,
|
|
||||||
payload: updated,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteComment = async (
|
|
||||||
req: DeleteCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
|
|
||||||
await DBClient.instance.beerComment.delete({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Comment deleted successfully',
|
|
||||||
statusCode: 200,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const router = createRouter<
|
const router = createRouter<
|
||||||
DeleteCommentRequest,
|
CommentRequest,
|
||||||
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
@@ -87,8 +24,8 @@ router
|
|||||||
.delete(
|
.delete(
|
||||||
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
|
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
checkIfCommentOwner,
|
checkIfBeerCommentOwner,
|
||||||
deleteComment,
|
deleteBeerPostComment,
|
||||||
)
|
)
|
||||||
.put(
|
.put(
|
||||||
validateRequest({
|
validateRequest({
|
||||||
@@ -96,8 +33,8 @@ router
|
|||||||
bodySchema: CreateCommentValidationSchema,
|
bodySchema: CreateCommentValidationSchema,
|
||||||
}),
|
}),
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
checkIfCommentOwner,
|
checkIfBeerCommentOwner,
|
||||||
editComment,
|
editBeerPostComment,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handler = router.handler(NextConnectOptions);
|
const handler = router.handler(NextConnectOptions);
|
||||||
|
|||||||
@@ -1,85 +1,21 @@
|
|||||||
import { UserExtendedNextApiRequest } from '@/config/auth/types';
|
|
||||||
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
||||||
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
||||||
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
||||||
import ServerError from '@/config/util/ServerError';
|
import {
|
||||||
import DBClient from '@/prisma/DBClient';
|
checkIfBeerStyleCommentOwner,
|
||||||
|
deleteBeerStyleComment,
|
||||||
|
editBeerStyleComment,
|
||||||
|
} from '@/controllers/beerStyleComments';
|
||||||
|
import { CommentRequest } from '@/controllers/requestTypes';
|
||||||
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
||||||
|
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
import { NextApiResponse } from 'next';
|
import { NextApiResponse } from 'next';
|
||||||
import { createRouter, NextHandler } from 'next-connect';
|
import { createRouter } from 'next-connect';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface DeleteCommentRequest extends UserExtendedNextApiRequest {
|
|
||||||
query: { id: string };
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EditCommentRequest extends UserExtendedNextApiRequest {
|
|
||||||
query: { id: string };
|
|
||||||
body: z.infer<typeof CreateCommentValidationSchema>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkIfCommentOwner = async (
|
|
||||||
req: DeleteCommentRequest | EditCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
next: NextHandler,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
const user = req.user!;
|
|
||||||
const comment = await DBClient.instance.beerStyleComment.findFirst({ where: { id } });
|
|
||||||
|
|
||||||
if (!comment) {
|
|
||||||
throw new ServerError('Comment not found', 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comment.postedById !== user.id) {
|
|
||||||
throw new ServerError('You are not authorized to modify this comment', 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
};
|
|
||||||
|
|
||||||
const editComment = async (
|
|
||||||
req: EditCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
|
|
||||||
const updated = await DBClient.instance.beerStyleComment.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
content: req.body.content,
|
|
||||||
rating: req.body.rating,
|
|
||||||
updatedAt: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Comment updated successfully',
|
|
||||||
statusCode: 200,
|
|
||||||
payload: updated,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteComment = async (
|
|
||||||
req: DeleteCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
|
|
||||||
await DBClient.instance.beerStyleComment.delete({ where: { id } });
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Comment deleted successfully',
|
|
||||||
statusCode: 200,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const router = createRouter<
|
const router = createRouter<
|
||||||
DeleteCommentRequest,
|
CommentRequest,
|
||||||
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
@@ -89,8 +25,8 @@ router
|
|||||||
querySchema: z.object({ id: z.string().cuid() }),
|
querySchema: z.object({ id: z.string().cuid() }),
|
||||||
}),
|
}),
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
checkIfCommentOwner,
|
checkIfBeerStyleCommentOwner,
|
||||||
deleteComment,
|
deleteBeerStyleComment,
|
||||||
)
|
)
|
||||||
.put(
|
.put(
|
||||||
validateRequest({
|
validateRequest({
|
||||||
@@ -98,8 +34,8 @@ router
|
|||||||
bodySchema: CreateCommentValidationSchema,
|
bodySchema: CreateCommentValidationSchema,
|
||||||
}),
|
}),
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
checkIfCommentOwner,
|
checkIfBeerStyleCommentOwner,
|
||||||
editComment,
|
editBeerStyleComment,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handler = router.handler(NextConnectOptions);
|
const handler = router.handler(NextConnectOptions);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { createRouter } from 'next-connect';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
||||||
import { NextApiResponse } from 'next';
|
import { NextApiResponse } from 'next';
|
||||||
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
|
|
||||||
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
||||||
|
|
||||||
interface CreateCommentRequest extends UserExtendedNextApiRequest {
|
interface CreateCommentRequest extends UserExtendedNextApiRequest {
|
||||||
@@ -30,7 +30,7 @@ const createComment = async (
|
|||||||
|
|
||||||
const beerPostId = req.query.id;
|
const beerPostId = req.query.id;
|
||||||
|
|
||||||
const newBeerComment: z.infer<typeof CommentQueryResult> = await createNewBeerComment({
|
const newBeerComment = await createNewBeerComment({
|
||||||
content,
|
content,
|
||||||
rating,
|
rating,
|
||||||
beerPostId,
|
beerPostId,
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ interface EditBeerPostRequest extends BeerPostRequest {
|
|||||||
body: z.infer<typeof EditBeerPostValidationSchema>;
|
body: z.infer<typeof EditBeerPostValidationSchema>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkIfBeerPostOwner = async (
|
const checkIfBeerPostOwner = async <BeerPostRequestType extends BeerPostRequest>(
|
||||||
req: BeerPostRequest,
|
req: BeerPostRequestType,
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
next: NextHandler,
|
next: NextHandler,
|
||||||
) => {
|
) => {
|
||||||
|
|||||||
@@ -1,86 +1,22 @@
|
|||||||
import { UserExtendedNextApiRequest } from '@/config/auth/types';
|
|
||||||
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
||||||
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
||||||
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
|
||||||
import ServerError from '@/config/util/ServerError';
|
import { checkIfBeerCommentOwner } from '@/controllers/beerComments';
|
||||||
import DBClient from '@/prisma/DBClient';
|
import {
|
||||||
import getBreweryCommentById from '@/services/BreweryComment/getBreweryCommentById';
|
deleteBreweryPostComment,
|
||||||
|
editBreweryPostComment,
|
||||||
|
} from '@/controllers/breweryComments';
|
||||||
|
import { CommentRequest } from '@/controllers/requestTypes';
|
||||||
|
|
||||||
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
|
||||||
|
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
import { NextApiResponse } from 'next';
|
import { NextApiResponse } from 'next';
|
||||||
import { createRouter, NextHandler } from 'next-connect';
|
import { createRouter } from 'next-connect';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface DeleteCommentRequest extends UserExtendedNextApiRequest {
|
|
||||||
query: { id: string };
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EditCommentRequest extends UserExtendedNextApiRequest {
|
|
||||||
query: { id: string };
|
|
||||||
body: z.infer<typeof CreateCommentValidationSchema>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkIfCommentOwner = async (
|
|
||||||
req: DeleteCommentRequest | EditCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
next: NextHandler,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
const user = req.user!;
|
|
||||||
const comment = await getBreweryCommentById(id);
|
|
||||||
|
|
||||||
if (!comment) {
|
|
||||||
throw new ServerError('Comment not found', 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comment.postedById !== user.id) {
|
|
||||||
throw new ServerError('You are not authorized to modify this comment', 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
};
|
|
||||||
|
|
||||||
const editComment = async (
|
|
||||||
req: EditCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
|
|
||||||
const updated = await DBClient.instance.breweryComment.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
content: req.body.content,
|
|
||||||
rating: req.body.rating,
|
|
||||||
updatedAt: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Comment updated successfully',
|
|
||||||
statusCode: 200,
|
|
||||||
payload: updated,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteComment = async (
|
|
||||||
req: DeleteCommentRequest,
|
|
||||||
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
|
|
||||||
) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
|
|
||||||
await DBClient.instance.breweryComment.delete({ where: { id } });
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Comment deleted successfully',
|
|
||||||
statusCode: 200,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const router = createRouter<
|
const router = createRouter<
|
||||||
DeleteCommentRequest,
|
CommentRequest,
|
||||||
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
@@ -90,8 +26,8 @@ router
|
|||||||
querySchema: z.object({ id: z.string().cuid() }),
|
querySchema: z.object({ id: z.string().cuid() }),
|
||||||
}),
|
}),
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
checkIfCommentOwner,
|
checkIfBeerCommentOwner,
|
||||||
deleteComment,
|
deleteBreweryPostComment,
|
||||||
)
|
)
|
||||||
.put(
|
.put(
|
||||||
validateRequest({
|
validateRequest({
|
||||||
@@ -99,8 +35,8 @@ router
|
|||||||
bodySchema: CreateCommentValidationSchema,
|
bodySchema: CreateCommentValidationSchema,
|
||||||
}),
|
}),
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
checkIfCommentOwner,
|
checkIfBeerCommentOwner,
|
||||||
editComment,
|
editBreweryPostComment,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handler = router.handler(NextConnectOptions);
|
const handler = router.handler(NextConnectOptions);
|
||||||
|
|||||||
@@ -35,10 +35,7 @@ const checkIfUserIsFollowedBySessionUser = async (
|
|||||||
const currentUser = req.user!;
|
const currentUser = req.user!;
|
||||||
|
|
||||||
const userIsFollowedBySessionUser = await DBClient.instance.userFollow.findFirst({
|
const userIsFollowedBySessionUser = await DBClient.instance.userFollow.findFirst({
|
||||||
where: {
|
where: { followerId: currentUser.id, followingId: id },
|
||||||
followerId: currentUser.id,
|
|
||||||
followingId: id,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!userIsFollowedBySessionUser) {
|
if (!userIsFollowedBySessionUser) {
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
import { UserExtendedNextApiRequest } from '@/config/auth/types';
|
|
||||||
import { singleUploadMiddleware } from '@/config/multer/uploadMiddleware';
|
|
||||||
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
|
||||||
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
|
|
||||||
import DBClient from '@/prisma/DBClient';
|
|
||||||
import GetUserSchema from '@/services/User/schema/GetUserSchema';
|
|
||||||
|
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
|
||||||
import { NextApiResponse } from 'next';
|
|
||||||
import { createRouter } from 'next-connect';
|
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
interface UpdateProfileRequest extends UserExtendedNextApiRequest {
|
|
||||||
file: Express.Multer.File;
|
|
||||||
body: {
|
|
||||||
bio: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UpdateUserProfileByIdParams {
|
|
||||||
id: string;
|
|
||||||
data: {
|
|
||||||
bio: string;
|
|
||||||
avatar: {
|
|
||||||
alt: string;
|
|
||||||
path: string;
|
|
||||||
caption: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateUserProfileById = async ({ id, data }: UpdateUserProfileByIdParams) => {
|
|
||||||
const user: z.infer<typeof GetUserSchema> = await DBClient.instance.user.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
bio: data.bio,
|
|
||||||
userAvatar: data.avatar
|
|
||||||
? {
|
|
||||||
upsert: {
|
|
||||||
create: {
|
|
||||||
alt: data.avatar.alt,
|
|
||||||
path: data.avatar.path,
|
|
||||||
caption: data.avatar.caption,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
alt: data.avatar.alt,
|
|
||||||
path: data.avatar.path,
|
|
||||||
caption: data.avatar.caption,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
username: true,
|
|
||||||
email: true,
|
|
||||||
bio: true,
|
|
||||||
userAvatar: true,
|
|
||||||
accountIsVerified: true,
|
|
||||||
createdAt: true,
|
|
||||||
firstName: true,
|
|
||||||
lastName: true,
|
|
||||||
updatedAt: true,
|
|
||||||
dateOfBirth: true,
|
|
||||||
role: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return user;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateProfile = async (req: UpdateProfileRequest, res: NextApiResponse) => {
|
|
||||||
const { file, body, user } = req;
|
|
||||||
|
|
||||||
await updateUserProfileById({
|
|
||||||
id: user!.id,
|
|
||||||
data: {
|
|
||||||
bio: body.bio,
|
|
||||||
avatar: { alt: file.originalname, path: file.path, caption: '' },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
res.status(200).json({
|
|
||||||
message: 'User confirmed successfully.',
|
|
||||||
statusCode: 200,
|
|
||||||
success: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const router = createRouter<
|
|
||||||
UpdateProfileRequest,
|
|
||||||
NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
|
|
||||||
>();
|
|
||||||
|
|
||||||
router.put(
|
|
||||||
getCurrentUser,
|
|
||||||
|
|
||||||
// @ts-expect-error
|
|
||||||
singleUploadMiddleware,
|
|
||||||
validateRequest({ bodySchema: z.object({ bio: z.string().max(1000) }) }),
|
|
||||||
|
|
||||||
updateProfile,
|
|
||||||
);
|
|
||||||
|
|
||||||
const handler = router.handler();
|
|
||||||
|
|
||||||
export default handler;
|
|
||||||
export const config = { api: { bodyParser: false } };
|
|
||||||
@@ -3,13 +3,14 @@ import { singleUploadMiddleware } from '@/config/multer/uploadMiddleware';
|
|||||||
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
|
||||||
|
|
||||||
import ServerError from '@/config/util/ServerError';
|
import ServerError from '@/config/util/ServerError';
|
||||||
import DBClient from '@/prisma/DBClient';
|
|
||||||
import GetUserSchema from '@/services/User/schema/GetUserSchema';
|
|
||||||
|
|
||||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||||
import { NextApiResponse } from 'next';
|
import { NextApiResponse } from 'next';
|
||||||
import { NextHandler, createRouter } from 'next-connect';
|
import { NextHandler, createRouter } from 'next-connect';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import updateUserAvatarById, {
|
||||||
|
UpdateUserAvatarByIdParams,
|
||||||
|
} from '@/services/UserAccount/UpdateUserAvatarByIdParams';
|
||||||
|
|
||||||
interface UpdateProfileRequest extends UserExtendedNextApiRequest {
|
interface UpdateProfileRequest extends UserExtendedNextApiRequest {
|
||||||
file: Express.Multer.File;
|
file: Express.Multer.File;
|
||||||
@@ -18,57 +19,6 @@ interface UpdateProfileRequest extends UserExtendedNextApiRequest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateUserProfileByIdParams {
|
|
||||||
id: string;
|
|
||||||
data: {
|
|
||||||
avatar: {
|
|
||||||
alt: string;
|
|
||||||
path: string;
|
|
||||||
caption: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateUserAvatarById = async ({ id, data }: UpdateUserProfileByIdParams) => {
|
|
||||||
const user: z.infer<typeof GetUserSchema> = await DBClient.instance.user.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
userAvatar: data.avatar
|
|
||||||
? {
|
|
||||||
upsert: {
|
|
||||||
create: {
|
|
||||||
alt: data.avatar.alt,
|
|
||||||
path: data.avatar.path,
|
|
||||||
caption: data.avatar.caption,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
alt: data.avatar.alt,
|
|
||||||
path: data.avatar.path,
|
|
||||||
caption: data.avatar.caption,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
username: true,
|
|
||||||
email: true,
|
|
||||||
bio: true,
|
|
||||||
userAvatar: true,
|
|
||||||
accountIsVerified: true,
|
|
||||||
createdAt: true,
|
|
||||||
firstName: true,
|
|
||||||
lastName: true,
|
|
||||||
updatedAt: true,
|
|
||||||
dateOfBirth: true,
|
|
||||||
role: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return user;
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkIfUserCanUpdateProfile = async (
|
const checkIfUserCanUpdateProfile = async (
|
||||||
req: UpdateProfileRequest,
|
req: UpdateProfileRequest,
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
@@ -86,12 +36,13 @@ const checkIfUserCanUpdateProfile = async (
|
|||||||
const updateProfile = async (req: UpdateProfileRequest, res: NextApiResponse) => {
|
const updateProfile = async (req: UpdateProfileRequest, res: NextApiResponse) => {
|
||||||
const { file, user } = req;
|
const { file, user } = req;
|
||||||
|
|
||||||
await updateUserAvatarById({
|
const avatar: UpdateUserAvatarByIdParams['data']['avatar'] = {
|
||||||
id: user!.id,
|
alt: file.originalname,
|
||||||
data: {
|
path: file.path,
|
||||||
avatar: { alt: file.originalname, path: file.path, caption: '' },
|
caption: '',
|
||||||
},
|
};
|
||||||
});
|
|
||||||
|
await updateUserAvatarById({ id: user!.id, data: { avatar } });
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
message: 'User avatar updated successfully.',
|
message: 'User avatar updated successfully.',
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ import { NextHandler, createRouter } from 'next-connect';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
interface UpdateProfileRequest extends UserExtendedNextApiRequest {
|
interface UpdateProfileRequest extends UserExtendedNextApiRequest {
|
||||||
body: {
|
body: { bio: string };
|
||||||
bio: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateUserProfileByIdParams {
|
interface UpdateUserProfileByIdParams {
|
||||||
|
|||||||
23
src/services/BeerStyleComment/updateBeerStyleCommentById.ts
Normal file
23
src/services/BeerStyleComment/updateBeerStyleCommentById.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import DBClient from '@/prisma/DBClient';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import CreateCommentValidationSchema from '../schema/CommentSchema/CreateCommentValidationSchema';
|
||||||
|
|
||||||
|
interface UpdateBeerStyleCommentByIdParams {
|
||||||
|
body: z.infer<typeof CreateCommentValidationSchema>;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateBeerStyleCommentById = ({ body, id }: UpdateBeerStyleCommentByIdParams) => {
|
||||||
|
const { content, rating } = body;
|
||||||
|
|
||||||
|
return DBClient.instance.beerStyleComment.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
content,
|
||||||
|
rating,
|
||||||
|
updatedAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default updateBeerStyleCommentById;
|
||||||
55
src/services/UserAccount/UpdateUserAvatarByIdParams.ts
Normal file
55
src/services/UserAccount/UpdateUserAvatarByIdParams.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import DBClient from '@/prisma/DBClient';
|
||||||
|
import GetUserSchema from '@/services/User/schema/GetUserSchema';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export interface UpdateUserAvatarByIdParams {
|
||||||
|
id: string;
|
||||||
|
data: {
|
||||||
|
avatar: {
|
||||||
|
alt: string;
|
||||||
|
path: string;
|
||||||
|
caption: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const updateUserAvatarById = async ({ id, data }: UpdateUserAvatarByIdParams) => {
|
||||||
|
const user: z.infer<typeof GetUserSchema> = await DBClient.instance.user.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
userAvatar: data.avatar
|
||||||
|
? {
|
||||||
|
upsert: {
|
||||||
|
create: {
|
||||||
|
alt: data.avatar.alt,
|
||||||
|
path: data.avatar.path,
|
||||||
|
caption: data.avatar.caption,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
alt: data.avatar.alt,
|
||||||
|
path: data.avatar.path,
|
||||||
|
caption: data.avatar.caption,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
username: true,
|
||||||
|
email: true,
|
||||||
|
bio: true,
|
||||||
|
userAvatar: true,
|
||||||
|
accountIsVerified: true,
|
||||||
|
createdAt: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
updatedAt: true,
|
||||||
|
dateOfBirth: true,
|
||||||
|
role: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return user;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default updateUserAvatarById;
|
||||||
Reference in New Issue
Block a user