Initial commit: Complete NodeJS-native setup
- Migrated from Python pre-commit to NodeJS-native solution - Reorganized documentation structure - Set up Husky + lint-staged for efficient pre-commit hooks - Fixed Dockerfile healthcheck issue - Added comprehensive documentation index
This commit is contained in:
95
services/auth/emailVerification.service.ts
Normal file
95
services/auth/emailVerification.service.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { EmailVerificationToken, AuthenticatedUser } from './auth.types';
|
||||
import { mailgunService } from '../mailgun.service';
|
||||
import { AccountStatus } from './auth.constants';
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
// Store token in localStorage for demo (in production, save to database)
|
||||
const tokens = JSON.parse(
|
||||
localStorage.getItem('verification_tokens') || '[]'
|
||||
);
|
||||
tokens.push(verificationToken);
|
||||
localStorage.setItem('verification_tokens', JSON.stringify(tokens));
|
||||
|
||||
// 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> {
|
||||
// Get tokens from localStorage
|
||||
const tokens = JSON.parse(
|
||||
localStorage.getItem('verification_tokens') || '[]'
|
||||
);
|
||||
const verificationToken = tokens.find(
|
||||
(t: EmailVerificationToken) => t.token === 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 { dbService } = await import('../couchdb');
|
||||
const user = await dbService.findUserByEmail(verificationToken.email);
|
||||
|
||||
return user as AuthenticatedUser;
|
||||
}
|
||||
|
||||
async markEmailVerified(user: AuthenticatedUser): Promise<void> {
|
||||
// Update user in database
|
||||
const { dbService } = await import('../couchdb');
|
||||
const updatedUser = {
|
||||
...user,
|
||||
emailVerified: true,
|
||||
status: AccountStatus.ACTIVE,
|
||||
};
|
||||
|
||||
await dbService.updateUser(updatedUser);
|
||||
|
||||
// Remove used token
|
||||
const tokens = JSON.parse(
|
||||
localStorage.getItem('verification_tokens') || '[]'
|
||||
);
|
||||
const filteredTokens = tokens.filter(
|
||||
(t: EmailVerificationToken) => t.userId !== user._id
|
||||
);
|
||||
localStorage.setItem('verification_tokens', JSON.stringify(filteredTokens));
|
||||
}
|
||||
|
||||
async sendPasswordResetEmail(email: string, token: string): Promise<boolean> {
|
||||
return mailgunService.sendPasswordResetEmail(email, token);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user