[bug] Add several state value defaults (#593)

* [bug] Add several state value defaults

* [refactor] Implement StateVersion as an enum

* [refactor] Implement StateVersion enum over magic number
This commit is contained in:
Addison Beck 2021-12-31 09:14:43 -05:00 committed by GitHub
parent d68c1dafaf
commit e4cd0af2f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 20 additions and 15 deletions

View File

@ -0,0 +1,5 @@
export enum StateVersion {
One = 1, // Original flat key/value pair store
Two = 2, // Move to a typed State object
Latest = Two,
}

View File

@ -139,7 +139,7 @@ export class AccountSettings {
protectedPin?: string; protectedPin?: string;
settings?: any; // TODO: Merge whatever is going on here into the AccountSettings model properly settings?: any; // TODO: Merge whatever is going on here into the AccountSettings model properly
vaultTimeout?: number; vaultTimeout?: number;
vaultTimeoutAction?: string; vaultTimeoutAction?: string = "lock";
} }
export class AccountTokens { export class AccountTokens {

View File

@ -1,15 +1,17 @@
import { StateVersion } from "../../enums/stateVersion";
export class GlobalState { export class GlobalState {
enableAlwaysOnTop?: boolean; enableAlwaysOnTop?: boolean;
installedVersion?: string; installedVersion?: string;
lastActive?: number; lastActive?: number;
locale?: string; locale?: string = "en";
openAtLogin?: boolean; openAtLogin?: boolean;
organizationInvitation?: any; organizationInvitation?: any;
ssoCodeVerifier?: string; ssoCodeVerifier?: string;
ssoOrganizationIdentifier?: string; ssoOrganizationIdentifier?: string;
ssoState?: string; ssoState?: string;
rememberedEmail?: string; rememberedEmail?: string;
theme?: string; theme?: string = "light";
window?: Map<string, any> = new Map<string, any>(); window?: Map<string, any> = new Map<string, any>();
twoFactorToken?: string; twoFactorToken?: string;
disableFavicon?: boolean; disableFavicon?: boolean;
@ -23,7 +25,7 @@ export class GlobalState {
biometricText?: string; biometricText?: string;
noAutoPromptBiometrics?: boolean; noAutoPromptBiometrics?: boolean;
noAutoPromptBiometricsText?: string; noAutoPromptBiometricsText?: string;
stateVersion: number; stateVersion: StateVersion = StateVersion.Latest;
environmentUrls?: any = { environmentUrls?: any = {
server: "bitwarden.com", server: "bitwarden.com",
}; };

View File

@ -74,7 +74,6 @@ export class StateService<TAccount extends Account = Account>
); );
this.state = diskState; this.state = diskState;
await this.pruneInMemoryAccounts(); await this.pruneInMemoryAccounts();
await this.saveStateToStorage(this.state, await this.defaultOnDiskMemoryOptions());
await this.pushAccounts(); await this.pushAccounts();
} }
} }

View File

@ -2,6 +2,7 @@ import { StorageService } from "../abstractions/storage.service";
import { Account } from "../models/domain/account"; import { Account } from "../models/domain/account";
import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory"; import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory";
import { GlobalState } from "../models/domain/globalState";
import { State } from "../models/domain/state"; import { State } from "../models/domain/state";
import { StorageOptions } from "../models/domain/storageOptions"; import { StorageOptions } from "../models/domain/storageOptions";
@ -16,6 +17,7 @@ import { SendData } from "../models/data/sendData";
import { HtmlStorageLocation } from "../enums/htmlStorageLocation"; import { HtmlStorageLocation } from "../enums/htmlStorageLocation";
import { KdfType } from "../enums/kdfType"; import { KdfType } from "../enums/kdfType";
import { StateVersion } from "../enums/stateVersion";
// Originally (before January 2022) storage was handled as a flat key/value pair store. // Originally (before January 2022) storage was handled as a flat key/value pair store.
// With the move to a typed object for state storage these keys should no longer be in use anywhere outside of this migration. // With the move to a typed object for state storage these keys should no longer be in use anywhere outside of this migration.
@ -111,8 +113,6 @@ const v1KeyPrefixes = {
}; };
export class StateMigrationService { export class StateMigrationService {
readonly latestVersion: number = 2;
constructor( constructor(
protected storageService: StorageService, protected storageService: StorageService,
protected secureStorageService: StorageService protected secureStorageService: StorageService
@ -124,15 +124,16 @@ export class StateMigrationService {
htmlStorageLocation: HtmlStorageLocation.Local, htmlStorageLocation: HtmlStorageLocation.Local,
}) })
)?.globals?.stateVersion; )?.globals?.stateVersion;
return currentStateVersion == null || currentStateVersion < this.latestVersion; return currentStateVersion == null || currentStateVersion < StateVersion.Latest;
} }
async migrate(): Promise<void> { async migrate(): Promise<void> {
let currentStateVersion = let currentStateVersion =
(await this.storageService.get<State<Account>>("state"))?.globals?.stateVersion ?? 1; (await this.storageService.get<State<Account>>("state"))?.globals?.stateVersion ??
while (currentStateVersion < this.latestVersion) { StateVersion.One;
while (currentStateVersion < StateVersion.Latest) {
switch (currentStateVersion) { switch (currentStateVersion) {
case 1: case StateVersion.One:
await this.migrateStateFrom1To2(); await this.migrateStateFrom1To2();
break; break;
} }
@ -147,9 +148,7 @@ export class StateMigrationService {
const initialState: State<Account> = const initialState: State<Account> =
userId == null userId == null
? { ? {
globals: { globals: new GlobalState(),
stateVersion: 2,
},
accounts: {}, accounts: {},
activeUserId: null, activeUserId: null,
} }
@ -209,7 +208,7 @@ export class StateMigrationService {
v1Keys.rememberedEmail, v1Keys.rememberedEmail,
options options
), ),
stateVersion: 2, stateVersion: StateVersion.Two,
theme: await this.storageService.get<string>(v1Keys.theme, options), theme: await this.storageService.get<string>(v1Keys.theme, options),
twoFactorToken: await this.storageService.get<string>( twoFactorToken: await this.storageService.get<string>(
v1KeyPrefixes.twoFactorToken + userId, v1KeyPrefixes.twoFactorToken + userId,