From 236e53205ef17c6a8eeff9f431ea2d81e9b93247 Mon Sep 17 00:00:00 2001 From: jaasen-livefront Date: Mon, 10 Nov 2025 11:29:10 -0800 Subject: [PATCH] add validation in exports --- .../common/src/models/export/cipher.export.ts | 2 +- .../models/export/fido2-credential.export.ts | 52 +++++++++++++++---- libs/common/src/models/export/field.export.ts | 4 +- .../models/export/password-history.export.ts | 21 ++++++-- .../src/models/export/ssh-key.export.ts | 31 ++++++----- 5 files changed, 80 insertions(+), 30 deletions(-) diff --git a/libs/common/src/models/export/cipher.export.ts b/libs/common/src/models/export/cipher.export.ts index 21ad16530d8..88702d70fc9 100644 --- a/libs/common/src/models/export/cipher.export.ts +++ b/libs/common/src/models/export/cipher.export.ts @@ -75,7 +75,7 @@ export class CipherExport { view.identity = req.identity ? IdentityExport.toView(req.identity) : new IdentityView(); break; case CipherType.SshKey: - view.sshKey = req.sshKey ? SshKeyExport.toView(req.sshKey) : new SshKeyView(); + view.sshKey = SshKeyExport.toView(req.sshKey) ?? new SshKeyView(); break; } diff --git a/libs/common/src/models/export/fido2-credential.export.ts b/libs/common/src/models/export/fido2-credential.export.ts index 38cf0eb36bc..ea26607b0ab 100644 --- a/libs/common/src/models/export/fido2-credential.export.ts +++ b/libs/common/src/models/export/fido2-credential.export.ts @@ -32,6 +32,36 @@ export class Fido2CredentialExport { return req; } + validateRequiredFields() { + if (!this.credentialId || this.credentialId.trim() === "") { + throw new Error("FIDO2 credential ID is required."); + } + if (!this.keyType || this.keyType.trim() === "") { + throw new Error("FIDO2 key type is required."); + } + if (!this.keyAlgorithm || this.keyAlgorithm.trim() === "") { + throw new Error("FIDO2 key algorithm is required."); + } + if (!this.keyCurve || this.keyCurve.trim() === "") { + throw new Error("FIDO2 key curve is required."); + } + if (!this.keyValue || this.keyValue.trim() === "") { + throw new Error("FIDO2 key value is required."); + } + if (!this.rpId || this.rpId.trim() === "") { + throw new Error("FIDO2 relying party ID is required."); + } + if (!this.counter || this.counter.trim() === "") { + throw new Error("FIDO2 counter is required."); + } + if (!this.discoverable || this.discoverable.trim() === "") { + throw new Error("FIDO2 discoverable flag is required."); + } + if (!this.creationDate) { + throw new Error("FIDO2 creation date is required."); + } + } + /** * Converts a Fido2CredentialExport object to its view representation. * @param req - The Fido2CredentialExport object to be converted. @@ -39,6 +69,8 @@ export class Fido2CredentialExport { * @returns Fido2CredentialView - The populated view, or a new instance if none was provided. */ static toView(req: Fido2CredentialExport, view = new Fido2CredentialView()) { + req.validateRequiredFields(); + view.credentialId = req.credentialId; view.keyType = req.keyType as "public-key"; view.keyAlgorithm = req.keyAlgorithm as "ECDSA"; @@ -62,6 +94,8 @@ export class Fido2CredentialExport { * @returns Fido2Credential - The populated domain, or a new instance if none was provided. */ static toDomain(req: Fido2CredentialExport, domain = new Fido2Credential()) { + req.validateRequiredFields(); + domain.credentialId = new EncString(req.credentialId); domain.keyType = new EncString(req.keyType); domain.keyAlgorithm = new EncString(req.keyAlgorithm); @@ -78,19 +112,19 @@ export class Fido2CredentialExport { return domain; } - credentialId: string = ""; - keyType: string = ""; - keyAlgorithm: string = ""; - keyCurve: string = ""; - keyValue: string = ""; - rpId: string = ""; + credentialId!: string; + keyType!: string; + keyAlgorithm!: string; + keyCurve!: string; + keyValue!: string; + rpId!: string; userHandle?: string; userName?: string; - counter: string = ""; + counter!: string; rpName?: string; userDisplayName?: string; - discoverable: string = ""; - creationDate: Date = new Date(); + discoverable!: string; + creationDate!: Date; /** * Constructs a new Fid2CredentialExport instance. diff --git a/libs/common/src/models/export/field.export.ts b/libs/common/src/models/export/field.export.ts index 72eefd0e427..708fa672728 100644 --- a/libs/common/src/models/export/field.export.ts +++ b/libs/common/src/models/export/field.export.ts @@ -41,8 +41,8 @@ export class FieldExport { return; } - this.name = safeGetString(o.name) ?? ""; - this.value = safeGetString(o.value) ?? ""; + this.name = safeGetString(o.name); + this.value = safeGetString(o.value); this.type = o.type; this.linkedId = o.linkedId; } diff --git a/libs/common/src/models/export/password-history.export.ts b/libs/common/src/models/export/password-history.export.ts index 2deaf7a9c66..0ff666e0a30 100644 --- a/libs/common/src/models/export/password-history.export.ts +++ b/libs/common/src/models/export/password-history.export.ts @@ -12,28 +12,39 @@ export class PasswordHistoryExport { return req; } + validateRequiredFields() { + if (!this.password || this.password.trim() === "") { + throw new Error("Password history password is required."); + } + } + static toView(req: PasswordHistoryExport, view = new PasswordHistoryView()) { + req.validateRequiredFields(); + view.password = req.password; - view.lastUsedDate = req.lastUsedDate ?? new Date(); + view.lastUsedDate = req.lastUsedDate; return view; } static toDomain(req: PasswordHistoryExport, domain = new Password()) { + req.validateRequiredFields(); + domain.password = new EncString(req.password); - domain.lastUsedDate = req.lastUsedDate ?? new Date(); + domain.lastUsedDate = req.lastUsedDate; return domain; } password: string = ""; - lastUsedDate: Date; + lastUsedDate: Date = new Date(); constructor(o?: PasswordHistoryView | Password) { if (o == null) { - this.lastUsedDate = new Date(); return; } + this.validateRequiredFields(); + this.password = safeGetString(o.password) ?? ""; - this.lastUsedDate = o.lastUsedDate ?? new Date(); + this.lastUsedDate = o.lastUsedDate; } } diff --git a/libs/common/src/models/export/ssh-key.export.ts b/libs/common/src/models/export/ssh-key.export.ts index dec52390faf..02eee587def 100644 --- a/libs/common/src/models/export/ssh-key.export.ts +++ b/libs/common/src/models/export/ssh-key.export.ts @@ -13,21 +13,24 @@ export class SshKeyExport { return req; } + validateRequiredFields() { + if (!this.privateKey || this.privateKey.trim() === "") { + throw new Error("SSH key private key is required."); + } + if (!this.publicKey || this.publicKey.trim() === "") { + throw new Error("SSH key public key is required."); + } + if (!this.keyFingerprint || this.keyFingerprint.trim() === "") { + throw new Error("SSH key fingerprint is required."); + } + } + static toView(req?: SshKeyExport, view = new SshKeyView()): SshKeyView | undefined { if (req == null) { return undefined; } - // Validate required fields - if (!req.privateKey || req.privateKey.trim() === "") { - throw new Error("SSH key private key is required."); - } - if (!req.publicKey || req.publicKey.trim() === "") { - throw new Error("SSH key public key is required."); - } - if (!req.keyFingerprint || req.keyFingerprint.trim() === "") { - throw new Error("SSH key fingerprint is required."); - } + req.validateRequiredFields(); view.privateKey = req.privateKey; view.publicKey = req.publicKey; @@ -36,15 +39,17 @@ export class SshKeyExport { } static toDomain(req: SshKeyExport, domain = new SshKeyDomain()) { + req.validateRequiredFields(); + domain.privateKey = new EncString(req.privateKey); domain.publicKey = new EncString(req.publicKey); domain.keyFingerprint = new EncString(req.keyFingerprint); return domain; } - privateKey: string = ""; - publicKey: string = ""; - keyFingerprint: string = ""; + privateKey!: string; + publicKey!: string; + keyFingerprint!: string; constructor(o?: SshKeyView | SshKeyDomain) { if (o == null) {