mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-21912] Require userID for KeyService's hasUserKey (#14890)
* Update keyService hasUserKey to require userId and remove unused/duplicate methods * Update lock component consumer * Update send commands to pass in userId * update SSO login to pass in userID * Update bw serve to pass in userID * remove unneeded method from electron-key.service
This commit is contained in:
@@ -138,24 +138,13 @@ export abstract class KeyService {
|
||||
userId: string,
|
||||
): Promise<UserKey | null>;
|
||||
|
||||
/**
|
||||
* Determines whether the user key is available for the given user.
|
||||
* @param userId The desired user. If not provided, the active user will be used. If no active user exists, the method will return false.
|
||||
* @returns True if the user key is available
|
||||
*/
|
||||
abstract hasUserKey(userId?: UserId): Promise<boolean>;
|
||||
/**
|
||||
* Determines whether the user key is available for the given user in memory.
|
||||
* @param userId The desired user. If not provided, the active user will be used. If no active user exists, the method will return false.
|
||||
* @returns True if the user key is available
|
||||
* @param userId The desired user. If null or undefined, will return false.
|
||||
* @returns True if the user key is available, returns false otherwise.
|
||||
*/
|
||||
abstract hasUserKeyInMemory(userId?: string): Promise<boolean>;
|
||||
/**
|
||||
* @param keySuffix The desired version of the user's key to check
|
||||
* @param userId The desired user
|
||||
* @returns True if the provided version of the user key is stored
|
||||
*/
|
||||
abstract hasUserKeyStored(keySuffix: KeySuffixOptions, userId?: string): Promise<boolean>;
|
||||
abstract hasUserKey(userId: UserId): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Generates a new user key
|
||||
* @throws Error when master key is null and there is no active user
|
||||
|
||||
@@ -148,39 +148,25 @@ describe("keyService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe.each(["hasUserKey", "hasUserKeyInMemory"])(`%s`, (methodName: string) => {
|
||||
describe("hasUserKey", () => {
|
||||
let mockUserKey: UserKey;
|
||||
let method: (userId?: UserId) => Promise<boolean>;
|
||||
|
||||
beforeEach(() => {
|
||||
const mockRandomBytes = new Uint8Array(64) as CsprngArray;
|
||||
mockUserKey = new SymmetricCryptoKey(mockRandomBytes) as UserKey;
|
||||
method =
|
||||
methodName === "hasUserKey"
|
||||
? keyService.hasUserKey.bind(keyService)
|
||||
: keyService.hasUserKeyInMemory.bind(keyService);
|
||||
});
|
||||
|
||||
test.each([null as unknown as UserId, undefined as unknown as UserId])(
|
||||
"returns false when userId is %s",
|
||||
async (userId) => {
|
||||
expect(await keyService.hasUserKey(userId)).toBe(false);
|
||||
},
|
||||
);
|
||||
|
||||
it.each([true, false])("returns %s if the user key is set", async (hasKey) => {
|
||||
stateProvider.singleUser.getFake(mockUserId, USER_KEY).nextState(hasKey ? mockUserKey : null);
|
||||
expect(await method(mockUserId)).toBe(hasKey);
|
||||
expect(await keyService.hasUserKey(mockUserId)).toBe(hasKey);
|
||||
});
|
||||
|
||||
it("returns false when no active userId is set", async () => {
|
||||
accountService.activeAccountSubject.next(null);
|
||||
expect(await method()).toBe(false);
|
||||
});
|
||||
|
||||
it.each([true, false])(
|
||||
"resolves %s for active user id when none is provided",
|
||||
async (hasKey) => {
|
||||
stateProvider.activeUserId$ = of(mockUserId);
|
||||
stateProvider.singleUser
|
||||
.getFake(mockUserId, USER_KEY)
|
||||
.nextState(hasKey ? mockUserKey : null);
|
||||
expect(await method()).toBe(hasKey);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("getUserKeyWithLegacySupport", () => {
|
||||
@@ -410,6 +396,19 @@ describe("keyService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("makeSendKey", () => {
|
||||
const mockRandomBytes = new Uint8Array(16) as CsprngArray;
|
||||
it("calls keyGenerationService with expected hard coded parameters", async () => {
|
||||
await keyService.makeSendKey(mockRandomBytes);
|
||||
|
||||
expect(keyGenerationService.deriveKeyFromMaterial).toHaveBeenCalledWith(
|
||||
mockRandomBytes,
|
||||
"bitwarden-send",
|
||||
"send",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearStoredUserKey", () => {
|
||||
describe("input validation", () => {
|
||||
const invalidUserIdTestCases = [
|
||||
|
||||
@@ -198,16 +198,7 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
return userKey;
|
||||
}
|
||||
|
||||
async hasUserKey(userId?: UserId): Promise<boolean> {
|
||||
userId ??= await firstValueFrom(this.stateProvider.activeUserId$);
|
||||
if (userId == null) {
|
||||
return false;
|
||||
}
|
||||
return await this.hasUserKeyInMemory(userId);
|
||||
}
|
||||
|
||||
async hasUserKeyInMemory(userId?: UserId): Promise<boolean> {
|
||||
userId ??= await firstValueFrom(this.stateProvider.activeUserId$);
|
||||
async hasUserKey(userId: UserId): Promise<boolean> {
|
||||
if (userId == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -215,10 +206,6 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
return (await firstValueFrom(this.stateProvider.getUserState$(USER_KEY, userId))) != null;
|
||||
}
|
||||
|
||||
async hasUserKeyStored(keySuffix: KeySuffixOptions, userId?: UserId): Promise<boolean> {
|
||||
return (await this.getKeyFromStorage(keySuffix, userId)) != null;
|
||||
}
|
||||
|
||||
async makeUserKey(masterKey: MasterKey | null): Promise<[UserKey, EncString]> {
|
||||
if (masterKey == null) {
|
||||
const userId = await firstValueFrom(this.stateProvider.activeUserId$);
|
||||
|
||||
Reference in New Issue
Block a user