giveAccessTo method
Give access to another dataOwner to the patient
Parameters:
Data owner id can be either a:
- healthcarePartyId,
- patientId
- deviceId
Implementation
@override
Future<Patient> giveAccessTo(Patient patient, String delegatedTo) async {
final localCrypto = _api.crypto;
final currentUser = (await _api.baseUserApi.getCurrentUser())
?? (throw StateError("There is no user currently logged in. You must call this method from an authenticated MedTechApi"));
if (currentUser.dataOwnerId() == null) {
throw StateError("The current user is not a data owner. You must been either a patient, a device or a healthcare professional to call this method");
}
// Check if delegatedBy has access
if (!patient.systemMetaData!.delegations.entries.any((element) => element.key == currentUser.dataOwnerId())) {
throw StateError("DataOwner ${currentUser.dataOwnerId()} does not have the right to access patient ${patient.id}");
}
final patientDto = patient.toPatientDto();
final myId = currentUser!.dataOwnerId()!;
final newSecretIds = await localCrypto.findAndDecryptPotentiallyUnknownKeysForDelegate(myId, delegatedTo, patientDto.delegations);
final newEncryptionKeys = await localCrypto.findAndDecryptPotentiallyUnknownKeysForDelegate(myId, delegatedTo, patientDto.encryptionKeys);
if (newSecretIds.isEmpty && newSecretIds.isEmpty) {
return patient;
}
DataOwnerDto? dataOwner = null;
final Map<String, String> encryptedKeys = {};
for (var clearKey in { ...newSecretIds, ...newEncryptionKeys }) {
final encryptedKeyAndOwner = await localCrypto.encryptAESKeyForHcp(
myId,
delegatedTo,
patientDto.id,
clearKey.formatAsKey()
);
encryptedKeys[clearKey] = encryptedKeyAndOwner.item1;
dataOwner = encryptedKeyAndOwner.item2 ?? dataOwner;
}
final newSecretIdsDelegations = newSecretIds.map((clearKey) =>
Delegation(owner: myId, delegatedTo: delegatedTo, key: encryptedKeys[clearKey]!)
);
final newEncryptionKeysDelegations = newEncryptionKeys.map((clearKey) =>
Delegation(owner: myId, delegatedTo: delegatedTo, key: encryptedKeys[clearKey]!)
);
if (patient.systemMetaData == null) {
patient.systemMetaData = SystemMetaDataOwnerEncrypted(delegations: {}, encryptionKeys: {});
}
final existingDelegationsForDelegate = patient.systemMetaData!.delegations[delegatedTo] ?? [];
patient.systemMetaData!.delegations[delegatedTo] = [...existingDelegationsForDelegate, ...newSecretIdsDelegations];
final existingEncryptionKeysForDelegate = patient.systemMetaData!.encryptionKeys[delegatedTo] ?? [];
patient.systemMetaData!.encryptionKeys[delegatedTo] = [...existingEncryptionKeysForDelegate, ...newEncryptionKeysDelegations];
if (dataOwner != null && dataOwner.dataOwnerId == patient.id) {
patient.rev = dataOwner.rev;
patient.systemMetaData!.hcPartyKeys = dataOwner.hcPartyKeys;
patient.systemMetaData!.aesExchangeKeys = dataOwner.aesExchangeKeys;
}
return (await createOrModifyPatient(patient)) ?? (throw StateError("Couldn't give access to $delegatedTo to patient ${patient.id}"));
}