1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

Migrate autoConfirmFingerPrints to StateProvider (#8337)

* Fix a typo in the `StateDefinition` description

* Introduce `OrganizationManagementPreferencesService`

* Declare `OrganizationManagementPreferencesService` in DI

* Update `autoConfirmFingerPrints` logic in emergency access files

* Update `autoConfirmFingerPrints` logic in `people` files

* Remove `autoConfirmFingerPrints` from `StateService` and `Account`

* Migrate existing client data for `autoConfirmFingerPrints`

* Update apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Update apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Use `set` instead of `update` for function names

---------

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>
This commit is contained in:
Addison Beck
2024-03-19 16:37:35 -05:00
committed by GitHub
parent 3953318c28
commit bf2d2cfbed
18 changed files with 346 additions and 43 deletions

View File

@@ -0,0 +1,102 @@
import { MockProxy } from "jest-mock-extended";
import { MigrationHelper } from "../migration-helper";
import { mockMigrationHelper, runMigrator } from "../migration-helper.spec";
import { AutoConfirmFingerPrintsMigrator } from "./43-move-auto-confirm-finger-prints-to-state-provider";
function rollbackJSON() {
return {
authenticatedAccounts: ["user-1", "user-2"],
"user_user-1_organizationManagementPreferences_autoConfirmFingerPrints": true,
"user_user-2_organizationManagementPreferences_autoConfirmFingerPrints": false,
"user-1": {
settings: {
extra: "data",
},
extra: "data",
},
"user-2": {
settings: {
extra: "data",
},
extra: "data",
},
};
}
describe("AutoConfirmFingerPrintsMigrator", () => {
const migrator = new AutoConfirmFingerPrintsMigrator(42, 43);
it("should migrate the autoConfirmFingerPrints property from the account settings object to a user StorageKey", async () => {
const output = await runMigrator(migrator, {
authenticatedAccounts: ["user-1", "user-2"] as const,
"user-1": {
settings: {
autoConfirmFingerPrints: true,
extra: "data",
},
extra: "data",
},
"user-2": {
settings: {
autoConfirmFingerPrints: false,
extra: "data",
},
extra: "data",
},
});
expect(output).toEqual({
authenticatedAccounts: ["user-1", "user-2"],
"user_user-1_organizationManagementPreferences_autoConfirmFingerPrints": true,
"user_user-2_organizationManagementPreferences_autoConfirmFingerPrints": false,
"user-1": {
settings: {
extra: "data",
},
extra: "data",
},
"user-2": {
settings: {
extra: "data",
},
extra: "data",
},
});
});
describe("rollback", () => {
let helper: MockProxy<MigrationHelper>;
let sut: AutoConfirmFingerPrintsMigrator;
const keyDefinitionLike = {
key: "autoConfirmFingerPrints",
stateDefinition: {
name: "organizationManagementPreferences",
},
};
beforeEach(() => {
helper = mockMigrationHelper(rollbackJSON(), 43);
sut = new AutoConfirmFingerPrintsMigrator(42, 43);
});
it("should null the autoConfirmFingerPrints user StorageKey for each account", async () => {
await sut.rollback(helper);
expect(helper.setToUser).toHaveBeenCalledWith("user-1", keyDefinitionLike, null);
});
it("should add the autoConfirmFingerPrints property back to the account settings object", async () => {
await sut.rollback(helper);
expect(helper.set).toHaveBeenCalledWith("user-1", {
settings: {
autoConfirmFingerPrints: true,
extra: "data",
},
extra: "data",
});
});
});
});

View File

@@ -0,0 +1,63 @@
import { KeyDefinitionLike, MigrationHelper, StateDefinitionLike } from "../migration-helper";
import { Migrator } from "../migrator";
type ExpectedAccountState = {
settings?: { autoConfirmFingerPrints?: boolean };
};
const ORGANIZATION_MANAGEMENT_PREFERENCES: StateDefinitionLike = {
name: "organizationManagementPreferences",
};
const AUTO_CONFIRM_FINGERPRINTS: KeyDefinitionLike = {
key: "autoConfirmFingerPrints",
stateDefinition: ORGANIZATION_MANAGEMENT_PREFERENCES,
};
export class AutoConfirmFingerPrintsMigrator extends Migrator<42, 43> {
async migrate(helper: MigrationHelper): Promise<void> {
const legacyAccounts = await helper.getAccounts<ExpectedAccountState>();
await Promise.all(
legacyAccounts.map(async ({ userId, account }) => {
if (account?.settings?.autoConfirmFingerPrints != null) {
await helper.setToUser(
userId,
AUTO_CONFIRM_FINGERPRINTS,
account.settings.autoConfirmFingerPrints,
);
delete account?.settings?.autoConfirmFingerPrints;
await helper.set(userId, account);
}
}),
);
}
async rollback(helper: MigrationHelper): Promise<void> {
async function rollbackUser(userId: string, account: ExpectedAccountState) {
let updatedAccount = false;
const autoConfirmFingerPrints = await helper.getFromUser<boolean>(
userId,
AUTO_CONFIRM_FINGERPRINTS,
);
if (autoConfirmFingerPrints) {
if (!account) {
account = {};
}
updatedAccount = true;
account.settings.autoConfirmFingerPrints = autoConfirmFingerPrints;
await helper.setToUser(userId, AUTO_CONFIRM_FINGERPRINTS, null);
}
if (updatedAccount) {
await helper.set(userId, account);
}
}
const accounts = await helper.getAccounts<ExpectedAccountState>();
await Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
}
}