1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-22 11:13:46 +00:00

[PM-6172] Run localStorage migrations for web (#7900)

* Create MigrationRunner

- Create MigrationRunner Service for running migrations in StateService
- Create web override so that migrations also run against `localStorage`

* Fix Web StateService

* Fix WebMigrationRunner

* Fix CLI

* Fix ElectronStateService

* Update Comment

* More Common Scenarios
This commit is contained in:
Justin Baur
2024-02-14 08:52:13 -05:00
committed by GitHub
parent 38bb8d596a
commit 1ff7bdd014
23 changed files with 700 additions and 58 deletions

View File

@@ -73,6 +73,8 @@ import { EncryptServiceImplementation } from "@bitwarden/common/platform/service
import { MultithreadEncryptServiceImplementation } from "@bitwarden/common/platform/services/cryptography/multithread-encrypt.service.implementation";
import { FileUploadService } from "@bitwarden/common/platform/services/file-upload/file-upload.service";
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
import { SystemService } from "@bitwarden/common/platform/services/system.service";
import { WebCryptoFunctionService } from "@bitwarden/common/platform/services/web-crypto-function.service";
import {
@@ -381,6 +383,13 @@ export default class MainBackground {
this.stateProvider,
this.accountService,
);
const migrationRunner = new MigrationRunner(
this.storageService,
this.logService,
new MigrationBuilderService(),
);
this.stateService = new BrowserStateService(
this.storageService,
this.secureStorageService,
@@ -389,6 +398,7 @@ export default class MainBackground {
new StateFactory(GlobalState, Account),
this.accountService,
this.environmentService,
migrationRunner,
);
this.platformUtilsService = new BrowserPlatformUtilsService(
this.messagingService,

View File

@@ -0,0 +1,32 @@
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
import { CachedServices, FactoryOptions, factory } from "./factory-options";
import { LogServiceInitOptions, logServiceFactory } from "./log-service.factory";
import {
DiskStorageServiceInitOptions,
diskStorageServiceFactory,
} from "./storage-service.factory";
type MigrationRunnerFactory = FactoryOptions;
export type MigrationRunnerInitOptions = MigrationRunnerFactory &
DiskStorageServiceInitOptions &
LogServiceInitOptions;
export async function migrationRunnerFactory(
cache: { migrationRunner?: MigrationRunner } & CachedServices,
opts: MigrationRunnerInitOptions,
): Promise<MigrationRunner> {
return factory(
cache,
"migrationRunner",
opts,
async () =>
new MigrationRunner(
await diskStorageServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
new MigrationBuilderService(),
),
);
}

View File

@@ -14,6 +14,7 @@ import {
} from "./environment-service.factory";
import { CachedServices, factory, FactoryOptions } from "./factory-options";
import { logServiceFactory, LogServiceInitOptions } from "./log-service.factory";
import { migrationRunnerFactory, MigrationRunnerInitOptions } from "./migration-runner.factory";
import {
diskStorageServiceFactory,
secureStorageServiceFactory,
@@ -36,7 +37,8 @@ export type StateServiceInitOptions = StateServiceFactoryOptions &
MemoryStorageServiceInitOptions &
LogServiceInitOptions &
AccountServiceInitOptions &
EnvironmentServiceInitOptions;
EnvironmentServiceInitOptions &
MigrationRunnerInitOptions;
export async function stateServiceFactory(
cache: { stateService?: BrowserStateService } & CachedServices,
@@ -55,11 +57,11 @@ export async function stateServiceFactory(
opts.stateServiceOptions.stateFactory,
await accountServiceFactory(cache, opts),
await environmentServiceFactory(cache, opts),
await migrationRunnerFactory(cache, opts),
opts.stateServiceOptions.useAccountCache,
),
);
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
service.init();
// TODO: If we run migration through a chrome installed/updated event we can turn off running migrations
await service.init();
return service;
}

View File

@@ -10,6 +10,7 @@ import {
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
import { State } from "@bitwarden/common/platform/models/domain/state";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
@@ -31,6 +32,7 @@ describe("Browser State Service", () => {
let useAccountCache: boolean;
let accountService: MockProxy<AccountService>;
let environmentService: MockProxy<EnvironmentService>;
let migrationRunner: MockProxy<MigrationRunner>;
let state: State<GlobalState, Account>;
const userId = "userId";
@@ -44,6 +46,7 @@ describe("Browser State Service", () => {
stateFactory = mock();
accountService = mock();
environmentService = mock();
migrationRunner = mock();
// turn off account cache for tests
useAccountCache = false;
@@ -70,6 +73,7 @@ describe("Browser State Service", () => {
stateFactory,
accountService,
environmentService,
migrationRunner,
useAccountCache,
);
});

View File

@@ -10,6 +10,7 @@ import {
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
import { GlobalState } from "@bitwarden/common/platform/models/domain/global-state";
import { StorageOptions } from "@bitwarden/common/platform/models/domain/storage-options";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
import { StateService as BaseStateService } from "@bitwarden/common/platform/services/state.service";
import { Account } from "../../models/account";
@@ -46,6 +47,7 @@ export class BrowserStateService
stateFactory: StateFactory<GlobalState, Account>,
accountService: AccountService,
environmentService: EnvironmentService,
migrationRunner: MigrationRunner,
useAccountCache = true,
) {
super(
@@ -56,6 +58,7 @@ export class BrowserStateService
stateFactory,
accountService,
environmentService,
migrationRunner,
useAccountCache,
);

View File

@@ -72,6 +72,7 @@ import { GlobalState } from "@bitwarden/common/platform/models/domain/global-sta
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
import { ContainerService } from "@bitwarden/common/platform/services/container.service";
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
import { DerivedStateProvider, StateProvider } from "@bitwarden/common/platform/state";
import { SearchService } from "@bitwarden/common/services/search.service";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
@@ -482,6 +483,7 @@ function getBgService<T>(service: keyof MainBackground) {
logService: LogServiceAbstraction,
accountService: AccountServiceAbstraction,
environmentService: EnvironmentService,
migrationRunner: MigrationRunner,
) => {
return new BrowserStateService(
storageService,
@@ -491,6 +493,7 @@ function getBgService<T>(service: keyof MainBackground) {
new StateFactory(GlobalState, Account),
accountService,
environmentService,
migrationRunner,
);
},
deps: [
@@ -500,6 +503,7 @@ function getBgService<T>(service: keyof MainBackground) {
LogServiceAbstraction,
AccountServiceAbstraction,
EnvironmentService,
MigrationRunner,
],
},
{