This commit is contained in:
Bastian Wagner
2026-07-17 14:07:04 +02:00
parent 8c6ad294b2
commit 45a41c2077
64 changed files with 2032 additions and 83 deletions

View File

@@ -3,9 +3,13 @@ import { ConfigService } from '@nestjs/config';
import { Request } from 'express';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Repository } from 'typeorm';
import { ApplicationErrorCategory, ApplicationErrorCode } from '../application-error-log/application-error-codes';
import { ApplicationErrorLoggerService } from '../application-error-log/application-error-logger.service';
import { maskEmail } from '../application-error-log/application-error-sanitizer';
import { AuditService } from '../audit/audit.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { RequestUser } from '../common/request-user';
import { RequestContextService } from '../common/request-context.service';
import { hashToken, randomToken } from '../common/token.util';
import { LldapService } from '../lldap/lldap.service';
import { PortalMailService } from '../mail/portal-mail.service';
@@ -24,6 +28,8 @@ export class AccountController {
private readonly mail: PortalMailService,
private readonly config: ConfigService,
private readonly audit: AuditService,
private readonly applicationErrorLogger: ApplicationErrorLoggerService,
private readonly requestContext: RequestContextService,
@InjectRepository(EmailChangeRequest)
private readonly emailChanges: Repository<EmailChangeRequest>,
@InjectRepository(AccountDeleteRequest)
@@ -64,7 +70,28 @@ export class AccountController {
expiresAt: new Date(Date.now() + 24 * 60 * 60_000),
}),
);
await this.mail.sendEmailChangeMail(dto.newEmail, token);
try {
await this.mail.sendEmailChangeMail(dto.newEmail, token);
} catch (error) {
await this.applicationErrorLogger.log({
error,
category: ApplicationErrorCategory.EMAIL,
code: ApplicationErrorCode.ACCOUNT_EMAIL_CHANGE_EMAIL_SEND_FAILED,
module: 'AccountModule',
service: AccountController.name,
operation: 'sendEmailChangeMail',
requestContext: {
...this.requestContext.get(),
userId: request.user.username,
},
context: {
maskedRecipient: maskEmail(dto.newEmail.toLowerCase()),
mailProvider: this.config.get<string>('SMTP_HOST') ?? 'smtp',
},
handled: true,
});
throw error;
}
await this.audit.record({
type: 'account.email_change_requested',
username: request.user.username,