import { Body, Controller, ForbiddenException, Get, Param, ParseUUIDPipe, Patch, Post, Put, Req } from '@nestjs/common'; import { CurrentAuth } from '../auth/decorators/current-auth.decorator'; import { RequirePermissions } from '../authorization/decorators/require-permissions.decorator'; import type { AuthPrincipal, RequestWithContext } from '../common/http/request-context'; import { administrationAuditContext } from '../administration/common/administration-audit'; import { AuditService } from '../audit/audit.service'; import { AuditAction } from '../database/entities'; import { InspectionDocumentDeliveryService } from './inspection-document-delivery.service'; import type { DeliveryRow } from './inspection-document-delivery.service'; import { SmtpDeliveryService } from './smtp-delivery.service'; import { UpdateDocumentDeliverySettingsDto } from './dto/update-document-delivery-settings.dto'; import { TestSmtpSettingsDto, UpdateSmtpSettingsDto } from './dto/update-smtp-settings.dto'; @Controller('document-delivery') export class DocumentDeliveryController { constructor( private readonly delivery: InspectionDocumentDeliveryService, private readonly smtp: SmtpDeliveryService, private readonly audit: AuditService, ) {} @Get('settings') @RequirePermissions('document_delivery.read') settings() { return this.delivery.settings(); } @Patch('settings') @RequirePermissions('document_delivery.manage') update( @Body() dto: UpdateDocumentDeliverySettingsDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.delivery.updateSettings(dto, principal, request); } @Get('smtp') @RequirePermissions('document_delivery.manage') smtpSettings(@CurrentAuth() principal: AuthPrincipal) { this.assertSystemAdmin(principal); return this.smtp.publicSettings(); } @Put('smtp') @RequirePermissions('document_delivery.manage') async updateSmtp( @Body() dto: UpdateSmtpSettingsDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { this.assertSystemAdmin(principal); const before = await this.smtp.publicSettings(); const after = await this.smtp.saveSettings(dto, principal.userId); await this.audit.record({ ...administrationAuditContext(principal, request), action: AuditAction.SMTP_SETTINGS_UPDATED, entityType: 'system_smtp_settings', entityId: 'singleton', beforeData: before as Record, afterData: after as Record, metadata: { passwordNeverReturned: true, restrictedToRole: 'admin' }, }); return after; } @Post('smtp/test') @RequirePermissions('document_delivery.manage') async testSmtp( @Body() dto: TestSmtpSettingsDto, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { this.assertSystemAdmin(principal); const sent = await this.smtp.send({ to: dto.email, subject: 'DH Inspección · Prueba SMTP', text: 'Este correo confirma que la configuración SMTP de DH Inspección funciona correctamente.', attachment: { filename: 'dh-inspeccion-smtp-test.txt', mimeType: 'text/plain', content: Buffer.from('DH Inspección · Prueba SMTP OK\n', 'utf8'), }, }); await this.audit.record({ ...administrationAuditContext(principal, request), action: AuditAction.SMTP_TEST_SENT, entityType: 'system_smtp_settings', entityId: 'singleton', afterData: { recipient: dto.email, messageId: sent.messageId }, metadata: { restrictedToRole: 'admin' }, }); return { ok: true, recipient: dto.email, messageId: sent.messageId }; } @Get('outbox') @RequirePermissions('document_delivery.read') outbox() { return this.delivery.list(); } @Post('outbox/:id/retry') @RequirePermissions('document_delivery.manage') retry( @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ): Promise { return this.delivery.retry(id, principal, request); } @Post('outbox/retry-pending') @RequirePermissions('document_delivery.manage') retryPending( @CurrentAuth() principal: AuthPrincipal, @Req() request: RequestWithContext, ) { return this.delivery.retryPending(principal, request); } private assertSystemAdmin(principal: AuthPrincipal): void { if (principal.roles.includes('admin')) return; throw new ForbiddenException({ code: 'SMTP_SUPERADMIN_REQUIRED', message: 'La configuración SMTP está reservada al Superadmin del sistema', }); } }