1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-18 09:13:33 +00:00

[PM-5275] Migrate state in Fido2ClientService to State Providers (#7745)

* added state definition and key definition

* created vault settings service

* created enable passkeys migrations

* created enable passkeys migrations

* renamed the state definition

* created vault settings service

* updated enable passkey key definition

* updated references with vault settings service

* renamed files to avoid conflict

* removed set and get enable passkeys from state service

* removed comment

* fixed comments

* added readonly keyword

* removed service registartion from service module

* removed readonly keyword from abstract class

* swicted to used optional chaining

* renamed files

* added disk-local argument for web
This commit is contained in:
SmithThe4th
2024-02-06 15:15:22 -05:00
committed by GitHub
parent 78008a9e1e
commit e9865c1cec
15 changed files with 218 additions and 30 deletions

View File

@@ -0,0 +1,17 @@
import { Observable } from "rxjs";
/**
* Service for managing vault settings.
*/
export abstract class VaultSettingsService {
/**
* An observable monitoring the state of the enable passkeys setting.
* The observable updates when the setting changes.
*/
enablePasskeys$: Observable<boolean>;
/**
* Saves the enable passkeys setting to disk.
* @param value The new value for the passkeys setting.
*/
setEnablePasskeys: (value: boolean) => Promise<void>;
}

View File

@@ -17,6 +17,7 @@ import {
CreateCredentialParams,
FallbackRequestedError,
} from "../../abstractions/fido2/fido2-client.service.abstraction";
import { VaultSettingsService } from "../../abstractions/vault-settings/vault-settings.service";
import { Fido2AuthenticatorService } from "./fido2-authenticator.service";
import { Fido2ClientService } from "./fido2-client.service";
@@ -32,6 +33,7 @@ describe("FidoAuthenticatorService", () => {
let configService!: MockProxy<ConfigServiceAbstraction>;
let authService!: MockProxy<AuthService>;
let stateService!: MockProxy<StateService>;
let vaultSettingsService: MockProxy<VaultSettingsService>;
let client!: Fido2ClientService;
let tab!: chrome.tabs.Tab;
@@ -40,10 +42,17 @@ describe("FidoAuthenticatorService", () => {
configService = mock<ConfigServiceAbstraction>();
authService = mock<AuthService>();
stateService = mock<StateService>();
vaultSettingsService = mock<VaultSettingsService>();
client = new Fido2ClientService(authenticator, configService, authService, stateService);
client = new Fido2ClientService(
authenticator,
configService,
authService,
stateService,
vaultSettingsService,
);
configService.serverConfig$ = of({ environment: { vault: VaultUrl } } as any);
stateService.getEnablePasskeys.mockResolvedValue(true);
vaultSettingsService.enablePasskeys$ = of(true);
authService.getAuthStatus.mockResolvedValue(AuthenticationStatus.Unlocked);
tab = { id: 123, windowId: 456 } as chrome.tabs.Tab;
});
@@ -226,7 +235,7 @@ describe("FidoAuthenticatorService", () => {
it("should throw FallbackRequestedError if passkeys state is not enabled", async () => {
const params = createParams();
stateService.getEnablePasskeys.mockResolvedValue(false);
vaultSettingsService.enablePasskeys$ = of(false);
const result = async () => await client.createCredential(params, tab);
@@ -396,7 +405,7 @@ describe("FidoAuthenticatorService", () => {
it("should throw FallbackRequestedError if passkeys state is not enabled", async () => {
const params = createParams();
stateService.getEnablePasskeys.mockResolvedValue(false);
vaultSettingsService.enablePasskeys$ = of(false);
const result = async () => await client.assertCredential(params, tab);

View File

@@ -26,6 +26,7 @@ import {
UserRequestedFallbackAbortReason,
UserVerification,
} from "../../abstractions/fido2/fido2-client.service.abstraction";
import { VaultSettingsService } from "../../abstractions/vault-settings/vault-settings.service";
import { isValidRpId } from "./domain-utils";
import { Fido2Utils } from "./fido2-utils";
@@ -42,11 +43,12 @@ export class Fido2ClientService implements Fido2ClientServiceAbstraction {
private configService: ConfigServiceAbstraction,
private authService: AuthService,
private stateService: StateService,
private vaultSettingsService: VaultSettingsService,
private logService?: LogService,
) {}
async isFido2FeatureEnabled(hostname: string, origin: string): Promise<boolean> {
const userEnabledPasskeys = await this.stateService.getEnablePasskeys();
const userEnabledPasskeys = await firstValueFrom(this.vaultSettingsService.enablePasskeys$);
const isUserLoggedIn =
(await this.authService.getAuthStatus()) !== AuthenticationStatus.LoggedOut;

View File

@@ -0,0 +1,9 @@
import { VAULT_SETTINGS_DISK, KeyDefinition } from "../../../platform/state";
export const USER_ENABLE_PASSKEYS = new KeyDefinition<boolean>(
VAULT_SETTINGS_DISK,
"enablePasskeys",
{
deserializer: (obj) => obj,
},
);

View File

@@ -0,0 +1,29 @@
import { Observable, map } from "rxjs";
import { GlobalState, StateProvider } from "../../../platform/state";
import { VaultSettingsService as VaultSettingsServiceAbstraction } from "../../abstractions/vault-settings/vault-settings.service";
import { USER_ENABLE_PASSKEYS } from "../key-state/enable-passkey.state";
/**
* {@link VaultSettingsServiceAbstraction}
*/
export class VaultSettingsService implements VaultSettingsServiceAbstraction {
private enablePasskeysState: GlobalState<boolean> =
this.stateProvider.getGlobal(USER_ENABLE_PASSKEYS);
/**
* {@link VaultSettingsServiceAbstraction.enablePasskeys$}
*/
readonly enablePasskeys$: Observable<boolean> = this.enablePasskeysState.state$.pipe(
map((x) => x ?? false),
);
constructor(private stateProvider: StateProvider) {}
/**
* {@link VaultSettingsServiceAbstraction.setEnablePasskeys}
*/
async setEnablePasskeys(value: boolean): Promise<void> {
await this.enablePasskeysState.update(() => value);
}
}