diff --git a/libs/common/src/vault/services/default-cipher-encryption.service.spec.ts b/libs/common/src/vault/services/default-cipher-encryption.service.spec.ts index a0ca4833b92..98b554b5762 100644 --- a/libs/common/src/vault/services/default-cipher-encryption.service.spec.ts +++ b/libs/common/src/vault/services/default-cipher-encryption.service.spec.ts @@ -95,6 +95,7 @@ describe("DefaultCipherEncryptionService", () => { vault: jest.fn().mockReturnValue({ ciphers: jest.fn().mockReturnValue({ encrypt: jest.fn(), + encrypt_list: jest.fn(), encrypt_cipher_for_rotation: jest.fn(), set_fido2_credentials: jest.fn(), decrypt: jest.fn(), @@ -280,10 +281,23 @@ describe("DefaultCipherEncryptionService", () => { name: "encrypted-name-3", } as unknown as Cipher; - mockSdkClient.vault().ciphers().encrypt.mockReturnValue({ - cipher: sdkCipher, - encryptedFor: userId, - }); + mockSdkClient + .vault() + .ciphers() + .encrypt_list.mockReturnValue([ + { + cipher: sdkCipher, + encryptedFor: userId, + }, + { + cipher: sdkCipher, + encryptedFor: userId, + }, + { + cipher: sdkCipher, + encryptedFor: userId, + }, + ]); jest .spyOn(Cipher, "fromSdkCipher") @@ -299,7 +313,8 @@ describe("DefaultCipherEncryptionService", () => { expect(results[1].cipher).toEqual(expectedCipher2); expect(results[2].cipher).toEqual(expectedCipher3); - expect(mockSdkClient.vault().ciphers().encrypt).toHaveBeenCalledTimes(3); + expect(mockSdkClient.vault().ciphers().encrypt_list).toHaveBeenCalledTimes(1); + expect(mockSdkClient.vault().ciphers().encrypt).not.toHaveBeenCalled(); expect(results[0].encryptedFor).toBe(userId); expect(results[1].encryptedFor).toBe(userId); @@ -311,7 +326,7 @@ describe("DefaultCipherEncryptionService", () => { expect(results).toBeDefined(); expect(results.length).toBe(0); - expect(mockSdkClient.vault().ciphers().encrypt).not.toHaveBeenCalled(); + expect(mockSdkClient.vault().ciphers().encrypt_list).not.toHaveBeenCalled(); }); }); diff --git a/libs/common/src/vault/services/default-cipher-encryption.service.ts b/libs/common/src/vault/services/default-cipher-encryption.service.ts index 588265846e0..45542091618 100644 --- a/libs/common/src/vault/services/default-cipher-encryption.service.ts +++ b/libs/common/src/vault/services/default-cipher-encryption.service.ts @@ -65,21 +65,14 @@ export class DefaultCipherEncryptionService implements CipherEncryptionService { using ref = sdk.take(); - const results: EncryptionContext[] = []; - - // TODO: https://bitwarden.atlassian.net/browse/PM-30580 - // Replace this loop with a native SDK encryptMany method for better performance. - for (const model of models) { - const sdkCipherView = this.toSdkCipherView(model, ref.value); - const encryptionContext = ref.value.vault().ciphers().encrypt(sdkCipherView); - - results.push({ + return ref.value + .vault() + .ciphers() + .encrypt_list(models.map((model) => this.toSdkCipherView(model, ref.value))) + .map((encryptionContext) => ({ cipher: Cipher.fromSdkCipher(encryptionContext.cipher)!, encryptedFor: uuidAsString(encryptionContext.encryptedFor) as UserId, - }); - } - - return results; + })); }), catchError((error: unknown) => { this.logService.error(`Failed to encrypt ciphers in batch: ${error}`); diff --git a/package-lock.json b/package-lock.json index 46f0bcf1d42..3bee72f6a73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,8 +23,8 @@ "@angular/platform-browser": "20.3.16", "@angular/platform-browser-dynamic": "20.3.16", "@angular/router": "20.3.16", - "@bitwarden/commercial-sdk-internal": "0.2.0-main.522", - "@bitwarden/sdk-internal": "0.2.0-main.522", + "@bitwarden/commercial-sdk-internal": "0.2.0-main.527", + "@bitwarden/sdk-internal": "0.2.0-main.527", "@electron/fuses": "1.8.0", "@emotion/css": "11.13.5", "@koa/multer": "4.0.0", @@ -4981,9 +4981,9 @@ "link": true }, "node_modules/@bitwarden/commercial-sdk-internal": { - "version": "0.2.0-main.522", - "resolved": "https://registry.npmjs.org/@bitwarden/commercial-sdk-internal/-/commercial-sdk-internal-0.2.0-main.522.tgz", - "integrity": "sha512-2wAbg30cGlDhSj14LaK2/ISuT91XPVeNgL/PU+eoxLhAehGKjAXdvZN3PSwFaAuaMbEFzlESvqC1pzzO4p/1zw==", + "version": "0.2.0-main.527", + "resolved": "https://registry.npmjs.org/@bitwarden/commercial-sdk-internal/-/commercial-sdk-internal-0.2.0-main.527.tgz", + "integrity": "sha512-4C4lwOgA2v184G2axUR5Jdb4UMXMhF52a/3c0lAZYbD/8Nid6jziE89nCa9hdfdazuPgWXhVFa3gPrhLZ4uTUQ==", "license": "BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT", "dependencies": { "type-fest": "^4.41.0" @@ -5086,9 +5086,9 @@ "link": true }, "node_modules/@bitwarden/sdk-internal": { - "version": "0.2.0-main.522", - "resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.522.tgz", - "integrity": "sha512-E+YqqX/FvGF0vGx6sNJfYaMj88C+rVo51fQPMSHoOePdryFcKQSJX706Glv86OMLMXE7Ln5Lua8LJRftlF/EFQ==", + "version": "0.2.0-main.527", + "resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.2.0-main.527.tgz", + "integrity": "sha512-dxPh4XjEGFDBASRBEd/JwUdoMAz10W/0QGygYkPwhKKGzJncfDEAgQ/KrT9wc36ycrDrOOspff7xs/vmmzI0+A==", "license": "GPL-3.0", "dependencies": { "type-fest": "^4.41.0" diff --git a/package.json b/package.json index 751c67afcd1..e09aba142fd 100644 --- a/package.json +++ b/package.json @@ -161,8 +161,8 @@ "@angular/platform-browser": "20.3.16", "@angular/platform-browser-dynamic": "20.3.16", "@angular/router": "20.3.16", - "@bitwarden/commercial-sdk-internal": "0.2.0-main.522", - "@bitwarden/sdk-internal": "0.2.0-main.522", + "@bitwarden/commercial-sdk-internal": "0.2.0-main.527", + "@bitwarden/sdk-internal": "0.2.0-main.527", "@electron/fuses": "1.8.0", "@emotion/css": "11.13.5", "@koa/multer": "4.0.0",