From d7bd236b82d225e1e43341db2fc33aa9f17e9ce1 Mon Sep 17 00:00:00 2001 From: Jackson Engstrom Date: Tue, 14 Jul 2026 16:31:52 -0700 Subject: [PATCH] [PM-39778] Fix new item subtitles when using sdk (#21591) * add bank account list view sdk support to allow for bankAccountSubtitle to work properly * Update sdk-internal to 0.2.0-main.900 * fix npm ci --------- Co-authored-by: bw-ghapp[bot] <178206702+bw-ghapp[bot]@users.noreply.github.com> --- .../utils/cipher-view-like-utils.spec.ts | 25 +++++++++++++------ .../src/vault/utils/cipher-view-like-utils.ts | 16 +++++++----- package-lock.json | 16 ++++++------ package.json | 4 +-- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/libs/common/src/vault/utils/cipher-view-like-utils.spec.ts b/libs/common/src/vault/utils/cipher-view-like-utils.spec.ts index bf41d5cdf67..f1f220ce875 100644 --- a/libs/common/src/vault/utils/cipher-view-like-utils.spec.ts +++ b/libs/common/src/vault/utils/cipher-view-like-utils.spec.ts @@ -262,7 +262,7 @@ describe("CipherViewLikeUtils", () => { cipherListView.type = "secureNote"; expect(CipherViewLikeUtils.getType(cipherListView)).toBe(CipherType.SecureNote); - cipherListView.type = "bankAccount"; + cipherListView.type = { bankAccount: { accountNumber: "1234", accountType: "checking" } }; expect(CipherViewLikeUtils.getType(cipherListView)).toBe(CipherType.BankAccount); cipherListView.type = "driversLicense"; @@ -362,12 +362,9 @@ describe("CipherViewLikeUtils", () => { expect(i18nService.t).not.toHaveBeenCalled(); }); - it("falls back to the SDK-provided subtitle for a CipherListView bank account", () => { - // CipherListViewType encodes bank account as a plain string discriminator and does - // not carry accountType/accountNumber inline. The SDK's pre-computed `subtitle` is - // the only signal we have. + it("falls back to the SDK-provided subtitle for a CipherListView bank account without inline data", () => { const cipherListView = { - type: "bankAccount", + type: { bankAccount: { accountNumber: undefined, accountType: undefined } }, subtitle: "SDK-provided fallback", } as CipherListView; @@ -376,6 +373,20 @@ describe("CipherViewLikeUtils", () => { ); }); + it("computes a translated subtitle from the inline data of a CipherListView bank account", () => { + const cipherListView = { + type: { + bankAccount: { accountNumber: "987651234", accountType: BankAccountType.Checking }, + }, + subtitle: "SDK-provided fallback", + } as CipherListView; + + expect(CipherViewLikeUtils.subtitle(cipherListView, i18nService)).toBe( + "translated:bankAccountTypeChecking, *1234", + ); + expect(i18nService.t).toHaveBeenCalledWith("bankAccountTypeChecking"); + }); + it("returns the base subtitle for non-bank-account ciphers even when i18nService is provided", () => { const cipherView = createCipherView(); cipherView.login = new LoginView(); @@ -767,7 +778,6 @@ describe("CipherViewLikeUtils", () => { it("returns true for copyable fields in a bank account cipher", () => { const cipherListView = { - type: "bankAccount", copyableFields: [ "BankAccountNameOnAccount", "BankAccountAccountNumber", @@ -777,6 +787,7 @@ describe("CipherViewLikeUtils", () => { "BankAccountIban", "BankAccountSwift", ], + type: { bankAccount: { accountNumber: undefined, accountType: undefined } }, } as CipherListView; expect(CipherViewLikeUtils.hasCopyableValue(cipherListView, "nameOnAccount")).toBe(true); diff --git a/libs/common/src/vault/utils/cipher-view-like-utils.ts b/libs/common/src/vault/utils/cipher-view-like-utils.ts index 8d12c4e152e..cb772528deb 100644 --- a/libs/common/src/vault/utils/cipher-view-like-utils.ts +++ b/libs/common/src/vault/utils/cipher-view-like-utils.ts @@ -1,4 +1,5 @@ import { + BankAccountListView, BankAccountView as SdkBankAccountView, CardListView, CipherListView, @@ -130,7 +131,7 @@ export class CipherViewLikeUtils { return CipherType.SecureNote; case cipher.type === "sshKey": return CipherType.SshKey; - case cipher.type === "bankAccount": + case typeof cipher.type === "object" && "bankAccount" in cipher.type: return CipherType.BankAccount; case cipher.type === "passport": return CipherType.Passport; @@ -173,13 +174,16 @@ export class CipherViewLikeUtils { } }; - private static getBankAccount = ( + /** @returns The bank account object from the input cipher. If the cipher is not of type BankAccount, returns null. */ + static getBankAccount = ( cipher: CipherViewLike, - ): BankAccountView | SdkBankAccountView | null => { - // CipherListViewType only inlines `card` and `login` data — bank account is a plain - // string discriminator without nested view data, so there is nothing to read here. + ): BankAccountView | SdkBankAccountView | BankAccountListView | null => { if (this.isCipherListView(cipher)) { - return null; + if (typeof cipher.type !== "object") { + return null; + } + + return "bankAccount" in cipher.type ? cipher.type.bankAccount : null; } return cipher.type === CipherType.BankAccount ? (cipher.bankAccount ?? null) : null; diff --git a/package-lock.json b/package-lock.json index 868badd19bb..a8c23099e54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,9 +23,9 @@ "@angular/platform-browser": "21.2.17", "@angular/platform-browser-dynamic": "21.2.17", "@angular/router": "21.2.17", - "@bitwarden/commercial-sdk-internal": "0.2.0-main.897", + "@bitwarden/commercial-sdk-internal": "0.2.0-main.900", "@bitwarden/desktop-napi": "file:apps/desktop/desktop_native/napi", - "@bitwarden/sdk-internal": "0.2.0-main.897", + "@bitwarden/sdk-internal": "0.2.0-main.900", "@bufbuild/protobuf": "2.11.0", "@electron/fuses": "2.1.1", "@emotion/css": "11.13.5", @@ -4835,9 +4835,9 @@ "link": true }, "node_modules/@bitwarden/commercial-sdk-internal": { - "version": "0.2.0-main.897", - "resolved": "https://registry.npmjs.org/@bitwarden/commercial-sdk-internal/-/commercial-sdk-internal-0.2.0-main.897.tgz", - "integrity": "sha512-U4CJXOzqkuPlQqra4pppXfWKafmJ984IrmGi5aVrO6oNZlJ+3NnGVtP7PRNGrIAAo0Y49KXsndEczDiuEZDP3Q==", + "version": "0.2.0-main.900", + "resolved": "https://registry.npmjs.org/@bitwarden/commercial-sdk-internal/-/commercial-sdk-internal-0.2.0-main.900.tgz", + "integrity": "sha512-ZLFiFazveJ5bMUEx1XM7tdEMTBViNb86iIjLbVCTrnR1gQZ4jm6xxB6XaISTnTOWGo3q4BaDGIWHaXft+v/+Zg==", "license": "BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT", "dependencies": { "type-fest": "^5.0.0" @@ -4959,9 +4959,9 @@ "link": true }, "node_modules/@bitwarden/sdk-internal": { - "version": "0.2.0-main.897", - "resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.897.tgz", - "integrity": "sha512-PCaJxhfBxv62gWdpHhq0HwfXkr0fQtA+F68EzpVn+kHXxF1KLkSBmU6vMPdGhfOmLln12jgiSHGPJ8+EnVH18w==", + "version": "0.2.0-main.900", + "resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.900.tgz", + "integrity": "sha512-abrTTSa4Em9HmpMieZ6R0srNoYJI8VvZvXkldrZuMyj75UcI7hqkAXfd3b0nNWJVX24MMryWSZgy+/5dGpbs0A==", "license": "GPL-3.0", "dependencies": { "type-fest": "^5.0.0" diff --git a/package.json b/package.json index 71611773812..f14c777939e 100644 --- a/package.json +++ b/package.json @@ -174,9 +174,9 @@ "@angular/platform-browser": "21.2.17", "@angular/platform-browser-dynamic": "21.2.17", "@angular/router": "21.2.17", - "@bitwarden/commercial-sdk-internal": "0.2.0-main.897", + "@bitwarden/commercial-sdk-internal": "0.2.0-main.900", "@bitwarden/desktop-napi": "file:apps/desktop/desktop_native/napi", - "@bitwarden/sdk-internal": "0.2.0-main.897", + "@bitwarden/sdk-internal": "0.2.0-main.900", "@bufbuild/protobuf": "2.11.0", "@electron/fuses": "2.1.1", "@emotion/css": "11.13.5",