mirror of
https://github.com/documenso/documenso.git
synced 2026-07-14 06:47:10 +10:00
844af17ec2
Each direct mailer.sendMail() call is replaced by a dedicated background job so that email delivery failures can be retried independently. New jobs: send-pending-email, send-completed-email, send-forgot-password-email, send-document-super-delete-email, send-recipient-removed-email, send-document-deleted-emails, send-2fa-token-email, send-resend-document-email, send-direct-template-created-email. Existing handlers (send-document-cancelled-emails, send-organisation-member-*, send-recipient-signed-email) have io.runTask wrappers removed since they interfere with the job scheduler. Job triggers are dispatched after transactions commit to avoid race conditions with uncommitted data.
56 lines
1.1 KiB
TypeScript
56 lines
1.1 KiB
TypeScript
import crypto from 'crypto';
|
|
|
|
import { prisma } from '@documenso/prisma';
|
|
|
|
import { ONE_DAY } from '../../constants/time';
|
|
import { jobs } from '../../jobs/client';
|
|
|
|
export const forgotPassword = async ({ email }: { email: string }) => {
|
|
const user = await prisma.user.findFirst({
|
|
where: {
|
|
email: {
|
|
equals: email,
|
|
mode: 'insensitive',
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!user) {
|
|
return;
|
|
}
|
|
|
|
// Find a token that was created in the last hour and hasn't expired
|
|
// const existingToken = await prisma.passwordResetToken.findFirst({
|
|
// where: {
|
|
// userId: user.id,
|
|
// expiry: {
|
|
// gt: new Date(),
|
|
// },
|
|
// createdAt: {
|
|
// gt: new Date(Date.now() - ONE_HOUR),
|
|
// },
|
|
// },
|
|
// });
|
|
|
|
// if (existingToken) {
|
|
// return;
|
|
// }
|
|
|
|
const token = crypto.randomBytes(18).toString('hex');
|
|
|
|
await prisma.passwordResetToken.create({
|
|
data: {
|
|
token,
|
|
expiry: new Date(Date.now() + ONE_DAY),
|
|
userId: user.id,
|
|
},
|
|
});
|
|
|
|
await jobs.triggerJob({
|
|
name: 'send.forgot.password.email',
|
|
payload: {
|
|
userId: user.id,
|
|
},
|
|
});
|
|
};
|