From e2447099ee5825c3c7d83fde3a5040bf8b06b0c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20=C3=85berg?= Date: Tue, 28 Oct 2025 12:21:04 +0100 Subject: [PATCH] Refactor setUserDecryptionOptions to accept UserId --- ...efault-set-initial-password.service.implementation.ts | 4 ++-- .../default-set-initial-password.service.spec.ts | 6 +++++- .../user-decryption-options.service.abstraction.ts | 8 +++++++- .../src/common/login-strategies/login.strategy.spec.ts | 1 + libs/auth/src/common/login-strategies/login.strategy.ts | 1 + .../user-decryption-options.service.spec.ts | 6 +++--- .../user-decryption-options.service.ts | 9 +++++++-- 7 files changed, 26 insertions(+), 9 deletions(-) diff --git a/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.implementation.ts b/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.implementation.ts index 01e87cae0ed..93df09793a0 100644 --- a/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.implementation.ts +++ b/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.implementation.ts @@ -195,10 +195,10 @@ export class DefaultSetInitialPasswordService implements SetInitialPasswordServi userId: UserId, ) { const userDecryptionOpts = await firstValueFrom( - this.userDecryptionOptionsService.userDecryptionOptions$, + this.userDecryptionOptionsService.userDecryptionOptionsById$(userId), ); userDecryptionOpts.hasMasterPassword = true; - await this.userDecryptionOptionsService.setUserDecryptionOptions(userDecryptionOpts); + await this.userDecryptionOptionsService.setUserDecryptionOptions(userDecryptionOpts, userId); await this.kdfConfigService.setKdfConfig(userId, kdfConfig); await this.masterPasswordService.setMasterKey(masterKey, userId); await this.keyService.setUserKey(masterKeyEncryptedUserKey[0], userId); diff --git a/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.spec.ts b/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.spec.ts index 7a1dfc91e67..bac4b2785dd 100644 --- a/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.spec.ts +++ b/libs/angular/src/auth/password-management/set-initial-password/default-set-initial-password.service.spec.ts @@ -149,7 +149,9 @@ describe("DefaultSetInitialPasswordService", () => { userDecryptionOptions = new UserDecryptionOptions({ hasMasterPassword: true }); userDecryptionOptionsSubject = new BehaviorSubject(userDecryptionOptions); - userDecryptionOptionsService.userDecryptionOptions$ = userDecryptionOptionsSubject; + userDecryptionOptionsService.userDecryptionOptionsById$ = jest + .fn() + .mockReturnValue(userDecryptionOptionsSubject); setPasswordRequest = new SetPasswordRequest( credentials.newServerMasterKeyHash, @@ -364,6 +366,7 @@ describe("DefaultSetInitialPasswordService", () => { expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest); expect(userDecryptionOptionsService.setUserDecryptionOptions).toHaveBeenCalledWith( userDecryptionOptions, + userId, ); expect(kdfConfigService.setKdfConfig).toHaveBeenCalledWith(userId, credentials.kdfConfig); expect(masterPasswordService.setMasterKey).toHaveBeenCalledWith( @@ -562,6 +565,7 @@ describe("DefaultSetInitialPasswordService", () => { expect(masterPasswordApiService.setPassword).toHaveBeenCalledWith(setPasswordRequest); expect(userDecryptionOptionsService.setUserDecryptionOptions).toHaveBeenCalledWith( userDecryptionOptions, + userId, ); expect(kdfConfigService.setKdfConfig).toHaveBeenCalledWith(userId, credentials.kdfConfig); expect(masterPasswordService.setMasterKey).toHaveBeenCalledWith( diff --git a/libs/auth/src/common/abstractions/user-decryption-options.service.abstraction.ts b/libs/auth/src/common/abstractions/user-decryption-options.service.abstraction.ts index e46fb09cff6..ace19a93e49 100644 --- a/libs/auth/src/common/abstractions/user-decryption-options.service.abstraction.ts +++ b/libs/auth/src/common/abstractions/user-decryption-options.service.abstraction.ts @@ -1,5 +1,7 @@ import { Observable } from "rxjs"; +import { UserId } from "@bitwarden/common/types/guid"; + import { UserDecryptionOptions } from "../models"; export abstract class UserDecryptionOptionsServiceAbstraction { @@ -29,6 +31,10 @@ export abstract class InternalUserDecryptionOptionsServiceAbstraction extends Us * @remark Intended to be used when user decryption options are received from server, does * not update the server. Consider syncing instead of updating locally. * @param userDecryptionOptions Current user decryption options received from server. + * @param userId The user id to set the decryption options for. */ - abstract setUserDecryptionOptions(userDecryptionOptions: UserDecryptionOptions): Promise; + abstract setUserDecryptionOptions( + userDecryptionOptions: UserDecryptionOptions, + userId: UserId, + ): Promise; } diff --git a/libs/auth/src/common/login-strategies/login.strategy.spec.ts b/libs/auth/src/common/login-strategies/login.strategy.spec.ts index a23f8034238..9523b181754 100644 --- a/libs/auth/src/common/login-strategies/login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/login.strategy.spec.ts @@ -259,6 +259,7 @@ describe("LoginStrategy", () => { expect(userDecryptionOptionsService.setUserDecryptionOptions).toHaveBeenCalledWith( UserDecryptionOptions.fromResponse(idTokenResponse), + userId, ); expect(masterPasswordService.mock.setMasterPasswordUnlockData).toHaveBeenCalledWith( new MasterPasswordUnlockData( diff --git a/libs/auth/src/common/login-strategies/login.strategy.ts b/libs/auth/src/common/login-strategies/login.strategy.ts index 7ad5cd24353..ae8a69c545b 100644 --- a/libs/auth/src/common/login-strategies/login.strategy.ts +++ b/libs/auth/src/common/login-strategies/login.strategy.ts @@ -197,6 +197,7 @@ export abstract class LoginStrategy { // as the user decryption options help determine the available timeout actions. await this.userDecryptionOptionsService.setUserDecryptionOptions( UserDecryptionOptions.fromResponse(tokenResponse), + userId, ); if (tokenResponse.userDecryptionOptions?.masterPasswordUnlock != null) { diff --git a/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.spec.ts b/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.spec.ts index c2fafc1a2f6..097433d9688 100644 --- a/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.spec.ts +++ b/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.spec.ts @@ -83,11 +83,11 @@ describe("UserDecryptionOptionsService", () => { }); describe("setUserDecryptionOptions", () => { - it("should set the active user's decryption options", async () => { - await sut.setUserDecryptionOptions(userDecryptionOptions); + it("should set the specified user's decryption options", async () => { + await sut.setUserDecryptionOptions(userDecryptionOptions, fakeUserId); const result = await firstValueFrom( - fakeStateProvider.getActive(USER_DECRYPTION_OPTIONS).state$, + fakeStateProvider.getUser(fakeUserId, USER_DECRYPTION_OPTIONS).state$, ); expect(result).toEqual(userDecryptionOptions); diff --git a/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.ts b/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.ts index 7c44a6f1682..6ae0f7962db 100644 --- a/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.ts +++ b/libs/auth/src/common/services/user-decryption-options/user-decryption-options.service.ts @@ -45,7 +45,12 @@ export class UserDecryptionOptionsService return this.stateProvider.getUser(userId, USER_DECRYPTION_OPTIONS).state$; } - async setUserDecryptionOptions(userDecryptionOptions: UserDecryptionOptions): Promise { - await this.userDecryptionOptionsState.update((_) => userDecryptionOptions); + async setUserDecryptionOptions( + userDecryptionOptions: UserDecryptionOptions, + userId: UserId, + ): Promise { + await this.stateProvider + .getUser(userId, USER_DECRYPTION_OPTIONS) + .update((_) => userDecryptionOptions); } }