Files
Zumri-Backend/app/utils/emailVerification.util.js
Sathira Sri Sathara b6b345f245 feat: Implement Phase 2 cross-cutting services with email and notification enhancements
- 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.
2026-09-03 14:22:34 +05:30

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,
};