b6b345f245
- Refactor email verification and password reset utilities to use new email service. - Introduce email delivery queue and notification delivery model for better tracking. - Enhance file validation and storage services for improved security and ownership management. - Add cron job for cleaning inactive notifications with retention policy. - Update document worker to handle document generation and storage more efficiently. - Implement logging improvements in activity and log workers. - Create comprehensive documentation for new API endpoints and services. - Add unit tests for file validation and notification policies to ensure robustness.
99 lines
2.7 KiB
JavaScript
99 lines
2.7 KiB
JavaScript
// app/utils/emailVerification.util.js
|
|
|
|
const crypto = require("crypto");
|
|
const emailService = require("../services/email/email.service");
|
|
const redis = require("../config/redisClient");
|
|
|
|
const EMAIL_VERIFICATION_TTL =
|
|
Number(process.env.EMAIL_VERIFICATION_TTL_SECONDS) || 1800;
|
|
|
|
const generateEmailVerificationToken = () => {
|
|
return crypto.randomBytes(32).toString("hex");
|
|
};
|
|
|
|
const hashEmailVerificationToken = (token) => {
|
|
return crypto.createHash("sha256").update(token).digest("hex");
|
|
};
|
|
|
|
const createEmailVerification = async (userId) => {
|
|
const previousKey = await redis.get(`email-verification-user:${userId}`);
|
|
if (previousKey) await redis.del(previousKey);
|
|
// 1. Generate raw token
|
|
const token = generateEmailVerificationToken();
|
|
|
|
// 2. Hash token
|
|
const tokenHash = hashEmailVerificationToken(token);
|
|
|
|
// 3. Create Redis key
|
|
const redisKey = `email-verification:${tokenHash}`;
|
|
|
|
await redis.set(redisKey, userId, "EX", EMAIL_VERIFICATION_TTL);
|
|
await redis.set(`email-verification-user:${userId}`, redisKey, "EX", EMAIL_VERIFICATION_TTL);
|
|
|
|
return token;
|
|
};
|
|
|
|
/**
|
|
* Check a verification token.
|
|
*/
|
|
const verifyEmailVerificationToken = async (token) => {
|
|
if (!token || typeof token !== "string") {
|
|
return null;
|
|
}
|
|
|
|
// 1. Hash token received from user
|
|
const tokenHash = hashEmailVerificationToken(token);
|
|
|
|
// 2. Build same Redis key
|
|
const redisKey = `email-verification:${tokenHash}`;
|
|
|
|
// 3. Search Redis
|
|
const userId = await redis.getdel(redisKey);
|
|
|
|
if (!userId) {
|
|
return null;
|
|
}
|
|
|
|
await redis.del(`email-verification-user:${userId}`);
|
|
|
|
return {
|
|
userId,
|
|
redisKey,
|
|
};
|
|
};
|
|
|
|
//send verification email to user
|
|
const sendVerificationEmail = async (email, firstName, verificationToken) => {
|
|
const confirmationLink = `${process.env.FRONTEND_URL}/verify-email?token=${verificationToken}`;
|
|
|
|
// Send email
|
|
await emailService.send({
|
|
recipient: email, templateKey: "emailVerification",
|
|
variables: {
|
|
customer_name: firstName,
|
|
confirmation_link: confirmationLink,
|
|
}, eventId: `verify-${hashEmailVerificationToken(verificationToken)}`,
|
|
});
|
|
};
|
|
|
|
const deleteEmailVerification = async (redisKey) => {
|
|
await redis.del(redisKey);
|
|
};
|
|
|
|
const consumeEmailVerificationToken = async (token) => {
|
|
if (!token || typeof token !== "string") return null;
|
|
const redisKey = `email-verification:${hashEmailVerificationToken(token)}`;
|
|
const userId = await redis.getdel(redisKey);
|
|
if (userId) await redis.del(`email-verification-user:${userId}`);
|
|
return userId;
|
|
};
|
|
|
|
module.exports = {
|
|
createEmailVerification,
|
|
verifyEmailVerificationToken,
|
|
sendVerificationEmail,
|
|
deleteEmailVerification,
|
|
consumeEmailVerificationToken,
|
|
hashEmailVerificationToken,
|
|
};
|