1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-14 23:33:31 +00:00

[PM-6404] Fully Integrate clearOn Events (#8134)

* Add New KeyDefinitionOption

* Add New Services

* Add WebStorageServiceProvider Tests

* Update Error Message

* Add `UserKeyDefinition`

* Fix Deserialization Helpers

* Fix KeyDefinition

* Add `UserKeyDefinition`

* Fix Deserialization Helpers

* Fix KeyDefinition

* Move `ClearEvent`

* Cleanup

* Fix Imports

* Integrate onClear Events

* Remove Accidental Addition

* Fix Test

* Add VaultTimeoutService Tests

* Only Register When Current State is Null

* Address Feedback
This commit is contained in:
Justin Baur
2024-03-04 14:33:25 -06:00
committed by GitHub
parent 4ba2717eb4
commit c3eba7f2c8
28 changed files with 471 additions and 345 deletions

View File

@@ -11,6 +11,7 @@ import { MessagingService } from "../../platform/abstractions/messaging.service"
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service";
import { StateService } from "../../platform/abstractions/state.service";
import { Account } from "../../platform/models/domain/account";
import { StateEventRunnerService } from "../../platform/state";
import { CipherService } from "../../vault/abstractions/cipher.service";
import { CollectionService } from "../../vault/abstractions/collection.service";
import { FolderService } from "../../vault/abstractions/folder/folder.service.abstraction";
@@ -28,6 +29,7 @@ describe("VaultTimeoutService", () => {
let stateService: MockProxy<StateService>;
let authService: MockProxy<AuthService>;
let vaultTimeoutSettingsService: MockProxy<VaultTimeoutSettingsService>;
let stateEventRunnerService: MockProxy<StateEventRunnerService>;
let lockedCallback: jest.Mock<Promise<void>, [userId: string]>;
let loggedOutCallback: jest.Mock<Promise<void>, [expired: boolean, userId?: string]>;
@@ -48,6 +50,7 @@ describe("VaultTimeoutService", () => {
stateService = mock();
authService = mock();
vaultTimeoutSettingsService = mock();
stateEventRunnerService = mock();
lockedCallback = jest.fn();
loggedOutCallback = jest.fn();
@@ -73,6 +76,7 @@ describe("VaultTimeoutService", () => {
stateService,
authService,
vaultTimeoutSettingsService,
stateEventRunnerService,
lockedCallback,
loggedOutCallback,
);
@@ -103,7 +107,8 @@ describe("VaultTimeoutService", () => {
return Promise.resolve(accounts[userId]?.authStatus);
});
stateService.getIsAuthenticated.mockImplementation((options) => {
return Promise.resolve(accounts[options.userId]?.isAuthenticated);
// Just like actual state service, if no userId is given fallback to active userId
return Promise.resolve(accounts[options.userId ?? globalSetups?.userId]?.isAuthenticated);
});
vaultTimeoutSettingsService.getVaultTimeout.mockImplementation((userId) => {
@@ -337,4 +342,80 @@ describe("VaultTimeoutService", () => {
expectNoAction("1");
});
});
describe("lock", () => {
const setupLock = () => {
setupAccounts(
{
user1: {
authStatus: AuthenticationStatus.Unlocked,
isAuthenticated: true,
},
user2: {
authStatus: AuthenticationStatus.Unlocked,
isAuthenticated: true,
},
},
{
userId: "user1",
},
);
};
it("should call state event runner with currently active user if no user passed into lock", async () => {
setupLock();
await vaultTimeoutService.lock();
expect(stateEventRunnerService.handleEvent).toHaveBeenCalledWith("lock", "user1");
});
it("should call messaging service locked message if no user passed into lock", async () => {
setupLock();
await vaultTimeoutService.lock();
// Currently these pass `undefined` (or what they were given) as the userId back
// but we could change this to give the user that was locked (active) to these methods
// so they don't have to get it their own way, but that is a behavioral change that needs
// to be tested.
expect(messagingService.send).toHaveBeenCalledWith("locked", { userId: undefined });
});
it("should call locked callback if no user passed into lock", async () => {
setupLock();
await vaultTimeoutService.lock();
// Currently these pass `undefined` (or what they were given) as the userId back
// but we could change this to give the user that was locked (active) to these methods
// so they don't have to get it their own way, but that is a behavioral change that needs
// to be tested.
expect(lockedCallback).toHaveBeenCalledWith(undefined);
});
it("should call state event runner with user passed into lock", async () => {
setupLock();
await vaultTimeoutService.lock("user2");
expect(stateEventRunnerService.handleEvent).toHaveBeenCalledWith("lock", "user2");
});
it("should call messaging service locked message with user passed into lock", async () => {
setupLock();
await vaultTimeoutService.lock("user2");
expect(messagingService.send).toHaveBeenCalledWith("locked", { userId: "user2" });
});
it("should call locked callback with user passed into lock", async () => {
setupLock();
await vaultTimeoutService.lock("user2");
expect(lockedCallback).toHaveBeenCalledWith("user2");
});
});
});

View File

@@ -11,6 +11,8 @@ import { CryptoService } from "../../platform/abstractions/crypto.service";
import { MessagingService } from "../../platform/abstractions/messaging.service";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service";
import { StateService } from "../../platform/abstractions/state.service";
import { StateEventRunnerService } from "../../platform/state";
import { UserId } from "../../types/guid";
import { CipherService } from "../../vault/abstractions/cipher.service";
import { CollectionService } from "../../vault/abstractions/collection.service";
import { FolderService } from "../../vault/abstractions/folder/folder.service.abstraction";
@@ -29,6 +31,7 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
private stateService: StateService,
private authService: AuthService,
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
private stateEventRunnerService: StateEventRunnerService,
private lockedCallback: (userId?: string) => Promise<void> = null,
private loggedOutCallback: (expired: boolean, userId?: string) => Promise<void> = null,
) {}
@@ -81,7 +84,9 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
await this.logOut(userId);
}
if (userId == null || userId === (await this.stateService.getUserId())) {
const currentUserId = await this.stateService.getUserId();
if (userId == null || userId === currentUserId) {
this.searchService.clearIndex();
await this.folderService.clearCache();
await this.collectionService.clearActiveUserCache();
@@ -98,6 +103,11 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
await this.cipherService.clearCache(userId);
await this.stateEventRunnerService.handleEvent("lock", (userId ?? currentUserId) as UserId);
// FIXME: We should send the userId of the user that was locked, in the case of this method being passed
// undefined then it should give back the currentUserId. Better yet, this method shouldn't take
// an undefined userId at all. All receivers need to be checked for how they handle getting undefined.
this.messagingService.send("locked", { userId: userId });
if (this.lockedCallback != null) {