Email verification Backend

This commit is contained in:
magdo
2025-10-26 19:59:02 +01:00
parent 4b06a65bd9
commit 8c25c56e88
7 changed files with 34 additions and 14 deletions
@@ -77,10 +77,12 @@ userRouter.post('/create',
email: req.body.email email: req.body.email
}); });
const result = await container.createUserCommandHandler.execute(req.body); const language = req.header('Accept-Language') || 'en';
logRequest('User created successfully', req, res, { const result = await container.createUserCommandHandler.execute({ ...req.body, language });
username: result.username
logRequest('User created successfully', req, res, {
username: result.username
}); });
res.status(201).json(result); res.status(201).json(result);
@@ -268,10 +270,11 @@ userRouter.post('/forgot-password',
async (req, res) => { async (req, res) => {
try { try {
const { email } = req.body; const { email } = req.body;
const language = req.header('Accept-Language') || 'en';
logRequest('Forgot password endpoint accessed', req, res, { email }); logRequest('Forgot password endpoint accessed', req, res, { email });
const result = await container.requestPasswordResetCommandHandler.execute({ email }); const result = await container.requestPasswordResetCommandHandler.execute({ language, email });
if (result) { if (result) {
logAuth('Password reset request successful', undefined, { email }, req, res); logAuth('Password reset request successful', undefined, { email }, req, res);
@@ -15,7 +15,7 @@ export interface ShortDeckDto {
type: number; type: number;
playedNumber: number; playedNumber: number;
ctype: number; ctype: number;
cardsCount: number; cardCount: number;
creator: string; creator: string;
creationdate: Date; creationdate: Date;
} }
@@ -10,7 +10,7 @@ export class DeckMapper {
type: deck.type, type: deck.type,
playedNumber: deck.playedNumber, playedNumber: deck.playedNumber,
ctype: deck.ctype, ctype: deck.ctype,
cardsCount: deck.cards.length, cardCount: deck.cards.length,
creator: deck.user?.username || 'Unknown', creator: deck.user?.username || 'Unknown',
creationdate: deck.creationdate creationdate: deck.creationdate
}; };
@@ -36,7 +36,7 @@ export class DeckMapper {
type: deck.type, type: deck.type,
playedNumber: deck.playedNumber, playedNumber: deck.playedNumber,
ctype: deck.ctype, ctype: deck.ctype,
cardsCount: deck.cards.length, cardCount: deck.cards.length,
creator: deck.user?.username || 'Unknown', creator: deck.user?.username || 'Unknown',
creationdate: deck.creationdate creationdate: deck.creationdate
})); }));
@@ -7,4 +7,5 @@ export interface CreateUserCommand {
code?: string; code?: string;
orgid?: string; orgid?: string;
phone?: string; phone?: string;
language: string;
} }
@@ -43,7 +43,7 @@ export class CreateUserCommandHandler {
const created = await this.userRepo.create(user); const created = await this.userRepo.create(user);
// Send verification email (non-blocking) // Send verification email (non-blocking)
this.sendVerificationEmailAsync(created, verificationTokenData.token); this.sendVerificationEmailAsync(cmd.language, created, verificationTokenData.token);
return UserMapper.toShortDto(created); return UserMapper.toShortDto(created);
} catch (error) { } catch (error) {
@@ -67,16 +67,24 @@ export class CreateUserCommandHandler {
} }
} }
private async sendVerificationEmailAsync(user: UserAggregate, token: string): Promise<void> { private async sendVerificationEmailAsync(language: string, user: UserAggregate, token: string): Promise<void> {
try { try {
const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173'; const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
const verificationUrl = TokenService.generateVerificationUrl(baseUrl, token); const verificationUrl = TokenService.generateVerificationUrl(baseUrl, token);
var lang: 'en' | 'hu' | 'de' = 'en';
if (language) {
lang = language.toLowerCase() as 'en' | 'hu' | 'de';
}
const emailSent = await this.emailService.sendVerificationEmail( const emailSent = await this.emailService.sendVerificationEmail(
user.email, user.email,
`${user.fname} ${user.lname}`, `${user.fname} ${user.lname}`,
token, token,
verificationUrl verificationUrl,
lang
); );
if (!emailSent) { if (!emailSent) {
@@ -1,3 +1,4 @@
export interface RequestPasswordResetCommand { export interface RequestPasswordResetCommand {
language: string;
email: string; email: string;
} }
@@ -38,14 +38,21 @@ export class RequestPasswordResetCommandHandler {
// Send password reset email // Send password reset email
try { try {
const baseUrl = process.env.APP_BASE_URL || 'http://localhost:3000'; const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
const resetUrl = TokenService.generatePasswordResetUrl(baseUrl, resetTokenData.token); const resetUrl = TokenService.generatePasswordResetUrl(baseUrl, resetTokenData.token);
var lang: 'en' | 'hu' | 'de' = 'en';
if (cmd.language) {
lang = cmd.language.toLowerCase() as 'en' | 'hu' | 'de';
}
const emailSent = await this.emailService.sendPasswordResetEmail( const emailSent = await this.emailService.sendPasswordResetEmail(
user.email, user.email,
`${user.fname} ${user.lname}`, `${user.fname} ${user.lname}`,
resetTokenData.token, resetTokenData.token,
resetUrl resetUrl,
lang
); );
if (!emailSent) { if (!emailSent) {