1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-29 22:31:29 +01:00

[PM-16895] Fix biometric prompt showing up in browser while disabled (#12781)

This commit is contained in:
Bernd Schoolmann 2025-01-13 09:29:42 +01:00 committed by GitHub
parent 4c8565f7f3
commit 5dc523bacb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 4 deletions

View File

@ -9,7 +9,12 @@ import {
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service"; import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { UserId } from "@bitwarden/common/types/guid"; import { UserId } from "@bitwarden/common/types/guid";
import { KeyService, BiometricsService, BiometricsStatus } from "@bitwarden/key-management"; import {
KeyService,
BiometricsService,
BiometricsStatus,
BiometricStateService,
} from "@bitwarden/key-management";
import { UnlockOptions } from "@bitwarden/key-management/angular"; import { UnlockOptions } from "@bitwarden/key-management/angular";
import { BrowserRouterService } from "../../../platform/popup/services/browser-router.service"; import { BrowserRouterService } from "../../../platform/popup/services/browser-router.service";
@ -26,6 +31,7 @@ describe("ExtensionLockComponentService", () => {
let vaultTimeoutSettingsService: MockProxy<VaultTimeoutSettingsService>; let vaultTimeoutSettingsService: MockProxy<VaultTimeoutSettingsService>;
let keyService: MockProxy<KeyService>; let keyService: MockProxy<KeyService>;
let routerService: MockProxy<BrowserRouterService>; let routerService: MockProxy<BrowserRouterService>;
let biometricStateService: MockProxy<BiometricStateService>;
beforeEach(() => { beforeEach(() => {
userDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>(); userDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
@ -35,6 +41,7 @@ describe("ExtensionLockComponentService", () => {
vaultTimeoutSettingsService = mock<VaultTimeoutSettingsService>(); vaultTimeoutSettingsService = mock<VaultTimeoutSettingsService>();
keyService = mock<KeyService>(); keyService = mock<KeyService>();
routerService = mock<BrowserRouterService>(); routerService = mock<BrowserRouterService>();
biometricStateService = mock<BiometricStateService>();
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [ providers: [
@ -67,6 +74,10 @@ describe("ExtensionLockComponentService", () => {
provide: BrowserRouterService, provide: BrowserRouterService,
useValue: routerService, useValue: routerService,
}, },
{
provide: BiometricStateService,
useValue: biometricStateService,
},
], ],
}); });
@ -306,6 +317,7 @@ describe("ExtensionLockComponentService", () => {
platformUtilsService.supportsSecureStorage.mockReturnValue( platformUtilsService.supportsSecureStorage.mockReturnValue(
mockInputs.platformSupportsSecureStorage, mockInputs.platformSupportsSecureStorage,
); );
biometricStateService.biometricUnlockEnabled$ = of(true);
// PIN // PIN
pinService.isPinDecryptionAvailable.mockResolvedValue(mockInputs.pinDecryptionAvailable); pinService.isPinDecryptionAvailable.mockResolvedValue(mockInputs.pinDecryptionAvailable);

View File

@ -1,14 +1,18 @@
// FIXME: Update this file to be type safe and remove this and next line // FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore // @ts-strict-ignore
import { inject } from "@angular/core"; import { inject } from "@angular/core";
import { combineLatest, defer, map, Observable } from "rxjs"; import { combineLatest, defer, firstValueFrom, map, Observable } from "rxjs";
import { import {
PinServiceAbstraction, PinServiceAbstraction,
UserDecryptionOptionsServiceAbstraction, UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common"; } from "@bitwarden/auth/common";
import { UserId } from "@bitwarden/common/types/guid"; import { UserId } from "@bitwarden/common/types/guid";
import { BiometricsService, BiometricsStatus } from "@bitwarden/key-management"; import {
BiometricsService,
BiometricsStatus,
BiometricStateService,
} from "@bitwarden/key-management";
import { LockComponentService, UnlockOptions } from "@bitwarden/key-management/angular"; import { LockComponentService, UnlockOptions } from "@bitwarden/key-management/angular";
import { BiometricErrors, BiometricErrorTypes } from "../../../models/biometricErrors"; import { BiometricErrors, BiometricErrorTypes } from "../../../models/biometricErrors";
@ -19,6 +23,7 @@ export class ExtensionLockComponentService implements LockComponentService {
private readonly biometricsService = inject(BiometricsService); private readonly biometricsService = inject(BiometricsService);
private readonly pinService = inject(PinServiceAbstraction); private readonly pinService = inject(PinServiceAbstraction);
private readonly routerService = inject(BrowserRouterService); private readonly routerService = inject(BrowserRouterService);
private readonly biometricStateService = inject(BiometricStateService);
getPreviousUrl(): string | null { getPreviousUrl(): string | null {
return this.routerService.getPreviousUrl(); return this.routerService.getPreviousUrl();
@ -45,7 +50,13 @@ export class ExtensionLockComponentService implements LockComponentService {
getAvailableUnlockOptions$(userId: UserId): Observable<UnlockOptions> { getAvailableUnlockOptions$(userId: UserId): Observable<UnlockOptions> {
return combineLatest([ return combineLatest([
// Note: defer is preferable b/c it delays the execution of the function until the observable is subscribed to // Note: defer is preferable b/c it delays the execution of the function until the observable is subscribed to
defer(async () => await this.biometricsService.getBiometricsStatusForUser(userId)), defer(async () => {
if (!(await firstValueFrom(this.biometricStateService.biometricUnlockEnabled$))) {
return BiometricsStatus.NotEnabledLocally;
} else {
return await this.biometricsService.getBiometricsStatusForUser(userId);
}
}),
this.userDecryptionOptionsService.userDecryptionOptionsById$(userId), this.userDecryptionOptionsService.userDecryptionOptionsById$(userId),
defer(() => this.pinService.isPinDecryptionAvailable(userId)), defer(() => this.pinService.isPinDecryptionAvailable(userId)),
]).pipe( ]).pipe(