feat(email): make verify-email org-aware like other transactional mail
Resolve the tenant org from the verification link callback URL (custom domain, tenant subdomain, or ?org=) and apply org logo, theme color, from name, and subject. Falls back to ClassroomIO branding on the main app. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>
This commit is contained in:
co-authored by
Rotimi Best
parent
f262a092ed
commit
a6d06f356f
@@ -1,5 +1,7 @@
|
||||
import { type BetterAuthOptions } from 'better-auth';
|
||||
import { sendEmail } from '@cio/email';
|
||||
import { buildEmailBranding, buildEmailFromName, sendEmail } from '@cio/email';
|
||||
|
||||
import { resolveVerificationOrg } from './resolve-verification-org';
|
||||
|
||||
type EmailVerificationOptions = Parameters<
|
||||
NonNullable<NonNullable<BetterAuthOptions['emailVerification']>['sendVerificationEmail']>
|
||||
@@ -9,17 +11,38 @@ type ChangeEmailConfirmationOptions = Parameters<
|
||||
NonNullable<NonNullable<NonNullable<BetterAuthOptions['user']>['changeEmail']>['sendChangeEmailConfirmation']>
|
||||
>[0];
|
||||
|
||||
/**
|
||||
* Email verification flow.
|
||||
*
|
||||
* 1. user says I want to change my email from email@old.com to email@new.com
|
||||
* 2. we send an email to email@old.com asking user to verify if they really want to change their email to email@new.com `sendChangeEmailConfirmation()`. [better-auth].
|
||||
* 3. user clicks the link in the email
|
||||
* 4. we update the email in the database. [better-auth].
|
||||
* 5. we send a confirmation email to email@new.com `sendVerificationEmail()`. [dashboard].
|
||||
* 6. user clicks the link in the email
|
||||
* 7. we mark email@new.com as verified. [better-auth].
|
||||
*/
|
||||
function stripTriggerParam(url: string): string {
|
||||
return url.replace('trigger=app', '').replace('trigger%3Dapp', '');
|
||||
}
|
||||
|
||||
async function sendOrgAwareVerifyEmail(options: {
|
||||
to: string;
|
||||
verificationUrl: string;
|
||||
userId: string;
|
||||
userName?: string | null;
|
||||
newEmail?: string;
|
||||
}) {
|
||||
const org = await resolveVerificationOrg({
|
||||
verificationUrl: options.verificationUrl,
|
||||
userId: options.userId
|
||||
});
|
||||
|
||||
const orgName = org?.name?.trim() || 'ClassroomIO';
|
||||
const branding = buildEmailBranding(org ? { name: org.name, avatarUrl: org.avatarUrl, theme: org.theme } : undefined);
|
||||
|
||||
await sendEmail('verifyEmail', {
|
||||
to: options.to,
|
||||
from: org?.name ? buildEmailFromName(`${org.name} (via ClassroomIO.com)`) : undefined,
|
||||
subject: org?.name ? `Confirm your email for ${org.name}` : undefined,
|
||||
fields: {
|
||||
link: stripTriggerParam(options.verificationUrl),
|
||||
newEmail: options.newEmail,
|
||||
userName: options.userName || undefined,
|
||||
orgName,
|
||||
branding
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a verification email to the user when they sign up or change their email address.
|
||||
@@ -35,15 +58,11 @@ export const sendVerificationEmail = async (options: EmailVerificationOptions) =
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove trigger=app or trigger%3Dapp from the URL
|
||||
const link = url.replace('trigger=app', '').replace('trigger%3Dapp', '');
|
||||
|
||||
await sendEmail('verifyEmail', {
|
||||
await sendOrgAwareVerifyEmail({
|
||||
to: user.email,
|
||||
fields: {
|
||||
link,
|
||||
userName: user.name || undefined
|
||||
}
|
||||
verificationUrl: url,
|
||||
userId: user.id,
|
||||
userName: user.name
|
||||
});
|
||||
};
|
||||
|
||||
@@ -56,12 +75,11 @@ export const sendChangeEmailConfirmation = async (options: ChangeEmailConfirmati
|
||||
const { user, newEmail, url } = options;
|
||||
console.log('\nsendChangeEmailConfirmation', options);
|
||||
|
||||
await sendEmail('verifyEmail', {
|
||||
await sendOrgAwareVerifyEmail({
|
||||
to: user.email,
|
||||
fields: {
|
||||
link: url,
|
||||
newEmail,
|
||||
userName: user.name || undefined
|
||||
}
|
||||
verificationUrl: url,
|
||||
userId: user.id,
|
||||
userName: user.name,
|
||||
newEmail
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user