import { IsBoolean, IsIn, IsInt, IsNotEmpty, IsOptional, IsString, IsUrl, Max, Min, Validate, ValidateIf, type ValidationArguments, ValidatorConstraint, type ValidatorConstraintInterface, } from 'class-validator'; /** * D-03: PMG kennt laut Recherche keinen API-Token (Annahme A1) — ein Server * vom Typ `pmg` mit `authMethod: 'token'` wird bereits beim Speichern mit * einer deutschen Klartextmeldung abgelehnt (400), nicht erst beim * Abfragen. Angebracht am Feld `authMethod`, liest aber `productType` * desselben Objekts (`args.object`) — class-validator erlaubt das. */ @ValidatorConstraint({ name: 'pmgOhneToken', async: false }) class PmgOhneTokenConstraint implements ValidatorConstraintInterface { validate(_value: unknown, args: ValidationArguments): boolean { const obj = args.object as { productType?: string; authMethod?: string }; return !(obj.productType === 'pmg' && obj.authMethod === 'token'); } defaultMessage(): string { return 'PMG unterstuetzt keinen API-Token-Zugang. Bitte Benutzer und Passwort waehlen.'; } } /** * DTO fuer das Anlegen eines Proxmox-Servers (Aufgabe 1). Pflichtfelder je * `authMethod` mit `@ValidateIf` (Aufgabe 2): ein Token-Zugang verlangt * `tokenId`/`tokenSecret`, ein Passwort-Zugang `username`/`password`. */ export class CreateProxmoxServerDto { @IsString() @IsNotEmpty() name!: string; @IsIn(['pve', 'pbs', 'pmg']) productType!: 'pve' | 'pbs' | 'pmg'; // require_tld: false — interne Namen wie "pve.intern" sind sonst abgelehnt. @IsUrl({ protocols: ['http', 'https'], require_tld: false }) baseUrl!: string; @IsIn(['token', 'password']) @Validate(PmgOhneTokenConstraint) authMethod!: 'token' | 'password'; @ValidateIf((o) => o.authMethod === 'token') @IsString() @IsNotEmpty() tokenId?: string; @ValidateIf((o) => o.authMethod === 'token') @IsString() @IsNotEmpty() tokenSecret?: string; @ValidateIf((o) => o.authMethod === 'password') @IsString() @IsNotEmpty() username?: string; @ValidateIf((o) => o.authMethod === 'password') @IsString() @IsNotEmpty() password?: string; @IsBoolean() @IsOptional() tlsRejectUnauthorized?: boolean; @IsInt() @Min(1) @Max(1440) @IsOptional() pollIntervalMin?: number; @IsBoolean() @IsOptional() isActive?: boolean; } /** * DTO fuer das Bearbeiten (Aufgabe 5). Alle Felder optional; ein NICHT * gesendetes Geheimnisfeld laesst den gespeicherten Wert unveraendert, eine * LEERE Zeichenkette bedeutet "loeschen" (Muster `LdapConfigService.updateConfig`) * — diese Unterscheidung lebt im Service, nicht im DTO, deshalb bleiben * `tokenSecret`/`password` hier einfache optionale Zeichenketten ohne * `IsNotEmpty`. */ export class UpdateProxmoxServerDto { @IsString() @IsNotEmpty() @IsOptional() name?: string; @IsIn(['pve', 'pbs', 'pmg']) @IsOptional() productType?: 'pve' | 'pbs' | 'pmg'; @IsUrl({ protocols: ['http', 'https'], require_tld: false }) @IsOptional() baseUrl?: string; @IsIn(['token', 'password']) @Validate(PmgOhneTokenConstraint) @IsOptional() authMethod?: 'token' | 'password'; @IsString() @IsOptional() tokenId?: string; @IsString() @IsOptional() tokenSecret?: string; @IsString() @IsOptional() username?: string; @IsString() @IsOptional() password?: string; @IsBoolean() @IsOptional() tlsRejectUnauthorized?: boolean; @IsInt() @Min(1) @Max(1440) @IsOptional() pollIntervalMin?: number; @IsBoolean() @IsOptional() isActive?: boolean; } /** * DTO fuer den Verbindungstest (Nachbesserung Befund 1, Rundgang zu Aufgabe 4): * derselbe Feldsatz wie `UpdateProxmoxServerDto` — der Test soll auf JEDEM * dieser Felder den ungespeicherten Formularwert pruefen koennen, nicht den * gespeicherten Stand. Ein NICHT gesendetes oder leeres Geheimnisfeld heisst * "gespeicherten Wert weiterverwenden" (Merge-Logik in * `ProxmoxService.resolveEffectiveTestServer`), genau wie beim Bearbeiten. * Fuer die Neuanlage (noch kein gespeicherter Server) bleiben alle Felder * optional, weil es dort keinen gespeicherten Fallback gibt — ein fehlendes * Pflichtfeld fuehrt dort einfach zum selben Fehlerschluessel wie ein leer * gelassenes Feld beim Anlegen selbst (z. B. `zugang` ohne Geheimnis). */ export class TestProxmoxServerDto extends UpdateProxmoxServerDto {}