mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[PM-5404, PM-3518] Migrate user decryption options to new service (#7344)
* create new user decryption options service * rename new service to user decryption options * add hasMasterPassword to user decryption options service * migrate device trust service to new user decryption options service * add migration for user-decryption-options * migrate sync service and calls to trust-device-service * rename abstraction file * migrate two factor component * migrate two factor spec * migrate sso component * migrate set-password component * migrate base login decryption component * migrate organization options component * fix component imports * add missing imports - remove state service calls - add update user decryption options method * remove acct decryption options from account * lint * fix tests and linting * fix browser * fix desktop * add user decryption options service to cli * remove default value from migration * bump migration number * fix merge conflict * fix vault timeout settings * fix cli * more fixes * add user decryption options service to deps of vault timeout settings service * update login strategy service with user decryption options * remove early return from sync bandaid for user decryption options * move user decryption options service to lib/auth * move user decryption options to libs/auth * fix reference * fix browser * check user decryption options after 2fa check * update migration and revert tsconfig changes * add more documentation * clear user decryption options on logout * fix tests by creating helper for user decryption options * fix tests * pr feedback * fix factory * update migration * add tests * update missed migration num in test
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
import { BehaviorSubject, firstValueFrom, map, of } from "rxjs";
|
||||
|
||||
import {
|
||||
FakeUserDecryptionOptions as UserDecryptionOptions,
|
||||
UserDecryptionOptionsServiceAbstraction,
|
||||
} from "@bitwarden/auth/common";
|
||||
|
||||
import { PolicyService } from "../../admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { Policy } from "../../admin-console/models/domain/policy";
|
||||
@@ -8,12 +13,12 @@ import { VaultTimeoutAction } from "../../enums/vault-timeout-action.enum";
|
||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
||||
import { StateService } from "../../platform/abstractions/state.service";
|
||||
import { BiometricStateService } from "../../platform/biometrics/biometric-state.service";
|
||||
import { AccountDecryptionOptions } from "../../platform/models/domain/account";
|
||||
import { EncString } from "../../platform/models/domain/enc-string";
|
||||
|
||||
import { VaultTimeoutSettingsService } from "./vault-timeout-settings.service";
|
||||
|
||||
describe("VaultTimeoutSettingsService", () => {
|
||||
let userDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>;
|
||||
let cryptoService: MockProxy<CryptoService>;
|
||||
let tokenService: MockProxy<TokenService>;
|
||||
let policyService: MockProxy<PolicyService>;
|
||||
@@ -21,12 +26,26 @@ describe("VaultTimeoutSettingsService", () => {
|
||||
const biometricStateService = mock<BiometricStateService>();
|
||||
let service: VaultTimeoutSettingsService;
|
||||
|
||||
let userDecryptionOptionsSubject: BehaviorSubject<UserDecryptionOptions>;
|
||||
|
||||
beforeEach(() => {
|
||||
userDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
|
||||
cryptoService = mock<CryptoService>();
|
||||
tokenService = mock<TokenService>();
|
||||
policyService = mock<PolicyService>();
|
||||
stateService = mock<StateService>();
|
||||
|
||||
userDecryptionOptionsSubject = new BehaviorSubject(null);
|
||||
userDecryptionOptionsService.userDecryptionOptions$ = userDecryptionOptionsSubject;
|
||||
userDecryptionOptionsService.hasMasterPassword$ = userDecryptionOptionsSubject.pipe(
|
||||
map((options) => options?.hasMasterPassword ?? false),
|
||||
);
|
||||
userDecryptionOptionsService.userDecryptionOptionsById$.mockReturnValue(
|
||||
userDecryptionOptionsSubject,
|
||||
);
|
||||
|
||||
service = new VaultTimeoutSettingsService(
|
||||
userDecryptionOptionsService,
|
||||
cryptoService,
|
||||
tokenService,
|
||||
policyService,
|
||||
@@ -49,9 +68,7 @@ describe("VaultTimeoutSettingsService", () => {
|
||||
});
|
||||
|
||||
it("contains Lock when the user has a master password", async () => {
|
||||
stateService.getAccountDecryptionOptions.mockResolvedValue(
|
||||
new AccountDecryptionOptions({ hasMasterPassword: true }),
|
||||
);
|
||||
userDecryptionOptionsSubject.next(new UserDecryptionOptions({ hasMasterPassword: true }));
|
||||
|
||||
const result = await firstValueFrom(service.availableVaultTimeoutActions$());
|
||||
|
||||
@@ -83,9 +100,7 @@ describe("VaultTimeoutSettingsService", () => {
|
||||
});
|
||||
|
||||
it("not contains Lock when the user does not have a master password, PIN, or biometrics", async () => {
|
||||
stateService.getAccountDecryptionOptions.mockResolvedValue(
|
||||
new AccountDecryptionOptions({ hasMasterPassword: false }),
|
||||
);
|
||||
userDecryptionOptionsSubject.next(new UserDecryptionOptions({ hasMasterPassword: false }));
|
||||
stateService.getPinKeyEncryptedUserKey.mockResolvedValue(null);
|
||||
stateService.getProtectedPin.mockResolvedValue(null);
|
||||
biometricStateService.biometricUnlockEnabled$ = of(false);
|
||||
@@ -107,9 +122,7 @@ describe("VaultTimeoutSettingsService", () => {
|
||||
`(
|
||||
"returns $expected when policy is $policy, and user preference is $userPreference",
|
||||
async ({ policy, userPreference, expected }) => {
|
||||
stateService.getAccountDecryptionOptions.mockResolvedValue(
|
||||
new AccountDecryptionOptions({ hasMasterPassword: true }),
|
||||
);
|
||||
userDecryptionOptionsSubject.next(new UserDecryptionOptions({ hasMasterPassword: true }));
|
||||
policyService.getAll$.mockReturnValue(
|
||||
of(policy === null ? [] : ([{ data: { action: policy } }] as unknown as Policy[])),
|
||||
);
|
||||
@@ -136,8 +149,8 @@ describe("VaultTimeoutSettingsService", () => {
|
||||
"returns $expected when policy is $policy, has unlock method is $unlockMethod, and user preference is $userPreference",
|
||||
async ({ unlockMethod, policy, userPreference, expected }) => {
|
||||
biometricStateService.biometricUnlockEnabled$ = of(unlockMethod);
|
||||
stateService.getAccountDecryptionOptions.mockResolvedValue(
|
||||
new AccountDecryptionOptions({ hasMasterPassword: false }),
|
||||
userDecryptionOptionsSubject.next(
|
||||
new UserDecryptionOptions({ hasMasterPassword: false }),
|
||||
);
|
||||
policyService.getAll$.mockReturnValue(
|
||||
of(policy === null ? [] : ([{ data: { action: policy } }] as unknown as Policy[])),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { defer, firstValueFrom } from "rxjs";
|
||||
|
||||
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
|
||||
|
||||
import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "../../abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { PolicyService } from "../../admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "../../admin-console/enums";
|
||||
@@ -19,6 +21,7 @@ export type PinLockType = "DISABLED" | "PERSISTANT" | "TRANSIENT";
|
||||
|
||||
export class VaultTimeoutSettingsService implements VaultTimeoutSettingsServiceAbstraction {
|
||||
constructor(
|
||||
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||
private cryptoService: CryptoService,
|
||||
private tokenService: TokenService,
|
||||
private policyService: PolicyService,
|
||||
@@ -174,12 +177,15 @@ export class VaultTimeoutSettingsService implements VaultTimeoutSettingsServiceA
|
||||
}
|
||||
|
||||
private async userHasMasterPassword(userId: string): Promise<boolean> {
|
||||
const acctDecryptionOpts = await this.stateService.getAccountDecryptionOptions({
|
||||
userId: userId,
|
||||
});
|
||||
if (userId) {
|
||||
const decryptionOptions = await firstValueFrom(
|
||||
this.userDecryptionOptionsService.userDecryptionOptionsById$(userId),
|
||||
);
|
||||
|
||||
if (acctDecryptionOpts?.hasMasterPassword != undefined) {
|
||||
return acctDecryptionOpts.hasMasterPassword;
|
||||
if (decryptionOptions?.hasMasterPassword != undefined) {
|
||||
return decryptionOptions.hasMasterPassword;
|
||||
}
|
||||
}
|
||||
return await firstValueFrom(this.userDecryptionOptionsService.hasMasterPassword$);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user