Files
documenso/packages/lib/server-only/auth/send-reset-password.ts
T
Lucas Smith 6a99b40cba fix: improve action auth flow for passwordless users (#3358)
Selecting password auth failed with a generic "Unauthorized" for users
who signed up via OAuth or passkey, with no way to set one.

Detect the missing password and email the existing reset link from the
signing dialog and security settings. Require a 2FA code and rate limit
update-password.
2026-09-11 14:17:34 +10:00

61 lines
1.8 KiB
TypeScript

import { mailer } from '@documenso/email/mailer';
import { ResetPasswordTemplate } from '@documenso/email/templates/reset-password';
import { prisma } from '@documenso/prisma';
import { msg } from '@lingui/core/macro';
import { createElement } from 'react';
import { match } from 'ts-pattern';
import { getI18nInstance } from '../../client-only/providers/i18n-server';
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
import type { TPasswordChangeSource } from '../../jobs/definitions/emails/send-password-reset-success-email';
import { env } from '../../utils/env';
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
export interface SendResetPasswordOptions {
userId: number;
source: TPasswordChangeSource;
}
export const sendResetPassword = async ({ userId, source }: SendResetPasswordOptions) => {
const user = await prisma.user.findFirstOrThrow({
where: {
id: userId,
},
});
const assetBaseUrl = NEXT_PUBLIC_WEBAPP_URL() || 'http://localhost:3000';
const template = createElement(ResetPasswordTemplate, {
assetBaseUrl,
userEmail: user.email,
userName: user.name || '',
source,
});
const [html, text] = await Promise.all([
renderEmailWithI18N(template),
renderEmailWithI18N(template, { plainText: true }),
]);
const i18n = await getI18nInstance();
const subject = match(source)
.with('RESET', () => i18n._(msg`Password Reset Success!`))
.with('UPDATE', () => i18n._(msg`Your password was changed`))
.exhaustive();
return await mailer.sendMail({
to: {
address: user.email,
name: user.name || '',
},
from: {
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
},
subject,
html,
text,
});
};