mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
Add state for everHadUserKey (#7208)
* Migrate ever had user key * Add DI for state providers * Add state for everHadUserKey * Use ever had user key migrator Co-authored-by: SmithThe4th <gsmithwalter@gmail.com> Co-authored-by: Carlos Gonçalves <LRNcardozoWDF@users.noreply.github.com> Co-authored-by: Jason Ng <Jcory.ng@gmail.com> * Fix test from merge * Prefer stored observables to getters getters create a new observable every time they're called, whereas one set in the constructor is created only once. * Fix another merge issue * Fix cli background build --------- Co-authored-by: SmithThe4th <gsmithwalter@gmail.com> Co-authored-by: Carlos Gonçalves <LRNcardozoWDF@users.noreply.github.com> Co-authored-by: Jason Ng <Jcory.ng@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { AbstractStorageService } from "../platform/abstractions/storage.service
|
||||
|
||||
import { MigrationBuilder } from "./migration-builder";
|
||||
import { MigrationHelper } from "./migration-helper";
|
||||
import { EverHadUserKeyMigrator } from "./migrations/10-move-ever-had-user-key-to-state-providers";
|
||||
import { FixPremiumMigrator } from "./migrations/3-fix-premium";
|
||||
import { RemoveEverBeenUnlockedMigrator } from "./migrations/4-remove-ever-been-unlocked";
|
||||
import { AddKeyTypeToOrgKeysMigrator } from "./migrations/5-add-key-type-to-org-keys";
|
||||
@@ -15,7 +16,7 @@ import { MoveBrowserSettingsToGlobal } from "./migrations/9-move-browser-setting
|
||||
import { MinVersionMigrator } from "./migrations/min-version";
|
||||
|
||||
export const MIN_VERSION = 2;
|
||||
export const CURRENT_VERSION = 9;
|
||||
export const CURRENT_VERSION = 10;
|
||||
export type MinVersion = typeof MIN_VERSION;
|
||||
|
||||
export async function migrate(
|
||||
@@ -40,7 +41,8 @@ export async function migrate(
|
||||
.with(RemoveLegacyEtmKeyMigrator, 5, 6)
|
||||
.with(MoveBiometricAutoPromptToAccount, 6, 7)
|
||||
.with(MoveStateVersionMigrator, 7, 8)
|
||||
.with(MoveBrowserSettingsToGlobal, 8, CURRENT_VERSION)
|
||||
.with(MoveBrowserSettingsToGlobal, 8, 9)
|
||||
.with(EverHadUserKeyMigrator, 9, CURRENT_VERSION)
|
||||
.migrate(migrationHelper);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
import { MockProxy, any } from "jest-mock-extended";
|
||||
|
||||
import { MigrationHelper } from "../migration-helper";
|
||||
import { mockMigrationHelper } from "../migration-helper.spec";
|
||||
|
||||
import { EverHadUserKeyMigrator } from "./10-move-ever-had-user-key-to-state-providers";
|
||||
|
||||
function exampleJSON() {
|
||||
return {
|
||||
global: {
|
||||
otherStuff: "otherStuff1",
|
||||
},
|
||||
authenticatedAccounts: [
|
||||
"c493ed01-4e08-4e88-abc7-332f380ca760",
|
||||
"23e61a5f-2ece-4f5e-b499-f0bc489482a9",
|
||||
"fd005ea6-a16a-45ef-ba4a-a194269bfd73",
|
||||
],
|
||||
"c493ed01-4e08-4e88-abc7-332f380ca760": {
|
||||
profile: {
|
||||
everHadUserKey: false,
|
||||
otherStuff: "overStuff2",
|
||||
},
|
||||
otherStuff: "otherStuff3",
|
||||
},
|
||||
"23e61a5f-2ece-4f5e-b499-f0bc489482a9": {
|
||||
profile: {
|
||||
everHadUserKey: true,
|
||||
otherStuff: "otherStuff4",
|
||||
},
|
||||
otherStuff: "otherStuff5",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function rollbackJSON() {
|
||||
return {
|
||||
"user_c493ed01-4e08-4e88-abc7-332f380ca760_crypto_everHadUserKey": false,
|
||||
"user_23e61a5f-2ece-4f5e-b499-f0bc489482a9_crypto_everHadUserKey": true,
|
||||
"user_fd005ea6-a16a-45ef-ba4a-a194269bfd73_crypto_everHadUserKey": false,
|
||||
global: {
|
||||
otherStuff: "otherStuff1",
|
||||
},
|
||||
authenticatedAccounts: [
|
||||
"c493ed01-4e08-4e88-abc7-332f380ca760",
|
||||
"23e61a5f-2ece-4f5e-b499-f0bc489482a9",
|
||||
"fd005ea6-a16a-45ef-ba4a-a194269bfd73",
|
||||
],
|
||||
"c493ed01-4e08-4e88-abc7-332f380ca760": {
|
||||
profile: {
|
||||
everHadUserKey: false,
|
||||
otherStuff: "overStuff2",
|
||||
},
|
||||
otherStuff: "otherStuff3",
|
||||
},
|
||||
"23e61a5f-2ece-4f5e-b499-f0bc489482a9": {
|
||||
profile: {
|
||||
everHadUserKey: true,
|
||||
otherStuff: "otherStuff4",
|
||||
},
|
||||
otherStuff: "otherStuff5",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe("EverHadUserKeyMigrator", () => {
|
||||
let helper: MockProxy<MigrationHelper>;
|
||||
let sut: EverHadUserKeyMigrator;
|
||||
const keyDefinitionLike = {
|
||||
key: "everHadUserKey",
|
||||
stateDefinition: {
|
||||
name: "crypto",
|
||||
},
|
||||
};
|
||||
|
||||
describe("migrate", () => {
|
||||
beforeEach(() => {
|
||||
helper = mockMigrationHelper(exampleJSON(), 9);
|
||||
sut = new EverHadUserKeyMigrator(9, 10);
|
||||
});
|
||||
|
||||
it("should remove everHadUserKey from all accounts", async () => {
|
||||
await sut.migrate(helper);
|
||||
expect(helper.set).toHaveBeenCalledWith("c493ed01-4e08-4e88-abc7-332f380ca760", {
|
||||
profile: {
|
||||
otherStuff: "overStuff2",
|
||||
},
|
||||
otherStuff: "otherStuff3",
|
||||
});
|
||||
expect(helper.set).toHaveBeenCalledWith("23e61a5f-2ece-4f5e-b499-f0bc489482a9", {
|
||||
profile: {
|
||||
otherStuff: "otherStuff4",
|
||||
},
|
||||
otherStuff: "otherStuff5",
|
||||
});
|
||||
});
|
||||
|
||||
it("should set everHadUserKey provider value for each account", async () => {
|
||||
await sut.migrate(helper);
|
||||
|
||||
expect(helper.setToUser).toHaveBeenCalledWith(
|
||||
"c493ed01-4e08-4e88-abc7-332f380ca760",
|
||||
keyDefinitionLike,
|
||||
false,
|
||||
);
|
||||
|
||||
expect(helper.setToUser).toHaveBeenCalledWith(
|
||||
"23e61a5f-2ece-4f5e-b499-f0bc489482a9",
|
||||
keyDefinitionLike,
|
||||
true,
|
||||
);
|
||||
|
||||
expect(helper.setToUser).toHaveBeenCalledWith(
|
||||
"fd005ea6-a16a-45ef-ba4a-a194269bfd73",
|
||||
keyDefinitionLike,
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("rollback", () => {
|
||||
beforeEach(() => {
|
||||
helper = mockMigrationHelper(rollbackJSON(), 10);
|
||||
sut = new EverHadUserKeyMigrator(9, 10);
|
||||
});
|
||||
|
||||
it.each([
|
||||
"c493ed01-4e08-4e88-abc7-332f380ca760",
|
||||
"23e61a5f-2ece-4f5e-b499-f0bc489482a9",
|
||||
"fd005ea6-a16a-45ef-ba4a-a194269bfd73",
|
||||
])("should null out new values", async (userId) => {
|
||||
await sut.rollback(helper);
|
||||
|
||||
expect(helper.setToUser).toHaveBeenCalledWith(userId, keyDefinitionLike, null);
|
||||
});
|
||||
|
||||
it("should add explicit value back to accounts", async () => {
|
||||
await sut.rollback(helper);
|
||||
|
||||
expect(helper.set).toHaveBeenCalledWith("c493ed01-4e08-4e88-abc7-332f380ca760", {
|
||||
profile: {
|
||||
everHadUserKey: false,
|
||||
otherStuff: "overStuff2",
|
||||
},
|
||||
otherStuff: "otherStuff3",
|
||||
});
|
||||
expect(helper.set).toHaveBeenCalledWith("23e61a5f-2ece-4f5e-b499-f0bc489482a9", {
|
||||
profile: {
|
||||
everHadUserKey: true,
|
||||
otherStuff: "otherStuff4",
|
||||
},
|
||||
otherStuff: "otherStuff5",
|
||||
});
|
||||
});
|
||||
|
||||
it("should not try to restore values to missing accounts", async () => {
|
||||
await sut.rollback(helper);
|
||||
|
||||
expect(helper.set).not.toHaveBeenCalledWith("fd005ea6-a16a-45ef-ba4a-a194269bfd73", any());
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { KeyDefinitionLike, MigrationHelper } from "../migration-helper";
|
||||
import { Migrator } from "../migrator";
|
||||
|
||||
type ExpectedAccountType = {
|
||||
profile?: {
|
||||
everHadUserKey?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
const USER_EVER_HAD_USER_KEY: KeyDefinitionLike = {
|
||||
key: "everHadUserKey",
|
||||
stateDefinition: {
|
||||
name: "crypto",
|
||||
},
|
||||
};
|
||||
|
||||
export class EverHadUserKeyMigrator extends Migrator<9, 10> {
|
||||
async migrate(helper: MigrationHelper): Promise<void> {
|
||||
const accounts = await helper.getAccounts<ExpectedAccountType>();
|
||||
async function migrateAccount(userId: string, account: ExpectedAccountType): Promise<void> {
|
||||
const value = account?.profile?.everHadUserKey;
|
||||
await helper.setToUser(userId, USER_EVER_HAD_USER_KEY, value ?? false);
|
||||
if (value != null) {
|
||||
delete account.profile.everHadUserKey;
|
||||
}
|
||||
await helper.set(userId, account);
|
||||
}
|
||||
|
||||
await Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||||
}
|
||||
async rollback(helper: MigrationHelper): Promise<void> {
|
||||
const accounts = await helper.getAccounts<ExpectedAccountType>();
|
||||
async function rollbackAccount(userId: string, account: ExpectedAccountType): Promise<void> {
|
||||
const value = await helper.getFromUser(userId, USER_EVER_HAD_USER_KEY);
|
||||
if (account) {
|
||||
account.profile = Object.assign(account.profile ?? {}, {
|
||||
everHadUserKey: value,
|
||||
});
|
||||
await helper.set(userId, account);
|
||||
}
|
||||
await helper.setToUser(userId, USER_EVER_HAD_USER_KEY, null);
|
||||
}
|
||||
|
||||
await Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user