1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

Auth/PM-17197 - UnauthGuard Trusted Devices Lock State Refactor (#12938)

* PM-17197 - Refactor DeviceTrustService to deprecate active user state as I need to call with a user id per latest best practice

* PM-17197 - Refactor Unauth Guard to be aware of TDE lock state + use active user best practice.
This commit is contained in:
Jared Snider
2025-01-24 13:20:42 -05:00
committed by GitHub
parent b1744c4e0a
commit 6acaa6c711
5 changed files with 177 additions and 28 deletions

View File

@@ -9,7 +9,18 @@ import { DeviceKey, UserKey } from "../../types/key";
import { DeviceResponse } from "./devices/responses/device.response";
export abstract class DeviceTrustServiceAbstraction {
/**
* @deprecated - use supportsDeviceTrustByUserId instead as active user state is being deprecated
* by Platform
* @description Checks if the device trust feature is supported for the active user.
*/
supportsDeviceTrust$: Observable<boolean>;
/**
* @description Checks if the device trust feature is supported for the given user.
*/
supportsDeviceTrustByUserId$: (userId: UserId) => Observable<boolean>;
/**
* @description Retrieves the users choice to trust the device which can only happen after decryption
* Note: this value should only be used once and then reset

View File

@@ -81,7 +81,17 @@ export class DeviceTrustService implements DeviceTrustServiceAbstraction {
private configService: ConfigService,
) {
this.supportsDeviceTrust$ = this.userDecryptionOptionsService.userDecryptionOptions$.pipe(
map((options) => options?.trustedDeviceOption != null ?? false),
map((options) => {
return options?.trustedDeviceOption != null ?? false;
}),
);
}
supportsDeviceTrustByUserId$(userId: UserId): Observable<boolean> {
return this.userDecryptionOptionsService.userDecryptionOptionsById$(userId).pipe(
map((options) => {
return options?.trustedDeviceOption != null ?? false;
}),
);
}

View File

@@ -1,5 +1,7 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { matches, mock } from "jest-mock-extended";
import { BehaviorSubject, of } from "rxjs";
import { BehaviorSubject, firstValueFrom, of } from "rxjs";
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
@@ -74,17 +76,56 @@ describe("deviceTrustService", () => {
userId: mockUserId,
};
let userDecryptionOptions: UserDecryptionOptions;
beforeEach(() => {
jest.clearAllMocks();
const supportsSecureStorage = false; // default to false; tests will override as needed
// By default all the tests will have a mocked active user in state provider.
deviceTrustService = createDeviceTrustService(mockUserId, supportsSecureStorage);
userDecryptionOptions = new UserDecryptionOptions();
});
it("instantiates", () => {
expect(deviceTrustService).not.toBeFalsy();
});
describe("supportsDeviceTrustByUserId$", () => {
it("returns true when the user has a non-null trusted device decryption option", async () => {
// Arrange
userDecryptionOptions.trustedDeviceOption = {
hasAdminApproval: false,
hasLoginApprovingDevice: false,
hasManageResetPasswordPermission: false,
isTdeOffboarding: false,
};
userDecryptionOptionsService.userDecryptionOptionsById$.mockReturnValue(
new BehaviorSubject<UserDecryptionOptions>(userDecryptionOptions),
);
const result = await firstValueFrom(
deviceTrustService.supportsDeviceTrustByUserId$(mockUserId),
);
expect(result).toBe(true);
});
it("returns false when the user has a null trusted device decryption option", async () => {
// Arrange
userDecryptionOptions.trustedDeviceOption = null;
userDecryptionOptionsService.userDecryptionOptionsById$.mockReturnValue(
new BehaviorSubject<UserDecryptionOptions>(userDecryptionOptions),
);
const result = await firstValueFrom(
deviceTrustService.supportsDeviceTrustByUserId$(mockUserId),
);
expect(result).toBe(false);
});
});
describe("User Trust Device Choice For Decryption", () => {
describe("getShouldTrustDevice", () => {
it("gets the user trust device choice for decryption", async () => {