updateCipher method
Implementation
Future<void> updateCipher({
String? path,
String? oldPw,
String? newPw,
}) async {
try {
final HiveCipher? oldCipher = cipherFromKey(key: oldPw);
final HiveCipher? newCipher = cipherFromKey(key: newPw);
/// only change the db if the new password is different from the old one
if (oldCipher != newCipher) {
await _ensureInit(pw: oldPw);
/// The types box contains only a single entry, which is a list of all of the
/// resource types that have been saved to the database
final Box<List<String>> typesBox = await Hive.openBox<List<String>>(
'types',
encryptionCipher: oldCipher);
/// get that list of types
final List<String> types = typesBox.get('types') ?? <String>[];
_types
.map((Dstu2ResourceType e) => resourceTypeToStringMap[e]!)
.toList();
/// Create a new temporary box to store resources while we are updating the boxes
/// with a new password
final Box<Map<dynamic, dynamic>> tempBox =
await Hive.openBox<Map<dynamic, dynamic>>('temp',
encryptionCipher: newCipher);
/// for each type in the list
for (final String type in types) {
/// Retrieve all resources currently in the box
final Box<Map<dynamic, dynamic>> oldBox =
await Hive.openBox<Map<dynamic, dynamic>>(type,
encryptionCipher: oldCipher);
/// for each map in the box
for (final Map<dynamic, dynamic> value in oldBox.values) {
/// Cast map to correct type
final Map<String, dynamic> newValue =
jsonDecode(jsonEncode(value)) as Map<String, dynamic>;
/// convert it to a resource
final Resource resource = Resource.fromJson(newValue);
/// Save it in the temporary box as we're changing over to the new password, so
/// in case something goes wrong, we don't lose the data
await tempBox.put(resource.fhirId, newValue);
}
/// after we have saved all of the resources in the temporary box, we can
/// delete the old box
await oldBox.deleteFromDisk();
/// Create the new box with the new password
final Box<Map<dynamic, dynamic>> newBox =
await Hive.openBox<Map<dynamic, dynamic>>(type,
encryptionCipher: newCipher);
/// for each map in the temp box
for (final Map<dynamic, dynamic> value in tempBox.values) {
/// Cast map to correct type
final Map<String, dynamic> newValue =
Map<String, dynamic>.from(value);
/// convert it to a resource
final Resource resource = Resource.fromJson(newValue);
/// Save it to the new box with the new password
await newBox.put(resource.fhirId, newValue);
}
/// clear everything from the tempBox so we can use it again
await tempBox.clear();
}
/// After we've been through all of the types, delete the tempBox.
await tempBox.deleteFromDisk();
/// Delete the typesBox because we need to replace it too using the new password
await typesBox.deleteFromDisk();
/// Recreate the types box
final Box<List<String>> newTypesBox = await Hive.openBox<List<String>>(
'types',
encryptionCipher: newCipher);
await newTypesBox.put('types', types);
await Hive.close();
}
} catch (e) {
print(e);
}
}