mirror of
https://github.com/bitwarden/browser
synced 2025-12-21 10:43:35 +00:00
* move pinKeyEncryptedUserKey * move pinKeyEncryptedUserKeyEphemeral * remove comments, move docs * cleanup * use UserKeyDefinition * refactor methods * add migration * fix browser dependency * add tests for migration * rename to pinService * move state to PinService * add PinService dep to CryptoService * move protectedPin to state provider * update service deps * renaming * move decryptUserKeyWithPin to pinService * update service injection * move more methods our of crypto service * remove CryptoService dep from PinService and update service injection * remove cryptoService reference * add method to FakeMasterPasswordService * fix circular dependency * fix desktop service injection * update browser dependencies * add protectedPin to migrations * move storePinKey to pinService * update and clarify documentation * more jsdoc updates * update import paths * refactor isPinLockSet method * update state definitions * initialize service before injecting into other services * initialize service before injecting into other services (bw.ts) * update clearOn and do additional cleanup * clarify docs and naming * assign abstract & private methods, add clarity to decryptAndMigrateOldPinKeyEncryptedMasterKey() method * derived state (attempt) * fix typos * use accountService to get active user email * use constant userId * add derived state * add get and clear for oldPinKeyEncryptedMasterKey * require userId * move pinProtected * add clear methods * remove pinProtected from account.ts and replace methods * add methods to create and store pinKeyEncryptedUserKey * add pinProtected/oldPinKeyEncrypterMasterKey to migration * update migration tests * update migration rollback tests * update to systemService and decryptAndMigrate... method * remove old test * increase length of state definition name to meet test requirements * rename 'TRANSIENT' to 'EPHEMERAL' for consistency * fix tests for login strategies, vault-export, and fake MP service * more updates to login-strategy tests * write new tests for core pinKeyEncrypterUserKey methods and isPinSet * write new tests for pinProtected and oldPinKeyEncryptedMasterKey methods * minor test reformatting * update test for decryptUserKeyWithPin() * fix bug with oldPinKeyEncryptedMasterKey * fix tests for vault-timeout-settings.service * fix bitwarden-password-protected-importer test * fix login strategy tests and auth-request.service test * update pinService tests * fix crypto service tests * add jsdoc * fix test file import * update jsdocs for decryptAndMigrateOldPinKeyEncryptedMasterKey() * update error messages and jsdocs * add null checks, move userId retrievals * update migration tests * update stateService calls to require userId * update test for decryptUserKeyWithPin() * update oldPinKeyEncryptedMasterKey migration tests * more test updates * fix factory import * update tests for isPinSet() and createProtectedPin() * add test for makePinKey() * add test for createPinKeyEncryptedUserKey() * add tests for getPinLockType() * consolidate userId verification tests * add tests for storePinKeyEncryptedUserKey() * fix service dep * get email based on userId * use MasterPasswordService instead of internal * rename protectedPin to userKeyEncryptedPin * rename to pinKeyEncryptedUserKeyPersistent * update method params * fix CryptoService tests * jsdoc update * use EncString for userKeyEncryptedPin * remove comment * use cryptoFunctionService.compareFast() * update tests * cleanup, remove comments * resolve merge conflict * fix DI of MasterPasswordService * more DI fixes
130 lines
4.1 KiB
TypeScript
130 lines
4.1 KiB
TypeScript
import { KeyDefinitionLike, MigrationHelper, StateDefinitionLike } from "../migration-helper";
|
|
import { Migrator } from "../migrator";
|
|
|
|
type ExpectedAccountState = {
|
|
settings?: {
|
|
pinKeyEncryptedUserKey?: string; // EncryptedString
|
|
protectedPin?: string; // EncryptedString
|
|
pinProtected?: {
|
|
encrypted?: string;
|
|
};
|
|
};
|
|
};
|
|
|
|
export const PIN_STATE: StateDefinitionLike = { name: "pinUnlock" };
|
|
|
|
export const PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT: KeyDefinitionLike = {
|
|
stateDefinition: PIN_STATE,
|
|
key: "pinKeyEncryptedUserKeyPersistent",
|
|
};
|
|
|
|
export const USER_KEY_ENCRYPTED_PIN: KeyDefinitionLike = {
|
|
stateDefinition: PIN_STATE,
|
|
key: "userKeyEncryptedPin",
|
|
};
|
|
|
|
export const OLD_PIN_KEY_ENCRYPTED_MASTER_KEY: KeyDefinitionLike = {
|
|
stateDefinition: PIN_STATE,
|
|
key: "oldPinKeyEncryptedMasterKey",
|
|
};
|
|
|
|
export class PinStateMigrator extends Migrator<60, 61> {
|
|
async migrate(helper: MigrationHelper): Promise<void> {
|
|
const legacyAccounts = await helper.getAccounts<ExpectedAccountState>();
|
|
let updatedAccount = false;
|
|
|
|
async function migrateAccount(userId: string, account: ExpectedAccountState) {
|
|
// Migrate pinKeyEncryptedUserKey (to `pinKeyEncryptedUserKeyPersistent`)
|
|
if (account?.settings?.pinKeyEncryptedUserKey != null) {
|
|
await helper.setToUser(
|
|
userId,
|
|
PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT,
|
|
account.settings.pinKeyEncryptedUserKey,
|
|
);
|
|
delete account.settings.pinKeyEncryptedUserKey;
|
|
updatedAccount = true;
|
|
}
|
|
|
|
// Migrate protectedPin (to `userKeyEncryptedPin`)
|
|
if (account?.settings?.protectedPin != null) {
|
|
await helper.setToUser(userId, USER_KEY_ENCRYPTED_PIN, account.settings.protectedPin);
|
|
delete account.settings.protectedPin;
|
|
updatedAccount = true;
|
|
}
|
|
|
|
// Migrate pinProtected (to `oldPinKeyEncryptedMasterKey`)
|
|
if (account?.settings?.pinProtected?.encrypted != null) {
|
|
await helper.setToUser(
|
|
userId,
|
|
OLD_PIN_KEY_ENCRYPTED_MASTER_KEY,
|
|
account.settings.pinProtected.encrypted,
|
|
);
|
|
delete account.settings.pinProtected;
|
|
updatedAccount = true;
|
|
}
|
|
|
|
if (updatedAccount) {
|
|
await helper.set(userId, account);
|
|
}
|
|
}
|
|
|
|
await Promise.all([
|
|
...legacyAccounts.map(({ userId, account }) => migrateAccount(userId, account)),
|
|
]);
|
|
}
|
|
|
|
async rollback(helper: MigrationHelper): Promise<void> {
|
|
const accounts = await helper.getAccounts<ExpectedAccountState>();
|
|
|
|
async function rollbackAccount(userId: string, account: ExpectedAccountState) {
|
|
let updatedAccount = false;
|
|
|
|
const accountPinKeyEncryptedUserKeyPersistent = await helper.getFromUser<string>(
|
|
userId,
|
|
PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT,
|
|
);
|
|
const accountUserKeyEncryptedPin = await helper.getFromUser<string>(
|
|
userId,
|
|
USER_KEY_ENCRYPTED_PIN,
|
|
);
|
|
const accountOldPinKeyEncryptedMasterKey = await helper.getFromUser<string>(
|
|
userId,
|
|
OLD_PIN_KEY_ENCRYPTED_MASTER_KEY,
|
|
);
|
|
|
|
if (!account) {
|
|
account = {};
|
|
}
|
|
|
|
if (accountPinKeyEncryptedUserKeyPersistent != null) {
|
|
account.settings.pinKeyEncryptedUserKey = accountPinKeyEncryptedUserKeyPersistent;
|
|
await helper.setToUser(userId, PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT, null);
|
|
updatedAccount = true;
|
|
}
|
|
|
|
if (accountUserKeyEncryptedPin != null) {
|
|
account.settings.protectedPin = accountUserKeyEncryptedPin;
|
|
await helper.setToUser(userId, USER_KEY_ENCRYPTED_PIN, null);
|
|
updatedAccount = true;
|
|
}
|
|
|
|
if (accountOldPinKeyEncryptedMasterKey != null) {
|
|
account.settings = Object.assign(account.settings ?? {}, {
|
|
pinProtected: {
|
|
encrypted: accountOldPinKeyEncryptedMasterKey,
|
|
},
|
|
});
|
|
|
|
await helper.setToUser(userId, OLD_PIN_KEY_ENCRYPTED_MASTER_KEY, null);
|
|
updatedAccount = true;
|
|
}
|
|
|
|
if (updatedAccount) {
|
|
await helper.set(userId, account);
|
|
}
|
|
}
|
|
|
|
await Promise.all(accounts.map(({ userId, account }) => rollbackAccount(userId, account)));
|
|
}
|
|
}
|