chore: import codes
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* Email Verification and Password Reset
|
||||
* Handles email verification tokens and password reset tokens
|
||||
*/
|
||||
|
||||
import { create, findOne, deleteWhere } from '../../../core/database/crud.js';
|
||||
import { generateToken, generateId } from './password.js';
|
||||
import { sendAuthEmail } from '../../../core/email/index.js';
|
||||
import { renderVerificationEmail, renderPasswordResetEmail, renderPasswordChangedEmail } from '../../../core/email/templates/index.js';
|
||||
|
||||
/**
|
||||
* Create an email verification token
|
||||
* @param {string} email - User email
|
||||
* @returns {Promise<Object>} Verification object with token
|
||||
*/
|
||||
async function createEmailVerification(email) {
|
||||
const token = generateToken(32);
|
||||
const verificationId = generateId();
|
||||
|
||||
// Token expires in 24 hours
|
||||
const expiresAt = new Date();
|
||||
expiresAt.setHours(expiresAt.getHours() + 24);
|
||||
|
||||
// Delete any existing verification tokens for this email
|
||||
await deleteWhere('zen_auth_verifications', {
|
||||
identifier: 'email_verification',
|
||||
value: email
|
||||
});
|
||||
|
||||
const verification = await create('zen_auth_verifications', {
|
||||
id: verificationId,
|
||||
identifier: 'email_verification',
|
||||
value: email,
|
||||
token,
|
||||
expires_at: expiresAt,
|
||||
updated_at: new Date()
|
||||
});
|
||||
|
||||
return {
|
||||
...verification,
|
||||
token
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify an email token
|
||||
* @param {string} email - User email
|
||||
* @param {string} token - Verification token
|
||||
* @returns {Promise<boolean>} True if valid, false otherwise
|
||||
*/
|
||||
async function verifyEmailToken(email, token) {
|
||||
const verification = await findOne('zen_auth_verifications', {
|
||||
identifier: 'email_verification',
|
||||
value: email
|
||||
});
|
||||
|
||||
if (!verification) return false;
|
||||
|
||||
// Verify token matches
|
||||
if (verification.token !== token) return false;
|
||||
|
||||
// Check if token is expired
|
||||
if (new Date(verification.expires_at) < new Date()) {
|
||||
await deleteWhere('zen_auth_verifications', { id: verification.id });
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete the verification token after use
|
||||
await deleteWhere('zen_auth_verifications', { id: verification.id });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a password reset token
|
||||
* @param {string} email - User email
|
||||
* @returns {Promise<Object>} Reset object with token
|
||||
*/
|
||||
async function createPasswordReset(email) {
|
||||
const token = generateToken(32);
|
||||
const resetId = generateId();
|
||||
|
||||
// Token expires in 1 hour
|
||||
const expiresAt = new Date();
|
||||
expiresAt.setHours(expiresAt.getHours() + 1);
|
||||
|
||||
// Delete any existing reset tokens for this email
|
||||
await deleteWhere('zen_auth_verifications', {
|
||||
identifier: 'password_reset',
|
||||
value: email
|
||||
});
|
||||
|
||||
const reset = await create('zen_auth_verifications', {
|
||||
id: resetId,
|
||||
identifier: 'password_reset',
|
||||
value: email,
|
||||
token,
|
||||
expires_at: expiresAt,
|
||||
updated_at: new Date()
|
||||
});
|
||||
|
||||
return {
|
||||
...reset,
|
||||
token
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password reset token
|
||||
* @param {string} email - User email
|
||||
* @param {string} token - Reset token
|
||||
* @returns {Promise<boolean>} True if valid, false otherwise
|
||||
*/
|
||||
async function verifyResetToken(email, token) {
|
||||
const reset = await findOne('zen_auth_verifications', {
|
||||
identifier: 'password_reset',
|
||||
value: email
|
||||
});
|
||||
|
||||
if (!reset) return false;
|
||||
|
||||
// Verify token matches
|
||||
if (reset.token !== token) return false;
|
||||
|
||||
// Check if token is expired
|
||||
if (new Date(reset.expires_at) < new Date()) {
|
||||
await deleteWhere('zen_auth_verifications', { id: reset.id });
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a password reset token
|
||||
* @param {string} email - User email
|
||||
* @returns {Promise<number>} Number of deleted tokens
|
||||
*/
|
||||
async function deleteResetToken(email) {
|
||||
return await deleteWhere('zen_auth_verifications', {
|
||||
identifier: 'password_reset',
|
||||
value: email
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send verification email using Resend
|
||||
* @param {string} email - User email
|
||||
* @param {string} token - Verification token
|
||||
* @param {string} baseUrl - Base URL of the application
|
||||
*/
|
||||
async function sendVerificationEmail(email, token, baseUrl) {
|
||||
const verificationUrl = `${baseUrl}/auth/confirm?email=${encodeURIComponent(email)}&token=${token}`;
|
||||
const appName = process.env.ZEN_NAME || 'ZEN';
|
||||
|
||||
const html = await renderVerificationEmail(verificationUrl, email, appName);
|
||||
|
||||
const result = await sendAuthEmail({
|
||||
to: email,
|
||||
subject: `Confirmez votre adresse courriel – ${appName}`,
|
||||
html
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
console.error(`[ZEN AUTH] Failed to send verification email to ${email}:`, result.error);
|
||||
throw new Error('Failed to send verification email');
|
||||
}
|
||||
|
||||
console.log(`[ZEN AUTH] Verification email sent to ${email}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send password reset email using Resend
|
||||
* @param {string} email - User email
|
||||
* @param {string} token - Reset token
|
||||
* @param {string} baseUrl - Base URL of the application
|
||||
*/
|
||||
async function sendPasswordResetEmail(email, token, baseUrl) {
|
||||
const resetUrl = `${baseUrl}/auth/reset?email=${encodeURIComponent(email)}&token=${token}`;
|
||||
const appName = process.env.ZEN_NAME || 'ZEN';
|
||||
|
||||
const html = await renderPasswordResetEmail(resetUrl, email, appName);
|
||||
|
||||
const result = await sendAuthEmail({
|
||||
to: email,
|
||||
subject: `Réinitialisation du mot de passe – ${appName}`,
|
||||
html
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
console.error(`[ZEN AUTH] Failed to send password reset email to ${email}:`, result.error);
|
||||
throw new Error('Failed to send password reset email');
|
||||
}
|
||||
|
||||
console.log(`[ZEN AUTH] Password reset email sent to ${email}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send password changed confirmation email using Resend
|
||||
* @param {string} email - User email
|
||||
*/
|
||||
async function sendPasswordChangedEmail(email) {
|
||||
const appName = process.env.ZEN_NAME || 'ZEN';
|
||||
|
||||
const html = await renderPasswordChangedEmail(email, appName);
|
||||
|
||||
const result = await sendAuthEmail({
|
||||
to: email,
|
||||
subject: `Mot de passe modifié – ${appName}`,
|
||||
html
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
console.error(`[ZEN AUTH] Failed to send password changed email to ${email}:`, result.error);
|
||||
throw new Error('Failed to send password changed email');
|
||||
}
|
||||
|
||||
console.log(`[ZEN AUTH] Password changed email sent to ${email}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export {
|
||||
createEmailVerification,
|
||||
verifyEmailToken,
|
||||
createPasswordReset,
|
||||
verifyResetToken,
|
||||
deleteResetToken,
|
||||
sendVerificationEmail,
|
||||
sendPasswordResetEmail,
|
||||
sendPasswordChangedEmail
|
||||
};
|
||||
Reference in New Issue
Block a user