mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[PM-21705] Require userID for refreshAdditionalKeys() on key-service (#14810)
* Require userID for refreshAdditionalKeys() * Add error handling to desktop Unlock settings * Add more unit test coverage
This commit is contained in:
@@ -92,7 +92,7 @@ export class VaultTimeoutSettingsService implements VaultTimeoutSettingsServiceA
|
||||
clientSecret,
|
||||
]);
|
||||
|
||||
await this.keyService.refreshAdditionalKeys();
|
||||
await this.keyService.refreshAdditionalKeys(userId);
|
||||
}
|
||||
|
||||
availableVaultTimeoutActions$(userId?: string): Observable<VaultTimeoutAction[]> {
|
||||
|
||||
@@ -83,8 +83,11 @@ export abstract class KeyService {
|
||||
* Gets the user key from memory and sets it again,
|
||||
* kicking off a refresh of any additional keys
|
||||
* (such as auto, biometrics, or pin)
|
||||
* @param userId The target user to refresh keys for.
|
||||
* @throws Error when userId is null or undefined.
|
||||
* @throws When userKey doesn't exist in memory for the target user.
|
||||
*/
|
||||
abstract refreshAdditionalKeys(): Promise<void>;
|
||||
abstract refreshAdditionalKeys(userId: UserId): Promise<void>;
|
||||
|
||||
/**
|
||||
* Observable value that returns whether or not the user has ever had a userKey,
|
||||
|
||||
@@ -90,6 +90,35 @@ describe("keyService", () => {
|
||||
expect(keyService).not.toBeFalsy();
|
||||
});
|
||||
|
||||
describe("refreshAdditionalKeys", () => {
|
||||
test.each([null as unknown as UserId, undefined as unknown as UserId])(
|
||||
"throws when the provided userId is %s",
|
||||
async (userId) => {
|
||||
await expect(keyService.refreshAdditionalKeys(userId)).rejects.toThrow(
|
||||
"UserId is required",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it("throws error if user key not found", async () => {
|
||||
stateProvider.singleUser.getFake(mockUserId, USER_KEY).nextState(null);
|
||||
|
||||
await expect(keyService.refreshAdditionalKeys(mockUserId)).rejects.toThrow(
|
||||
"No user key found for: " + mockUserId,
|
||||
);
|
||||
});
|
||||
|
||||
it("refreshes additional keys when user key is available", async () => {
|
||||
const mockUserKey = new SymmetricCryptoKey(new Uint8Array(64)) as UserKey;
|
||||
stateProvider.singleUser.getFake(mockUserId, USER_KEY).nextState(mockUserKey);
|
||||
const setUserKeySpy = jest.spyOn(keyService, "setUserKey");
|
||||
|
||||
await keyService.refreshAdditionalKeys(mockUserId);
|
||||
|
||||
expect(setUserKeySpy).toHaveBeenCalledWith(mockUserKey, mockUserId);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getUserKey", () => {
|
||||
let mockUserKey: UserKey;
|
||||
|
||||
|
||||
@@ -122,15 +122,17 @@ export class DefaultKeyService implements KeyServiceAbstraction {
|
||||
await this.setPrivateKey(encPrivateKey, userId);
|
||||
}
|
||||
|
||||
async refreshAdditionalKeys(): Promise<void> {
|
||||
const activeUserId = await firstValueFrom(this.stateProvider.activeUserId$);
|
||||
|
||||
if (activeUserId == null) {
|
||||
throw new Error("Can only refresh keys while there is an active user.");
|
||||
async refreshAdditionalKeys(userId: UserId): Promise<void> {
|
||||
if (userId == null) {
|
||||
throw new Error("UserId is required.");
|
||||
}
|
||||
|
||||
const key = await this.getUserKey(activeUserId);
|
||||
await this.setUserKey(key, activeUserId);
|
||||
const key = await firstValueFrom(this.userKey$(userId));
|
||||
if (key == null) {
|
||||
throw new Error("No user key found for: " + userId);
|
||||
}
|
||||
|
||||
await this.setUserKey(key, userId);
|
||||
}
|
||||
|
||||
everHadUserKey$(userId: UserId): Observable<boolean> {
|
||||
|
||||
Reference in New Issue
Block a user