mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 05:13:29 +00:00
[PM-22419] dismiss account nudge when biometric unlock is set (#15139)
* update account-security-nudge service to look at biomentricUnlockEnabled$ observable, add success toast for biometric unlock
This commit is contained in:
@@ -5062,6 +5062,9 @@
|
||||
"unlockPinSet": {
|
||||
"message": "Unlock PIN set"
|
||||
},
|
||||
"unlockBiometricSet": {
|
||||
"message": "Unlock biometrics set"
|
||||
},
|
||||
"authenticating": {
|
||||
"message": "Authenticating"
|
||||
},
|
||||
|
||||
@@ -534,6 +534,11 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
|
||||
if (!successful) {
|
||||
await this.biometricStateService.setFingerprintValidated(false);
|
||||
}
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("unlockBiometricSet"),
|
||||
});
|
||||
} catch (error) {
|
||||
this.form.controls.biometric.setValue(false);
|
||||
this.validationService.showError(error);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { Injectable, inject } from "@angular/core";
|
||||
import { Observable, combineLatest, from, of } from "rxjs";
|
||||
import { catchError, map } from "rxjs/operators";
|
||||
import { catchError, switchMap } from "rxjs/operators";
|
||||
|
||||
import { VaultProfileService } from "@bitwarden/angular/vault/services/vault-profile.service";
|
||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { PinServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/key-management/vault-timeout";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { BiometricStateService } from "@bitwarden/key-management";
|
||||
|
||||
import { DefaultSingleNudgeService } from "../default-single-nudge.service";
|
||||
import { NudgeStatus, NudgeType } from "../nudges.service";
|
||||
@@ -21,6 +25,9 @@ export class AccountSecurityNudgeService extends DefaultSingleNudgeService {
|
||||
private logService = inject(LogService);
|
||||
private pinService = inject(PinServiceAbstraction);
|
||||
private vaultTimeoutSettingsService = inject(VaultTimeoutSettingsService);
|
||||
private biometricStateService = inject(BiometricStateService);
|
||||
private policyService = inject(PolicyService);
|
||||
private organizationService = inject(OrganizationService);
|
||||
|
||||
nudgeStatus$(nudgeType: NudgeType, userId: UserId): Observable<NudgeStatus> {
|
||||
const profileDate$ = from(this.vaultProfileService.getProfileCreationDate(userId)).pipe(
|
||||
@@ -36,16 +43,45 @@ export class AccountSecurityNudgeService extends DefaultSingleNudgeService {
|
||||
this.getNudgeStatus$(nudgeType, userId),
|
||||
of(Date.now() - THIRTY_DAYS_MS),
|
||||
from(this.pinService.isPinSet(userId)),
|
||||
from(this.vaultTimeoutSettingsService.isBiometricLockSet(userId)),
|
||||
this.biometricStateService.biometricUnlockEnabled$,
|
||||
this.organizationService.organizations$(userId),
|
||||
this.policyService.policiesByType$(PolicyType.RemoveUnlockWithPin, userId),
|
||||
]).pipe(
|
||||
map(([profileCreationDate, status, profileCutoff, isPinSet, isBiometricLockSet]) => {
|
||||
const profileOlderThanCutoff = profileCreationDate.getTime() < profileCutoff;
|
||||
const hideNudge = profileOlderThanCutoff || isPinSet || isBiometricLockSet;
|
||||
return {
|
||||
hasBadgeDismissed: status.hasBadgeDismissed || hideNudge,
|
||||
hasSpotlightDismissed: status.hasSpotlightDismissed || hideNudge,
|
||||
};
|
||||
}),
|
||||
switchMap(
|
||||
async ([
|
||||
profileCreationDate,
|
||||
status,
|
||||
profileCutoff,
|
||||
isPinSet,
|
||||
biometricUnlockEnabled,
|
||||
organizations,
|
||||
policies,
|
||||
]) => {
|
||||
const profileOlderThanCutoff = profileCreationDate.getTime() < profileCutoff;
|
||||
|
||||
const hasOrgWithRemovePinPolicyOn = organizations.some((org) => {
|
||||
return policies.some(
|
||||
(p) => p.type === PolicyType.RemoveUnlockWithPin && p.organizationId === org.id,
|
||||
);
|
||||
});
|
||||
|
||||
const hideNudge =
|
||||
profileOlderThanCutoff ||
|
||||
isPinSet ||
|
||||
biometricUnlockEnabled ||
|
||||
hasOrgWithRemovePinPolicyOn;
|
||||
|
||||
const acctSecurityNudgeStatus = {
|
||||
hasBadgeDismissed: status.hasBadgeDismissed || hideNudge,
|
||||
hasSpotlightDismissed: status.hasSpotlightDismissed || hideNudge,
|
||||
};
|
||||
|
||||
if (isPinSet || biometricUnlockEnabled || hasOrgWithRemovePinPolicyOn) {
|
||||
await this.setNudgeStatus(nudgeType, acctSecurityNudgeStatus, userId);
|
||||
}
|
||||
return acctSecurityNudgeStatus;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import { firstValueFrom, of } from "rxjs";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { PinServiceAbstraction } from "@bitwarden/auth/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/key-management/vault-timeout";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
@@ -13,6 +15,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { BiometricStateService } from "@bitwarden/key-management";
|
||||
|
||||
import { FakeStateProvider, mockAccountServiceWith } from "../../../../../libs/common/spec";
|
||||
|
||||
@@ -91,6 +94,18 @@ describe("Vault Nudges Service", () => {
|
||||
provide: VaultTimeoutSettingsService,
|
||||
useValue: mock<VaultTimeoutSettingsService>(),
|
||||
},
|
||||
{
|
||||
provide: BiometricStateService,
|
||||
useValue: mock<BiometricStateService>(),
|
||||
},
|
||||
{
|
||||
provide: PolicyService,
|
||||
useValue: mock<PolicyService>(),
|
||||
},
|
||||
{
|
||||
provide: OrganizationService,
|
||||
useValue: mock<OrganizationService>(),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user