feat(admin): add email change flow with confirmation for users
- add `ConfirmEmailChangePage.client.js` for email change token confirmation - add `emailChange.js` core utility to generate and verify email change tokens - add `EmailChangeConfirmEmail.js` and `EmailChangeNotifyEmail.js` email templates - update `UserEditModal` to handle email changes with password verification for self-edits - update `ProfilePage` to support email change initiation - update `UsersPage` to pass `currentUserId` to `UserEditModal` - add email change API endpoints in `auth/api.js` and `auth/email.js` - register `ConfirmEmailChangePage` in `AdminPage.client.js`
This commit is contained in:
@@ -4,10 +4,15 @@ import { sendEmail } from '@zen/core/email';
|
||||
import { VerificationEmail } from './templates/VerificationEmail.js';
|
||||
import { PasswordResetEmail } from './templates/PasswordResetEmail.js';
|
||||
import { PasswordChangedEmail } from './templates/PasswordChangedEmail.js';
|
||||
import { EmailChangeConfirmEmail } from './templates/EmailChangeConfirmEmail.js';
|
||||
import { EmailChangeNotifyEmail } from './templates/EmailChangeNotifyEmail.js';
|
||||
|
||||
export { createEmailVerification, verifyEmailToken, createPasswordReset, verifyResetToken, deleteResetToken }
|
||||
from '../../core/users/verifications.js';
|
||||
|
||||
export { createEmailChangeToken, verifyEmailChangeToken, applyEmailChange }
|
||||
from '../../core/users/emailChange.js';
|
||||
|
||||
async function sendVerificationEmail(email, token, baseUrl) {
|
||||
const appName = process.env.ZEN_NAME || 'ZEN';
|
||||
const verificationUrl = `${baseUrl}/auth/confirm?email=${encodeURIComponent(email)}&token=${token}`;
|
||||
@@ -46,4 +51,46 @@ async function sendPasswordChangedEmail(email) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export { sendVerificationEmail, sendPasswordResetEmail, sendPasswordChangedEmail };
|
||||
async function sendEmailChangeConfirmEmail(newEmail, token, baseUrl) {
|
||||
const appName = process.env.ZEN_NAME || 'ZEN';
|
||||
const confirmUrl = `${baseUrl}/admin/confirm-email-change?token=${encodeURIComponent(token)}`;
|
||||
const html = await render(<EmailChangeConfirmEmail confirmUrl={confirmUrl} newEmail={newEmail} companyName={appName} />);
|
||||
const result = await sendEmail({ to: newEmail, subject: `Confirmez votre nouvelle adresse courriel – ${appName}`, html });
|
||||
if (!result.success) {
|
||||
fail(`Auth: failed to send email change confirmation to ${newEmail}: ${result.error}`);
|
||||
throw new Error('Failed to send email change confirmation');
|
||||
}
|
||||
info(`Auth: email change confirmation sent to ${newEmail}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
async function sendEmailChangeOldNotifyEmail(oldEmail, newEmail, variant) {
|
||||
const appName = process.env.ZEN_NAME || 'ZEN';
|
||||
const subjects = {
|
||||
pending: `Demande de modification de courriel – ${appName}`,
|
||||
changed: `Votre adresse courriel a été modifiée – ${appName}`,
|
||||
};
|
||||
const subject = subjects[variant] || subjects.changed;
|
||||
const html = await render(<EmailChangeNotifyEmail oldEmail={oldEmail} newEmail={newEmail} variant={variant} companyName={appName} />);
|
||||
const result = await sendEmail({ to: oldEmail, subject, html });
|
||||
if (!result.success) {
|
||||
fail(`Auth: failed to send email change notification to ${oldEmail}: ${result.error}`);
|
||||
throw new Error('Failed to send email change notification');
|
||||
}
|
||||
info(`Auth: email change notification (${variant}) sent to ${oldEmail}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
async function sendEmailChangeNewNotifyEmail(newEmail, oldEmail) {
|
||||
const appName = process.env.ZEN_NAME || 'ZEN';
|
||||
const html = await render(<EmailChangeNotifyEmail oldEmail={oldEmail} newEmail={newEmail} variant="admin_new" companyName={appName} />);
|
||||
const result = await sendEmail({ to: newEmail, subject: `Votre compte est maintenant associé à cette adresse – ${appName}`, html });
|
||||
if (!result.success) {
|
||||
fail(`Auth: failed to send email change welcome to ${newEmail}: ${result.error}`);
|
||||
throw new Error('Failed to send email change welcome');
|
||||
}
|
||||
info(`Auth: email change welcome sent to ${newEmail}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export { sendVerificationEmail, sendPasswordResetEmail, sendPasswordChangedEmail, sendEmailChangeConfirmEmail, sendEmailChangeOldNotifyEmail, sendEmailChangeNewNotifyEmail };
|
||||
|
||||
Reference in New Issue
Block a user