import { KeyDefinitionLike, MigrationHelper } from "../migration-helper"; import { Migrator } from "../migrator"; enum KdfType { PBKDF2_SHA256 = 0, Argon2id = 1, } class KdfConfig { iterations: number; kdfType: KdfType; memory?: number; parallelism?: number; } type ExpectedAccountType = { profile?: { kdfIterations: number; kdfType: KdfType; kdfMemory?: number; kdfParallelism?: number; }; }; const kdfConfigKeyDefinition: KeyDefinitionLike = { key: "kdfConfig", stateDefinition: { name: "kdfConfig", }, }; export class KdfConfigMigrator extends Migrator<58, 59> { async migrate(helper: MigrationHelper): Promise { const accounts = await helper.getAccounts(); async function migrateAccount(userId: string, account: ExpectedAccountType): Promise { const iterations = account?.profile?.kdfIterations; const kdfType = account?.profile?.kdfType; const memory = account?.profile?.kdfMemory; const parallelism = account?.profile?.kdfParallelism; const kdfConfig: KdfConfig = { iterations: iterations, kdfType: kdfType, memory: memory, parallelism: parallelism, }; if (kdfConfig != null) { await helper.setToUser(userId, kdfConfigKeyDefinition, kdfConfig); delete account?.profile?.kdfIterations; delete account?.profile?.kdfType; delete account?.profile?.kdfMemory; delete account?.profile?.kdfParallelism; } await helper.set(userId, account); } await Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]); } async rollback(helper: MigrationHelper): Promise { const accounts = await helper.getAccounts(); async function rollbackAccount(userId: string, account: ExpectedAccountType): Promise { const kdfConfig: KdfConfig = await helper.getFromUser(userId, kdfConfigKeyDefinition); if (kdfConfig != null) { account.profile.kdfIterations = kdfConfig.iterations; account.profile.kdfType = kdfConfig.kdfType; account.profile.kdfMemory = kdfConfig.memory; account.profile.kdfParallelism = kdfConfig.parallelism; await helper.setToUser(userId, kdfConfigKeyDefinition, null); } await helper.set(userId, account); } await Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]); } }