1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-23 19:53:43 +00:00
Files
browser/libs/state/src/state-migrations/migrations/23-move-biometric-prompts-to-state-providers.ts
Addison Beck 361f7e3447 refactor: introduce @bitwarden/state and other common libs (#15772)
* refactor: introduce @bitwarden/serialization

* refactor: introduce @bitwarden/guid

* refactor: introduce @bitwaren/client-type

* refactor: introduce @bitwarden/core-test-utils

* refactor: introduce @bitwarden/state and @bitwarden/state-test-utils

Creates initial project structure for centralized application state management. Part of modularization effort to extract state code from common.

* Added state provider documentation to README.

* Changed callouts to Github format.

* Fixed linting on file name.

* Forced git to accept rename

---------

Co-authored-by: Todd Martin <tmartin@bitwarden.com>
2025-08-04 11:01:28 -04:00

100 lines
3.1 KiB
TypeScript

import { KeyDefinitionLike, MigrationHelper } from "../migration-helper";
import { Migrator } from "../migrator";
type ExpectedAccountType = {
settings?: {
disableAutoBiometricsPrompt?: boolean;
dismissedBiometricRequirePasswordOnStartCallout?: boolean;
};
};
// prompt cancelled is refreshed on every app start/quit/unlock, so we don't need to migrate it
export const DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT: KeyDefinitionLike = {
key: "dismissedBiometricRequirePasswordOnStartCallout",
stateDefinition: { name: "biometricSettings" },
};
export const PROMPT_AUTOMATICALLY: KeyDefinitionLike = {
key: "promptAutomatically",
stateDefinition: { name: "biometricSettings" },
};
export class MoveBiometricPromptsToStateProviders extends Migrator<22, 23> {
async migrate(helper: MigrationHelper): Promise<void> {
const legacyAccounts = await helper.getAccounts<ExpectedAccountType>();
await Promise.all(
legacyAccounts.map(async ({ userId, account }) => {
if (account == null) {
return;
}
// Move account data
if (account?.settings?.dismissedBiometricRequirePasswordOnStartCallout != null) {
await helper.setToUser(
userId,
DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT,
account.settings.dismissedBiometricRequirePasswordOnStartCallout,
);
}
if (account?.settings?.disableAutoBiometricsPrompt != null) {
await helper.setToUser(
userId,
PROMPT_AUTOMATICALLY,
!account.settings.disableAutoBiometricsPrompt,
);
}
// Delete old account data
delete account?.settings?.dismissedBiometricRequirePasswordOnStartCallout;
delete account?.settings?.disableAutoBiometricsPrompt;
await helper.set(userId, account);
}),
);
}
async rollback(helper: MigrationHelper): Promise<void> {
async function rollbackUser(userId: string, account: ExpectedAccountType) {
let updatedAccount = false;
const userDismissed = await helper.getFromUser<boolean>(
userId,
DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT,
);
if (userDismissed) {
account ??= {};
account.settings ??= {};
updatedAccount = true;
account.settings.dismissedBiometricRequirePasswordOnStartCallout = userDismissed;
await helper.setToUser(userId, DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT, null);
}
const userPromptAutomatically = await helper.getFromUser<boolean>(
userId,
PROMPT_AUTOMATICALLY,
);
if (userPromptAutomatically != null) {
account ??= {};
account.settings ??= {};
updatedAccount = true;
account.settings.disableAutoBiometricsPrompt = !userPromptAutomatically;
await helper.setToUser(userId, PROMPT_AUTOMATICALLY, null);
}
if (updatedAccount) {
await helper.set(userId, account);
}
}
const accounts = await helper.getAccounts<ExpectedAccountType>();
await Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
}
}