feat: send email to user on successful password reset

This commit is contained in:
Ephraim Atta-Duncan
2023-09-18 14:31:04 +00:00
committed by Mythie
parent 84bc6eb4f3
commit dabeead57f
6 changed files with 57 additions and 15 deletions

View File

@ -5,6 +5,7 @@ import backgroundPattern from '~/assets/background-pattern.png';
import { ForgotPasswordForm } from '~/components/forms/forgot-password';
export default function ForgotPasswordPage() {
// TODO: Fix width reducing with screen size
return (
<main className="bg-sand-100 relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-4 py-12 md:p-12 lg:p-24">
<div className="relative flex w-1/5 items-center gap-x-24">

View File

@ -43,10 +43,7 @@ export const ForgotPasswordForm = ({ className }: ForgotPasswordFormProps) => {
const { mutateAsync: forgotPassword } = trpc.profile.forgotPassword.useMutation();
const onFormSubmit = async ({ email }: TForgotPasswordFormSchema) => {
// check if the email is available
// if not, throw an error
// if the email is available, create a password reset token and send an email
// TODO: Handle error with try/catch
await forgotPassword({
email,
});

View File

@ -3,8 +3,8 @@ import { Img, Section, Tailwind, Text } from '@react-email/components';
import * as config from '@documenso/tailwind-config';
export interface TemplateResetPasswordProps {
inviterName: string;
inviterEmail: string;
userName: string;
userEmail: string;
assetBaseUrl: string;
}

View File

@ -23,9 +23,8 @@ import {
export type ResetPasswordTemplateProps = Partial<TemplateResetPasswordProps>;
export const ResetPasswordTemplate = ({
inviterName = 'Lucas Smith',
inviterEmail = 'lucas@documenso.com',
userName = 'Lucas Smith',
userEmail = 'lucas@documenso.com',
assetBaseUrl = 'http://localhost:3002',
}: ResetPasswordTemplateProps) => {
const previewText = `Password Reset Successful`;
@ -58,8 +57,8 @@ export const ResetPasswordTemplate = ({
/>
<TemplateResetPassword
inviterName={inviterName}
inviterEmail={inviterEmail}
userName={userName}
userEmail={userEmail}
assetBaseUrl={assetBaseUrl}
/>
</Section>
@ -68,9 +67,9 @@ export const ResetPasswordTemplate = ({
<Container className="mx-auto mt-12 max-w-xl">
<Section>
<Text className="my-4 text-base font-semibold">
Hi, {inviterName}{' '}
<Link className="font-normal text-slate-400" href="mailto:{inviterEmail}">
({inviterEmail})
Hi, {userName}{' '}
<Link className="font-normal text-slate-400" href="mailto:{userEmail}">
({userEmail})
</Link>
</Text>

View File

@ -0,0 +1,44 @@
import { createElement } from 'react';
import { mailer } from '@documenso/email/mailer';
import { render } from '@documenso/email/render';
import { ResetPasswordTemplate } from '@documenso/email/templates/reset-password';
import { prisma } from '@documenso/prisma';
export interface SendResetPasswordOptions {
userId: number;
}
export const sendResetPassword = async ({ userId }: SendResetPasswordOptions) => {
const user = await prisma.user.findFirstOrThrow({
where: {
id: userId,
},
});
if (!user) {
throw new Error('User not found');
}
const assetBaseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000';
const template = createElement(ResetPasswordTemplate, {
assetBaseUrl,
userEmail: user.email,
userName: user.name || '',
});
return await mailer.sendMail({
to: {
address: user.email,
name: user.name || '',
},
from: {
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
},
subject: 'Password Reset Success!',
html: render(template),
text: render(template, { plainText: true }),
});
};

View File

@ -3,6 +3,7 @@ import { compare, hash } from 'bcrypt';
import { prisma } from '@documenso/prisma';
import { SALT_ROUNDS } from '../../constants/auth';
import { sendResetPassword } from '../auth/send-reset-password';
export type ResetPasswordOptions = {
token: string;
@ -61,6 +62,6 @@ export const resetPassword = async ({ token, password }: ResetPasswordOptions) =
throw new Error('Unable to update password');
}
// await sendResetPasswordSuccessMail(foundToken.User);
await sendResetPassword({ userId: foundToken.userId });
return transactions;
};