Email a set-password link when an admin creates a user
This commit is contained in:
@@ -5,8 +5,23 @@ import { sveltekitCookies } from 'better-auth/svelte-kit';
|
||||
import { getRequestEvent } from '$app/server';
|
||||
import { sendMail } from './server/resend';
|
||||
import { sendVerificationEmail } from './server/email-verification';
|
||||
import { sendRegistrationEmail } from './server/registration-email';
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
/**
|
||||
* An admin-created user is invited with a set-password link. That reuses the
|
||||
* password-reset token flow but marks the request with `invite=1` so we send a
|
||||
* welcome/registration email instead of a "you requested a reset" email.
|
||||
*/
|
||||
function isRegistrationInvite(url: string): boolean {
|
||||
try {
|
||||
const callbackURL = new URL(url).searchParams.get('callbackURL') ?? '';
|
||||
return callbackURL.includes('invite=1');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const auth = betterAuth({
|
||||
baseURL: env.BETTER_AUTH_URL,
|
||||
database: prismaAdapter(prisma, {
|
||||
@@ -27,6 +42,13 @@ export const auth = betterAuth({
|
||||
enabled: true,
|
||||
requireEmailVerification: true,
|
||||
sendResetPassword: async ({ user, url }) => {
|
||||
if (isRegistrationInvite(url)) {
|
||||
void sendRegistrationEmail({ email: user.email, url }).catch((e) => {
|
||||
console.error('sendRegistrationEmail template email failed:', e);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
void sendMail({
|
||||
to: user.email,
|
||||
templateId: 'password-reset-email',
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
import { sendMail } from './resend';
|
||||
|
||||
/**
|
||||
* Send the "finish your registration" email to a user created by an admin.
|
||||
*
|
||||
* The link points at Better Auth's reset-password callback, which redirects to
|
||||
* `/reset-password?invite=1&token=...`. There the user sets a password, then
|
||||
* logs in and is sent to `/profile/setup` to complete their profile.
|
||||
*
|
||||
* Uses a Resend-hosted template (`registration-email` by default, or
|
||||
* `RESEND_REGISTRATION_TEMPLATE_ID`) with variables:
|
||||
* - `target_email_address`
|
||||
* - `registration_link`
|
||||
*/
|
||||
export async function sendRegistrationEmail(options: { email: string; url: string }) {
|
||||
await sendMail({
|
||||
to: options.email,
|
||||
subject: 'Welcome to Radiant Wave — set your password',
|
||||
templateId: env.RESEND_REGISTRATION_TEMPLATE_ID || 'registration-email',
|
||||
data: {
|
||||
target_email_address: options.email,
|
||||
registration_link: options.url
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user