Verification reset-password email and site corrections
This commit is contained in:
@@ -77,7 +77,9 @@ userRouter.post('/create',
|
||||
email: req.body.email
|
||||
});
|
||||
|
||||
const language = req.header('Accept-Language') || 'en';
|
||||
const acceptLanguage = req.header('Accept-Language') || 'en';
|
||||
const language : 'hu' | 'de' | 'en' = acceptLanguage.toLowerCase().startsWith('hu') ? 'hu' :
|
||||
acceptLanguage.toLowerCase().startsWith('de') ? 'de' : 'en';
|
||||
|
||||
const result = await container.createUserCommandHandler.execute({ ...req.body, language });
|
||||
|
||||
@@ -270,7 +272,9 @@ userRouter.post('/forgot-password',
|
||||
async (req, res) => {
|
||||
try {
|
||||
const { email } = req.body;
|
||||
const language = req.header('Accept-Language') || 'en';
|
||||
const acceptLanguage = req.header('Accept-Language') || 'en';
|
||||
const language: 'hu' | 'de' | 'en' = acceptLanguage.toLowerCase().startsWith('hu') ? 'hu' :
|
||||
acceptLanguage.toLowerCase().startsWith('de') ? 'de' : 'en';
|
||||
|
||||
logRequest('Forgot password endpoint accessed', req, res, { email });
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import sharp from 'sharp';
|
||||
import { logError, logAuth, logStartup } from './Logger';
|
||||
import { EmailTemplateHelper, LocalizedSubjects } from './EmailTemplateHelper';
|
||||
|
||||
|
||||
export interface EmailOptions {
|
||||
to: string;
|
||||
subject: string;
|
||||
@@ -36,7 +37,7 @@ export class EmailService {
|
||||
this.templatesPath = path.join(__dirname, '../../Templates');
|
||||
this.logoPath = path.join(__dirname, '../../../assets/Logo.png');
|
||||
// Load logo asynchronously after initialization
|
||||
this.loadLogoBase64().catch(err => console.error('[EmailService] Error loading logo:', err));
|
||||
this.loadLogo().catch(err => logError('Error loading logo:', err));
|
||||
|
||||
this.config = {
|
||||
host: process.env.EMAIL_HOST || 'smtp.gmail.com',
|
||||
@@ -70,9 +71,9 @@ export class EmailService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and resize logo for email attachments - 32x32 pixels
|
||||
* Load and resize logo for email attachments - 60x60 pixels
|
||||
*/
|
||||
private async loadLogoBase64(): Promise<void> {
|
||||
private async loadLogo(): Promise<void> {
|
||||
try {
|
||||
if (fs.existsSync(this.logoPath)) {
|
||||
const logoBuffer = fs.readFileSync(this.logoPath);
|
||||
@@ -86,11 +87,8 @@ export class EmailService {
|
||||
})
|
||||
.png()
|
||||
.toBuffer();
|
||||
|
||||
console.log(`[EmailService] ✅ Logo loaded and resized to 60x60`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[EmailService] ❌ Failed to load/resize logo:`, error);
|
||||
logError('Failed to load logo for emails', error instanceof Error ? error : new Error(String(error)));
|
||||
}
|
||||
}
|
||||
@@ -101,6 +99,11 @@ export class EmailService {
|
||||
*/
|
||||
async sendEmail(options: EmailOptions): Promise<boolean> {
|
||||
try {
|
||||
// Ensure logo is loaded before sending
|
||||
if (!this.resizedLogoBuffer) {
|
||||
await this.loadLogo();
|
||||
}
|
||||
|
||||
let htmlContent = options.html;
|
||||
let textContent = options.text;
|
||||
|
||||
@@ -126,6 +129,9 @@ export class EmailService {
|
||||
content: this.resizedLogoBuffer,
|
||||
cid: 'logo@serpentrace' // Content-ID for referencing in HTML
|
||||
});
|
||||
console.log('[EmailService] 📎 Logo attached to email as CID: logo@serpentrace');
|
||||
} else {
|
||||
console.warn('[EmailService] ⚠️ Logo buffer not available, email will be sent without logo');
|
||||
}
|
||||
|
||||
const result = await this.transporter.sendMail(mailOptions);
|
||||
|
||||
@@ -137,7 +137,7 @@ export class TokenService {
|
||||
try {
|
||||
// Remove trailing slash from baseUrl if present
|
||||
const cleanBaseUrl = baseUrl.replace(/\/$/, '');
|
||||
return `${cleanBaseUrl}/api/auth/reset-password?token=${encodeURIComponent(token)}`;
|
||||
return `${cleanBaseUrl}/reset-password?token=${encodeURIComponent(token)}`;
|
||||
} catch (error) {
|
||||
logError('TokenService.generatePasswordResetUrl error', error instanceof Error ? error : new Error(String(error)));
|
||||
throw new Error('Failed to generate password reset URL');
|
||||
|
||||
@@ -7,5 +7,5 @@ export interface CreateUserCommand {
|
||||
code?: string;
|
||||
orgid?: string;
|
||||
phone?: string;
|
||||
language: string;
|
||||
language: 'hu' | 'de' | 'en';
|
||||
}
|
||||
|
||||
@@ -67,24 +67,17 @@ export class CreateUserCommandHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private async sendVerificationEmailAsync(language: string, user: UserAggregate, token: string): Promise<void> {
|
||||
private async sendVerificationEmailAsync(language: 'hu' | 'de' | 'en', user: UserAggregate, token: string): Promise<void> {
|
||||
try {
|
||||
const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
|
||||
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(
|
||||
user.email,
|
||||
`${user.fname} ${user.lname}`,
|
||||
token,
|
||||
verificationUrl,
|
||||
lang
|
||||
language
|
||||
);
|
||||
|
||||
if (!emailSent) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface RequestPasswordResetCommand {
|
||||
language: string;
|
||||
language: 'hu' | 'de' | 'en';
|
||||
email: string;
|
||||
}
|
||||
|
||||
+1
-6
@@ -41,18 +41,13 @@ export class RequestPasswordResetCommandHandler {
|
||||
const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
|
||||
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(
|
||||
user.email,
|
||||
`${user.fname} ${user.lname}`,
|
||||
resetTokenData.token,
|
||||
resetUrl,
|
||||
lang
|
||||
cmd.language
|
||||
);
|
||||
|
||||
if (!emailSent) {
|
||||
|
||||
Reference in New Issue
Block a user