@icure/api 8.0.0-RC.6 → 8.0.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 (212) hide show
  1. package/icc-api/api/IccAccesslogApi.d.ts +3 -7
  2. package/icc-api/api/IccAccesslogApi.js +2 -2
  3. package/icc-api/api/IccAccesslogApi.js.map +1 -1
  4. package/icc-api/api/IccAgendaApi.d.ts +1 -1
  5. package/icc-api/api/IccAgendaApi.js +2 -2
  6. package/icc-api/api/IccAgendaApi.js.map +1 -1
  7. package/icc-api/api/IccAnonymousAccessApi.d.ts +10 -0
  8. package/icc-api/api/IccAnonymousAccessApi.js +33 -0
  9. package/icc-api/api/IccAnonymousAccessApi.js.map +1 -1
  10. package/icc-api/api/IccApplicationsettingsApi.d.ts +1 -1
  11. package/icc-api/api/IccApplicationsettingsApi.js +2 -2
  12. package/icc-api/api/IccApplicationsettingsApi.js.map +1 -1
  13. package/icc-api/api/IccArticleApi.d.ts +1 -1
  14. package/icc-api/api/IccArticleApi.js +2 -2
  15. package/icc-api/api/IccArticleApi.js.map +1 -1
  16. package/icc-api/api/IccAuthApi.d.ts +4 -2
  17. package/icc-api/api/IccAuthApi.js +11 -4
  18. package/icc-api/api/IccAuthApi.js.map +1 -1
  19. package/icc-api/api/IccCalendarItemApi.d.ts +4 -12
  20. package/icc-api/api/IccCalendarItemApi.js +2 -2
  21. package/icc-api/api/IccCalendarItemApi.js.map +1 -1
  22. package/icc-api/api/IccCalendarItemTypeApi.d.ts +1 -1
  23. package/icc-api/api/IccCalendarItemTypeApi.js +2 -2
  24. package/icc-api/api/IccCalendarItemTypeApi.js.map +1 -1
  25. package/icc-api/api/IccClassificationApi.d.ts +4 -12
  26. package/icc-api/api/IccClassificationApi.js +2 -2
  27. package/icc-api/api/IccClassificationApi.js.map +1 -1
  28. package/icc-api/api/IccClassificationTemplateApi.d.ts +1 -1
  29. package/icc-api/api/IccClassificationTemplateApi.js +2 -2
  30. package/icc-api/api/IccClassificationTemplateApi.js.map +1 -1
  31. package/icc-api/api/IccCodeApi.d.ts +1 -1
  32. package/icc-api/api/IccCodeApi.js +2 -2
  33. package/icc-api/api/IccCodeApi.js.map +1 -1
  34. package/icc-api/api/IccContactApi.d.ts +3 -11
  35. package/icc-api/api/IccContactApi.js.map +1 -1
  36. package/icc-api/api/IccDataownerApi.d.ts +1 -1
  37. package/icc-api/api/IccDataownerApi.js +2 -2
  38. package/icc-api/api/IccDataownerApi.js.map +1 -1
  39. package/icc-api/api/IccDeviceApi.d.ts +1 -1
  40. package/icc-api/api/IccDeviceApi.js +2 -2
  41. package/icc-api/api/IccDeviceApi.js.map +1 -1
  42. package/icc-api/api/IccDoctemplateApi.d.ts +1 -1
  43. package/icc-api/api/IccDoctemplateApi.js +2 -2
  44. package/icc-api/api/IccDoctemplateApi.js.map +1 -1
  45. package/icc-api/api/IccDocumentApi.d.ts +3 -7
  46. package/icc-api/api/IccDocumentApi.js +2 -2
  47. package/icc-api/api/IccDocumentApi.js.map +1 -1
  48. package/icc-api/api/IccEntityrefApi.d.ts +1 -1
  49. package/icc-api/api/IccEntityrefApi.js +2 -2
  50. package/icc-api/api/IccEntityrefApi.js.map +1 -1
  51. package/icc-api/api/IccEntitytemplateApi.d.ts +1 -1
  52. package/icc-api/api/IccEntitytemplateApi.js +2 -2
  53. package/icc-api/api/IccEntitytemplateApi.js.map +1 -1
  54. package/icc-api/api/IccFormApi.d.ts +4 -12
  55. package/icc-api/api/IccFormApi.js +2 -2
  56. package/icc-api/api/IccFormApi.js.map +1 -1
  57. package/icc-api/api/IccFrontendmigrationApi.d.ts +1 -1
  58. package/icc-api/api/IccFrontendmigrationApi.js +2 -2
  59. package/icc-api/api/IccFrontendmigrationApi.js.map +1 -1
  60. package/icc-api/api/IccGroupApi.d.ts +1 -1
  61. package/icc-api/api/IccGroupApi.js +2 -2
  62. package/icc-api/api/IccGroupApi.js.map +1 -1
  63. package/icc-api/api/IccHcpartyApi.d.ts +1 -1
  64. package/icc-api/api/IccHcpartyApi.js +2 -2
  65. package/icc-api/api/IccHcpartyApi.js.map +1 -1
  66. package/icc-api/api/IccHelementApi.d.ts +4 -12
  67. package/icc-api/api/IccHelementApi.js +2 -2
  68. package/icc-api/api/IccHelementApi.js.map +1 -1
  69. package/icc-api/api/IccIcureApi.d.ts +1 -1
  70. package/icc-api/api/IccIcureApi.js +2 -2
  71. package/icc-api/api/IccIcureApi.js.map +1 -1
  72. package/icc-api/api/IccInsuranceApi.d.ts +1 -1
  73. package/icc-api/api/IccInsuranceApi.js +2 -2
  74. package/icc-api/api/IccInsuranceApi.js.map +1 -1
  75. package/icc-api/api/IccInvoiceApi.d.ts +4 -12
  76. package/icc-api/api/IccInvoiceApi.js +2 -2
  77. package/icc-api/api/IccInvoiceApi.js.map +1 -1
  78. package/icc-api/api/IccKeywordApi.d.ts +1 -1
  79. package/icc-api/api/IccKeywordApi.js +2 -2
  80. package/icc-api/api/IccKeywordApi.js.map +1 -1
  81. package/icc-api/api/IccMaintenanceTaskApi.d.ts +3 -7
  82. package/icc-api/api/IccMaintenanceTaskApi.js +2 -2
  83. package/icc-api/api/IccMaintenanceTaskApi.js.map +1 -1
  84. package/icc-api/api/IccMedexApi.d.ts +1 -1
  85. package/icc-api/api/IccMedexApi.js +2 -2
  86. package/icc-api/api/IccMedexApi.js.map +1 -1
  87. package/icc-api/api/IccMedicallocationApi.d.ts +1 -1
  88. package/icc-api/api/IccMedicallocationApi.js +2 -2
  89. package/icc-api/api/IccMedicallocationApi.js.map +1 -1
  90. package/icc-api/api/IccMessageApi.d.ts +3 -7
  91. package/icc-api/api/IccMessageApi.js +2 -2
  92. package/icc-api/api/IccMessageApi.js.map +1 -1
  93. package/icc-api/api/IccPatientApi.d.ts +3 -7
  94. package/icc-api/api/IccPatientApi.js +2 -2
  95. package/icc-api/api/IccPatientApi.js.map +1 -1
  96. package/icc-api/api/IccPermissionApi.d.ts +1 -1
  97. package/icc-api/api/IccPermissionApi.js +2 -2
  98. package/icc-api/api/IccPermissionApi.js.map +1 -1
  99. package/icc-api/api/IccPlaceApi.d.ts +1 -1
  100. package/icc-api/api/IccPlaceApi.js +2 -2
  101. package/icc-api/api/IccPlaceApi.js.map +1 -1
  102. package/icc-api/api/IccReceiptApi.d.ts +3 -7
  103. package/icc-api/api/IccReceiptApi.js +2 -2
  104. package/icc-api/api/IccReceiptApi.js.map +1 -1
  105. package/icc-api/api/IccReplicationApi.d.ts +1 -1
  106. package/icc-api/api/IccReplicationApi.js +2 -2
  107. package/icc-api/api/IccReplicationApi.js.map +1 -1
  108. package/icc-api/api/IccRoleApi.d.ts +1 -1
  109. package/icc-api/api/IccRoleApi.js +2 -2
  110. package/icc-api/api/IccRoleApi.js.map +1 -1
  111. package/icc-api/api/IccTarificationApi.d.ts +1 -1
  112. package/icc-api/api/IccTarificationApi.js +2 -2
  113. package/icc-api/api/IccTarificationApi.js.map +1 -1
  114. package/icc-api/api/IccTimeTableApi.d.ts +3 -7
  115. package/icc-api/api/IccTimeTableApi.js +2 -2
  116. package/icc-api/api/IccTimeTableApi.js.map +1 -1
  117. package/icc-api/api/IccTopicApi.d.ts +3 -7
  118. package/icc-api/api/IccTopicApi.js +2 -2
  119. package/icc-api/api/IccTopicApi.js.map +1 -1
  120. package/icc-api/api/IccUserApi.d.ts +16 -1
  121. package/icc-api/api/IccUserApi.js +46 -2
  122. package/icc-api/api/IccUserApi.js.map +1 -1
  123. package/icc-api/api/XHR.d.ts +1 -1
  124. package/icc-api/api/XHR.js +4 -3
  125. package/icc-api/api/XHR.js.map +1 -1
  126. package/icc-api/api/internal/IccExchangeDataMapApi.d.ts +0 -3
  127. package/icc-api/api/internal/IccExchangeDataMapApi.js +0 -31
  128. package/icc-api/api/internal/IccExchangeDataMapApi.js.map +1 -1
  129. package/icc-api/api/internal/IccSecureDelegationKeyMapApi.d.ts +2 -6
  130. package/icc-api/api/internal/IccSecureDelegationKeyMapApi.js.map +1 -1
  131. package/icc-api/model/MedicalLocation.d.ts +3 -0
  132. package/icc-api/model/MedicalLocation.js.map +1 -1
  133. package/icc-api/model/PaginatedListMedicalLocation.d.ts +20 -0
  134. package/icc-api/model/PaginatedListMedicalLocation.js +10 -0
  135. package/icc-api/model/PaginatedListMedicalLocation.js.map +1 -0
  136. package/icc-api/model/requests/BulkShareOrUpdateMetadataParams.d.ts +12 -0
  137. package/icc-api/model/requests/BulkShareOrUpdateMetadataParams.js +3 -0
  138. package/icc-api/model/requests/BulkShareOrUpdateMetadataParams.js.map +1 -0
  139. package/icc-x-api/auth/AuthService.d.ts +2 -1
  140. package/icc-x-api/auth/AuthService.js.map +1 -1
  141. package/icc-x-api/auth/AuthenticationProvider.d.ts +1 -1
  142. package/icc-x-api/auth/AuthenticationProvider.js +1 -1
  143. package/icc-x-api/auth/AuthenticationProvider.js.map +1 -1
  144. package/icc-x-api/auth/EnsembleAuthService.d.ts +1 -1
  145. package/icc-x-api/auth/EnsembleAuthService.js +2 -2
  146. package/icc-x-api/auth/EnsembleAuthService.js.map +1 -1
  147. package/icc-x-api/auth/JwtAuthService.d.ts +0 -2
  148. package/icc-x-api/auth/JwtAuthService.js +3 -15
  149. package/icc-x-api/auth/JwtAuthService.js.map +1 -1
  150. package/icc-x-api/auth/JwtBridgedAuthService.js +1 -1
  151. package/icc-x-api/auth/JwtBridgedAuthService.js.map +1 -1
  152. package/icc-x-api/auth/JwtUtils.d.ts +10 -0
  153. package/icc-x-api/auth/JwtUtils.js +31 -0
  154. package/icc-x-api/auth/JwtUtils.js.map +1 -0
  155. package/icc-x-api/auth/SmartAuthProvider.d.ts +132 -0
  156. package/icc-x-api/auth/SmartAuthProvider.js +419 -0
  157. package/icc-x-api/auth/SmartAuthProvider.js.map +1 -0
  158. package/icc-x-api/crypto/BaseExchangeDataManager.d.ts +20 -0
  159. package/icc-x-api/crypto/BaseExchangeDataManager.js +32 -2
  160. package/icc-x-api/crypto/BaseExchangeDataManager.js.map +1 -1
  161. package/icc-x-api/crypto/ConfidentialEntities.d.ts +2 -6
  162. package/icc-x-api/crypto/ConfidentialEntities.js.map +1 -1
  163. package/icc-x-api/crypto/CryptoStrategies.d.ts +3 -1
  164. package/icc-x-api/crypto/CryptoStrategies.js.map +1 -1
  165. package/icc-x-api/crypto/ExchangeDataManager.d.ts +3 -1
  166. package/icc-x-api/crypto/ExchangeDataManager.js +36 -22
  167. package/icc-x-api/crypto/ExchangeDataManager.js.map +1 -1
  168. package/icc-x-api/crypto/ExchangeDataMapManager.d.ts +0 -5
  169. package/icc-x-api/crypto/ExchangeDataMapManager.js +0 -11
  170. package/icc-x-api/crypto/ExchangeDataMapManager.js.map +1 -1
  171. package/icc-x-api/crypto/ExtendedApisUtils.d.ts +4 -16
  172. package/icc-x-api/crypto/ExtendedApisUtils.js.map +1 -1
  173. package/icc-x-api/crypto/ExtendedApisUtilsImpl.d.ts +4 -16
  174. package/icc-x-api/crypto/ExtendedApisUtilsImpl.js +12 -3
  175. package/icc-x-api/crypto/ExtendedApisUtilsImpl.js.map +1 -1
  176. package/icc-x-api/crypto/KeyPairRecoverer.d.ts +34 -0
  177. package/icc-x-api/crypto/KeyPairRecoverer.js +32 -0
  178. package/icc-x-api/crypto/KeyPairRecoverer.js.map +1 -0
  179. package/icc-x-api/crypto/RecoveryDataEncryption.d.ts +85 -0
  180. package/icc-x-api/crypto/RecoveryDataEncryption.js +171 -0
  181. package/icc-x-api/crypto/RecoveryDataEncryption.js.map +1 -0
  182. package/icc-x-api/crypto/SecureDelegationsManager.js +2 -2
  183. package/icc-x-api/crypto/SecureDelegationsManager.js.map +1 -1
  184. package/icc-x-api/crypto/ShamirKeysManager.js +1 -1
  185. package/icc-x-api/crypto/ShamirKeysManager.js.map +1 -1
  186. package/icc-x-api/crypto/UserEncryptionKeysManager.d.ts +4 -1
  187. package/icc-x-api/crypto/UserEncryptionKeysManager.js +4 -3
  188. package/icc-x-api/crypto/UserEncryptionKeysManager.js.map +1 -1
  189. package/icc-x-api/icc-bekmehr-x-api.d.ts +1 -0
  190. package/icc-x-api/icc-bekmehr-x-api.js +37 -36
  191. package/icc-x-api/icc-bekmehr-x-api.js.map +1 -1
  192. package/icc-x-api/icc-contact-x-api.js +15 -12
  193. package/icc-x-api/icc-contact-x-api.js.map +1 -1
  194. package/icc-x-api/icc-crypto-x-api.d.ts +1 -0
  195. package/icc-x-api/icc-crypto-x-api.js.map +1 -1
  196. package/icc-x-api/icc-maintenance-task-x-api.d.ts +1 -1
  197. package/icc-x-api/icc-maintenance-task-x-api.js.map +1 -1
  198. package/icc-x-api/icc-patient-x-api.d.ts +18 -0
  199. package/icc-x-api/icc-patient-x-api.js +29 -0
  200. package/icc-x-api/icc-patient-x-api.js.map +1 -1
  201. package/icc-x-api/icc-recovery-x-api.d.ts +127 -0
  202. package/icc-x-api/icc-recovery-x-api.js +217 -0
  203. package/icc-x-api/icc-recovery-x-api.js.map +1 -1
  204. package/icc-x-api/icc-user-x-api.js +15 -2
  205. package/icc-x-api/icc-user-x-api.js.map +1 -1
  206. package/icc-x-api/index.d.ts +46 -2
  207. package/icc-x-api/index.js +44 -11
  208. package/icc-x-api/index.js.map +1 -1
  209. package/icc-x-api/utils/collection-utils.d.ts +14 -1
  210. package/icc-x-api/utils/collection-utils.js +49 -3
  211. package/icc-x-api/utils/collection-utils.js.map +1 -1
  212. package/package.json +1 -1
@@ -1,2 +1,219 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.IccRecoveryXApi = exports.RecoveryDataUseFailureReason = void 0;
13
+ const utils_1 = require("./utils");
14
+ const RecoveryData_1 = require("../icc-api/model/internal/RecoveryData");
15
+ var RecoveryDataEncryption_1 = require("./crypto/RecoveryDataEncryption");
16
+ Object.defineProperty(exports, "RecoveryDataUseFailureReason", { enumerable: true, get: function () { return RecoveryDataEncryption_1.RecoveryDataUseFailureReason; } });
17
+ class IccRecoveryXApi {
18
+ constructor(baseRecoveryApi, recoveryDataEncryption, keyManager, dataOwnerApi, primitives, exchangeData) {
19
+ this.baseRecoveryApi = baseRecoveryApi;
20
+ this.recoveryDataEncryption = recoveryDataEncryption;
21
+ this.keyManager = keyManager;
22
+ this.dataOwnerApi = dataOwnerApi;
23
+ this.primitives = primitives;
24
+ this.exchangeData = exchangeData;
25
+ }
26
+ /**
27
+ * Create recovery data for the logged user and stores it encrypted on the iCure server. This allows the user that created
28
+ * it to recover all the currently available keypairs at a later time by just providing the string returned by this method to the
29
+ * {@link recoverKeyPairs} method.
30
+ *
31
+ * You can also provide an expiration time for the recovery data (through `options.lifetimeSeconds`). If you do so, the recovery dat
32
+ * a will be deleted automatically after that amount seconds has passed. If you don't provide an expiration time, the recovery data
33
+ * will be available until it is explicitly deleted.
34
+ *
35
+ * This could be used to:
36
+ * - Provide some sort of one-use "recovery codes" to the user, which he can use to recover his keypair if he loses
37
+ * his device. In this case you should not put any expiration time on the recovery data.
38
+ * - Provide a way for the user to easily "copy" the key from one device to another. In this case you should put a
39
+ * short expiration time on the recovery data (a few minutes), so that it will automatically be deleted if it is
40
+ * not used after all.
41
+ *
42
+ * # Important
43
+ *
44
+ * A malicious user that can login as the creator of the recovery data or that can access directly the database
45
+ * containing the recovery data will be able to get the private key of the data owner from the recovery key returned
46
+ * by this method. Therefore, the resulting recovery key must be kept secret, just like a private key.
47
+ *
48
+ * @param options optional parameters:
49
+ * - `includeParentsKeys` if true, the recovery data will also contain any available keypairs for parents data owners.
50
+ * - `lifetimeSeconds` the amount of seconds the recovery data will be available. If not provided, the recovery data will be available until it is
51
+ * explicitly deleted.
52
+ * @return an hexadecimal string that is the `recoveryKey` which will allow the user to recover his keypair later or
53
+ * from another device. This value must be kept secret from other users. You can use this value with {@link recoverKeyPairs}
54
+ */
55
+ createRecoveryInfoForAvailableKeyPairs(options = {}) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ const selfId = yield this.dataOwnerApi.getCurrentDataOwnerId();
58
+ const allAvailableKeys = yield this.keyManager.getCurrentUserHierarchyAvailableKeypairs();
59
+ let dataOwnersToInclude;
60
+ if (options.includeParentsKeys) {
61
+ dataOwnersToInclude = [allAvailableKeys.self, ...allAvailableKeys.parents];
62
+ }
63
+ else {
64
+ dataOwnersToInclude = [allAvailableKeys.self];
65
+ }
66
+ const keyPairsToSave = {};
67
+ for (const { dataOwnerId, keys } of dataOwnersToInclude) {
68
+ const dataOwner = yield this.dataOwnerApi.getDataOwner(dataOwnerId);
69
+ const sha1Keys = new Set(this.dataOwnerApi.getHexPublicKeysWithSha1Of(dataOwner.dataOwner));
70
+ const sha256Keys = new Set(this.dataOwnerApi.getHexPublicKeysWithSha256Of(dataOwner.dataOwner));
71
+ const pairs = [];
72
+ for (const { pair, verified } of keys) {
73
+ if (verified) {
74
+ const pubKeyHex = (0, utils_1.ua2hex)(yield this.primitives.RSA.exportKey(pair.publicKey, 'spki'));
75
+ if (sha256Keys.has(pubKeyHex)) {
76
+ pairs.push({ pair, algorithm: 'sha-256' });
77
+ }
78
+ else if (sha1Keys.has(pubKeyHex)) {
79
+ pairs.push({ pair, algorithm: 'sha-1' });
80
+ }
81
+ else {
82
+ console.warn(`Found stored key ${pubKeyHex} for data owner ${dataOwnerId} which is not saved in the data owner. Ignoring.`);
83
+ }
84
+ }
85
+ }
86
+ keyPairsToSave[dataOwnerId] = pairs;
87
+ }
88
+ return yield this.recoveryDataEncryption.createAndSaveKeyPairsRecoveryDataFor(selfId, keyPairsToSave, options.lifetimeSeconds);
89
+ });
90
+ }
91
+ /**
92
+ * Equivalent to {@link KeyPairRecoverer.recoverWithRecoveryKey}
93
+ */
94
+ recoverKeyPairs(recoveryKey, autoDelete) {
95
+ return this.recoveryDataEncryption.getAndDecryptKeyPairsRecoveryData(recoveryKey, autoDelete);
96
+ }
97
+ /**
98
+ * Create recovery data that allows the delegate {@link delegateId} recover the content of exchange data from the
99
+ * current data owner to the delegate.
100
+ *
101
+ * This can be useful in the following situations:
102
+ * - A user lost access to his old keypair and is asking for access back to his data. This is similar to the
103
+ * give-access-back mechanism, except that instead of having to verify the public key of the delegate as in the
104
+ * give-access-back, the delegator has to provide the recovery key to the delegate: the delegator has to properly
105
+ * identify the delegate instead of validating that the public key belongs to the delegate.
106
+ * - A patient is not yet registered in the system and therefore has no keypair, but the doctor wants to already share
107
+ * some data with them. The doctor can create some placeholder exchange data, encrypted only with his own key
108
+ * through the {@link IccPatientXApi.forceInitialiseExchangeDataToNewlyInvitedPatient} method, then create recovery data
109
+ * for it and share the recovery key with the patient. The moment the patient logs in and creates his keypair he
110
+ * will use the {@link recoverExchangeData} method to "complete" the placeholder exchange data.
111
+ *
112
+ * @param delegateId id of the delegate that needs access to his exchange data from the current data owner. This can't
113
+ * be the id of the current data owner (you should instead recover the keypair).
114
+ * @param options optional parameters:
115
+ * - `lifetimeSeconds` the amount of seconds the recovery data will be available. If not provided, the recovery data will be available until it is
116
+ * explicitly deleted.
117
+ * @return an hexadecimal string that is the `recoveryKey` which will allow the delegate to gain access to the exchange data.
118
+ * This value must be kept secret from users other than the current data owner and the delegate.
119
+ * You can use this value with {@link recoverExchangeData}
120
+ */
121
+ createExchangeDataRecoveryInfo(delegateId, options = {}) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ const exchangeDataToDelegate = yield this.exchangeData.base.getExchangeDataByDelegatorDelegatePair(yield this.dataOwnerApi.getCurrentDataOwnerId(), delegateId);
124
+ const decryptionKeys = this.keyManager.getDecryptionKeys();
125
+ const decryptedInformation = [];
126
+ for (const exchangeData of exchangeDataToDelegate) {
127
+ const decryptedData = yield this.exchangeData.base.tryRawDecryptExchangeData(exchangeData, decryptionKeys);
128
+ if (decryptedData !== undefined) {
129
+ decryptedInformation.push(Object.assign(Object.assign({}, decryptedData), { exchangeDataId: exchangeData.id }));
130
+ }
131
+ }
132
+ return this.recoveryDataEncryption.createAndSaveExchangeDataRecoveryData(delegateId, decryptedInformation, options.lifetimeSeconds);
133
+ });
134
+ }
135
+ /**
136
+ * Recover the content of exchange data from the delegator that created the recovery data at the provided.
137
+ * {@link recoveryKey} to the current delegate. This will enable the current user to access the exchange data with
138
+ * any of his private keys available on the device from which this method was called.
139
+ * The exchange data will be automatically deleted from the server after the process completes successfully.
140
+ *
141
+ * @param recoveryKey the result of a call to {@link createExchangeDataRecoveryInfo} by a delegator.
142
+ * @return null on success or a failure reason if the recovery data could not be used to perform the operation.
143
+ * @throws If the recovery data is valid but the process fails for other reasons.
144
+ */
145
+ recoverExchangeData(recoveryKey) {
146
+ return __awaiter(this, void 0, void 0, function* () {
147
+ const selfEncryptionKeys = Object.fromEntries(this.keyManager.getSelfVerifiedKeys().map((k) => [k.fingerprint, k.pair.publicKey]));
148
+ const recoveredExchangeData = yield this.recoveryDataEncryption.getAndDecryptExchangeDataRecoveryData(recoveryKey);
149
+ if ('failure' in recoveredExchangeData) {
150
+ return recoveredExchangeData.failure;
151
+ }
152
+ for (const exchangeDataInfo of recoveredExchangeData.success) {
153
+ const retrievedData = yield this.exchangeData.base.getExchangeDataById(exchangeDataInfo.exchangeDataId);
154
+ if (!retrievedData) {
155
+ console.warn(`Could not recover exchange data with id ${exchangeDataInfo.exchangeDataId} as it was not found. Ignoring`);
156
+ }
157
+ else {
158
+ yield this.exchangeData.base.updateExchangeDataWithRawDecryptedContent(retrievedData, selfEncryptionKeys, exchangeDataInfo.rawExchangeKey, exchangeDataInfo.rawAccessControlSecret, exchangeDataInfo.rawSharedSignatureKey);
159
+ }
160
+ }
161
+ yield this.baseRecoveryApi.deleteRecoveryData(yield this.recoveryDataEncryption.recoveryKeyToId(recoveryKey)).catch((e) => {
162
+ console.warn(`Could not delete recovery data with id ${recoveryKey} after successful recovery: ${e}. Ignoring.`);
163
+ });
164
+ yield this.exchangeData.clearOrRepopulateCache();
165
+ return null;
166
+ });
167
+ }
168
+ /**
169
+ * Deletes the recovery information associated to a certain recovery key. You can use this method with the recovery key for any kind of data,
170
+ * regardless of how you obtained the recovery key (from the {@link createRecoveryInfoForAvailableKeyPairs} or from the
171
+ * {@link createExchangeDataRecoveryInfo} methods).
172
+ * If there is no data associated to the provided recovery key, this method will do nothing.
173
+ * @param recoveryKey the recovery key associated to the recovery information to delete.
174
+ */
175
+ deleteRecoveryInfo(recoveryKey) {
176
+ return __awaiter(this, void 0, void 0, function* () {
177
+ yield this.baseRecoveryApi.deleteRecoveryData(yield this.recoveryDataEncryption.recoveryKeyToId(recoveryKey));
178
+ });
179
+ }
180
+ /**
181
+ * Deletes the recovery information associated to a certain data owner, regardless of type.
182
+ * @param dataOwnerId the data owner for which to delete the recovery data.
183
+ * @return the number of deleted recovery information.
184
+ */
185
+ deleteAllRecoveryInfoFor(dataOwnerId) {
186
+ return __awaiter(this, void 0, void 0, function* () {
187
+ return this.getCountFromDeleteAllRes(yield this.baseRecoveryApi.deleteAllRecoveryDataForRecipient(dataOwnerId));
188
+ });
189
+ }
190
+ /**
191
+ * Deletes all key pair recovery information for a certain data owner.
192
+ * @param dataOwnerId the data owner for which to delete the key pair recovery information.
193
+ * @return the number of deleted key pair recovery information.
194
+ */
195
+ deleteAllKeyPairRecoveryInfoFor(dataOwnerId) {
196
+ return __awaiter(this, void 0, void 0, function* () {
197
+ return this.getCountFromDeleteAllRes(yield this.baseRecoveryApi.deleteAllRecoveryDataOfTypeForRecipient(RecoveryData_1.RecoveryData.Type.KEYPAIR_RECOVERY, dataOwnerId));
198
+ });
199
+ }
200
+ /**
201
+ * Deletes all exchange data recovery information for a certain data owner.
202
+ * @param dataOwnerId the data owner for which to delete the exchange data recovery information.
203
+ * @return the number of deleted exchange data recovery information.
204
+ */
205
+ deleteAllExchangeDataRecoveryInfoFor(dataOwnerId) {
206
+ return __awaiter(this, void 0, void 0, function* () {
207
+ return this.getCountFromDeleteAllRes(yield this.baseRecoveryApi.deleteAllRecoveryDataOfTypeForRecipient(RecoveryData_1.RecoveryData.Type.EXCHANGE_KEY_RECOVERY, dataOwnerId));
208
+ });
209
+ }
210
+ getCountFromDeleteAllRes(deleteAllRes) {
211
+ return __awaiter(this, void 0, void 0, function* () {
212
+ if (deleteAllRes.numberValue !== undefined)
213
+ return deleteAllRes.numberValue;
214
+ throw new Error(`Unexpected result from delete method: ${JSON.stringify(deleteAllRes)}`);
215
+ });
216
+ }
217
+ }
218
+ exports.IccRecoveryXApi = IccRecoveryXApi;
2
219
  //# sourceMappingURL=icc-recovery-x-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"icc-recovery-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-recovery-x-api.ts"],"names":[],"mappings":"","sourcesContent":[""]}
1
+ {"version":3,"file":"icc-recovery-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-recovery-x-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyPair, ShaVersion } from './crypto/RSA'\nimport { RecoveryDataEncryption, RecoveryDataUseFailureReason } from './crypto/RecoveryDataEncryption'\nimport { IccRecoveryDataApi } from '../icc-api/api/internal/IccRecoveryDataApi'\nimport { UserEncryptionKeysManager } from './crypto/UserEncryptionKeysManager'\nimport { IccDataOwnerXApi } from './icc-data-owner-x-api'\nimport { CryptoPrimitives } from './crypto/CryptoPrimitives'\nimport { ua2hex } from './utils'\nimport { Content } from '../icc-api/model/Content'\nimport { RecoveryData } from '../icc-api/model/internal/RecoveryData'\nimport { ExchangeDataManager } from './crypto/ExchangeDataManager'\n\nexport { RecoveryDataUseFailureReason } from './crypto/RecoveryDataEncryption'\n\nexport class IccRecoveryXApi {\n constructor(\n private readonly baseRecoveryApi: IccRecoveryDataApi,\n private readonly recoveryDataEncryption: RecoveryDataEncryption,\n private readonly keyManager: UserEncryptionKeysManager,\n private readonly dataOwnerApi: IccDataOwnerXApi,\n private readonly primitives: CryptoPrimitives,\n private readonly exchangeData: ExchangeDataManager\n ) {}\n\n /**\n * Create recovery data for the logged user and stores it encrypted on the iCure server. This allows the user that created\n * it to recover all the currently available keypairs at a later time by just providing the string returned by this method to the\n * {@link recoverKeyPairs} method.\n *\n * You can also provide an expiration time for the recovery data (through `options.lifetimeSeconds`). If you do so, the recovery dat\n * a will be deleted automatically after that amount seconds has passed. If you don't provide an expiration time, the recovery data\n * will be available until it is explicitly deleted.\n *\n * This could be used to:\n * - Provide some sort of one-use \"recovery codes\" to the user, which he can use to recover his keypair if he loses\n * his device. In this case you should not put any expiration time on the recovery data.\n * - Provide a way for the user to easily \"copy\" the key from one device to another. In this case you should put a\n * short expiration time on the recovery data (a few minutes), so that it will automatically be deleted if it is\n * not used after all.\n *\n * # Important\n *\n * A malicious user that can login as the creator of the recovery data or that can access directly the database\n * containing the recovery data will be able to get the private key of the data owner from the recovery key returned\n * by this method. Therefore, the resulting recovery key must be kept secret, just like a private key.\n *\n * @param options optional parameters:\n * - `includeParentsKeys` if true, the recovery data will also contain any available keypairs for parents data owners.\n * - `lifetimeSeconds` the amount of seconds the recovery data will be available. If not provided, the recovery data will be available until it is\n * explicitly deleted.\n * @return an hexadecimal string that is the `recoveryKey` which will allow the user to recover his keypair later or\n * from another device. This value must be kept secret from other users. You can use this value with {@link recoverKeyPairs}\n */\n async createRecoveryInfoForAvailableKeyPairs(options: { includeParentsKeys?: boolean; lifetimeSeconds?: number } = {}): Promise<string> {\n const selfId = await this.dataOwnerApi.getCurrentDataOwnerId()\n const allAvailableKeys = await this.keyManager.getCurrentUserHierarchyAvailableKeypairs()\n let dataOwnersToInclude: { dataOwnerId: string; keys: { pair: KeyPair<CryptoKey>; verified: boolean }[] }[]\n if (options.includeParentsKeys) {\n dataOwnersToInclude = [allAvailableKeys.self, ...allAvailableKeys.parents]\n } else {\n dataOwnersToInclude = [allAvailableKeys.self]\n }\n const keyPairsToSave: { [delegateId: string]: { pair: KeyPair<CryptoKey>; algorithm: ShaVersion }[] } = {}\n for (const { dataOwnerId, keys } of dataOwnersToInclude) {\n const dataOwner = await this.dataOwnerApi.getDataOwner(dataOwnerId)\n const sha1Keys = new Set(this.dataOwnerApi.getHexPublicKeysWithSha1Of(dataOwner.dataOwner))\n const sha256Keys = new Set(this.dataOwnerApi.getHexPublicKeysWithSha256Of(dataOwner.dataOwner))\n const pairs: { pair: KeyPair<CryptoKey>; algorithm: ShaVersion }[] = []\n for (const { pair, verified } of keys) {\n if (verified) {\n const pubKeyHex = ua2hex(await this.primitives.RSA.exportKey(pair.publicKey, 'spki'))\n if (sha256Keys.has(pubKeyHex)) {\n pairs.push({ pair, algorithm: 'sha-256' })\n } else if (sha1Keys.has(pubKeyHex)) {\n pairs.push({ pair, algorithm: 'sha-1' })\n } else {\n console.warn(`Found stored key ${pubKeyHex} for data owner ${dataOwnerId} which is not saved in the data owner. Ignoring.`)\n }\n }\n }\n keyPairsToSave[dataOwnerId] = pairs\n }\n return await this.recoveryDataEncryption.createAndSaveKeyPairsRecoveryDataFor(selfId, keyPairsToSave, options.lifetimeSeconds)\n }\n\n /**\n * Equivalent to {@link KeyPairRecoverer.recoverWithRecoveryKey}\n */\n recoverKeyPairs(\n recoveryKey: string,\n autoDelete: boolean\n ): Promise<{ success: { [dataOwnerId: string]: { [publicKeySpki: string]: KeyPair<CryptoKey> } } } | { failure: RecoveryDataUseFailureReason }> {\n return this.recoveryDataEncryption.getAndDecryptKeyPairsRecoveryData(recoveryKey, autoDelete)\n }\n\n /**\n * Create recovery data that allows the delegate {@link delegateId} recover the content of exchange data from the\n * current data owner to the delegate.\n *\n * This can be useful in the following situations:\n * - A user lost access to his old keypair and is asking for access back to his data. This is similar to the\n * give-access-back mechanism, except that instead of having to verify the public key of the delegate as in the\n * give-access-back, the delegator has to provide the recovery key to the delegate: the delegator has to properly\n * identify the delegate instead of validating that the public key belongs to the delegate.\n * - A patient is not yet registered in the system and therefore has no keypair, but the doctor wants to already share\n * some data with them. The doctor can create some placeholder exchange data, encrypted only with his own key\n * through the {@link IccPatientXApi.forceInitialiseExchangeDataToNewlyInvitedPatient} method, then create recovery data\n * for it and share the recovery key with the patient. The moment the patient logs in and creates his keypair he\n * will use the {@link recoverExchangeData} method to \"complete\" the placeholder exchange data.\n *\n * @param delegateId id of the delegate that needs access to his exchange data from the current data owner. This can't\n * be the id of the current data owner (you should instead recover the keypair).\n * @param options optional parameters:\n * - `lifetimeSeconds` the amount of seconds the recovery data will be available. If not provided, the recovery data will be available until it is\n * explicitly deleted.\n * @return an hexadecimal string that is the `recoveryKey` which will allow the delegate to gain access to the exchange data.\n * This value must be kept secret from users other than the current data owner and the delegate.\n * You can use this value with {@link recoverExchangeData}\n */\n async createExchangeDataRecoveryInfo(delegateId: string, options: { lifetimeSeconds?: number } = {}): Promise<string> {\n const exchangeDataToDelegate = await this.exchangeData.base.getExchangeDataByDelegatorDelegatePair(\n await this.dataOwnerApi.getCurrentDataOwnerId(),\n delegateId\n )\n const decryptionKeys = this.keyManager.getDecryptionKeys()\n const decryptedInformation: {\n exchangeDataId: string\n rawExchangeKey: ArrayBuffer\n rawAccessControlSecret: ArrayBuffer\n rawSharedSignatureKey: ArrayBuffer\n }[] = []\n for (const exchangeData of exchangeDataToDelegate) {\n const decryptedData = await this.exchangeData.base.tryRawDecryptExchangeData(exchangeData, decryptionKeys)\n if (decryptedData !== undefined) {\n decryptedInformation.push({ ...decryptedData, exchangeDataId: exchangeData.id! })\n }\n }\n return this.recoveryDataEncryption.createAndSaveExchangeDataRecoveryData(delegateId, decryptedInformation, options.lifetimeSeconds)\n }\n\n /**\n * Recover the content of exchange data from the delegator that created the recovery data at the provided.\n * {@link recoveryKey} to the current delegate. This will enable the current user to access the exchange data with\n * any of his private keys available on the device from which this method was called.\n * The exchange data will be automatically deleted from the server after the process completes successfully.\n *\n * @param recoveryKey the result of a call to {@link createExchangeDataRecoveryInfo} by a delegator.\n * @return null on success or a failure reason if the recovery data could not be used to perform the operation.\n * @throws If the recovery data is valid but the process fails for other reasons.\n */\n async recoverExchangeData(recoveryKey: string): Promise<RecoveryDataUseFailureReason | null> {\n const selfEncryptionKeys = Object.fromEntries(this.keyManager.getSelfVerifiedKeys().map((k) => [k.fingerprint, k.pair.publicKey]))\n const recoveredExchangeData = await this.recoveryDataEncryption.getAndDecryptExchangeDataRecoveryData(recoveryKey)\n if ('failure' in recoveredExchangeData) {\n return recoveredExchangeData.failure\n }\n for (const exchangeDataInfo of recoveredExchangeData.success) {\n const retrievedData = await this.exchangeData.base.getExchangeDataById(exchangeDataInfo.exchangeDataId)\n if (!retrievedData) {\n console.warn(`Could not recover exchange data with id ${exchangeDataInfo.exchangeDataId} as it was not found. Ignoring`)\n } else {\n await this.exchangeData.base.updateExchangeDataWithRawDecryptedContent(\n retrievedData,\n selfEncryptionKeys,\n exchangeDataInfo.rawExchangeKey,\n exchangeDataInfo.rawAccessControlSecret,\n exchangeDataInfo.rawSharedSignatureKey\n )\n }\n }\n await this.baseRecoveryApi.deleteRecoveryData(await this.recoveryDataEncryption.recoveryKeyToId(recoveryKey)).catch((e) => {\n console.warn(`Could not delete recovery data with id ${recoveryKey} after successful recovery: ${e}. Ignoring.`)\n })\n await this.exchangeData.clearOrRepopulateCache()\n return null\n }\n\n /**\n * Deletes the recovery information associated to a certain recovery key. You can use this method with the recovery key for any kind of data,\n * regardless of how you obtained the recovery key (from the {@link createRecoveryInfoForAvailableKeyPairs} or from the\n * {@link createExchangeDataRecoveryInfo} methods).\n * If there is no data associated to the provided recovery key, this method will do nothing.\n * @param recoveryKey the recovery key associated to the recovery information to delete.\n */\n async deleteRecoveryInfo(recoveryKey: string): Promise<void> {\n await this.baseRecoveryApi.deleteRecoveryData(await this.recoveryDataEncryption.recoveryKeyToId(recoveryKey))\n }\n\n /**\n * Deletes the recovery information associated to a certain data owner, regardless of type.\n * @param dataOwnerId the data owner for which to delete the recovery data.\n * @return the number of deleted recovery information.\n */\n async deleteAllRecoveryInfoFor(dataOwnerId: string): Promise<number> {\n return this.getCountFromDeleteAllRes(await this.baseRecoveryApi.deleteAllRecoveryDataForRecipient(dataOwnerId))\n }\n\n /**\n * Deletes all key pair recovery information for a certain data owner.\n * @param dataOwnerId the data owner for which to delete the key pair recovery information.\n * @return the number of deleted key pair recovery information.\n */\n async deleteAllKeyPairRecoveryInfoFor(dataOwnerId: string): Promise<number> {\n return this.getCountFromDeleteAllRes(\n await this.baseRecoveryApi.deleteAllRecoveryDataOfTypeForRecipient(RecoveryData.Type.KEYPAIR_RECOVERY, dataOwnerId)\n )\n }\n\n /**\n * Deletes all exchange data recovery information for a certain data owner.\n * @param dataOwnerId the data owner for which to delete the exchange data recovery information.\n * @return the number of deleted exchange data recovery information.\n */\n async deleteAllExchangeDataRecoveryInfoFor(dataOwnerId: string): Promise<number> {\n return this.getCountFromDeleteAllRes(\n await this.baseRecoveryApi.deleteAllRecoveryDataOfTypeForRecipient(RecoveryData.Type.EXCHANGE_KEY_RECOVERY, dataOwnerId)\n )\n }\n\n private async getCountFromDeleteAllRes(deleteAllRes: Content): Promise<number> {\n if (deleteAllRes.numberValue !== undefined) return deleteAllRes.numberValue\n throw new Error(`Unexpected result from delete method: ${JSON.stringify(deleteAllRes)}`)\n }\n}\n"]}
@@ -14,6 +14,7 @@ const IccUserApi_1 = require("../icc-api/api/IccUserApi");
14
14
  const AuthenticationProvider_1 = require("./auth/AuthenticationProvider");
15
15
  const Connection_1 = require("../icc-api/model/Connection");
16
16
  const utils_1 = require("./utils");
17
+ const collection_utils_1 = require("./utils/collection-utils");
17
18
  class IccUserXApi extends IccUserApi_1.IccUserApi {
18
19
  constructor(host, headers, authenticationProvider = new AuthenticationProvider_1.NoAuthenticationProvider(), authApi, fetchImpl = typeof window !== 'undefined'
19
20
  ? window.fetch
@@ -33,12 +34,24 @@ class IccUserXApi extends IccUserApi_1.IccUserApi {
33
34
  }
34
35
  modifyUser(body) {
35
36
  const _super = Object.create(null, {
36
- modifyUser: { get: () => super.modifyUser }
37
+ modifyUser: { get: () => super.modifyUser },
38
+ getCurrentUser: { get: () => super.getCurrentUser }
37
39
  });
38
40
  return __awaiter(this, void 0, void 0, function* () {
41
+ //If we do not load the current user, we cannot know if the modification is on the current user
42
+ yield this.getCurrentUser();
39
43
  if (this.cachedCurrentUser && (yield this.cachedCurrentUser).id === (body === null || body === void 0 ? void 0 : body.id)) {
40
44
  try {
41
- const modifiedUser = yield _super.modifyUser.call(this, body);
45
+ const modifiedUser = yield _super.modifyUser.call(this, body).catch((e) => __awaiter(this, void 0, void 0, function* () {
46
+ //It is
47
+ if (e.statusCode === 409) {
48
+ let userInDb = yield _super.getCurrentUser.call(this);
49
+ if ((0, collection_utils_1.objectEquals)((yield this.cachedCurrentUser), userInDb, ['authenticationTokens', 'rev'])) {
50
+ return yield _super.modifyUser.call(this, Object.assign(Object.assign({}, body), { rev: userInDb.rev, authenticationTokens: userInDb.authenticationTokens }));
51
+ }
52
+ }
53
+ throw e;
54
+ }));
42
55
  this.cachedCurrentUser = Promise.resolve(modifiedUser);
43
56
  return modifiedUser;
44
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"icc-user-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-user-x-api.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,0DAAsD;AACtD,0EAAgG;AAGhG,4DAAwE;AACxE,mCAAsE;AAGtE,MAAa,WAAY,SAAQ,uBAAU;IAIzC,YACE,IAAY,EACZ,OAAkC,EAClC,yBAAiD,IAAI,iDAAwB,EAAE,EAC9D,OAAmB,EACpC,YAA2E,OAAO,MAAM,KAAK,WAAW;QACtG,CAAC,CAAC,MAAM,CAAC,KAAK;QACd,CAAC,CAAC,OAAO,IAAI,KAAK,WAAW;YAC7B,CAAC,CAAC,IAAI,CAAC,KAAK;YACZ,CAAC,CAAC,KAAK;QAET,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,sBAAsB,EAAE,SAAS,CAAC,CAAA;QAPtC,YAAO,GAAP,OAAO,CAAY;QAQpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC5B,CAAC;IAED,cAAc,CAAC,cAAuB,KAAK;;QACzC,IAAI,WAAW;YAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;;YACpE,OAAO,MAAA,IAAI,CAAC,iBAAiB,mCAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;IACzF,CAAC;IAEK,UAAU,CAAC,IAAW;;;;;YAC1B,IAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAK,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,EAAE,CAAA,EAAE;gBAC5E,IAAI;oBACF,MAAM,YAAY,GAAG,MAAM,OAAM,UAAU,YAAC,IAAI,CAAC,CAAA;oBACjD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;oBACtD,OAAO,YAAY,CAAA;iBACpB;gBAAC,OAAO,CAAC,EAAE;oBACV,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAA;oBAClC,MAAM,CAAC,CAAA;iBACR;aACF;;gBAAM,OAAO,OAAM,UAAU,YAAC,IAAI,EAAC;QACtC,CAAC;KAAA;IAEK,qBAAqB,CACzB,UAA8C,EAC9C,MAAwC,EACxC,UAAyC,EACzC,UAA+B,EAAE;;YAEjC,MAAM,EAAE,GAAG,MAAM,IAAA,+BAAuB,EAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;YAClH,OAAO,IAAI,2BAAc,CAAC,EAAE,CAAC,CAAA;QAC/B,CAAC;KAAA;CACF;AA9CD,kCA8CC","sourcesContent":["import { IccUserApi } from '../icc-api/api/IccUserApi'\nimport { AuthenticationProvider, NoAuthenticationProvider } from './auth/AuthenticationProvider'\nimport { AbstractFilter } from './filters/filters'\nimport { User } from '../icc-api/model/User'\nimport { Connection, ConnectionImpl } from '../icc-api/model/Connection'\nimport { subscribeToEntityEvents , SubscriptionOptions} from './utils'\nimport { IccAuthApi } from '../icc-api'\n\nexport class IccUserXApi extends IccUserApi {\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response>\n private cachedCurrentUser: Promise<User> | undefined\n\n constructor(\n host: string,\n headers: { [key: string]: string },\n authenticationProvider: AuthenticationProvider = new NoAuthenticationProvider(),\n private readonly authApi: IccAuthApi,\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response> = typeof window !== 'undefined'\n ? window.fetch\n : typeof self !== 'undefined'\n ? self.fetch\n : fetch\n ) {\n super(host, headers, authenticationProvider, fetchImpl)\n this.fetchImpl = fetchImpl\n }\n\n getCurrentUser(bypassCache: boolean = false): Promise<User> {\n if (bypassCache) return (this.cachedCurrentUser = super.getCurrentUser())\n else return this.cachedCurrentUser ?? (this.cachedCurrentUser = super.getCurrentUser())\n }\n\n async modifyUser(body?: User): Promise<User> {\n if (this.cachedCurrentUser && (await this.cachedCurrentUser).id === body?.id) {\n try {\n const modifiedUser = await super.modifyUser(body)\n this.cachedCurrentUser = Promise.resolve(modifiedUser)\n return modifiedUser\n } catch (e) {\n this.cachedCurrentUser = undefined\n throw e\n }\n } else return super.modifyUser(body)\n }\n\n async subscribeToUserEvents(\n eventTypes: ('CREATE' | 'UPDATE' | 'DELETE')[],\n filter: AbstractFilter<User> | undefined,\n eventFired: (user: User) => Promise<void>,\n options: SubscriptionOptions = {}\n ): Promise<Connection> {\n const rs = await subscribeToEntityEvents(this.host, this.authApi, 'User', eventTypes, filter, eventFired, options)\n return new ConnectionImpl(rs)\n }\n}\n"]}
1
+ {"version":3,"file":"icc-user-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-user-x-api.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,0DAAsD;AACtD,0EAAgG;AAGhG,4DAAwE;AACxE,mCAAsE;AAEtE,+DAAuD;AAEvD,MAAa,WAAY,SAAQ,uBAAU;IAIzC,YACE,IAAY,EACZ,OAAkC,EAClC,yBAAiD,IAAI,iDAAwB,EAAE,EAC9D,OAAmB,EACpC,YAA2E,OAAO,MAAM,KAAK,WAAW;QACtG,CAAC,CAAC,MAAM,CAAC,KAAK;QACd,CAAC,CAAC,OAAO,IAAI,KAAK,WAAW;YAC7B,CAAC,CAAC,IAAI,CAAC,KAAK;YACZ,CAAC,CAAC,KAAK;QAET,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,sBAAsB,EAAE,SAAS,CAAC,CAAA;QAPtC,YAAO,GAAP,OAAO,CAAY;QAQpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC5B,CAAC;IAED,cAAc,CAAC,cAAuB,KAAK;;QACzC,IAAI,WAAW;YAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;;YACpE,OAAO,MAAA,IAAI,CAAC,iBAAiB,mCAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;IACzF,CAAC;IAEK,UAAU,CAAC,IAAW;;;;;;YAC1B,+FAA+F;YAC/F,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;YAC3B,IAAI,IAAI,CAAC,iBAAiB,IAAI,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAK,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,EAAE,CAAA,EAAE;gBAC5E,IAAI;oBACF,MAAM,YAAY,GAAG,MAAM,OAAM,UAAU,YAAC,IAAI,EAAE,KAAK,CAAC,CAAO,CAAC,EAAE,EAAE;wBAClE,OAAO;wBACP,IAAI,CAAC,CAAC,UAAU,KAAK,GAAG,EAAE;4BACxB,IAAI,QAAQ,GAAG,MAAM,OAAM,cAAc,WAAE,CAAA;4BAC3C,IAAI,IAAA,+BAAY,EAAC,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAE,EAAE,QAAQ,EAAE,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC,EAAE;gCAC5F,OAAO,MAAM,OAAM,UAAU,4CAAM,IAAI,KAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,oBAAoB,EAAE,QAAQ,CAAC,oBAAoB,IAAG,CAAA;6BACnH;yBACF;wBACD,MAAM,CAAC,CAAA;oBACT,CAAC,CAAA,CAAC,CAAA;oBACF,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;oBACtD,OAAO,YAAY,CAAA;iBACpB;gBAAC,OAAO,CAAC,EAAE;oBACV,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAA;oBAClC,MAAM,CAAC,CAAA;iBACR;aACF;;gBAAM,OAAO,OAAM,UAAU,YAAC,IAAI,EAAC;QACtC,CAAC;KAAA;IAEK,qBAAqB,CACzB,UAA8C,EAC9C,MAAwC,EACxC,UAAyC,EACzC,UAA+B,EAAE;;YAEjC,MAAM,EAAE,GAAG,MAAM,IAAA,+BAAuB,EAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;YAClH,OAAO,IAAI,2BAAc,CAAC,EAAE,CAAC,CAAA;QAC/B,CAAC;KAAA;CACF;AAzDD,kCAyDC","sourcesContent":["import { IccUserApi } from '../icc-api/api/IccUserApi'\nimport { AuthenticationProvider, NoAuthenticationProvider } from './auth/AuthenticationProvider'\nimport { AbstractFilter } from './filters/filters'\nimport { User } from '../icc-api/model/User'\nimport { Connection, ConnectionImpl } from '../icc-api/model/Connection'\nimport { subscribeToEntityEvents, SubscriptionOptions } from './utils'\nimport { IccAuthApi } from '../icc-api'\nimport { objectEquals } from './utils/collection-utils'\n\nexport class IccUserXApi extends IccUserApi {\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response>\n private cachedCurrentUser: Promise<User> | undefined\n\n constructor(\n host: string,\n headers: { [key: string]: string },\n authenticationProvider: AuthenticationProvider = new NoAuthenticationProvider(),\n private readonly authApi: IccAuthApi,\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response> = typeof window !== 'undefined'\n ? window.fetch\n : typeof self !== 'undefined'\n ? self.fetch\n : fetch\n ) {\n super(host, headers, authenticationProvider, fetchImpl)\n this.fetchImpl = fetchImpl\n }\n\n getCurrentUser(bypassCache: boolean = false): Promise<User> {\n if (bypassCache) return (this.cachedCurrentUser = super.getCurrentUser())\n else return this.cachedCurrentUser ?? (this.cachedCurrentUser = super.getCurrentUser())\n }\n\n async modifyUser(body?: User): Promise<User> {\n //If we do not load the current user, we cannot know if the modification is on the current user\n await this.getCurrentUser()\n if (this.cachedCurrentUser && (await this.cachedCurrentUser).id === body?.id) {\n try {\n const modifiedUser = await super.modifyUser(body).catch(async (e) => {\n //It is\n if (e.statusCode === 409) {\n let userInDb = await super.getCurrentUser()\n if (objectEquals((await this.cachedCurrentUser)!, userInDb, ['authenticationTokens', 'rev'])) {\n return await super.modifyUser({ ...body, rev: userInDb.rev, authenticationTokens: userInDb.authenticationTokens })\n }\n }\n throw e\n })\n this.cachedCurrentUser = Promise.resolve(modifiedUser)\n return modifiedUser\n } catch (e) {\n this.cachedCurrentUser = undefined\n throw e\n }\n } else return super.modifyUser(body)\n }\n\n async subscribeToUserEvents(\n eventTypes: ('CREATE' | 'UPDATE' | 'DELETE')[],\n filter: AbstractFilter<User> | undefined,\n eventFired: (user: User) => Promise<void>,\n options: SubscriptionOptions = {}\n ): Promise<Connection> {\n const rs = await subscribeToEntityEvents(this.host, this.authApi, 'User', eventTypes, filter, eventFired, options)\n return new ConnectionImpl(rs)\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { IccAgendaApi, IccAnonymousAccessApi, IccApplicationsettingsApi, IccArticleApi, IccAuthApi, IccBeefactApi, IccBeresultexportApi, IccBeresultimportApi, IccBesamv2Api, IccCalendarItemTypeApi, IccClassificationTemplateApi, IccEntityrefApi, IccEntitytemplateApi, IccFrontendmigrationApi, IccGroupApi, IccIcureApi, IccInsuranceApi, IccKeywordApi, IccMedexApi, IccMedicallocationApi, IccPermissionApi, IccPlaceApi, IccPubsubApi, IccReplicationApi, IccTarificationApi, IccTmpApi } from '../icc-api';
1
+ import { IccAgendaApi, IccAnonymousAccessApi, IccApplicationsettingsApi, IccArticleApi, IccAuthApi, IccBeefactApi, IccBeresultexportApi, IccBeresultimportApi, IccBesamv2Api, IccCalendarItemTypeApi, IccClassificationTemplateApi, IccEntityrefApi, IccEntitytemplateApi, IccFrontendmigrationApi, IccGroupApi, IccIcureApi, IccInsuranceApi, IccKeywordApi, IccMedexApi, IccMedicallocationApi, IccPermissionApi, IccPlaceApi, IccPubsubApi, IccReplicationApi, IccTarificationApi, IccTmpApi, OAuthThirdParty } from '../icc-api';
2
2
  import { IccUserXApi } from './icc-user-x-api';
3
3
  import { IccCryptoXApi } from './icc-crypto-x-api';
4
4
  import { IccContactXApi } from './icc-contact-x-api';
@@ -29,6 +29,8 @@ import { IccDoctemplateXApi } from './icc-doctemplate-x-api';
29
29
  import { UserGroup } from '../icc-api/model/UserGroup';
30
30
  import { IccTopicXApi } from './icc-topic-x-api';
31
31
  import { IccRoleApi } from '../icc-api/api/IccRoleApi';
32
+ import { AuthSecretProvider } from './auth/SmartAuthProvider';
33
+ import { IccRecoveryXApi } from './icc-recovery-x-api';
32
34
  export * from './icc-accesslog-x-api';
33
35
  export * from './icc-bekmehr-x-api';
34
36
  export * from './icc-calendar-item-x-api';
@@ -113,6 +115,7 @@ export interface Apis extends BasicApis {
113
115
  readonly tmpApi: IccTmpApi;
114
116
  readonly topicApi: IccTopicXApi;
115
117
  readonly roleApi: IccRoleApi;
118
+ readonly recoveryApi: IccRecoveryXApi;
116
119
  }
117
120
  /**
118
121
  * Allows to customise the behaviour of the iCure API by providing various optional parameters.
@@ -352,6 +355,44 @@ export type AuthenticationDetails = {
352
355
  thirdPartyTokens: {
353
356
  [thirdParty: string]: string;
354
357
  };
358
+ } | SmartAuthenticationDetails;
359
+ /**
360
+ * Allows to perform authentication through an {@link AuthSecretProvider}.
361
+ *
362
+ * The iCure SDK can authenticate to the backend using different kinds of secrets, such as passwords, long-lived authentication tokens, and
363
+ * short-lived authentication tokens generated through the message gateway. iCure associates to each kind of secret a certain security level, and for
364
+ * some sensitive operations, depending on the configurations of the user and his group, some operations may require a secret of a certain security
365
+ * level. For example, with the default configurations, in order to change his own email the user can't have logged in with a long-lived token, but he
366
+ * needs to provide his current password or a short-lived token.
367
+ *
368
+ * By using this authentication option, the iCure SDK will automatically request and cache the secret from the {@link AuthSecretProvider} only when
369
+ * needed, which should help to minimise the interaction with the user.
370
+ *
371
+ * Another advantage of using this authentication option over others is that in case all the cached tokens and secrets were to expire while performing
372
+ * a request, instead of having the request fail the SDK will ask for a new secret from the {@link SmartAuthProvider} and the request will
373
+ * automatically be retried with the new secret.
374
+ *
375
+ * You must provide the following information:
376
+ * - username: any kind of value that can identify the user (userId, groupId/userId, username, email, ...). More generic identifiers, valid
377
+ * on multiple groups, allow for simpler group switching by using {@link IcureApi.switchGroup}.
378
+ * - secretProvider: the secret provider to use for authentication. Will handle interaction with the gui.
379
+ *
380
+ * You can also provide the following optional information, which may allow to reduce the requests for secrets initially:
381
+ * - initialSecret: an initial secret (password, token, ...) that will be used to get new authentication tokens as needed. If it is expired it will be ignored.
382
+ * - initialAuthToken: an initial authentication token used on each request. If it is expired it will be ignored.
383
+ * - initialRefreshToken: an initial refresh token used to get new authentication tokens as needed. If it is expired it will be ignored.
384
+ */
385
+ export type SmartAuthenticationDetails = {
386
+ username: string;
387
+ secretProvider: AuthSecretProvider;
388
+ initialSecret?: {
389
+ plainSecret: string;
390
+ } | {
391
+ oauthToken: string;
392
+ oauthType: OAuthThirdParty;
393
+ };
394
+ initialAuthToken?: string;
395
+ initialRefreshToken?: string;
355
396
  };
356
397
  /**
357
398
  * Main entry point for the iCure API. Provides entity-specific sub-apis and some general methods which are not related to a specific entity.
@@ -361,9 +402,12 @@ export interface IcureApi extends Apis {
361
402
  * Get the information on groups that the current user can access and the current group that this api instance is working on.
362
403
  * Note that the values you will get for `availableGroups` may differ from the values you would get if you call {@link IccUserApi.getMatchingUsers}
363
404
  * on {@link Apis.userApi}, since the latter is specialised on the specific instance of the user in `currentGroup`.
405
+ * - `currentGroup`: the group that this api instance is working on, or undefined if the backend environment is not multi-group.
406
+ * - `availableGroups`: the list of groups that the current user can access with the provided secret. Empty if the backend environment is not
407
+ * multi-group.
364
408
  */
365
409
  getGroupsInfo(): Promise<{
366
- currentGroup: UserGroup;
410
+ currentGroup: UserGroup | undefined;
367
411
  availableGroups: UserGroup[];
368
412
  }>;
369
413
  /**
@@ -79,6 +79,11 @@ const IccRoleApi_1 = require("../icc-api/api/IccRoleApi");
79
79
  const DataOwnerTypeEnum_1 = require("../icc-api/model/DataOwnerTypeEnum");
80
80
  const DelegationsDeAnonymization_1 = require("./crypto/DelegationsDeAnonymization");
81
81
  const JwtBridgedAuthService_1 = require("./auth/JwtBridgedAuthService");
82
+ const SmartAuthProvider_1 = require("./auth/SmartAuthProvider");
83
+ const KeyPairRecoverer_1 = require("./crypto/KeyPairRecoverer");
84
+ const IccRecoveryDataApi_1 = require("../icc-api/api/internal/IccRecoveryDataApi");
85
+ const RecoveryDataEncryption_1 = require("./crypto/RecoveryDataEncryption");
86
+ const icc_recovery_x_api_1 = require("./icc-recovery-x-api");
82
87
  __exportStar(require("./icc-accesslog-x-api"), exports);
83
88
  __exportStar(require("./icc-bekmehr-x-api"), exports);
84
89
  __exportStar(require("./icc-calendar-item-x-api"), exports);
@@ -156,17 +161,24 @@ var IcureApi;
156
161
  : typeof self !== 'undefined'
157
162
  ? self.fetch
158
163
  : fetch, options = {}) {
164
+ var _a;
159
165
  return __awaiter(this, void 0, void 0, function* () {
160
166
  const params = new IcureApiOptions.WithDefaults(options);
161
167
  let grouplessAuthenticationProvider = yield getAuthenticationProvider(host, authenticationOptions, params.headers, fetchImpl);
168
+ // TODO if this uses a smart auth provider the groupless auth provider does not share the secret cache with the group specific one.
162
169
  const grouplessUserApi = new icc_api_1.IccUserApi(host, params.headers, grouplessAuthenticationProvider, fetchImpl);
163
- const matches = yield grouplessUserApi.getMatchingUsers();
164
- const chosenGroupId = matches.length > 1 ? yield params.groupSelector(matches) : matches[0].groupId;
170
+ const matches = yield getMatchesOrEmpty(grouplessUserApi);
171
+ const chosenGroupId = matches.length > 1 && !!options.groupSelector ? yield options.groupSelector(matches) : (_a = matches[0]) === null || _a === void 0 ? void 0 : _a.groupId;
172
+ const groupSpecificAuthenticationProviderInfo = matches.length > 1 && chosenGroupId
173
+ ? yield grouplessAuthenticationProvider.switchGroup(chosenGroupId, matches)
174
+ : { switchedProvider: grouplessAuthenticationProvider, isGroupLocked: false };
165
175
  /*TODO
166
176
  * On new very new users switching the authentication provider to a specific group may fail and block the user for too many requests. This is
167
177
  * probably linked to replication of the user in the fallback database.
168
178
  */
169
- const groupSpecificAuthenticationProvider = matches.length > 1 ? yield grouplessAuthenticationProvider.switchGroup(chosenGroupId, matches) : grouplessAuthenticationProvider;
179
+ const groupSpecificAuthenticationProvider = matches.length > 1 && chosenGroupId
180
+ ? yield grouplessAuthenticationProvider.switchGroup(chosenGroupId, matches)
181
+ : grouplessAuthenticationProvider;
170
182
  const cryptoInitInfo = yield initialiseCryptoWithProvider(host, fetchImpl, groupSpecificAuthenticationProvider, params, cryptoStrategies, crypto);
171
183
  return new IcureApiImpl(cryptoInitInfo, host, groupSpecificAuthenticationProvider, fetch, grouplessUserApi, matches, matches.find((match) => match.groupId === chosenGroupId), params, cryptoStrategies);
172
184
  });
@@ -177,13 +189,7 @@ function getAuthenticationProvider(host, authenticationOptions, headers, fetchIm
177
189
  return __awaiter(this, void 0, void 0, function* () {
178
190
  let authenticationProvider;
179
191
  if ('getIcureTokens' in authenticationOptions && 'switchGroup' in authenticationOptions && 'getAuthService' in authenticationOptions) {
180
- const tokens = yield authenticationOptions.getIcureTokens();
181
- if (!!tokens && !!tokens.token && !!tokens.refreshToken) {
182
- authenticationProvider = new AuthenticationProvider_1.JwtAuthenticationProvider(new icc_api_1.IccAuthApi(host, headers, new AuthenticationProvider_1.NoAuthenticationProvider(), fetchImpl), undefined, undefined, undefined, tokens);
183
- }
184
- else {
185
- authenticationProvider = authenticationOptions;
186
- }
192
+ authenticationProvider = authenticationOptions;
187
193
  }
188
194
  else if ('icureTokens' in authenticationOptions && !!authenticationOptions.icureTokens) {
189
195
  authenticationProvider = new AuthenticationProvider_1.JwtAuthenticationProvider(new icc_api_1.IccAuthApi(host, headers, new AuthenticationProvider_1.NoAuthenticationProvider(), fetchImpl), undefined, undefined, undefined, authenticationOptions.icureTokens);
@@ -197,6 +203,13 @@ function getAuthenticationProvider(host, authenticationOptions, headers, fetchIm
197
203
  else if ('thirdPartyTokens' in authenticationOptions && !!authenticationOptions.thirdPartyTokens) {
198
204
  authenticationProvider = new AuthenticationProvider_1.JwtAuthenticationProvider(new icc_api_1.IccAuthApi(host, headers, new AuthenticationProvider_1.NoAuthenticationProvider(), fetchImpl), undefined, undefined, new JwtBridgedAuthService_1.JwtBridgedAuthService(new icc_api_1.IccAuthApi(host, headers, new AuthenticationProvider_1.NoAuthenticationProvider(), fetchImpl), undefined, undefined, authenticationOptions.thirdPartyTokens));
199
205
  }
206
+ else if ('username' in authenticationOptions && 'secretProvider' in authenticationOptions) {
207
+ authenticationProvider = SmartAuthProvider_1.SmartAuthProvider.initialise(new icc_api_1.IccAuthApi(host, headers, new AuthenticationProvider_1.NoAuthenticationProvider(), fetchImpl), authenticationOptions.username, authenticationOptions.secretProvider, {
208
+ initialSecret: authenticationOptions.initialSecret,
209
+ initialAuthToken: authenticationOptions.initialAuthToken,
210
+ initialRefreshToken: authenticationOptions.initialRefreshToken,
211
+ });
212
+ }
200
213
  else {
201
214
  throw new Error('Invalid authentication options provided');
202
215
  }
@@ -229,13 +242,16 @@ function initialiseCryptoWithProvider(host, fetchImpl, groupSpecificAuthenticati
229
242
  const basePatientApi = new icc_api_1.IccPatientApi(host, updatedHeaders, groupSpecificAuthenticationProvider, fetchImpl);
230
243
  const dataOwnerApi = new icc_data_owner_x_api_1.IccDataOwnerXApi(host, updatedHeaders, groupSpecificAuthenticationProvider, fetchImpl);
231
244
  const exchangeDataApi = new IccExchangeDataApi_1.IccExchangeDataApi(host, updatedHeaders, groupSpecificAuthenticationProvider, fetchImpl);
245
+ const baseRecoveryDataApi = new IccRecoveryDataApi_1.IccRecoveryDataApi(host, updatedHeaders, groupSpecificAuthenticationProvider, fetchImpl);
232
246
  // Crypto initialisation
233
247
  const icureStorage = new IcureStorageFacade_1.IcureStorageFacade(params.keyStorage, params.storage, params.entryKeysFactory);
234
248
  const cryptoPrimitives = new CryptoPrimitives_1.CryptoPrimitives(crypto);
235
249
  const baseExchangeKeysManager = new BaseExchangeKeysManager_1.BaseExchangeKeysManager(cryptoPrimitives, dataOwnerApi, healthcarePartyApi, basePatientApi, deviceApi);
236
250
  const baseExchangeDataManager = new BaseExchangeDataManager_1.BaseExchangeDataManager(exchangeDataApi, dataOwnerApi, cryptoPrimitives, dataOwnerRequiresAnonymousDelegation);
237
251
  const keyRecovery = new KeyRecovery_1.KeyRecovery(cryptoPrimitives, dataOwnerApi, baseExchangeKeysManager, baseExchangeDataManager);
238
- const userEncryptionKeysManager = new UserEncryptionKeysManager_1.UserEncryptionKeysManager(cryptoPrimitives, dataOwnerApi, icureStorage, keyRecovery, cryptoStrategies, !params.disableParentKeysInitialisation);
252
+ const recoveryDataEncryption = new RecoveryDataEncryption_1.RecoveryDataEncryption(cryptoPrimitives, baseRecoveryDataApi);
253
+ const keyPairRecoverer = new KeyPairRecoverer_1.KeyPairRecoverer(recoveryDataEncryption);
254
+ const userEncryptionKeysManager = new UserEncryptionKeysManager_1.UserEncryptionKeysManager(cryptoPrimitives, dataOwnerApi, icureStorage, keyRecovery, cryptoStrategies, !params.disableParentKeysInitialisation, keyPairRecoverer);
239
255
  const userSignatureKeysManager = new UserSignatureKeysManager_1.UserSignatureKeysManager(icureStorage, dataOwnerApi, cryptoPrimitives);
240
256
  const newKey = yield userEncryptionKeysManager.initialiseKeys();
241
257
  yield new TransferKeysManager_1.TransferKeysManager(cryptoPrimitives, baseExchangeDataManager, dataOwnerApi, userEncryptionKeysManager, userSignatureKeysManager, icureStorage).updateTransferKeys(yield dataOwnerApi.getCurrentDataOwnerStub());
@@ -268,6 +284,7 @@ function initialiseCryptoWithProvider(host, fetchImpl, groupSpecificAuthenticati
268
284
  icureMaintenanceTaskApi,
269
285
  headers: updatedHeaders,
270
286
  dataOwnerRequiresAnonymousDelegation,
287
+ recoveryApi: new icc_recovery_x_api_1.IccRecoveryXApi(baseRecoveryDataApi, recoveryDataEncryption, userEncryptionKeysManager, dataOwnerApi, cryptoPrimitives, exchangeDataManager),
271
288
  };
272
289
  });
273
290
  }
@@ -283,6 +300,9 @@ class IcureApiImpl {
283
300
  this.cryptoStrategies = cryptoStrategies;
284
301
  this.latestGroupsRequest = Promise.resolve(latestMatches);
285
302
  }
303
+ get recoveryApi() {
304
+ return this.cryptoInitInfos.recoveryApi;
305
+ }
286
306
  get authApi() {
287
307
  var _a;
288
308
  return ((_a = this._authApi) !== null && _a !== void 0 ? _a : (this._authApi = new icc_api_1.IccAuthApi(this.host, this.cryptoInitInfos.headers, this.groupSpecificAuthenticationProvider, this.fetch)));
@@ -529,4 +549,17 @@ const BasicApis = function (host, authenticationOptions, crypto = typeof window
529
549
  });
530
550
  };
531
551
  exports.BasicApis = BasicApis;
552
+ function getMatchesOrEmpty(userApi) {
553
+ return __awaiter(this, void 0, void 0, function* () {
554
+ try {
555
+ return yield userApi.getMatchingUsers();
556
+ }
557
+ catch (err) {
558
+ if (err instanceof Error && 'statusCode' in err && err.statusCode === 404)
559
+ return Promise.resolve([]);
560
+ else
561
+ return Promise.reject(err);
562
+ }
563
+ });
564
+ }
532
565
  //# sourceMappingURL=index.js.map