1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 01:33:33 +00:00

PM-5273 Initial migration work for localData

This commit is contained in:
Carlos Gonçalves
2024-02-29 18:01:20 +00:00
parent b17239595d
commit 60ac34182d
10 changed files with 248 additions and 9 deletions

View File

@@ -0,0 +1,117 @@
import { MockProxy } from "jest-mock-extended";
import { MigrationHelper } from "../migration-helper";
import { mockMigrationHelper } from "../migration-helper.spec";
import { LocalDataMigrator } from "./23-move-local-data-to-state-provider";
function exampleJSON() {
return {
global: {
otherStuff: "otherStuff1",
},
authenticatedAccounts: ["user-1", "user-2"],
"user-1": {
localData: [
{
"6865ba55-7966-4d63-b743-b12000d49631": {
lastUsedDate: 1708950970632,
},
},
{
"f895f099-6739-4cca-9d61-b12200d04bfa": {
lastUsedDate: 1709031916943,
},
},
],
},
"user-2": {
localData: {
"fce9e7bf-bb3d-4650-897f-b12300f43541": {
lastUsedDate: 1708950970632,
},
"ffb90bc2-a4ff-4571-b954-b12300f4207e": {
lastUsedDate: 1709031916943,
},
},
},
};
}
function rollbackJSON() {
return {
authenticatedAccounts: ["user-1", "user-2"],
"user-1": {
localdata: [
{
"6865ba55-7966-4d63-b743-b12000d49631": {
lastUsedDate: 1708950970632,
},
"f895f099-6739-4cca-9d61-b12200d04bfa": {
lastUsedDate: 1709031916943,
},
},
],
},
"user-2": {
localdata: [
{
"fce9e7bf-bb3d-4650-897f-b12300f43541": {
lastUsedDate: 1708950970632,
},
"ffb90bc2-a4ff-4571-b954-b12300f4207e": {
lastUsedDate: 1709031916943,
},
},
],
},
};
}
describe("LocalDataMigrator", () => {
let helper: MockProxy<MigrationHelper>;
let sut: LocalDataMigrator;
const keyDefinitionLike = {
key: "local_data",
stateDefinition: {
name: "localData",
},
};
describe("migrate", () => {
beforeEach(() => {
helper = mockMigrationHelper(exampleJSON(), 23);
sut = new LocalDataMigrator(22, 23);
});
it("should remove local data from all accounts", async () => {
await sut.migrate(helper);
expect(helper.set).toHaveBeenCalledWith("user-1", {
localData: [
{
"6865ba55-7966-4d63-b743-b12000d49631": {
lastUsedDate: 1708950970632,
},
},
{
"f895f099-6739-4cca-9d61-b12200d04bfa": {
lastUsedDate: 1709031916943,
},
},
],
});
});
});
describe("rollback", () => {
beforeEach(() => {
helper = mockMigrationHelper(rollbackJSON(), 23);
sut = new LocalDataMigrator(22, 23);
});
it.each(["user-1", "user-2"])("should null out new values", async (userId) => {
await sut.rollback(helper);
expect(helper.setToUser).toHaveBeenCalledWith(userId, keyDefinitionLike, null);
});
});
});

View File

@@ -0,0 +1,50 @@
import { KeyDefinitionLike, MigrationHelper } from "../migration-helper";
import { Migrator } from "../migrator";
type ExpectedAccountType = {
[cipherId: string]: LocalData;
};
type LocalData = {
lastUsedDate?: number;
lastLaunched?: number;
};
const LOCAL_DATA: KeyDefinitionLike = {
key: "local_data",
stateDefinition: {
name: "localData",
},
};
export class LocalDataMigrator extends Migrator<22, 23> {
async migrate(helper: MigrationHelper): Promise<void> {
const accounts = await helper.getAccounts<ExpectedAccountType>();
async function migrateAccount(userId: string, account: ExpectedAccountType): Promise<void> {
const value = account?.localData;
if (value != null) {
await helper.setToUser(userId, LOCAL_DATA, value);
delete account.LocalData;
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, LOCAL_DATA);
if (account) {
account.localData = Object.assign(account.localData ?? {}, {
localData: value,
});
await helper.set(userId, account);
}
await helper.setToUser(userId, LOCAL_DATA, null);
}
await Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
}
}