Update brewery post services, transactional emails

This commit is contained in:
Aaron William Po
2023-12-17 23:44:57 -05:00
parent bffa28b93d
commit db17a61f24
10 changed files with 106 additions and 63 deletions

View File

@@ -1,11 +1,11 @@
import Local from 'passport-local'; import Local from 'passport-local';
import { findUserByUsername } from '@/services/users/auth'; import { findUserByUsernameService } from '@/services/users/auth';
import ServerError from '../util/ServerError'; import ServerError from '../util/ServerError';
import { validatePassword } from './passwordFns'; import { validatePassword } from './passwordFns';
const localStrat = new Local.Strategy(async (username, password, done) => { const localStrat = new Local.Strategy(async (username, password, done) => {
try { try {
const user = await findUserByUsername({ username }); const user = await findUserByUsernameService({ username });
if (!user) { if (!user) {
throw new ServerError('Username or password is incorrect.', 401); throw new ServerError('Username or password is incorrect.', 401);
} }

View File

@@ -2,9 +2,9 @@ import { NextApiResponse } from 'next';
import { NextHandler } from 'next-connect'; import { NextHandler } from 'next-connect';
import ServerError from '@/config/util/ServerError'; import ServerError from '@/config/util/ServerError';
import { getLoginSession } from '../../auth/session'; import { findUserByIdService } from '@/services/users/auth';
import { UserExtendedNextApiRequest } from '../../auth/types'; import { getLoginSession } from '@/config/auth/session';
import { findUserById } from '@/services/users/auth'; import { UserExtendedNextApiRequest } from '@/config/auth/types';
/** Get the current user from the session. Adds the user to the request object. */ /** Get the current user from the session. Adds the user to the request object. */
const getCurrentUser = async ( const getCurrentUser = async (
@@ -13,7 +13,7 @@ const getCurrentUser = async (
next: NextHandler, next: NextHandler,
) => { ) => {
const session = await getLoginSession(req); const session = await getLoginSession(req);
const user = await findUserById({ userId: session?.id }); const user = await findUserByIdService({ userId: session?.id });
if (!user) { if (!user) {
throw new ServerError('User is not logged in.', 401); throw new ServerError('User is not logged in.', 401);

View File

@@ -12,10 +12,12 @@ import {
createBreweryPostLocationService, createBreweryPostLocationService,
getMapBreweryPostsService, getMapBreweryPostsService,
getBreweryPostByIdService, getBreweryPostByIdService,
updateBreweryPostService,
deleteBreweryPostService,
} from '@/services/posts/brewery-post'; } from '@/services/posts/brewery-post';
import { getBeerPostsByBreweryIdService } from '@/services/posts/beer-post'; import { getBeerPostsByBreweryIdService } from '@/services/posts/beer-post';
import { NextHandler } from 'next-connect'; import { NextHandler } from 'next-connect';
import DBClient from '@/prisma/DBClient';
import { import {
BreweryPostRequest, BreweryPostRequest,
CreateBreweryPostRequest, CreateBreweryPostRequest,
@@ -188,10 +190,7 @@ export const editBreweryPost = async (
query: { id }, query: { id },
} = req; } = req;
await DBClient.instance.breweryPost.update({ await updateBreweryPostService({ breweryPostId: id, body });
where: { id },
data: body,
});
res.status(200).json({ res.status(200).json({
message: 'Brewery post updated successfully', message: 'Brewery post updated successfully',
@@ -204,11 +203,8 @@ export const deleteBreweryPost = async (
req: BreweryPostRequest, req: BreweryPostRequest,
res: NextApiResponse, res: NextApiResponse,
) => { ) => {
const { const { id } = req.query;
query: { id }, const deleted = await deleteBreweryPostService({ breweryPostId: id });
} = req;
const deleted = await DBClient.instance.breweryPost.delete({ where: { id } });
if (!deleted) { if (!deleted) {
throw new ServerError('Brewery post not found', 404); throw new ServerError('Brewery post not found', 404);

View File

@@ -18,15 +18,15 @@ import { verifyConfirmationToken } from '@/config/jwt';
import { hashPassword } from '@/config/auth/passwordFns'; import { hashPassword } from '@/config/auth/passwordFns';
import { import {
createNewUser, createNewUserService,
deleteUserById, deleteUserService,
findUserByEmail, findUserByEmailService,
findUserByUsername, findUserByUsernameService,
sendConfirmationEmail, sendConfirmationEmailService,
sendResetPasswordEmail, sendResetPasswordEmailService,
updateUserById, updateUserService,
updateUserPassword, updateUserPasswordService,
updateUserToBeConfirmedById, confirmUserService,
} from '@/services/users/auth'; } from '@/services/users/auth';
import { EditUserRequest, UserRouteRequest } from '@/controllers/users/profile/types'; import { EditUserRequest, UserRouteRequest } from '@/controllers/users/profile/types';
@@ -98,8 +98,8 @@ export const registerUser = async (
) => { ) => {
const [usernameTaken, emailTaken] = ( const [usernameTaken, emailTaken] = (
await Promise.all([ await Promise.all([
findUserByUsername({ username: req.body.username }), findUserByUsernameService({ username: req.body.username }),
findUserByEmail({ email: req.body.email }), findUserByEmailService({ email: req.body.email }),
]) ])
).map((user) => !!user); ).map((user) => !!user);
@@ -117,14 +117,14 @@ export const registerUser = async (
); );
} }
const user = await createNewUser(req.body); const user = await createNewUserService(req.body);
await setLoginSession(res, { await setLoginSession(res, {
id: user.id, id: user.id,
username: user.username, username: user.username,
}); });
await sendConfirmationEmail({ await sendConfirmationEmailService({
email: user.email, email: user.email,
username: user.username, username: user.username,
userId: user.id, userId: user.id,
@@ -155,7 +155,7 @@ export const confirmUser = async (
throw new ServerError('Could not confirm user.', 401); throw new ServerError('Could not confirm user.', 401);
} }
await updateUserToBeConfirmedById({ userId: id }); await confirmUserService({ userId: id });
res.status(200).json({ res.status(200).json({
message: 'User confirmed successfully.', message: 'User confirmed successfully.',
@@ -170,10 +170,10 @@ export const resetPassword = async (
) => { ) => {
const { email } = req.body; const { email } = req.body;
const user = await findUserByEmail({ email }); const user = await findUserByEmailService({ email });
if (user) { if (user) {
await sendResetPasswordEmail({ await sendResetPasswordEmailService({
email: user.email, email: user.email,
username: user.username, username: user.username,
userId: user.id, userId: user.id,
@@ -204,7 +204,7 @@ export const sendCurrentUser = async (
export const checkEmail = async (req: CheckEmailRequest, res: NextApiResponse) => { export const checkEmail = async (req: CheckEmailRequest, res: NextApiResponse) => {
const { email: emailToCheck } = req.query; const { email: emailToCheck } = req.query;
const email = await findUserByEmail({ email: emailToCheck }); const email = await findUserByEmailService({ email: emailToCheck });
res.json({ res.json({
success: true, success: true,
@@ -217,7 +217,7 @@ export const checkEmail = async (req: CheckEmailRequest, res: NextApiResponse) =
export const checkUsername = async (req: CheckUsernameRequest, res: NextApiResponse) => { export const checkUsername = async (req: CheckUsernameRequest, res: NextApiResponse) => {
const { username: usernameToCheck } = req.query; const { username: usernameToCheck } = req.query;
const username = await findUserByUsername({ username: usernameToCheck }); const username = await findUserByUsernameService({ username: usernameToCheck });
res.json({ res.json({
success: true, success: true,
@@ -234,7 +234,10 @@ export const updatePassword = async (
const user = req.user!; const user = req.user!;
const { password } = req.body; const { password } = req.body;
await updateUserPassword({ userId: user.id, password: await hashPassword(password) }); await updateUserPasswordService({
userId: user.id,
password: await hashPassword(password),
});
res.json({ res.json({
message: 'Updated user password.', message: 'Updated user password.',
@@ -249,7 +252,7 @@ export const resendConfirmation = async (
) => { ) => {
const user = req.user!; const user = req.user!;
await sendConfirmationEmail({ await sendConfirmationEmailService({
userId: user.id, userId: user.id,
username: user.username, username: user.username,
email: user.email, email: user.email,
@@ -267,7 +270,7 @@ export const editUserInfo = async (
) => { ) => {
const { email, firstName, lastName, username } = req.body; const { email, firstName, lastName, username } = req.body;
const updatedUser = await updateUserById({ const updatedUser = await updateUserService({
userId: req.user!.id, userId: req.user!.id,
data: { email, firstName, lastName, username }, data: { email, firstName, lastName, username },
}); });
@@ -285,7 +288,7 @@ export const deleteAccount = async (
res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>, res: NextApiResponse<z.infer<typeof APIResponseValidationSchema>>,
) => { ) => {
const { id } = req.query; const { id } = req.query;
const deletedUser = await deleteUserById({ userId: id }); const deletedUser = await deleteUserService({ userId: id });
if (!deletedUser) { if (!deletedUser) {
throw new ServerError('Could not find a user with that id.', 400); throw new ServerError('Could not find a user with that id.', 400);

View File

@@ -7,7 +7,7 @@ import { NextHandler } from 'next-connect';
import { UserExtendedNextApiRequest } from '@/config/auth/types'; import { UserExtendedNextApiRequest } from '@/config/auth/types';
import { findUserById } from '@/services/users/auth'; import { findUserByIdService } from '@/services/users/auth';
import { import {
createUserFollow, createUserFollow,
@@ -32,7 +32,7 @@ export const followUser = async (
) => { ) => {
const { id } = req.query; const { id } = req.query;
const user = await findUserById({ userId: id }); const user = await findUserByIdService({ userId: id });
if (!user) { if (!user) {
throw new ServerError('User not found', 404); throw new ServerError('User not found', 404);
} }
@@ -70,7 +70,7 @@ export const getUserFollowers = async (
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
const { id, page_num, page_size } = req.query; const { id, page_num, page_size } = req.query;
const user = await findUserById({ userId: id }); const user = await findUserByIdService({ userId: id });
if (!user) { if (!user) {
throw new ServerError('User not found', 404); throw new ServerError('User not found', 404);
} }
@@ -101,7 +101,7 @@ export const getUsersFollowed = async (
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
const { id, page_num, page_size } = req.query; const { id, page_num, page_size } = req.query;
const user = await findUserById({ userId: id }); const user = await findUserByIdService({ userId: id });
if (!user) { if (!user) {
throw new ServerError('User not found', 404); throw new ServerError('User not found', 404);
} }
@@ -131,7 +131,7 @@ export const checkIfUserIsFollowedBySessionUser = async (
) => { ) => {
const { id } = req.query; const { id } = req.query;
const user = await findUserById({ userId: id }); const user = await findUserByIdService({ userId: id });
if (!user) { if (!user) {
throw new ServerError('User not found', 404); throw new ServerError('User not found', 404);
} }
@@ -162,7 +162,7 @@ export const checkIfUserCanEditUser = async (
) => { ) => {
const authenticatedUser = req.user!; const authenticatedUser = req.user!;
const userToUpdate = await findUserById({ userId: req.query.id }); const userToUpdate = await findUserByIdService({ userId: req.query.id });
if (!userToUpdate) { if (!userToUpdate) {
throw new ServerError('User not found', 404); throw new ServerError('User not found', 404);
} }

View File

@@ -7,7 +7,7 @@ import { FC } from 'react';
import { z } from 'zod'; import { z } from 'zod';
import withPageAuthRequired from '@/util/withPageAuthRequired'; import withPageAuthRequired from '@/util/withPageAuthRequired';
import UserHeader from '@/components/UserPage/UserHeader'; import UserHeader from '@/components/UserPage/UserHeader';
import { findUserById } from '@/services/users/auth'; import { findUserByIdService } from '@/services/users/auth';
interface UserInfoPageProps { interface UserInfoPageProps {
user: z.infer<typeof GetUserSchema>; user: z.infer<typeof GetUserSchema>;
@@ -40,7 +40,7 @@ export default UserInfoPage;
export const getServerSideProps = withPageAuthRequired<UserInfoPageProps>( export const getServerSideProps = withPageAuthRequired<UserInfoPageProps>(
async (context) => { async (context) => {
const { id } = context.params!; const { id } = context.params!;
const user = await findUserById({ userId: id as string }); const user = await findUserByIdService({ userId: id as string });
return user return user
? { props: { user: JSON.parse(JSON.stringify(user)) } } ? { props: { user: JSON.parse(JSON.stringify(user)) } }
: { notFound: true }; : { notFound: true };

View File

@@ -1,7 +1,7 @@
import { setLoginSession } from '@/config/auth/session'; import { setLoginSession } from '@/config/auth/session';
import { verifyResetPasswordToken } from '@/config/jwt'; import { verifyResetPasswordToken } from '@/config/jwt';
import ServerError from '@/config/util/ServerError'; import ServerError from '@/config/util/ServerError';
import { findUserById } from '@/services/users/auth'; import { findUserByIdService } from '@/services/users/auth';
import { GetServerSideProps, NextApiResponse, NextPage } from 'next'; import { GetServerSideProps, NextApiResponse, NextPage } from 'next';
@@ -29,7 +29,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
const { id } = await verifyResetPasswordToken(token as string); const { id } = await verifyResetPasswordToken(token as string);
const user = await findUserById({ userId: id as string }); const user = await findUserByIdService({ userId: id as string });
if (!user) { if (!user) {
throw new ServerError('User not found', 404); throw new ServerError('User not found', 404);
} }

View File

@@ -7,6 +7,7 @@ import {
GetAllBreweryPostsByPostedById, GetAllBreweryPostsByPostedById,
GetBreweryPostById, GetBreweryPostById,
GetMapBreweryPosts, GetMapBreweryPosts,
UpdateBreweryPost,
} from './types'; } from './types';
/** /**
@@ -205,3 +206,36 @@ export const getMapBreweryPostsService: GetMapBreweryPosts = async ({
const count = await DBClient.instance.breweryPost.count(); const count = await DBClient.instance.breweryPost.count();
return { breweryPosts, count }; return { breweryPosts, count };
}; };
/**
* Updates a brewery post.
*
* @param args - The arguments to update a brewery post.
* @param args.breweryPostId - The ID of the brewery post to update.
* @param args.body - The body of the request.
* @param args.body.name - The name of the brewery.
* @param args.body.description - The description of the brewery.
* @param args.body.dateEstablished - The date the brewery was established.
* @returns The updated brewery post.
*/
export const updateBreweryPostService: UpdateBreweryPost = async ({
breweryPostId,
body,
}) => {
const breweryPost = await DBClient.instance.breweryPost.update({
where: { id: breweryPostId },
data: body,
select: breweryPostSelect,
});
return breweryPost as Awaited<ReturnType<typeof updateBreweryPostService>>;
};
export const deleteBreweryPostService: GetBreweryPostById = async ({ breweryPostId }) => {
const breweryPost = await DBClient.instance.breweryPost.delete({
where: { id: breweryPostId },
select: breweryPostSelect,
});
return breweryPost as Awaited<ReturnType<typeof deleteBreweryPostService>>;
};

View File

@@ -46,3 +46,12 @@ export type GetMapBreweryPosts = (args: {
breweryPosts: z.infer<typeof BreweryPostMapQueryResult>[]; breweryPosts: z.infer<typeof BreweryPostMapQueryResult>[];
count: number; count: number;
}>; }>;
export type UpdateBreweryPost = (args: {
breweryPostId: string;
body: {
name: string;
description: string;
dateEstablished: Date;
};
}) => Promise<z.infer<typeof BreweryPostQueryResult>>;

View File

@@ -76,7 +76,7 @@ const authUserSelect = {
* @param args.username The username of the user to create. * @param args.username The username of the user to create.
* @returns The user. * @returns The user.
*/ */
export const createNewUser: CreateNewUser = async ({ export const createNewUserService: CreateNewUser = async ({
email, email,
password, password,
firstName, firstName,
@@ -108,7 +108,7 @@ export const createNewUser: CreateNewUser = async ({
* @param args.userId The id of the user to delete. * @param args.userId The id of the user to delete.
* @returns The user that was deleted if found, otherwise null. * @returns The user that was deleted if found, otherwise null.
*/ */
export const deleteUserById: DeleteUserById = ({ userId }) => { export const deleteUserService: DeleteUserById = ({ userId }) => {
return DBClient.instance.user.delete({ where: { id: userId }, select: authUserSelect }); return DBClient.instance.user.delete({ where: { id: userId }, select: authUserSelect });
}; };
@@ -120,7 +120,7 @@ export const deleteUserById: DeleteUserById = ({ userId }) => {
* @returns The user if found, otherwise null. * @returns The user if found, otherwise null.
*/ */
export const findUserByUsername: FindUserByUsername = async ({ username }) => { export const findUserByUsernameService: FindUserByUsername = async ({ username }) => {
return DBClient.instance.user.findUnique({ return DBClient.instance.user.findUnique({
where: { username }, where: { username },
select: authUserSelect, select: authUserSelect,
@@ -133,7 +133,7 @@ export const findUserByUsername: FindUserByUsername = async ({ username }) => {
* @param args The arguments for service. * @param args The arguments for service.
* @param args.email The email of the user to find. * @param args.email The email of the user to find.
*/ */
export const findUserByEmail: FindUserByEmail = async ({ email }) => { export const findUserByEmailService: FindUserByEmail = async ({ email }) => {
return DBClient.instance.user.findUnique({ where: { email }, select: userSelect }); return DBClient.instance.user.findUnique({ where: { email }, select: userSelect });
}; };
@@ -144,7 +144,7 @@ export const findUserByEmail: FindUserByEmail = async ({ email }) => {
* @param args.userId The id of the user to find. * @param args.userId The id of the user to find.
* @returns The user if found, otherwise null. * @returns The user if found, otherwise null.
*/ */
export const findUserById: FindUserById = ({ userId }) => { export const findUserByIdService: FindUserById = ({ userId }) => {
return DBClient.instance.user.findUnique({ where: { id: userId }, select: userSelect }); return DBClient.instance.user.findUnique({ where: { id: userId }, select: userSelect });
}; };
@@ -157,7 +157,7 @@ export const findUserById: FindUserById = ({ userId }) => {
* @param args.email The email of the user to send the confirmation email to. * @param args.email The email of the user to send the confirmation email to.
* @returns The user if found, otherwise null. * @returns The user if found, otherwise null.
*/ */
export const sendConfirmationEmail: SendConfirmationEmail = async ({ export const sendConfirmationEmailService: SendConfirmationEmail = async ({
userId, userId,
username, username,
email, email,
@@ -189,7 +189,7 @@ export const sendConfirmationEmail: SendConfirmationEmail = async ({
* @param args.email The email of the user to send the reset password email to. * @param args.email The email of the user to send the reset password email to.
* @returns A promise that resolves to void. * @returns A promise that resolves to void.
*/ */
export const sendResetPasswordEmail: SendResetPasswordEmail = async ({ export const sendResetPasswordEmailService: SendResetPasswordEmail = async ({
userId, userId,
username, username,
email, email,
@@ -221,9 +221,7 @@ export const sendResetPasswordEmail: SendResetPasswordEmail = async ({
* @param args.userId The id of the user to update. * @param args.userId The id of the user to update.
* @returns The user. * @returns The user.
*/ */
export const updateUserToBeConfirmedById: UpdateUserToBeConfirmedById = async ({ export const confirmUserService: UpdateUserToBeConfirmedById = async ({ userId }) => {
userId,
}) => {
return DBClient.instance.user.update({ return DBClient.instance.user.update({
where: { id: userId }, where: { id: userId },
data: { accountIsVerified: true, updatedAt: new Date() }, data: { accountIsVerified: true, updatedAt: new Date() },
@@ -231,7 +229,10 @@ export const updateUserToBeConfirmedById: UpdateUserToBeConfirmedById = async ({
}); });
}; };
export const updateUserPassword: UpdateUserPassword = async ({ password, userId }) => { export const updateUserPasswordService: UpdateUserPassword = async ({
password,
userId,
}) => {
const hash = await hashPassword(password); const hash = await hashPassword(password);
const user = await DBClient.instance.user.update({ const user = await DBClient.instance.user.update({
@@ -254,7 +255,7 @@ export const updateUserPassword: UpdateUserPassword = async ({ password, userId
* @param args.data.lastName The last name of the user to update. * @param args.data.lastName The last name of the user to update.
* @param args.data.username The username of the user to update. * @param args.data.username The username of the user to update.
*/ */
export const updateUserById: UpdateUserById = async ({ userId, data }) => { export const updateUserService: UpdateUserById = async ({ userId, data }) => {
const user = await DBClient.instance.user.findUnique({ const user = await DBClient.instance.user.findUnique({
where: { id: userId }, where: { id: userId },
select: userSelect, select: userSelect,
@@ -272,12 +273,12 @@ export const updateUserById: UpdateUserById = async ({ userId, data }) => {
} as const; } as const;
if (updatedFields.email) { if (updatedFields.email) {
const emailIsTaken = await findUserByEmail({ email: data.email }); const emailIsTaken = await findUserByEmailService({ email: data.email });
if (emailIsTaken) { if (emailIsTaken) {
throw new ServerError('Email is already taken', 400); throw new ServerError('Email is already taken', 400);
} }
await sendConfirmationEmail({ await sendConfirmationEmailService({
userId, userId,
username: data.username, username: data.username,
email: data.email, email: data.email,
@@ -285,7 +286,7 @@ export const updateUserById: UpdateUserById = async ({ userId, data }) => {
} }
if (updatedFields.username) { if (updatedFields.username) {
const usernameIsTaken = await findUserByUsername({ username: data.username }); const usernameIsTaken = await findUserByUsernameService({ username: data.username });
if (usernameIsTaken) { if (usernameIsTaken) {
throw new ServerError('Username is already taken', 400); throw new ServerError('Username is already taken', 400);
} }