migrateLegacyPasswordHashes static method
Migrates legacy password hashes to the latest hash algorithm.
batchSize
is the number of entries to migrate in each batch.
maxMigratedEntries
is the maximum number of entries that will be
migrated. If null, all entries in the database will be migrated.
Returns the number of migrated entries.
Implementation
static Future<int> migrateLegacyPasswordHashes(
Session session, {
int batchSize = 100,
int? maxMigratedEntries,
}) async {
var updatedEntries = 0;
int lastEntryId = 0;
while (true) {
var entries = await EmailAuth.db.find(
session,
where: (t) => t.hash.notLike(r'%$%') & (t.id > lastEntryId),
orderBy: (t) => t.id,
limit: batchSize,
);
if (entries.isEmpty) {
return updatedEntries;
}
if (maxMigratedEntries != null) {
if (maxMigratedEntries == updatedEntries) {
return updatedEntries;
}
var entrySurplus =
(updatedEntries + entries.length) - maxMigratedEntries;
if (entrySurplus > 0) {
entries = entries.sublist(0, entries.length - entrySurplus);
}
}
lastEntryId = entries.last.id!;
var migratedEntries = await Future.wait(entries.where((entry) {
try {
return PasswordHash(
entry.hash,
legacySalt: EmailSecrets.legacySalt,
).isLegacyHash();
} catch (e) {
session.log(
'Error when checking if hash is legacy: $e',
level: LogLevel.error,
);
return false;
}
}).map((entry) async {
return entry.copyWith(
hash: await PasswordHash.migratedLegacyToArgon2idHash(
entry.hash,
legacySalt: EmailSecrets.legacySalt,
pepper: EmailSecrets.pepper,
allowUnsecureRandom: AuthConfig.current.allowUnsecureRandom,
),
);
}).toList());
try {
await EmailAuth.db.update(session, migratedEntries);
updatedEntries += migratedEntries.length;
} catch (e) {
session.log(
'Failed to update migrated entries: $e',
level: LogLevel.error,
);
}
}
}