Files
rxminder/services/auth/emailVerification.service.ts

80 lines
2.3 KiB
TypeScript

import { v4 as uuidv4 } from 'uuid';
import { EmailVerificationToken, AuthenticatedUser } from './auth.types';
import { mailgunService } from '../mailgun.service';
import { AccountStatus } from './auth.constants';
import { databaseService } from '../database';
import { tokenService } from './token.service';
const TOKEN_EXPIRY_HOURS = 24;
export class EmailVerificationService {
async generateVerificationToken(
user: AuthenticatedUser
): Promise<EmailVerificationToken> {
const token = uuidv4().replace(/-/g, ''); // Generate a random token using UUID
const expiresAt = new Date();
expiresAt.setHours(expiresAt.getHours() + TOKEN_EXPIRY_HOURS);
const verificationToken: EmailVerificationToken = {
userId: user._id,
email: user.email || '',
token,
expiresAt,
};
// Persist verification token via TokenService
await tokenService.saveVerificationToken(verificationToken);
// Send verification email via Mailgun
if (user.email) {
const emailSent = await mailgunService.sendVerificationEmail(
user.email,
token
);
if (!emailSent) {
console.warn('Failed to send verification email');
}
}
return verificationToken;
}
async validateVerificationToken(
token: string
): Promise<AuthenticatedUser | null> {
const verificationToken = await tokenService.findVerificationToken(token);
if (!verificationToken) {
return null;
}
// Check if token is expired
if (new Date() > new Date(verificationToken.expiresAt)) {
return null;
}
// Find the user (in production, this would be a proper database lookup)
const user = await databaseService.findUserByEmail(verificationToken.email);
return user as AuthenticatedUser;
}
async markEmailVerified(user: AuthenticatedUser): Promise<void> {
// Update user in database
const updatedUser = {
...user,
emailVerified: true,
status: AccountStatus.ACTIVE,
};
await databaseService.updateUser(updatedUser);
// Remove used token(s) for this user
await tokenService.deleteVerificationTokensForUser(user._id);
}
async sendPasswordResetEmail(email: string, token: string): Promise<boolean> {
return mailgunService.sendPasswordResetEmail(email, token);
}
}