1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 00:03:56 +00:00

PM-3585 Improve state migrations (#5009)

* WIP: safer state migrations

Co-authored-by: Justin Baur <justindbaur@users.noreply.github.com>

* Add min version check and remove old migrations

Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>

* Add rollback and version checking

* Add state version move migration

* Expand tests and improve typing for Migrations

* Remove StateMigration Service

* Rewrite version 5 and 6 migrations

* Add all but initial migration to supported migrations

* Handle stateVersion location in migrator update versions

* Move to unique migrations directory

* Disallow imports outside of state-migrations

* Lint and test fixes

* Do not run migrations if we cannot determine state

* Fix desktop background StateService build

* Document Migration builder class

* Add debug logging to migrations

* Comment on migrator overrides

* Use specific property names

* `npm run prettier` 🤖

* Insert new migration

* Set stateVersion when creating new globals object

* PR comments

* Fix migrate imports

* Move migration building into `migrate` function

* Export current version from migration definitions

* Move file version concerns to migrator

* Update migrate spec to reflect new version requirements

* Fix import paths

* Prefer unique state data

* Remove unnecessary async

* Prefer to not use `any`

---------

Co-authored-by: Justin Baur <justindbaur@users.noreply.github.com>
Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>
This commit is contained in:
Matt Gibson
2023-08-30 12:57:20 -05:00
committed by GitHub
parent b444eed0b5
commit 3340af8084
51 changed files with 1538 additions and 980 deletions

View File

@@ -21,6 +21,7 @@ import {
import { VaultTimeoutAction } from "../../enums/vault-timeout-action.enum";
import { EventData } from "../../models/data/event.data";
import { WindowState } from "../../models/domain/window-state";
import { migrate } from "../../state-migrations";
import { GeneratedPasswordHistory } from "../../tools/generator/password";
import { SendData } from "../../tools/send/models/data/send.data";
import { SendView } from "../../tools/send/models/view/send.view";
@@ -32,7 +33,6 @@ import { CipherView } from "../../vault/models/view/cipher.view";
import { CollectionView } from "../../vault/models/view/collection.view";
import { AddEditCipherInfo } from "../../vault/types/add-edit-cipher-info";
import { LogService } from "../abstractions/log.service";
import { StateMigrationService } from "../abstractions/state-migration.service";
import { StateService as StateServiceAbstraction } from "../abstractions/state.service";
import {
AbstractMemoryStorageService,
@@ -61,6 +61,7 @@ import {
const keys = {
state: "state",
stateVersion: "stateVersion",
global: "global",
authenticatedAccounts: "authenticatedAccounts",
activeUserId: "activeUserId",
@@ -106,7 +107,6 @@ export class StateService<
protected secureStorageService: AbstractStorageService,
protected memoryStorageService: AbstractMemoryStorageService,
protected logService: LogService,
protected stateMigrationService: StateMigrationService,
protected stateFactory: StateFactory<TGlobalState, TAccount>,
protected useAccountCache: boolean = true
) {
@@ -133,9 +133,7 @@ export class StateService<
return;
}
if (await this.stateMigrationService.needsMigration()) {
await this.stateMigrationService.migrate();
}
await migrate(this.storageService, this.logService);
await this.state().then(async (state) => {
if (state == null) {
@@ -2724,16 +2722,6 @@ export class StateService<
);
}
async getStateVersion(): Promise<number> {
return (await this.getGlobals(await this.defaultOnDiskLocalOptions())).stateVersion ?? 1;
}
async setStateVersion(value: number): Promise<void> {
const globals = await this.getGlobals(await this.defaultOnDiskOptions());
globals.stateVersion = value;
await this.saveGlobals(globals, await this.defaultOnDiskOptions());
}
async getWindow(): Promise<WindowState> {
const globals = await this.getGlobals(await this.defaultOnDiskOptions());
return globals?.window != null && Object.keys(globals.window).length > 0
@@ -2838,7 +2826,11 @@ export class StateService<
globals = await this.getGlobalsFromDisk(options);
}
return globals ?? this.createGlobals();
if (globals == null) {
globals = this.createGlobals();
}
return globals;
}
protected async saveGlobals(globals: TGlobalState, options: StorageOptions) {