mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
[PM-21443] Require userId for KeyService's everHadUserKey$ (#14712)
* Require userId for KeyService's everHadUserKey$ * handle null active user in tdeDecryptionRequiredGuard
This commit is contained in:
@@ -85,11 +85,13 @@ export abstract class KeyService {
|
||||
* (such as auto, biometrics, or pin)
|
||||
*/
|
||||
abstract refreshAdditionalKeys(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Observable value that returns whether or not the currently active user has ever had auser key,
|
||||
* Observable value that returns whether or not the user has ever had a userKey,
|
||||
* i.e. has ever been unlocked/decrypted. This is key for differentiating between TDE locked and standard locked states.
|
||||
*/
|
||||
abstract everHadUserKey$: Observable<boolean>;
|
||||
abstract everHadUserKey$(userId: UserId): Observable<boolean>;
|
||||
|
||||
/**
|
||||
* Retrieves the user key
|
||||
* @param userId The desired user
|
||||
|
||||
@@ -34,7 +34,6 @@ import {
|
||||
FakeAccountService,
|
||||
mockAccountServiceWith,
|
||||
FakeStateProvider,
|
||||
FakeActiveUserState,
|
||||
FakeSingleUserState,
|
||||
} from "@bitwarden/common/spec";
|
||||
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||
@@ -190,28 +189,28 @@ describe("keyService", () => {
|
||||
});
|
||||
|
||||
describe("everHadUserKey$", () => {
|
||||
let everHadUserKeyState: FakeActiveUserState<boolean>;
|
||||
let everHadUserKeyState: FakeSingleUserState<boolean>;
|
||||
|
||||
beforeEach(() => {
|
||||
everHadUserKeyState = stateProvider.activeUser.getFake(USER_EVER_HAD_USER_KEY);
|
||||
everHadUserKeyState = stateProvider.singleUser.getFake(mockUserId, USER_EVER_HAD_USER_KEY);
|
||||
});
|
||||
|
||||
it("should return true when stored value is true", async () => {
|
||||
everHadUserKeyState.nextState(true);
|
||||
|
||||
expect(await firstValueFrom(keyService.everHadUserKey$)).toBe(true);
|
||||
expect(await firstValueFrom(keyService.everHadUserKey$(mockUserId))).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false when stored value is false", async () => {
|
||||
everHadUserKeyState.nextState(false);
|
||||
|
||||
expect(await firstValueFrom(keyService.everHadUserKey$)).toBe(false);
|
||||
expect(await firstValueFrom(keyService.everHadUserKey$(mockUserId))).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when stored value is null", async () => {
|
||||
everHadUserKeyState.nextState(null);
|
||||
|
||||
expect(await firstValueFrom(keyService.everHadUserKey$)).toBe(false);
|
||||
expect(await firstValueFrom(keyService.everHadUserKey$(mockUserId))).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ import {
|
||||
USER_EVER_HAD_USER_KEY,
|
||||
USER_KEY,
|
||||
} from "@bitwarden/common/platform/services/key-state/user-key.state";
|
||||
import { ActiveUserState, StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||
import { OrganizationId, ProviderId, UserId } from "@bitwarden/common/types/guid";
|
||||
import {
|
||||
@@ -63,10 +63,6 @@ import {
|
||||
import { KdfConfig } from "./models/kdf-config";
|
||||
|
||||
export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
private readonly activeUserEverHadUserKey: ActiveUserState<boolean>;
|
||||
|
||||
readonly everHadUserKey$: Observable<boolean>;
|
||||
|
||||
readonly activeUserOrgKeys$: Observable<Record<OrganizationId, OrgKey>>;
|
||||
|
||||
constructor(
|
||||
@@ -82,10 +78,6 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
protected stateProvider: StateProvider,
|
||||
protected kdfConfigService: KdfConfigService,
|
||||
) {
|
||||
// User Key
|
||||
this.activeUserEverHadUserKey = stateProvider.getActive(USER_EVER_HAD_USER_KEY);
|
||||
this.everHadUserKey$ = this.activeUserEverHadUserKey.state$.pipe(map((x) => x ?? false));
|
||||
|
||||
this.activeUserOrgKeys$ = this.stateProvider.activeUserId$.pipe(
|
||||
switchMap((userId) => (userId != null ? this.orgKeys$(userId) : NEVER)),
|
||||
) as Observable<Record<OrganizationId, OrgKey>>;
|
||||
@@ -141,6 +133,12 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
await this.setUserKey(key, activeUserId);
|
||||
}
|
||||
|
||||
everHadUserKey$(userId: UserId): Observable<boolean> {
|
||||
return this.stateProvider
|
||||
.getUser(userId, USER_EVER_HAD_USER_KEY)
|
||||
.state$.pipe(map((x) => x ?? false));
|
||||
}
|
||||
|
||||
getInMemoryUserKeyFor$(userId: UserId): Observable<UserKey> {
|
||||
return this.stateProvider.getUserState$(USER_KEY, userId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user