continue extracting user controllers out of routes

This commit is contained in:
Aaron William Po
2023-12-06 20:30:11 -05:00
parent 2ff39613cd
commit c7d5c65ffb
31 changed files with 584 additions and 543 deletions

View File

@@ -10,6 +10,7 @@ import getBeerRecommendations from '@/services/BeerPost/getBeerRecommendations';
import getAllBeerPosts from '@/services/BeerPost/getAllBeerPosts'; import getAllBeerPosts from '@/services/BeerPost/getAllBeerPosts';
import DBClient from '@/prisma/DBClient'; import DBClient from '@/prisma/DBClient';
import createNewBeerPost from '@/services/BeerPost/createNewBeerPost'; import createNewBeerPost from '@/services/BeerPost/createNewBeerPost';
import getBeerPostsByPostedById from '@/services/BeerPost/getBeerPostsByPostedById';
import { import {
BeerPostRequest, BeerPostRequest,
CreateBeerPostRequest, CreateBeerPostRequest,
@@ -17,6 +18,7 @@ import {
GetAllBeerPostsRequest, GetAllBeerPostsRequest,
GetBeerRecommendationsRequest, GetBeerRecommendationsRequest,
} from './types'; } from './types';
import { GetPostsByUserIdRequest } from '../types';
export const checkIfBeerPostOwner = async <BeerPostRequestType extends BeerPostRequest>( export const checkIfBeerPostOwner = async <BeerPostRequestType extends BeerPostRequest>(
req: BeerPostRequestType, req: BeerPostRequestType,
@@ -141,3 +143,32 @@ export const createBeerPost = async (
success: true, success: true,
}); });
}; };
export const getBeerPostsByUserId = async (
req: GetPostsByUserIdRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const pageNum = parseInt(req.query.page_num, 10);
const pageSize = parseInt(req.query.page_size, 10);
const { id } = req.query;
const beerPosts = await getBeerPostsByPostedById({
pageNum,
pageSize,
postedById: id,
});
const beerPostCount = await DBClient.instance.beerPost.count({
where: { postedBy: { id } },
});
res.setHeader('X-Total-Count', beerPostCount);
res.status(200).json({
message: `Beer posts by user ${id} fetched successfully`,
statusCode: 200,
payload: beerPosts,
success: true,
});
};

View File

@@ -0,0 +1,36 @@
import DBClient from '@/prisma/DBClient';
import getAllBreweryPostsByPostedById from '@/services/BreweryPost/getAllBreweryPostsByPostedById';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next';
import { z } from 'zod';
import { GetPostsByUserIdRequest } from '../types';
// eslint-disable-next-line import/prefer-default-export
export const getBreweryPostsByUserId = async (
req: GetPostsByUserIdRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const pageNum = parseInt(req.query.page_num, 10);
const pageSize = parseInt(req.query.page_size, 10);
const { id } = req.query;
const breweryPosts = await getAllBreweryPostsByPostedById({
pageNum,
pageSize,
postedById: id,
});
const breweryPostCount = await DBClient.instance.breweryPost.count({
where: { postedBy: { id } },
});
res.setHeader('X-Total-Count', breweryPostCount);
res.status(200).json({
message: `Brewery posts by user ${id} fetched successfully`,
statusCode: 200,
payload: breweryPosts,
success: true,
});
};

View File

@@ -3,3 +3,7 @@ import { NextApiRequest } from 'next';
export interface GetAllPostsRequest extends NextApiRequest { export interface GetAllPostsRequest extends NextApiRequest {
query: { page_size: string; page_num: string }; query: { page_size: string; page_num: string };
} }
export interface GetPostsByUserIdRequest extends NextApiRequest {
query: { id: string; page_size: string; page_num: string };
}

View File

@@ -19,11 +19,17 @@ import { verifyConfirmationToken } from '@/config/jwt';
import updateUserToBeConfirmedById from '@/services/User/updateUserToBeConfirmedById'; import updateUserToBeConfirmedById from '@/services/User/updateUserToBeConfirmedById';
import DBClient from '@/prisma/DBClient'; import DBClient from '@/prisma/DBClient';
import sendResetPasswordEmail from '@/services/User/sendResetPasswordEmail'; import sendResetPasswordEmail from '@/services/User/sendResetPasswordEmail';
import { hashPassword } from '@/config/auth/passwordFns';
import deleteUserById from '@/services/User/deleteUserById';
import { import {
CheckEmailRequest,
CheckUsernameRequest,
RegisterUserRequest, RegisterUserRequest,
ResetPasswordRequest, ResetPasswordRequest,
TokenValidationRequest, TokenValidationRequest,
UpdatePasswordRequest,
} from './types'; } from './types';
import { EditUserRequest, UserRouteRequest } from '../profile/types';
export const authenticateUser = expressWrapper( export const authenticateUser = expressWrapper(
async ( async (
@@ -165,3 +171,135 @@ export const resetPassword = async (
'If an account with that email exists, we have sent you an email to reset your password.', 'If an account with that email exists, we have sent you an email to reset your password.',
}); });
}; };
export const sendCurrentUser = async (
req: UserExtendedNextApiRequest,
res: NextApiResponse,
) => {
const { user } = req;
res.status(200).json({
message: `Currently logged in as ${user!.username}`,
statusCode: 200,
success: true,
payload: user,
});
};
export const checkEmail = async (req: CheckEmailRequest, res: NextApiResponse) => {
const { email: emailToCheck } = req.query;
const email = await findUserByEmail(emailToCheck);
res.json({
success: true,
payload: { emailIsTaken: !!email },
statusCode: 200,
message: 'Getting email availability.',
});
};
export const checkUsername = async (req: CheckUsernameRequest, res: NextApiResponse) => {
const { username: usernameToCheck } = req.query;
const username = await findUserByUsername(usernameToCheck);
res.json({
success: true,
payload: { usernameIsTaken: !!username },
statusCode: 200,
message: username ? 'Username is taken.' : 'Username is available.',
});
};
export const updatePassword = async (
req: UpdatePasswordRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { password } = req.body;
const hash = await hashPassword(password);
const user = req.user!;
await DBClient.instance.user.update({
data: { hash },
where: { id: user.id },
});
res.json({
message: 'Updated user password.',
statusCode: 200,
success: true,
});
};
export const resendConfirmation = async (
req: UserExtendedNextApiRequest,
res: NextApiResponse,
) => {
const user = req.user!;
await sendConfirmationEmail(user);
res.status(200).json({
message: `Resent the confirmation email for ${user.username}.`,
statusCode: 200,
success: true,
});
};
export const editUserInfo = async (
req: EditUserRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { email, firstName, lastName, username } = req.body;
const [usernameIsTaken, emailIsTaken] = await Promise.all([
findUserByUsername(username),
findUserByEmail(email),
]);
const emailChanged = req.user!.email !== email;
const usernameChanged = req.user!.username !== username;
if (emailIsTaken && emailChanged) {
throw new ServerError('Email is already taken', 400);
}
if (usernameIsTaken && usernameChanged) {
throw new ServerError('Username is already taken', 400);
}
const updatedUser = await DBClient.instance.user.update({
where: { id: req.user!.id },
data: {
email,
firstName,
lastName,
username,
accountIsVerified: emailChanged ? false : undefined,
},
});
res.json({
message: 'User edited successfully',
payload: updatedUser,
success: true,
statusCode: 200,
});
};
export const deleteAccount = async (
req: UserRouteRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { id } = req.query;
const deletedUser = await deleteUserById(id);
if (!deletedUser) {
throw new ServerError('Could not find a user with that id.', 400);
}
res.send({
message: 'Successfully deleted user.',
statusCode: 200,
success: true,
});
};

View File

@@ -1,5 +1,8 @@
import { UserExtendedNextApiRequest } from '@/config/auth/types'; import { UserExtendedNextApiRequest } from '@/config/auth/types';
import { CreateUserValidationSchema } from '@/services/User/schema/CreateUserValidationSchemas'; import {
CreateUserValidationSchema,
UpdatePasswordSchema,
} from '@/services/User/schema/CreateUserValidationSchemas';
import TokenValidationSchema from '@/services/User/schema/TokenValidationSchema'; import TokenValidationSchema from '@/services/User/schema/TokenValidationSchema';
import { NextApiRequest } from 'next'; import { NextApiRequest } from 'next';
import { z } from 'zod'; import { z } from 'zod';
@@ -15,3 +18,14 @@ export interface TokenValidationRequest extends UserExtendedNextApiRequest {
export interface ResetPasswordRequest extends NextApiRequest { export interface ResetPasswordRequest extends NextApiRequest {
body: { email: string }; body: { email: string };
} }
export interface UpdatePasswordRequest extends UserExtendedNextApiRequest {
body: z.infer<typeof UpdatePasswordSchema>;
}
export interface CheckEmailRequest extends NextApiRequest {
query: { email: string };
}
export interface CheckUsernameRequest extends NextApiRequest {
query: { username: string };
}

View File

@@ -0,0 +1,237 @@
import ServerError from '@/config/util/ServerError';
import DBClient from '@/prisma/DBClient';
import findUserById from '@/services/User/findUserById';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next';
import { z } from 'zod';
import getUsersFollowingUser from '@/services/UserFollows/getUsersFollowingUser';
import getUsersFollowedByUser from '@/services/UserFollows/getUsersFollowedByUser';
import { NextHandler } from 'next-connect';
import updateUserAvatarById, {
UpdateUserAvatarByIdParams,
} from '@/services/UserAccount/UpdateUserAvatarByIdParams';
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import updateUserProfileById from '@/services/User/updateUserProfileById';
import {
UserRouteRequest,
GetUserFollowInfoRequest,
EditUserRequest,
UpdateAvatarRequest,
UpdateProfileRequest,
} from './types';
export const followUser = async (
req: UserRouteRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { id } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const currentUser = req.user!;
const userIsFollowedBySessionUser = await DBClient.instance.userFollow.findFirst({
where: {
followerId: currentUser.id,
followingId: id,
},
});
if (!userIsFollowedBySessionUser) {
await DBClient.instance.userFollow.create({
data: { followerId: currentUser.id, followingId: id },
});
res.status(200).json({
message: 'Now following user.',
success: true,
statusCode: 200,
});
return;
}
await DBClient.instance.userFollow.delete({
where: {
followerId_followingId: {
followerId: currentUser.id,
followingId: id,
},
},
});
res.status(200).json({
message: 'No longer following user.',
success: true,
statusCode: 200,
});
};
export const getUserFollowers = async (
req: GetUserFollowInfoRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { id, page_num, page_size } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const pageNum = parseInt(page_num, 10);
const pageSize = parseInt(page_size, 10);
const following = await getUsersFollowingUser({
userId: id,
pageNum,
pageSize,
});
const followingCount = await DBClient.instance.userFollow.count({
where: { following: { id } },
});
res.setHeader('X-Total-Count', followingCount);
res.json({
message: 'Retrieved users that are followed by queried user',
payload: following,
success: true,
statusCode: 200,
});
};
export const getUsersFollowed = async (
req: GetUserFollowInfoRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { id, page_num, page_size } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const pageNum = parseInt(page_num, 10);
const pageSize = parseInt(page_size, 10);
const following = await getUsersFollowedByUser({
userId: id,
pageNum,
pageSize,
});
const followingCount = await DBClient.instance.userFollow.count({
where: { follower: { id } },
});
res.setHeader('X-Total-Count', followingCount);
res.json({
message: 'Retrieved users that are followed by queried user',
payload: following,
success: true,
statusCode: 200,
});
};
export const checkIfUserIsFollowedBySessionUser = async (
req: GetUserFollowInfoRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { id } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const currentUser = req.user!;
const userIsFollowedBySessionUser = await DBClient.instance.userFollow.findFirst({
where: { followerId: currentUser.id, followingId: id },
});
if (!userIsFollowedBySessionUser) {
res.status(200).json({
message: 'User is not followed by the current user.',
success: true,
statusCode: 200,
payload: { isFollowed: false },
});
return;
}
res.status(200).json({
message: 'User is followed by the current user.',
success: true,
statusCode: 200,
payload: { isFollowed: true },
});
};
export const checkIfUserCanEditUser = async (
req: EditUserRequest,
res: NextApiResponse,
next: NextHandler,
) => {
const authenticatedUser = req.user!;
const userToUpdate = await findUserById(req.query.id);
if (!userToUpdate) {
throw new ServerError('User not found', 404);
}
if (authenticatedUser.id !== userToUpdate.id) {
throw new ServerError('You are not permitted to modify this user', 403);
}
return next();
};
export const checkIfUserCanUpdateProfile = async <T extends UserExtendedNextApiRequest>(
req: T,
res: NextApiResponse,
next: NextHandler,
) => {
const user = req.user!;
if (user.id !== req.query.id) {
throw new ServerError('You can only update your own profile.', 403);
}
await next();
};
export const updateAvatar = async (req: UpdateAvatarRequest, res: NextApiResponse) => {
const { file, user } = req;
const avatar: UpdateUserAvatarByIdParams['data']['avatar'] = {
alt: file.originalname,
path: file.path,
caption: '',
};
await updateUserAvatarById({ id: user!.id, data: { avatar } });
res.status(200).json({
message: 'User avatar updated successfully.',
statusCode: 200,
success: true,
});
};
export const updateProfile = async (req: UpdateProfileRequest, res: NextApiResponse) => {
const user = req.user!;
const { body } = req;
await updateUserProfileById({ id: user!.id, data: { bio: body.bio } });
res.status(200).json({
message: 'Profile updated successfully.',
statusCode: 200,
success: true,
});
};

View File

@@ -0,0 +1,23 @@
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import EditUserSchema from '@/services/User/schema/EditUserSchema';
import { z } from 'zod';
export interface UserRouteRequest extends UserExtendedNextApiRequest {
query: { id: string };
}
export interface GetUserFollowInfoRequest extends UserExtendedNextApiRequest {
query: { id: string; page_size: string; page_num: string };
}
export interface EditUserRequest extends UserRouteRequest {
body: z.infer<typeof EditUserSchema>;
}
export interface UpdateAvatarRequest extends UserExtendedNextApiRequest {
file: Express.Multer.File;
}
export interface UpdateProfileRequest extends UserExtendedNextApiRequest {
body: { bio: string };
}

View File

@@ -2,9 +2,7 @@ import { UserExtendedNextApiRequest } from '@/config/auth/types';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
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 ServerError from '@/config/util/ServerError'; import { followUser } from '@/controllers/users/profile';
import DBClient from '@/prisma/DBClient';
import findUserById from '@/services/User/findUserById';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
@@ -21,55 +19,6 @@ const router = createRouter<
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();
const followUser = async (
req: GetUserFollowInfoRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { id } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const currentUser = req.user!;
const userIsFollowedBySessionUser = await DBClient.instance.userFollow.findFirst({
where: {
followerId: currentUser.id,
followingId: id,
},
});
if (!userIsFollowedBySessionUser) {
await DBClient.instance.userFollow.create({
data: { followerId: currentUser.id, followingId: id },
});
res.status(200).json({
message: 'Now following user.',
success: true,
statusCode: 200,
});
return;
}
await DBClient.instance.userFollow.delete({
where: {
followerId_followingId: {
followerId: currentUser.id,
followingId: id,
},
},
});
res.status(200).json({
message: 'No longer following user.',
success: true,
statusCode: 200,
});
};
router.post( router.post(
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }), validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
getCurrentUser, getCurrentUser,

View File

@@ -1,59 +1,18 @@
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import ServerError from '@/config/util/ServerError'; import { getUserFollowers } from '@/controllers/users/profile';
import DBClient from '@/prisma/DBClient'; import { GetUserFollowInfoRequest } from '@/controllers/users/profile/types';
import findUserById from '@/services/User/findUserById';
import getUsersFollowingUser from '@/services/UserFollows/getUsersFollowingUser';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
interface GetUserFollowInfoRequest extends UserExtendedNextApiRequest {
query: { id: string; page_size: string; page_num: string };
}
const router = createRouter< const router = createRouter<
GetUserFollowInfoRequest, GetUserFollowInfoRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();
const getFollowingInfo = async (
req: GetUserFollowInfoRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { id, page_num, page_size } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const pageNum = parseInt(page_num, 10);
const pageSize = parseInt(page_size, 10);
const following = await getUsersFollowingUser({
userId: id,
pageNum,
pageSize,
});
const followingCount = await DBClient.instance.userFollow.count({
where: { following: { id } },
});
res.setHeader('X-Total-Count', followingCount);
res.json({
message: 'Retrieved users that are followed by queried user',
payload: following,
success: true,
statusCode: 200,
});
};
router.get( router.get(
validateRequest({ validateRequest({
querySchema: z.object({ querySchema: z.object({
@@ -62,7 +21,7 @@ router.get(
page_num: z.string().regex(/^\d+$/), page_num: z.string().regex(/^\d+$/),
}), }),
}), }),
getFollowingInfo, getUserFollowers,
); );
const handler = router.handler(NextConnectOptions); const handler = router.handler(NextConnectOptions);

View File

@@ -1,10 +1,7 @@
import { UserExtendedNextApiRequest } from '@/config/auth/types'; import { UserExtendedNextApiRequest } from '@/config/auth/types';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import ServerError from '@/config/util/ServerError'; import { getUsersFollowed } from '@/controllers/users/profile';
import DBClient from '@/prisma/DBClient';
import findUserById from '@/services/User/findUserById';
import getUsersFollowedByUser from '@/services/UserFollows/getUsersFollowedByUser';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
@@ -20,40 +17,6 @@ const router = createRouter<
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();
const getFollowingInfo = async (
req: GetUserFollowInfoRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { id, page_num, page_size } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const pageNum = parseInt(page_num, 10);
const pageSize = parseInt(page_size, 10);
const following = await getUsersFollowedByUser({
userId: id,
pageNum,
pageSize,
});
const followingCount = await DBClient.instance.userFollow.count({
where: { follower: { id } },
});
res.setHeader('X-Total-Count', followingCount);
res.json({
message: 'Retrieved users that are followed by queried user',
payload: following,
success: true,
statusCode: 200,
});
};
router.get( router.get(
validateRequest({ validateRequest({
querySchema: z.object({ querySchema: z.object({
@@ -62,7 +25,7 @@ router.get(
page_num: z.string().regex(/^\d+$/), page_num: z.string().regex(/^\d+$/),
}), }),
}), }),
getFollowingInfo, getUsersFollowed,
); );
const handler = router.handler(NextConnectOptions); const handler = router.handler(NextConnectOptions);

View File

@@ -1,113 +1,16 @@
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
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 ServerError from '@/config/util/ServerError'; import { editUserInfo, deleteAccount } from '@/controllers/users/auth';
import DBClient from '@/prisma/DBClient'; import { checkIfUserCanEditUser } from '@/controllers/users/profile';
import deleteUserById from '@/services/User/deleteUserById'; import { EditUserRequest } from '@/controllers/users/profile/types';
import findUserByEmail from '@/services/User/findUserByEmail'; import EditUserSchema from '@/services/User/schema/EditUserSchema';
import findUserById from '@/services/User/findUserById';
import findUserByUsername from '@/services/User/findUserByUsername';
import { BaseCreateUserSchema } from '@/services/User/schema/CreateUserValidationSchemas';
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 { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
const EditUserSchema = BaseCreateUserSchema.pick({
username: true,
email: true,
firstName: true,
lastName: true,
});
interface UserRouteRequest extends UserExtendedNextApiRequest {
query: { id: string };
}
interface EditUserRequest extends UserRouteRequest {
body: z.infer<typeof EditUserSchema>;
}
const checkIfUserCanEditUser = async (
req: EditUserRequest,
res: NextApiResponse,
next: NextHandler,
) => {
const authenticatedUser = req.user!;
const userToUpdate = await findUserById(req.query.id);
if (!userToUpdate) {
throw new ServerError('User not found', 404);
}
if (authenticatedUser.id !== userToUpdate.id) {
throw new ServerError('You are not permitted to modify this user', 403);
}
return next();
};
const editUser = async (
req: EditUserRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { email, firstName, lastName, username } = req.body;
const [usernameIsTaken, emailIsTaken] = await Promise.all([
findUserByUsername(username),
findUserByEmail(email),
]);
const emailChanged = req.user!.email !== email;
const usernameChanged = req.user!.username !== username;
if (emailIsTaken && emailChanged) {
throw new ServerError('Email is already taken', 400);
}
if (usernameIsTaken && usernameChanged) {
throw new ServerError('Username is already taken', 400);
}
const updatedUser = await DBClient.instance.user.update({
where: { id: req.user!.id },
data: {
email,
firstName,
lastName,
username,
accountIsVerified: emailChanged ? false : undefined,
},
});
res.json({
message: 'User edited successfully',
payload: updatedUser,
success: true,
statusCode: 200,
});
};
const deleteUser = async (
req: UserRouteRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { id } = req.query;
const deletedUser = await deleteUserById(id);
if (!deletedUser) {
throw new ServerError('Could not find a user with that id.', 400);
}
res.send({
message: 'Successfully deleted user.',
statusCode: 200,
success: true,
});
};
const router = createRouter< const router = createRouter<
EditUserRequest, EditUserRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
@@ -120,7 +23,7 @@ router.put(
querySchema: z.object({ id: z.string().cuid() }), querySchema: z.object({ id: z.string().cuid() }),
}), }),
checkIfUserCanEditUser, checkIfUserCanEditUser,
editUser, editUserInfo,
); );
router.delete( router.delete(
@@ -129,7 +32,7 @@ router.delete(
querySchema: z.object({ id: z.string().cuid() }), querySchema: z.object({ id: z.string().cuid() }),
}), }),
checkIfUserCanEditUser, checkIfUserCanEditUser,
deleteUser, deleteAccount,
); );
const handler = router.handler(NextConnectOptions); const handler = router.handler(NextConnectOptions);

View File

@@ -1,62 +1,21 @@
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import ServerError from '@/config/util/ServerError';
import DBClient from '@/prisma/DBClient';
import findUserById from '@/services/User/findUserById';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
interface GetUserFollowInfoRequest extends UserExtendedNextApiRequest { import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
query: { id: string }; import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
} import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import { checkIfUserIsFollowedBySessionUser } from '@/controllers/users/profile';
import { GetUserFollowInfoRequest } from '@/controllers/users/profile/types';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
const router = createRouter< const router = createRouter<
GetUserFollowInfoRequest, GetUserFollowInfoRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();
const checkIfUserIsFollowedBySessionUser = async (
req: GetUserFollowInfoRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { id } = req.query;
const user = await findUserById(id);
if (!user) {
throw new ServerError('User not found', 404);
}
const currentUser = req.user!;
const userIsFollowedBySessionUser = await DBClient.instance.userFollow.findFirst({
where: { followerId: currentUser.id, followingId: id },
});
if (!userIsFollowedBySessionUser) {
res.status(200).json({
message: 'User is not followed by the current user.',
success: true,
statusCode: 200,
payload: { isFollowed: false },
});
return;
}
res.status(200).json({
message: 'User is followed by the current user.',
success: true,
statusCode: 200,
payload: { isFollowed: true },
});
};
router.get( router.get(
validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }), validateRequest({ querySchema: z.object({ id: z.string().cuid() }) }),
getCurrentUser, getCurrentUser,

View File

@@ -1,48 +1,15 @@
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import DBClient from '@/prisma/DBClient';
import getBeerPostsByPostedById from '@/services/BeerPost/getBeerPostsByPostedById';
import PaginatedQueryResponseSchema from '@/services/schema/PaginatedQueryResponseSchema'; import PaginatedQueryResponseSchema from '@/services/schema/PaginatedQueryResponseSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { GetPostsByUserIdRequest } from '@/controllers/posts/types';
interface GetBeerPostsRequest extends NextApiRequest { import { getBeerPostsByUserId } from '@/controllers/posts/beerPosts';
query: {
page_num: string;
page_size: string;
id: string;
};
}
const getBeerPostsByUserId = async (
req: GetBeerPostsRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const pageNum = parseInt(req.query.page_num, 10);
const pageSize = parseInt(req.query.page_size, 10);
const { id } = req.query;
const beerPosts = await getBeerPostsByPostedById({ pageNum, pageSize, postedById: id });
const beerPostCount = await DBClient.instance.beerPost.count({
where: { postedBy: { id } },
});
res.setHeader('X-Total-Count', beerPostCount);
res.status(200).json({
message: `Beer posts by user ${id} fetched successfully`,
statusCode: 200,
payload: beerPosts,
success: true,
});
};
const router = createRouter< const router = createRouter<
GetBeerPostsRequest, GetPostsByUserIdRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();

View File

@@ -1,52 +1,15 @@
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import DBClient from '@/prisma/DBClient';
import getAllBreweryPostsByPostedById from '@/services/BreweryPost/getAllBreweryPostsByPostedById';
import PaginatedQueryResponseSchema from '@/services/schema/PaginatedQueryResponseSchema'; import PaginatedQueryResponseSchema from '@/services/schema/PaginatedQueryResponseSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { getBreweryPostsByUserId } from '@/controllers/posts/breweries';
interface GetBreweryPostsRequest extends NextApiRequest { import { GetPostsByUserIdRequest } from '@/controllers/posts/types';
query: {
page_num: string;
page_size: string;
id: string;
};
}
const getBreweryPostsByUserId = async (
req: GetBreweryPostsRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const pageNum = parseInt(req.query.page_num, 10);
const pageSize = parseInt(req.query.page_size, 10);
const { id } = req.query;
const breweryPosts = await getAllBreweryPostsByPostedById({
pageNum,
pageSize,
postedById: id,
});
const breweryPostCount = await DBClient.instance.breweryPost.count({
where: { postedBy: { id } },
});
res.setHeader('X-Total-Count', breweryPostCount);
res.status(200).json({
message: `Brewery posts by user ${id} fetched successfully`,
statusCode: 200,
payload: breweryPosts,
success: true,
});
};
const router = createRouter< const router = createRouter<
GetBreweryPostsRequest, GetPostsByUserIdRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();

View File

@@ -33,7 +33,7 @@ const checkIfUserCanUpdateProfile = async (
await next(); await next();
}; };
const updateProfile = async (req: UpdateProfileRequest, res: NextApiResponse) => { const updateAvatar = async (req: UpdateProfileRequest, res: NextApiResponse) => {
const { file, user } = req; const { file, user } = req;
const avatar: UpdateUserAvatarByIdParams['data']['avatar'] = { const avatar: UpdateUserAvatarByIdParams['data']['avatar'] = {
@@ -60,7 +60,7 @@ router.put(
checkIfUserCanUpdateProfile, checkIfUserCanUpdateProfile,
// @ts-expect-error // @ts-expect-error
singleUploadMiddleware, singleUploadMiddleware,
updateProfile, updateAvatar,
); );
const handler = router.handler(); const handler = router.handler();

View File

@@ -1,75 +1,13 @@
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 ServerError from '@/config/util/ServerError'; import { checkIfUserCanUpdateProfile, updateProfile } from '@/controllers/users/profile';
import DBClient from '@/prisma/DBClient'; import { UpdateProfileRequest } from '@/controllers/users/profile/types';
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 { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
interface UpdateProfileRequest extends UserExtendedNextApiRequest {
body: { bio: string };
}
interface UpdateUserProfileByIdParams {
id: string;
data: { bio: string };
}
const updateUserProfileById = async ({ id, data }: UpdateUserProfileByIdParams) => {
const user: z.infer<typeof GetUserSchema> = await DBClient.instance.user.update({
where: { id },
data: { bio: data.bio },
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 user = req.user!;
const { body } = req;
await updateUserProfileById({ id: user!.id, data: { bio: body.bio } });
res.status(200).json({
message: 'Profile updated successfully.',
statusCode: 200,
success: true,
});
};
const checkIfUserCanUpdateProfile = async (
req: UpdateProfileRequest,
res: NextApiResponse,
next: NextHandler,
) => {
const user = req.user!;
if (user.id !== req.query.id) {
throw new ServerError('You can only update your own profile.', 403);
}
await next();
};
const router = createRouter< const router = createRouter<
UpdateProfileRequest, UpdateProfileRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>

View File

@@ -1,38 +1,18 @@
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import findUserByEmail from '@/services/User/findUserByEmail'; import { CheckEmailRequest } from '@/controllers/users/auth/types';
import { checkEmail } from '@/controllers/users/auth';
const CheckEmailRequestQuerySchema = z.object({
email: z.string(),
});
interface CheckEmailRequestSchema extends NextApiRequest {
query: z.infer<typeof CheckEmailRequestQuerySchema>;
}
const router = createRouter< const router = createRouter<
CheckEmailRequestSchema, CheckEmailRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();
const checkEmail = async (req: NextApiRequest, res: NextApiResponse) => {
const { email: emailToCheck } = req.query;
const email = await findUserByEmail(emailToCheck as string);
res.json({
success: true,
payload: { emailIsTaken: !!email },
statusCode: 200,
message: 'Getting email availability.',
});
};
router.get( router.get(
validateRequest({ querySchema: z.object({ email: z.string().email() }) }), validateRequest({ querySchema: z.object({ email: z.string().email() }) }),
checkEmail, checkEmail,

View File

@@ -1,38 +1,19 @@
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import findUserByUsername from '@/services/User/findUserByUsername';
const CheckUsernameRequestQuerySchema = z.object({ import { CheckUsernameRequest } from '@/controllers/users/auth/types';
username: z.string(), import { checkUsername } from '@/controllers/users/auth';
});
interface CheckUsernameRequestSchema extends NextApiRequest {
query: z.infer<typeof CheckUsernameRequestQuerySchema>;
}
const router = createRouter< const router = createRouter<
CheckUsernameRequestSchema, CheckUsernameRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>
>(); >();
const checkUsername = async (req: NextApiRequest, res: NextApiResponse) => {
const { username: usernameToCheck } = req.query;
const user = await findUserByUsername(usernameToCheck as string);
res.json({
success: true,
payload: { usernameIsTaken: !!user },
statusCode: 200,
message: 'Getting username availability.',
});
};
router.get( router.get(
validateRequest({ querySchema: z.object({ username: z.string() }) }), validateRequest({ querySchema: z.object({ username: z.string() }) }),
checkUsername, checkUsername,

View File

@@ -7,8 +7,8 @@ import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import { TokenValidationRequest } from '@/controllers/auth/types'; import { TokenValidationRequest } from '@/controllers/users/auth/types';
import { confirmUser } from '@/controllers/auth'; import { confirmUser } from '@/controllers/users/auth';
import TokenValidationSchema from '@/services/User/schema/TokenValidationSchema'; import TokenValidationSchema from '@/services/User/schema/TokenValidationSchema';
const router = createRouter< const router = createRouter<

View File

@@ -5,16 +5,7 @@ import { NextApiResponse } from 'next';
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser'; import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import { sendCurrentUser } from '@/controllers/users/auth';
const sendCurrentUser = async (req: UserExtendedNextApiRequest, res: NextApiResponse) => {
const { user } = req;
res.status(200).json({
message: `Currently logged in as ${user!.username}`,
statusCode: 200,
success: true,
payload: user,
});
};
const router = createRouter< const router = createRouter<
UserExtendedNextApiRequest, UserExtendedNextApiRequest,

View File

@@ -1,38 +1,14 @@
import { hashPassword } from '@/config/auth/passwordFns';
import { UserExtendedNextApiRequest } from '@/config/auth/types';
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
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 DBClient from '@/prisma/DBClient'; import { updatePassword } from '@/controllers/users/auth';
import { UpdatePasswordRequest } from '@/controllers/users/auth/types';
import { UpdatePasswordSchema } from '@/services/User/schema/CreateUserValidationSchemas'; import { UpdatePasswordSchema } from '@/services/User/schema/CreateUserValidationSchemas';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { NextApiResponse } from 'next'; import { NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
interface UpdatePasswordRequest extends UserExtendedNextApiRequest {
body: z.infer<typeof UpdatePasswordSchema>;
}
const updatePassword = async (
req: UpdatePasswordRequest,
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => {
const { password } = req.body;
const hash = await hashPassword(password);
const user = req.user!;
await DBClient.instance.user.update({
data: { hash },
where: { id: user.id },
});
res.json({
message: 'Updated user password.',
statusCode: 200,
success: true,
});
};
const router = createRouter< const router = createRouter<
UpdatePasswordRequest, UpdatePasswordRequest,
NextApiResponse<z.infer<typeof APIResponseValidationSchema>> NextApiResponse<z.infer<typeof APIResponseValidationSchema>>

View File

@@ -5,8 +5,8 @@ import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import { resetPassword } from '@/controllers/auth'; import { resetPassword } from '@/controllers/users/auth';
import { ResetPasswordRequest } from '@/controllers/auth/types'; import { ResetPasswordRequest } from '@/controllers/users/auth/types';
const router = createRouter< const router = createRouter<
ResetPasswordRequest, ResetPasswordRequest,

View File

@@ -6,7 +6,7 @@ import { z } from 'zod';
import LoginValidationSchema from '@/services/User/schema/LoginValidationSchema'; import LoginValidationSchema from '@/services/User/schema/LoginValidationSchema';
import { UserExtendedNextApiRequest } from '@/config/auth/types'; import { UserExtendedNextApiRequest } from '@/config/auth/types';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import { authenticateUser, loginUser } from '@/controllers/auth'; import { authenticateUser, loginUser } from '@/controllers/users/auth';
const router = createRouter< const router = createRouter<
UserExtendedNextApiRequest, UserExtendedNextApiRequest,

View File

@@ -3,7 +3,7 @@ import APIResponseValidationSchema from '@/validation/APIResponseValidationSchem
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiRequest, NextApiResponse } from 'next';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import { logoutUser } from '@/controllers/auth'; import { logoutUser } from '@/controllers/users/auth';
const router = createRouter< const router = createRouter<
NextApiRequest, NextApiRequest,

View File

@@ -5,8 +5,8 @@ import { CreateUserValidationSchema } from '@/services/User/schema/CreateUserVal
import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; import NextConnectOptions from '@/config/nextConnect/NextConnectOptions';
import validateRequest from '@/config/nextConnect/middleware/validateRequest'; import validateRequest from '@/config/nextConnect/middleware/validateRequest';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { registerUser } from '@/controllers/auth'; import { registerUser } from '@/controllers/users/auth';
import { RegisterUserRequest } from '@/controllers/auth/types'; import { RegisterUserRequest } from '@/controllers/users/auth/types';
const router = createRouter< const router = createRouter<
RegisterUserRequest, RegisterUserRequest,

View File

@@ -5,21 +5,7 @@ import { NextApiResponse } from 'next';
import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser'; import getCurrentUser from '@/config/nextConnect/middleware/getCurrentUser';
import { createRouter } from 'next-connect'; import { createRouter } from 'next-connect';
import { z } from 'zod'; import { z } from 'zod';
import sendConfirmationEmail from '@/services/User/sendConfirmationEmail'; import { resendConfirmation } from '@/controllers/users/auth';
const resendConfirmation = async (
req: UserExtendedNextApiRequest,
res: NextApiResponse,
) => {
const user = req.user!;
await sendConfirmationEmail(user);
res.status(200).json({
message: `Resent the confirmation email for ${user.username}.`,
statusCode: 200,
success: true,
});
};
const router = createRouter< const router = createRouter<
UserExtendedNextApiRequest, UserExtendedNextApiRequest,

View File

@@ -16,7 +16,7 @@ const getBeerPostsByBeerStyleId = async ({
const beers = await DBClient.instance.beerPost.findMany({ const beers = await DBClient.instance.beerPost.findMany({
where: { styleId }, where: { styleId },
take: pageSize, take: pageSize,
skip: pageNum * pageSize, skip: (pageNum - 1) * pageSize,
select: { select: {
id: true, id: true,
name: true, name: true,

View File

@@ -16,7 +16,7 @@ const getAllBeerPostsByBreweryId = async ({
const beers = await DBClient.instance.beerPost.findMany({ const beers = await DBClient.instance.beerPost.findMany({
where: { breweryId }, where: { breweryId },
take: pageSize, take: pageSize,
skip: pageNum * pageSize, skip: (pageNum - 1) * pageSize,
select: { select: {
id: true, id: true,
name: true, name: true,

View File

@@ -16,7 +16,7 @@ const getBeerPostsByPostedById = async ({
const beers = await DBClient.instance.beerPost.findMany({ const beers = await DBClient.instance.beerPost.findMany({
where: { postedBy: { id: postedById } }, where: { postedBy: { id: postedById } },
take: pageSize, take: pageSize,
skip: pageNum * pageSize, skip: (pageNum - 1) * pageSize,
select: { select: {
id: true, id: true,
name: true, name: true,

View File

@@ -0,0 +1,10 @@
import { BaseCreateUserSchema } from './CreateUserValidationSchemas';
const EditUserSchema = BaseCreateUserSchema.pick({
username: true,
email: true,
firstName: true,
lastName: true,
});
export default EditUserSchema;

View File

@@ -0,0 +1,33 @@
import DBClient from '@/prisma/DBClient';
import { z } from 'zod';
import GetUserSchema from './schema/GetUserSchema';
interface UpdateUserProfileByIdParams {
id: string;
data: { bio: string };
}
const updateUserProfileById = async ({ id, data }: UpdateUserProfileByIdParams) => {
const user: z.infer<typeof GetUserSchema> = await DBClient.instance.user.update({
where: { id },
data: { bio: data.bio },
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 updateUserProfileById;