feat(07-03): SettingsModule — SMTP config backend + connection test (DKV-05)
- SmtpConfigDto: host/port/encryption/username/password/fromAddress with class-validator - SettingsService: getSmtpConfig (SMTP_SAFE_SELECT, no password), saveSmtpConfig (AES-256-GCM encryption via CalendarCryptoService, preserve existing password on empty), getDecryptedSmtpConfig (internal, used by DkvMailService), testSmtpConfig (nodemailer.verify(), returns boolean, T-07-16), getStartupSmtpConfig (tenant-agnostic, used by MailModule factory, D-06) - SettingsController: GET/PUT /settings/smtp + POST /settings/smtp/test, all @Roles(ADMIN, SUPER_ADMIN) - SettingsModule: imports CalendarModule, exports SettingsService - AppModule: imports SettingsModule
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
IsEmail,
|
||||
IsIn,
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsString,
|
||||
Max,
|
||||
Min,
|
||||
} from 'class-validator';
|
||||
|
||||
/**
|
||||
* DTO for saving or testing an SMTP configuration.
|
||||
*
|
||||
* Security: T-07-08 — host/port/encryption validated to prevent open-relay abuse.
|
||||
* Password field is optional on PUT (empty string = preserve existing stored password).
|
||||
*/
|
||||
export class SmtpConfigDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
host!: string;
|
||||
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Max(65535)
|
||||
port!: number;
|
||||
|
||||
/** 'none' | 'starttls' | 'ssl-tls' */
|
||||
@IsIn(['none', 'starttls', 'ssl-tls'])
|
||||
encryption!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
username?: string;
|
||||
|
||||
/**
|
||||
* Plaintext password submitted by the client.
|
||||
* Empty string means "keep existing stored password" on PUT.
|
||||
* Never returned in GET responses.
|
||||
*/
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
password?: string;
|
||||
|
||||
@IsEmail()
|
||||
fromAddress!: string;
|
||||
}
|
||||
Reference in New Issue
Block a user