@icure/api 6.4.0 → 7.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/icc-api/api/IccDeviceApi.d.ts +1 -1
  2. package/icc-api/api/IccDeviceApi.js.map +1 -1
  3. package/icc-api/api/IccDoctemplateApi.js.map +1 -1
  4. package/icc-api/api/IccDocumentTemplateApi.js.map +1 -1
  5. package/icc-api/api/IccHcpartyApi.d.ts +1 -1
  6. package/icc-api/api/IccHcpartyApi.js.map +1 -1
  7. package/icc-api/api/IccPatientApi.d.ts +1 -1
  8. package/icc-api/api/IccPatientApi.js.map +1 -1
  9. package/icc-api/model/MaintenanceTask.d.ts +6 -5
  10. package/icc-api/model/MaintenanceTask.js +5 -0
  11. package/icc-api/model/MaintenanceTask.js.map +1 -1
  12. package/icc-api/model/User.d.ts +23 -1
  13. package/icc-api/model/User.js +21 -0
  14. package/icc-api/model/User.js.map +1 -1
  15. package/icc-api/model/models.d.ts +14 -0
  16. package/icc-api/model/models.js.map +1 -1
  17. package/icc-x-api/crypto/AES.d.ts +2 -0
  18. package/icc-x-api/crypto/AES.js +12 -0
  19. package/icc-x-api/crypto/AES.js.map +1 -1
  20. package/icc-x-api/crypto/BaseExchangeKeysManager.d.ts +122 -0
  21. package/icc-x-api/crypto/BaseExchangeKeysManager.js +356 -0
  22. package/icc-x-api/crypto/BaseExchangeKeysManager.js.map +1 -0
  23. package/icc-x-api/crypto/ConfidentialEntities.d.ts +58 -0
  24. package/icc-x-api/crypto/ConfidentialEntities.js +99 -0
  25. package/icc-x-api/crypto/ConfidentialEntities.js.map +1 -0
  26. package/icc-x-api/crypto/CryptoPrimitives.d.ts +31 -0
  27. package/icc-x-api/crypto/CryptoPrimitives.js +55 -0
  28. package/icc-x-api/crypto/CryptoPrimitives.js.map +1 -0
  29. package/icc-x-api/crypto/CryptoStrategies.d.ts +82 -0
  30. package/icc-x-api/crypto/CryptoStrategies.js +3 -0
  31. package/icc-x-api/crypto/CryptoStrategies.js.map +1 -0
  32. package/icc-x-api/crypto/EntitiesEncryption.d.ts +254 -0
  33. package/icc-x-api/crypto/EntitiesEncryption.js +700 -0
  34. package/icc-x-api/crypto/EntitiesEncryption.js.map +1 -0
  35. package/icc-x-api/crypto/ExchangeKeysManager.d.ts +56 -0
  36. package/icc-x-api/crypto/ExchangeKeysManager.js +147 -0
  37. package/icc-x-api/crypto/ExchangeKeysManager.js.map +1 -0
  38. package/icc-x-api/crypto/KeyManager.d.ts +103 -0
  39. package/icc-x-api/crypto/KeyManager.js +288 -0
  40. package/icc-x-api/crypto/KeyManager.js.map +1 -0
  41. package/icc-x-api/crypto/KeyRecovery.d.ts +34 -0
  42. package/icc-x-api/crypto/KeyRecovery.js +253 -0
  43. package/icc-x-api/crypto/KeyRecovery.js.map +1 -0
  44. package/icc-x-api/crypto/LegacyCryptoStrategies.d.ts +28 -0
  45. package/icc-x-api/crypto/LegacyCryptoStrategies.js +22 -0
  46. package/icc-x-api/crypto/LegacyCryptoStrategies.js.map +1 -0
  47. package/icc-x-api/crypto/RSA.d.ts +19 -20
  48. package/icc-x-api/crypto/RSA.js +30 -1
  49. package/icc-x-api/crypto/RSA.js.map +1 -1
  50. package/icc-x-api/crypto/ShamirKeysManager.d.ts +43 -0
  51. package/icc-x-api/crypto/ShamirKeysManager.js +150 -0
  52. package/icc-x-api/crypto/ShamirKeysManager.js.map +1 -0
  53. package/icc-x-api/crypto/ShareMetadataBehaviour.d.ts +19 -0
  54. package/icc-x-api/crypto/ShareMetadataBehaviour.js +24 -0
  55. package/icc-x-api/crypto/ShareMetadataBehaviour.js.map +1 -0
  56. package/icc-x-api/crypto/TransferKeysManager.d.ts +29 -0
  57. package/icc-x-api/crypto/TransferKeysManager.js +121 -0
  58. package/icc-x-api/crypto/TransferKeysManager.js.map +1 -0
  59. package/icc-x-api/crypto/utils.d.ts +46 -0
  60. package/icc-x-api/crypto/utils.js +128 -0
  61. package/icc-x-api/crypto/utils.js.map +1 -1
  62. package/icc-x-api/filters/ContactByHcPartyTagCodeDateFilter.d.ts +11 -0
  63. package/icc-x-api/filters/ContactByHcPartyTagCodeDateFilter.js +11 -0
  64. package/icc-x-api/filters/ContactByHcPartyTagCodeDateFilter.js.map +1 -1
  65. package/icc-x-api/filters/DeviceByHcPartyFilter.d.ts +11 -0
  66. package/icc-x-api/filters/DeviceByHcPartyFilter.js +11 -0
  67. package/icc-x-api/filters/DeviceByHcPartyFilter.js.map +1 -1
  68. package/icc-x-api/filters/DeviceByIdsFilter.d.ts +11 -0
  69. package/icc-x-api/filters/DeviceByIdsFilter.js +11 -0
  70. package/icc-x-api/filters/DeviceByIdsFilter.js.map +1 -1
  71. package/icc-x-api/filters/HealthElementByHcPartySecretForeignKeysFilter.d.ts +11 -0
  72. package/icc-x-api/filters/HealthElementByHcPartySecretForeignKeysFilter.js +11 -0
  73. package/icc-x-api/filters/HealthElementByHcPartySecretForeignKeysFilter.js.map +1 -1
  74. package/icc-x-api/icc-accesslog-x-api.d.ts +49 -4
  75. package/icc-x-api/icc-accesslog-x-api.js +112 -102
  76. package/icc-x-api/icc-accesslog-x-api.js.map +1 -1
  77. package/icc-x-api/icc-calendar-item-x-api.d.ts +53 -5
  78. package/icc-x-api/icc-calendar-item-x-api.js +112 -100
  79. package/icc-x-api/icc-calendar-item-x-api.js.map +1 -1
  80. package/icc-x-api/icc-classification-x-api.d.ts +45 -2
  81. package/icc-x-api/icc-classification-x-api.js +89 -41
  82. package/icc-x-api/icc-classification-x-api.js.map +1 -1
  83. package/icc-x-api/icc-contact-x-api.d.ts +57 -19
  84. package/icc-x-api/icc-contact-x-api.js +149 -154
  85. package/icc-x-api/icc-contact-x-api.js.map +1 -1
  86. package/icc-x-api/icc-crypto-x-api.d.ts +266 -366
  87. package/icc-x-api/icc-crypto-x-api.js +416 -1327
  88. package/icc-x-api/icc-crypto-x-api.js.map +1 -1
  89. package/icc-x-api/icc-data-owner-x-api.d.ts +110 -11
  90. package/icc-x-api/icc-data-owner-x-api.js +188 -14
  91. package/icc-x-api/icc-data-owner-x-api.js.map +1 -1
  92. package/icc-x-api/icc-doctemplate-x-api.js +3 -3
  93. package/icc-x-api/icc-doctemplate-x-api.js.map +1 -1
  94. package/icc-x-api/icc-document-x-api.d.ts +76 -5
  95. package/icc-x-api/icc-document-x-api.js +137 -59
  96. package/icc-x-api/icc-document-x-api.js.map +1 -1
  97. package/icc-x-api/icc-form-x-api.d.ts +47 -7
  98. package/icc-x-api/icc-form-x-api.js +85 -86
  99. package/icc-x-api/icc-form-x-api.js.map +1 -1
  100. package/icc-x-api/icc-hcparty-x-api.d.ts +1 -1
  101. package/icc-x-api/icc-hcparty-x-api.js +1 -1
  102. package/icc-x-api/icc-hcparty-x-api.js.map +1 -1
  103. package/icc-x-api/icc-helement-x-api.d.ts +50 -3
  104. package/icc-x-api/icc-helement-x-api.js +101 -118
  105. package/icc-x-api/icc-helement-x-api.js.map +1 -1
  106. package/icc-x-api/icc-icure-maintenance-x-api.d.ts +31 -0
  107. package/icc-x-api/icc-icure-maintenance-x-api.js +124 -0
  108. package/icc-x-api/icc-icure-maintenance-x-api.js.map +1 -0
  109. package/icc-x-api/icc-invoice-x-api.d.ts +45 -5
  110. package/icc-x-api/icc-invoice-x-api.js +89 -64
  111. package/icc-x-api/icc-invoice-x-api.js.map +1 -1
  112. package/icc-x-api/icc-maintenance-task-x-api.d.ts +38 -6
  113. package/icc-x-api/icc-maintenance-task-x-api.js +73 -102
  114. package/icc-x-api/icc-maintenance-task-x-api.js.map +1 -1
  115. package/icc-x-api/icc-message-x-api.d.ts +55 -2
  116. package/icc-x-api/icc-message-x-api.js +92 -33
  117. package/icc-x-api/icc-message-x-api.js.map +1 -1
  118. package/icc-x-api/icc-patient-x-api.d.ts +67 -7
  119. package/icc-x-api/icc-patient-x-api.js +409 -473
  120. package/icc-x-api/icc-patient-x-api.js.map +1 -1
  121. package/icc-x-api/icc-receipt-x-api.d.ts +49 -5
  122. package/icc-x-api/icc-receipt-x-api.js +85 -47
  123. package/icc-x-api/icc-receipt-x-api.js.map +1 -1
  124. package/icc-x-api/icc-time-table-x-api.d.ts +34 -10
  125. package/icc-x-api/icc-time-table-x-api.js +61 -18
  126. package/icc-x-api/icc-time-table-x-api.js.map +1 -1
  127. package/icc-x-api/index.d.ts +30 -1
  128. package/icc-x-api/index.js +112 -49
  129. package/icc-x-api/index.js.map +1 -1
  130. package/icc-x-api/maintenance/KeyPairUpdateRequest.d.ts +35 -0
  131. package/icc-x-api/maintenance/KeyPairUpdateRequest.js +54 -0
  132. package/icc-x-api/maintenance/KeyPairUpdateRequest.js.map +1 -0
  133. package/icc-x-api/storage/DefaultStorageEntryKeysFactory.d.ts +9 -0
  134. package/icc-x-api/storage/DefaultStorageEntryKeysFactory.js +23 -0
  135. package/icc-x-api/storage/DefaultStorageEntryKeysFactory.js.map +1 -0
  136. package/icc-x-api/storage/IcureStorageFacade.d.ts +55 -0
  137. package/icc-x-api/storage/IcureStorageFacade.js +95 -0
  138. package/icc-x-api/storage/IcureStorageFacade.js.map +1 -0
  139. package/icc-x-api/storage/StorageEntryKeysFactory.d.ts +31 -0
  140. package/icc-x-api/storage/StorageEntryKeysFactory.js +3 -0
  141. package/icc-x-api/storage/StorageEntryKeysFactory.js.map +1 -0
  142. package/icc-x-api/utils/collection-utils.d.ts +8 -0
  143. package/icc-x-api/utils/collection-utils.js +26 -0
  144. package/icc-x-api/utils/collection-utils.js.map +1 -0
  145. package/icc-x-api/utils/crypto-utils.d.ts +8 -1
  146. package/icc-x-api/utils/crypto-utils.js +19 -3
  147. package/icc-x-api/utils/crypto-utils.js.map +1 -1
  148. package/icc-x-api/utils/graph-utils.d.ts +45 -0
  149. package/icc-x-api/utils/graph-utils.js +203 -0
  150. package/icc-x-api/utils/graph-utils.js.map +1 -0
  151. package/icc-x-api/utils/lru-temporised-async-cache.d.ts +27 -0
  152. package/icc-x-api/utils/lru-temporised-async-cache.js +120 -0
  153. package/icc-x-api/utils/lru-temporised-async-cache.js.map +1 -0
  154. package/package.json +1 -1
@@ -31,79 +31,54 @@ class IccContactXApi extends icc_api_1.IccContactApi {
31
31
  this.crypto = crypto;
32
32
  this.dataOwnerApi = dataOwnerApi;
33
33
  }
34
- newInstance(user, patient, c, confidential = false, delegates = []) {
35
- const contact = new models.Contact(_.extend({
36
- id: this.crypto.randomUuid(),
37
- _type: 'org.taktik.icure.entities.Contact',
38
- created: new Date().getTime(),
39
- modified: new Date().getTime(),
40
- responsible: this.dataOwnerApi.getDataOwnerOf(user),
41
- author: user.id,
42
- codes: [],
43
- tags: [],
44
- groupId: this.crypto.randomUuid(),
45
- subContacts: [],
46
- services: [],
47
- openingDate: parseInt(moment().format('YYYYMMDDHHmmss')),
48
- }, c || {}));
49
- return this.initDelegationsAndEncryptionKeys(user, patient, contact, confidential, delegates);
50
- }
51
34
  /**
52
- * 1. Extract(decrypt) the patient's secretForeignKeys from the
53
- * "delegations" object.
54
- * 2. Initialize & encrypt the Contact's delegations & cryptedForeignKeys.
55
- * 3. Initialize & encrypt the Contact's encryptionKeys.
56
- * 4. Return the contact with the extended delegations, cryptedForeignKeys
57
- * & encryptionKeys.
35
+ * Creates a new instance of contact with initialised encryption metadata (not in the database).
36
+ * @param user the current user.
37
+ * @param patient the patient this contact refers to.
38
+ * @param c initialised data for the contact. Metadata such as id, creation data, etc. will be automatically initialised, but you can specify other
39
+ * kinds of data or overwrite generated metadata with this. You can't specify encryption metadata.
40
+ * @param options optional parameters:
41
+ * - additionalDelegates: delegates which will have access to the entity in addition to the current data owner and delegates from the
42
+ * auto-delegations. Must be an object which associates each data owner id with the access level to give to that data owner. May overlap with
43
+ * auto-delegations, in such case the access level specified here will be used. Currently only WRITE access is supported, but in future also read
44
+ * access will be possible.
45
+ * - preferredSfk: secret id of the patient to use as the secret foreign key to use for the classification. The default value will be a
46
+ * secret id of patient known by the topmost parent in the current data owner hierarchy.
47
+ * - confidential: if true, the entity will be created as confidential. Confidential entities are not shared with auto-delegations, and the default
48
+ * foreign key used is any key that is not shared with any of the data owner parents. By default entities are created as non-confidential.
49
+ * @return a new instance of contact.
58
50
  */
59
- initDelegationsAndEncryptionKeys(user, patient, contact, confidential = false, delegates = []) {
60
- const dataOwnerId = this.dataOwnerApi.getDataOwnerOf(user);
61
- return this.crypto.extractPreferredSfk(patient, dataOwnerId, confidential).then((key) => __awaiter(this, void 0, void 0, function* () {
62
- if (!key) {
63
- console.error(`SFK cannot be found for Contact ${key}. The contact will not be reachable from the patient side`);
64
- }
65
- const dels = yield this.crypto.initObjectDelegations(contact, patient, dataOwnerId, key !== null && key !== void 0 ? key : null);
66
- const eks = yield this.crypto.initEncryptionKeys(contact, dataOwnerId);
67
- _.extend(contact, {
68
- delegations: dels.delegations,
69
- cryptedForeignKeys: dels.cryptedForeignKeys,
70
- secretForeignKeys: dels.secretForeignKeys,
71
- encryptionKeys: eks.encryptionKeys,
72
- });
73
- let promise = Promise.resolve(contact);
74
- _.uniq(delegates.concat(user.autoDelegations ? (user.autoDelegations.all || []).concat(user.autoDelegations.medicalInformation || []) : [])).forEach((delegateId) => (promise = promise.then((contact) => this.crypto.addDelegationsAndEncryptionKeys(patient, contact, dataOwnerId, delegateId, dels.secretId, eks.secretId).catch((e) => {
75
- console.log(e);
76
- return contact;
77
- }))));
78
- (user.autoDelegations && user.autoDelegations.anonymousMedicalInformation ? user.autoDelegations.anonymousMedicalInformation : []).forEach((delegateId) => (promise = promise.then((contact) => this.crypto.addDelegationsAndEncryptionKeys(patient, contact, dataOwnerId, delegateId, null, eks.secretId).catch((e) => {
79
- console.log(e);
80
- return contact;
81
- }))));
82
- return promise;
83
- }));
84
- }
85
- initEncryptionKeys(user, ctc) {
86
- const dataOwnerId = this.dataOwnerApi.getDataOwnerOf(user);
87
- return this.crypto.initEncryptionKeys(ctc, dataOwnerId).then((eks) => {
88
- let promise = Promise.resolve(_.extend(ctc, {
89
- encryptionKeys: eks.encryptionKeys,
90
- }));
91
- (user.autoDelegations
92
- ? (user.autoDelegations.all || [])
93
- .concat(user.autoDelegations.medicalInformation || [])
94
- .concat(user.autoDelegations.anonymousMedicalInformation || [])
95
- : []).forEach((delegateId) => (promise = promise.then((contact) => this.crypto
96
- .appendEncryptionKeys(contact, dataOwnerId, delegateId, eks.secretId)
97
- .then((extraEks) => {
98
- return _.extend(extraEks.modifiedObject, {
99
- encryptionKeys: extraEks.encryptionKeys,
100
- });
101
- })
102
- .catch((e) => {
103
- console.log(e.message);
104
- return contact;
105
- }))));
106
- return promise;
51
+ newInstance(user, patient, c, options = {}) {
52
+ var _a, _b, _c, _d, _e, _f;
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ const contact = new models.Contact(_.extend({
55
+ id: this.crypto.primitives.randomUuid(),
56
+ _type: 'org.taktik.icure.entities.Contact',
57
+ created: new Date().getTime(),
58
+ modified: new Date().getTime(),
59
+ responsible: this.dataOwnerApi.getDataOwnerIdOf(user),
60
+ author: user.id,
61
+ codes: [],
62
+ tags: [],
63
+ groupId: this.crypto.primitives.randomUuid(),
64
+ subContacts: [],
65
+ services: [],
66
+ openingDate: parseInt(moment().format('YYYYMMDDHHmmss')),
67
+ }, c || {}));
68
+ const ownerId = this.dataOwnerApi.getDataOwnerIdOf(user);
69
+ if (ownerId !== (yield this.dataOwnerApi.getCurrentDataOwnerId()))
70
+ throw new Error('Can only initialise entities as current data owner.');
71
+ const sfk = (_a = options.preferredSfk) !== null && _a !== void 0 ? _a : (!!options.confidential
72
+ ? yield this.crypto.confidential.getConfidentialSecretId(patient)
73
+ : yield this.crypto.confidential.getAnySecretIdSharedWithParents(patient));
74
+ if (!sfk)
75
+ throw new Error(`Couldn't find any sfk of parent patient ${patient.id} for confidential=${!!options.confidential}`);
76
+ const extraDelegations = [
77
+ ...Object.keys((_b = options.additionalDelegates) !== null && _b !== void 0 ? _b : {}),
78
+ ...(options.confidential ? [] : [...((_d = (_c = user.autoDelegations) === null || _c === void 0 ? void 0 : _c.all) !== null && _d !== void 0 ? _d : []), ...((_f = (_e = user.autoDelegations) === null || _e === void 0 ? void 0 : _e.medicalInformation) !== null && _f !== void 0 ? _f : [])]),
79
+ ];
80
+ const initialisationInfo = yield this.crypto.entities.entityWithInitialisedEncryptedMetadata(contact, patient.id, sfk, true, extraDelegations);
81
+ return new models.Contact(initialisationInfo.updatedEntity);
107
82
  });
108
83
  }
109
84
  /**
@@ -123,33 +98,35 @@ class IccContactXApi extends icc_api_1.IccContactApi {
123
98
  * @param usingPost
124
99
  */
125
100
  findBy(hcpartyId, patient, usingPost = false) {
126
- return this.crypto.extractSFKsHierarchyFromDelegations(patient, hcpartyId).then((secretForeignKeys) => secretForeignKeys && secretForeignKeys.length > 0
127
- ? Promise.all(secretForeignKeys
128
- .reduce((acc, level) => {
129
- return acc.concat([
130
- {
131
- hcpartyId: level.hcpartyId,
132
- extractedKeys: level.extractedKeys.filter((key) => !acc.some((previousLevel) => previousLevel.extractedKeys.includes(key))),
133
- },
134
- ]);
135
- }, [])
136
- .filter((l) => l.extractedKeys.length > 0)
137
- .map(({ hcpartyId, extractedKeys }) => usingPost ?
138
- this.findByHCPartyPatientSecretFKeysArray(hcpartyId, _.uniq(extractedKeys)) :
139
- this.findByHCPartyPatientSecretFKeys(hcpartyId, _.uniq(extractedKeys).join(',')))).then((results) => _.uniqBy(_.flatMap(results), (x) => x.id))
140
- : Promise.resolve([]));
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ return yield this.crypto.entities.secretIdsForHcpHierarchyOf(patient).then((keysHierarchy) => keysHierarchy && keysHierarchy.length > 0
103
+ ? Promise.all(keysHierarchy
104
+ .reduce((acc, level) => {
105
+ return acc.concat([
106
+ {
107
+ hcpartyId: level.ownerId,
108
+ extractedKeys: level.extracted.filter((key) => !acc.some((previousLevel) => previousLevel.extractedKeys.includes(key))),
109
+ },
110
+ ]);
111
+ }, [])
112
+ .filter((l) => l.extractedKeys.length > 0)
113
+ .map(({ hcpartyId, extractedKeys }) => usingPost
114
+ ? this.findByHCPartyPatientSecretFKeysArray(hcpartyId, _.uniq(extractedKeys))
115
+ : this.findByHCPartyPatientSecretFKeys(hcpartyId, _.uniq(extractedKeys).join(',')))).then((results) => _.uniqBy(_.flatMap(results), (x) => x.id))
116
+ : Promise.resolve([]));
117
+ });
141
118
  }
142
119
  findByPatientSFKs(hcpartyId, patients) {
143
120
  return __awaiter(this, void 0, void 0, function* () {
144
121
  const perHcpId = {};
145
122
  for (const patient of patients) {
146
123
  ;
147
- (yield this.crypto.extractSFKsHierarchyFromDelegations(patient, hcpartyId))
124
+ (yield this.crypto.entities.secretIdsForHcpHierarchyOf(patient))
148
125
  .reduce((acc, level) => {
149
126
  return acc.concat([
150
127
  {
151
- hcpartyId: level.hcpartyId,
152
- extractedKeys: level.extractedKeys.filter((key) => !acc.some((previousLevel) => previousLevel.extractedKeys.includes(key))),
128
+ hcpartyId: level.ownerId,
129
+ extractedKeys: level.extracted.filter((key) => !acc.some((previousLevel) => previousLevel.extractedKeys.includes(key))),
153
130
  },
154
131
  ]);
155
132
  }, [])
@@ -218,36 +195,34 @@ class IccContactXApi extends icc_api_1.IccContactApi {
218
195
  var _a;
219
196
  return super
220
197
  .filterServicesBy(undefined, (_a = serviceIds.ids) === null || _a === void 0 ? void 0 : _a.length, new models_1.FilterChainService({ filter: new ServiceByIdsFilter_1.ServiceByIdsFilter({ ids: serviceIds.ids }) }))
221
- .then((paginatedList) => { var _a; return this.decryptServices(user.healthcarePartyId || user.patientId, (_a = paginatedList.rows) !== null && _a !== void 0 ? _a : [], undefined, undefined); });
198
+ .then((paginatedList) => { var _a; return this.decryptServices(user.healthcarePartyId || user.patientId, (_a = paginatedList.rows) !== null && _a !== void 0 ? _a : []); });
222
199
  }
223
200
  findByHCPartyFormIdWithUser(user, hcPartyId, formId) {
224
- return super.findByHCPartyFormId(hcPartyId, formId).then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), ctcs));
201
+ return super.findByHCPartyFormId(hcPartyId, formId).then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerIdOf(user), ctcs));
225
202
  }
226
203
  findByHCPartyFormIdsWithUser(user, hcPartyId, body) {
227
- return super.findByHCPartyFormIds(hcPartyId, body).then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), ctcs));
204
+ return super.findByHCPartyFormIds(hcPartyId, body).then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerIdOf(user), ctcs));
228
205
  }
229
206
  getContactWithUser(user, contactId) {
230
207
  return super
231
208
  .getContact(contactId)
232
- .then((ctc) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), [ctc]))
209
+ .then((ctc) => this.decrypt(this.dataOwnerApi.getDataOwnerIdOf(user), [ctc]))
233
210
  .then((ctcs) => ctcs[0]);
234
211
  }
235
212
  getContactsWithUser(user, body) {
236
- return super.getContacts(body).then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), ctcs));
213
+ return super.getContacts(body).then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerIdOf(user), ctcs));
237
214
  }
238
215
  modifyContactWithUser(user, body) {
239
- const _super = Object.create(null, {
240
- modifyContact: { get: () => super.modifyContact }
241
- });
242
216
  return __awaiter(this, void 0, void 0, function* () {
243
- return body
244
- ? this.encrypt(user, [_.cloneDeep(body)])
245
- .then((ctcs) => _super.modifyContact.call(this, ctcs[0]))
246
- .then((ctc) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), [ctc]))
247
- .then((ctcs) => ctcs[0])
248
- : null;
217
+ return body ? this.modifyAs(this.dataOwnerApi.getDataOwnerIdOf(user), body) : null;
249
218
  });
250
219
  }
220
+ modifyAs(dataOwner, contact) {
221
+ return this.encryptAs(dataOwner, [_.cloneDeep(contact)])
222
+ .then((ctcs) => super.modifyContact(ctcs[0]))
223
+ .then((ctc) => this.decrypt(dataOwner, [ctc]))
224
+ .then((ctcs) => ctcs[0]);
225
+ }
251
226
  modifyContactsWithUser(user, bodies) {
252
227
  const _super = Object.create(null, {
253
228
  modifyContacts: { get: () => super.modifyContacts }
@@ -256,7 +231,7 @@ class IccContactXApi extends icc_api_1.IccContactApi {
256
231
  return bodies
257
232
  ? this.encrypt(user, bodies.map((c) => _.cloneDeep(c)))
258
233
  .then((ctcs) => _super.modifyContacts.call(this, ctcs))
259
- .then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), ctcs))
234
+ .then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerIdOf(user), ctcs))
260
235
  : null;
261
236
  });
262
237
  }
@@ -268,7 +243,7 @@ class IccContactXApi extends icc_api_1.IccContactApi {
268
243
  return body
269
244
  ? this.encrypt(user, [_.cloneDeep(body)])
270
245
  .then((ctcs) => _super.createContact.call(this, ctcs[0]))
271
- .then((ctc) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), [ctc]))
246
+ .then((ctc) => this.decrypt(this.dataOwnerApi.getDataOwnerIdOf(user), [ctc]))
272
247
  .then((ctcs) => ctcs[0])
273
248
  : null;
274
249
  });
@@ -281,7 +256,7 @@ class IccContactXApi extends icc_api_1.IccContactApi {
281
256
  return bodies
282
257
  ? this.encrypt(user, bodies.map((c) => _.cloneDeep(c)))
283
258
  .then((ctcs) => _super.createContacts.call(this, ctcs))
284
- .then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerOf(user), ctcs))
259
+ .then((ctcs) => this.decrypt(this.dataOwnerApi.getDataOwnerIdOf(user), ctcs))
285
260
  : null;
286
261
  });
287
262
  }
@@ -309,99 +284,90 @@ class IccContactXApi extends icc_api_1.IccContactApi {
309
284
  }))));
310
285
  }
311
286
  else {
312
- svc.encryptedSelf = (0, binary_utils_1.b2a)((0, binary_utils_1.ua2string)(yield this.crypto.AES.encrypt(key, (0, binary_utils_1.utf8_2ua)(JSON.stringify({ content: svc.content })), rawKey)));
287
+ svc.encryptedSelf = (0, binary_utils_1.b2a)((0, binary_utils_1.ua2string)(yield this.crypto.primitives.AES.encrypt(key, (0, binary_utils_1.utf8_2ua)(JSON.stringify({ content: svc.content })), rawKey)));
313
288
  delete svc.content;
314
289
  }
315
290
  return svc;
316
291
  })));
317
292
  }
318
293
  encrypt(user, ctcs) {
319
- const hcpartyId = this.dataOwnerApi.getDataOwnerOf(user);
294
+ return this.encryptAs(this.dataOwnerApi.getDataOwnerIdOf(user), ctcs);
295
+ }
296
+ encryptAs(hcpartyId, ctcs) {
320
297
  const bypassEncryption = false; //Used for debug
321
298
  return Promise.all(ctcs.map((ctc) => __awaiter(this, void 0, void 0, function* () {
322
299
  const initialisedCtc = bypassEncryption //Prevent encryption for test ctc
323
300
  ? ctc
324
- : yield (ctc.encryptionKeys && Object.keys(ctc.encryptionKeys || {}).length ? Promise.resolve(ctc) : this.initEncryptionKeys(user, ctc));
325
- const sfks = yield this.crypto.extractKeysFromDelegationsForHcpHierarchy(hcpartyId, initialisedCtc.id, initialisedCtc.encryptionKeys);
326
- const rawKey = sfks.extractedKeys[0].replace(/-/g, '');
327
- const key = yield this.crypto.AES.importKey('raw', (0, binary_utils_1.hex2ua)(rawKey));
328
- initialisedCtc.services = yield this.encryptServices(key, rawKey, ctc.services || []);
329
- initialisedCtc.encryptedSelf = (0, binary_utils_1.b2a)((0, binary_utils_1.ua2string)(yield this.crypto.AES.encrypt(key, (0, binary_utils_1.utf8_2ua)(JSON.stringify({ descr: ctc.descr })), rawKey)));
301
+ : yield this.crypto.entities.ensureEncryptionKeysInitialised(ctc);
302
+ const encryptionKey = yield this.crypto.entities.importFirstValidKey(yield this.crypto.entities.encryptionKeysOf(ctc, hcpartyId), ctc.id);
303
+ initialisedCtc.services = yield this.encryptServices(encryptionKey.key, encryptionKey.raw, ctc.services || []);
304
+ initialisedCtc.encryptedSelf = (0, binary_utils_1.b2a)((0, binary_utils_1.ua2string)(yield this.crypto.primitives.AES.encrypt(encryptionKey.key, (0, binary_utils_1.utf8_2ua)(JSON.stringify({ descr: ctc.descr })), encryptionKey.raw)));
330
305
  delete initialisedCtc.descr;
331
306
  return initialisedCtc;
332
307
  })));
333
308
  }
334
309
  decrypt(hcpartyId, ctcs) {
335
310
  return Promise.all(ctcs.map((ctc) => __awaiter(this, void 0, void 0, function* () {
336
- const { extractedKeys: sfks } = yield this.crypto.extractKeysFromDelegationsForHcpHierarchy(hcpartyId, ctc.id, _.size(ctc.encryptionKeys) ? ctc.encryptionKeys : ctc.delegations);
337
- if (!sfks || !sfks.length) {
311
+ const keys = yield this.crypto.entities.importAllValidKeys(yield this.crypto.entities.encryptionKeysOf(ctc, hcpartyId));
312
+ if (!keys || !keys.length) {
338
313
  console.log('Cannot decrypt contact', ctc.id);
339
314
  return ctc;
340
315
  }
341
- const rawKey = sfks[0].replace(/-/g, '');
342
- const key = yield this.crypto.AES.importKey('raw', (0, binary_utils_1.hex2ua)(rawKey));
343
- ctc.services = yield this.decryptServices(hcpartyId, ctc.services || [], key, rawKey);
316
+ ctc.services = yield this.decryptServices(hcpartyId, ctc.services || [], keys);
344
317
  if (ctc.encryptedSelf) {
345
318
  try {
346
- const dec = yield this.crypto.AES.decrypt(key, (0, binary_utils_1.string2ua)((0, binary_utils_1.a2b)(ctc.encryptedSelf)), rawKey);
347
- let jsonContent;
348
- try {
349
- jsonContent = dec && (0, binary_utils_1.ua2utf8)(dec);
350
- jsonContent && _.assign(ctc, JSON.parse(jsonContent));
319
+ const json = yield this.crypto.entities.tryDecryptJson(keys, (0, binary_utils_1.string2ua)((0, binary_utils_1.a2b)(ctc.encryptedSelf)), false);
320
+ if (json) {
321
+ _.assign(ctc, json);
351
322
  }
352
- catch (e) {
353
- console.log('Cannot parse ctc', ctc.id, jsonContent || '<- Invalid encoding');
323
+ else {
324
+ console.log('Cannot decrypt ctc: no valid key could produce valid json', ctc.id);
354
325
  }
355
326
  }
356
- catch (_a) {
357
- console.log('Cannot decrypt contact', ctc.id);
327
+ catch (e) {
328
+ console.log('Failed to decrypt ctc', ctc.id, e);
358
329
  }
359
330
  }
360
331
  return ctc;
361
332
  })));
362
333
  }
363
- decryptServices(hcpartyId, svcs, key, rawKey) {
334
+ decryptServices(hcpartyId, svcs, keys) {
364
335
  return Promise.all(svcs.map((svc) => __awaiter(this, void 0, void 0, function* () {
365
- if (!key) {
366
- const { extractedKeys: sfks } = yield this.crypto.extractKeysFromDelegationsForHcpHierarchy(hcpartyId, svc.id, _.size(svc.encryptionKeys) ? svc.encryptionKeys : svc.delegations);
367
- key = yield this.crypto.AES.importKey('raw', (0, binary_utils_1.hex2ua)(sfks[0].replace(/-/g, '')));
336
+ if (!keys) {
337
+ keys = yield this.crypto.entities.importAllValidKeys(yield this.crypto.entities.encryptionKeysOf(svc, hcpartyId));
368
338
  }
369
339
  if (svc.encryptedContent) {
370
340
  try {
371
- const dec = yield this.crypto.AES.decrypt(key, (0, binary_utils_1.string2ua)((0, binary_utils_1.a2b)(svc.encryptedContent)));
372
- let jsonContent;
373
- try {
374
- jsonContent = (0, binary_utils_1.ua2utf8)((0, utils_1.truncateTrailingNulls)(new Uint8Array(dec)));
375
- Object.assign(svc, { content: JSON.parse(jsonContent) });
341
+ const json = yield this.crypto.entities.tryDecryptJson(keys, (0, binary_utils_1.string2ua)((0, binary_utils_1.a2b)(svc.encryptedContent)), true);
342
+ if (json) {
343
+ Object.assign(svc, { content: json });
376
344
  }
377
- catch (e) {
378
- console.log('Cannot parse service', svc.id, jsonContent || '<- Invalid encoding');
345
+ else {
346
+ console.log('Cannot decrypt service: no valid key could produce valid json', svc.id);
379
347
  }
380
348
  }
381
- catch (_a) {
382
- console.log('Cannot decrypt service', svc.id);
349
+ catch (e) {
350
+ console.log('Cannot decrypt service', svc.id, e);
383
351
  }
384
352
  }
385
353
  else if (svc.encryptedSelf) {
386
354
  try {
387
- const dec = yield this.crypto.AES.decrypt(key, (0, binary_utils_1.string2ua)((0, binary_utils_1.a2b)(svc.encryptedSelf)));
388
- let jsonContent;
389
- try {
390
- jsonContent = (0, binary_utils_1.ua2utf8)((0, utils_1.truncateTrailingNulls)(new Uint8Array(dec)));
391
- Object.assign(svc, JSON.parse(jsonContent));
355
+ const json = yield this.crypto.entities.tryDecryptJson(keys, (0, binary_utils_1.string2ua)((0, binary_utils_1.a2b)(svc.encryptedSelf)), true);
356
+ if (json) {
357
+ Object.assign(svc, json);
392
358
  }
393
- catch (e) {
394
- console.log('Cannot parse service', svc.id, jsonContent || '<- Invalid encoding');
359
+ else {
360
+ console.log('Cannot decrypt service: no valid key could produce valid json', svc.id);
395
361
  }
396
362
  }
397
- catch (_b) {
398
- console.log('Cannot decrypt service', svc.id);
363
+ catch (e) {
364
+ console.log('Cannot decrypt service', svc.id, e);
399
365
  }
400
366
  }
401
367
  else {
402
368
  svc.content = _.fromPairs(yield Promise.all(_.toPairs(svc.content).map((p) => __awaiter(this, void 0, void 0, function* () {
403
369
  if (p[1].compoundValue) {
404
- p[1].compoundValue = yield this.decryptServices(hcpartyId, p[1].compoundValue, key, rawKey);
370
+ p[1].compoundValue = yield this.decryptServices(hcpartyId, p[1].compoundValue, keys);
405
371
  }
406
372
  return p;
407
373
  }))));
@@ -509,7 +475,7 @@ class IccContactXApi extends icc_api_1.IccContactApi {
509
475
  const existing = ctc.services.find((s) => s.id === svc.id);
510
476
  const promoted = _.extend(_.extend(existing || {}, svc), {
511
477
  author: user.id,
512
- responsible: this.dataOwnerApi.getDataOwnerOf(user),
478
+ responsible: this.dataOwnerApi.getDataOwnerIdOf(user),
513
479
  modified: new Date().getTime(),
514
480
  });
515
481
  if (!existing) {
@@ -597,11 +563,11 @@ class IccContactXApi extends icc_api_1.IccContactApi {
597
563
  service() {
598
564
  return {
599
565
  newInstance: (user, s) => _.extend({
600
- id: this.crypto.randomUuid(),
566
+ id: this.crypto.primitives.randomUuid(),
601
567
  _type: 'org.taktik.icure.entities.embed.Service',
602
568
  created: new Date().getTime(),
603
569
  modified: new Date().getTime(),
604
- responsible: this.dataOwnerApi.getDataOwnerOf(user),
570
+ responsible: this.dataOwnerApi.getDataOwnerIdOf(user),
605
571
  author: user.id,
606
572
  codes: [],
607
573
  tags: [],
@@ -764,6 +730,35 @@ class IccContactXApi extends icc_api_1.IccContactApi {
764
730
  };
765
731
  return myself;
766
732
  }
733
+ /**
734
+ * @param contact a contact
735
+ * @return the id of the patient that the contact refers to, retrieved from the encrypted metadata. Normally there should only be one element
736
+ * in the returned array, but in case of entity merges there could be multiple values.
737
+ */
738
+ decryptPatientIdOf(contact) {
739
+ return __awaiter(this, void 0, void 0, function* () {
740
+ return this.crypto.entities.owningEntityIdsOf(contact, undefined);
741
+ });
742
+ }
743
+ /**
744
+ * Share an existing contact with other data owners, allowing them to access the non-encrypted data of the contact and optionally also
745
+ * the encrypted content.
746
+ * @param delegateId the id of the data owner which will be granted access to the contact.
747
+ * @param contact the contact to share.
748
+ * @param options optional parameters to customize the sharing behaviour:
749
+ * - shareEncryptionKey: specifies if the encryption key of the access log should be shared with the delegate, giving access to all encrypted
750
+ * content of the entity, excluding other encrypted metadata (defaults to {@link ShareMetadataBehaviour.IF_AVAILABLE}). Note that by default a
751
+ * contact does not have encrypted content.
752
+ * - sharePatientId: specifies if the id of the patient that this contact refers to should be shared with the delegate (defaults to
753
+ * {@link ShareMetadataBehaviour.IF_AVAILABLE}).
754
+ * @return a promise which will contain the updated contact.
755
+ */
756
+ shareWith(delegateId, contact, options = {}) {
757
+ return __awaiter(this, void 0, void 0, function* () {
758
+ const self = yield this.dataOwnerApi.getCurrentDataOwnerId();
759
+ return yield this.modifyAs(self, yield this.crypto.entities.entityWithAutoExtendedEncryptedMetadata(contact, delegateId, undefined, options.shareEncryptionKey, options.sharePatientId));
760
+ });
761
+ }
767
762
  }
768
763
  exports.IccContactXApi = IccContactXApi;
769
764
  //# sourceMappingURL=icc-contact-x-api.js.map