CentralBackend/services/EmailVerificationService.js
2025-09-07 12:44:01 +02:00

91 lines
3.6 KiB
JavaScript

const EmailVerificationRepository = require('../repositories/EmailVerificationRepository');
const MailService = require('./MailService');
const { logger } = require('../middleware/logger');
class EmailVerificationService {
static async sendVerificationEmail(user, unitOfWork) {
logger.info('EmailVerificationService.sendVerificationEmail:start', { userId: user.id, email: user.email });
const emailVerificationRepo = new EmailVerificationRepository(unitOfWork);
try {
// Check if already verified
const status = await unitOfWork.connection.query(
'SELECT email_verified FROM user_status WHERE user_id = ?', [user.id]
);
if (status[0][0] && status[0][0].email_verified) {
logger.warn('EmailVerificationService.sendVerificationEmail:already_verified', { userId: user.id });
throw new Error('Email already verified');
}
// Generate 6-digit code and expiry
const code = Math.floor(100000 + Math.random() * 900000).toString();
const expiresAt = new Date(Date.now() + 10 * 60 * 1000); // 10 minutes
// Upsert code in DB
await emailVerificationRepo.upsertCode(user.id, code, expiresAt);
logger.info('EmailVerificationService.sendVerificationEmail:code_upserted', { userId: user.id });
// Send email
await MailService.sendVerificationCodeEmail({
email: user.email,
code,
expiresAt
});
logger.info('EmailVerificationService.sendVerificationEmail:email_sent', { userId: user.id, email: user.email });
logger.info('EmailVerificationService.sendVerificationEmail:success', { userId: user.id });
return true;
} catch (error) {
logger.error('EmailVerificationService.sendVerificationEmail:error', { userId: user.id, error: error.message });
throw error;
}
}
static async verifyCode(userId, code, unitOfWork) {
logger.info('EmailVerificationService.verifyCode:start', { userId, code });
const emailVerificationRepo = new EmailVerificationRepository(unitOfWork);
try {
// Get latest, unexpired, unverified code
const record = await emailVerificationRepo.getByUserId(userId);
if (
!record ||
record.verified_at ||
new Date(record.expires_at) < new Date() ||
record.verification_code !== code
) {
logger.warn('EmailVerificationService.verifyCode:invalid_or_expired', { userId, code });
// Optionally increment attempts
if (record) {
await emailVerificationRepo.incrementAttempts(record.id);
}
return { success: false, error: 'Invalid or expired code' };
}
// Mark as verified
await emailVerificationRepo.setVerified(record.id);
logger.info('EmailVerificationService.verifyCode:code_verified', { userId });
// Update user_status
await unitOfWork.connection.query(
`UPDATE user_status SET email_verified = 1, email_verified_at = NOW() WHERE user_id = ?`,
[userId]
);
logger.info('EmailVerificationService.verifyCode:user_status_updated', { userId });
// Check if all steps are complete and set status to 'pending' if so
const UserStatusService = require('./UserStatusService');
await UserStatusService.checkAndSetPendingIfComplete(userId, unitOfWork);
logger.info('EmailVerificationService.verifyCode:pending_check_complete', { userId });
logger.info('EmailVerificationService.verifyCode:success', { userId });
return { success: true };
} catch (error) {
logger.error('EmailVerificationService.verifyCode:error', { userId, error: error.message });
throw error;
}
}
}
module.exports = EmailVerificationService;