@icure/api 8.0.64 → 8.0.66

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 (131) hide show
  1. package/icc-api/api/internal/IccExchangeDataApi.d.ts +2 -0
  2. package/icc-api/api/internal/IccExchangeDataApi.js +10 -0
  3. package/icc-api/api/internal/IccExchangeDataApi.js.map +1 -1
  4. package/icc-api/iccApi.d.ts +0 -1
  5. package/icc-api/iccApi.js +0 -1
  6. package/icc-api/iccApi.js.map +1 -1
  7. package/icc-api/index.d.ts +0 -1
  8. package/icc-api/index.js +0 -1
  9. package/icc-api/index.js.map +1 -1
  10. package/icc-x-api/crypto/AccessControlSecretUtils.d.ts +4 -13
  11. package/icc-x-api/crypto/AccessControlSecretUtils.js +19 -29
  12. package/icc-x-api/crypto/AccessControlSecretUtils.js.map +1 -1
  13. package/icc-x-api/crypto/BaseExchangeDataManager.d.ts +8 -3
  14. package/icc-x-api/crypto/BaseExchangeDataManager.js +45 -10
  15. package/icc-x-api/crypto/BaseExchangeDataManager.js.map +1 -1
  16. package/icc-x-api/crypto/BaseExchangeKeysManager.d.ts +2 -3
  17. package/icc-x-api/crypto/BaseExchangeKeysManager.js +17 -20
  18. package/icc-x-api/crypto/BaseExchangeKeysManager.js.map +1 -1
  19. package/icc-x-api/crypto/CryptoPrimitives.d.ts +2 -0
  20. package/icc-x-api/crypto/CryptoPrimitives.js +3 -0
  21. package/icc-x-api/crypto/CryptoPrimitives.js.map +1 -1
  22. package/icc-x-api/crypto/DelegationsDeAnonymization.d.ts +3 -3
  23. package/icc-x-api/crypto/DelegationsDeAnonymization.js +7 -7
  24. package/icc-x-api/crypto/DelegationsDeAnonymization.js.map +1 -1
  25. package/icc-x-api/crypto/ExchangeDataManager.d.ts +19 -29
  26. package/icc-x-api/crypto/ExchangeDataManager.js +200 -225
  27. package/icc-x-api/crypto/ExchangeDataManager.js.map +1 -1
  28. package/icc-x-api/crypto/ExchangeDataMapManager.js +6 -4
  29. package/icc-x-api/crypto/ExchangeDataMapManager.js.map +1 -1
  30. package/icc-x-api/crypto/ExchangeKeysManager.d.ts +4 -16
  31. package/icc-x-api/crypto/ExchangeKeysManager.js +44 -41
  32. package/icc-x-api/crypto/ExchangeKeysManager.js.map +1 -1
  33. package/icc-x-api/crypto/ExtendedApisUtils.d.ts +47 -25
  34. package/icc-x-api/crypto/ExtendedApisUtils.js.map +1 -1
  35. package/icc-x-api/crypto/ExtendedApisUtilsImpl.d.ts +19 -18
  36. package/icc-x-api/crypto/ExtendedApisUtilsImpl.js +213 -134
  37. package/icc-x-api/crypto/ExtendedApisUtilsImpl.js.map +1 -1
  38. package/icc-x-api/crypto/HMACUtils.d.ts +2 -2
  39. package/icc-x-api/crypto/HMACUtils.js +3 -4
  40. package/icc-x-api/crypto/HMACUtils.js.map +1 -1
  41. package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.d.ts +1 -0
  42. package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.js +5 -0
  43. package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.js.map +1 -1
  44. package/icc-x-api/crypto/SecureDelegationsManager.d.ts +0 -1
  45. package/icc-x-api/crypto/SecureDelegationsManager.js +17 -49
  46. package/icc-x-api/crypto/SecureDelegationsManager.js.map +1 -1
  47. package/icc-x-api/crypto/SecurityMetadataDecryptor.d.ts +59 -90
  48. package/icc-x-api/crypto/SecurityMetadataDecryptor.js +470 -56
  49. package/icc-x-api/crypto/SecurityMetadataDecryptor.js.map +1 -1
  50. package/icc-x-api/crypto/ShamirKeysManager.js +1 -1
  51. package/icc-x-api/crypto/ShamirKeysManager.js.map +1 -1
  52. package/icc-x-api/crypto/TransferKeysManager.d.ts +1 -3
  53. package/icc-x-api/crypto/TransferKeysManager.js +2 -4
  54. package/icc-x-api/crypto/TransferKeysManager.js.map +1 -1
  55. package/icc-x-api/icc-accesslog-x-api.d.ts +2 -2
  56. package/icc-x-api/icc-accesslog-x-api.js +7 -3
  57. package/icc-x-api/icc-accesslog-x-api.js.map +1 -1
  58. package/icc-x-api/icc-calendar-item-x-api.js +4 -2
  59. package/icc-x-api/icc-calendar-item-x-api.js.map +1 -1
  60. package/icc-x-api/icc-contact-x-api.d.ts +0 -1
  61. package/icc-x-api/icc-contact-x-api.js +33 -48
  62. package/icc-x-api/icc-contact-x-api.js.map +1 -1
  63. package/icc-x-api/icc-crypto-x-api.js +1 -1
  64. package/icc-x-api/icc-crypto-x-api.js.map +1 -1
  65. package/icc-x-api/icc-document-x-api.d.ts +2 -2
  66. package/icc-x-api/icc-document-x-api.js +45 -42
  67. package/icc-x-api/icc-document-x-api.js.map +1 -1
  68. package/icc-x-api/icc-form-x-api.js +3 -1
  69. package/icc-x-api/icc-form-x-api.js.map +1 -1
  70. package/icc-x-api/icc-helement-x-api.js +4 -4
  71. package/icc-x-api/icc-helement-x-api.js.map +1 -1
  72. package/icc-x-api/icc-maintenance-task-x-api.js +4 -2
  73. package/icc-x-api/icc-maintenance-task-x-api.js.map +1 -1
  74. package/icc-x-api/icc-message-x-api.js +4 -2
  75. package/icc-x-api/icc-message-x-api.js.map +1 -1
  76. package/icc-x-api/icc-patient-x-api.js +5 -7
  77. package/icc-x-api/icc-patient-x-api.js.map +1 -1
  78. package/icc-x-api/icc-topic-x-api.js +2 -2
  79. package/icc-x-api/icc-topic-x-api.js.map +1 -1
  80. package/icc-x-api/index.d.ts +6 -2
  81. package/icc-x-api/index.js +16 -20
  82. package/icc-x-api/index.js.map +1 -1
  83. package/icc-x-api/utils/crypto-utils.d.ts +6 -4
  84. package/icc-x-api/utils/crypto-utils.js +27 -6
  85. package/icc-x-api/utils/crypto-utils.js.map +1 -1
  86. package/icc-x-api/utils/simple-lru-cache.d.ts +19 -0
  87. package/icc-x-api/utils/simple-lru-cache.js +90 -0
  88. package/icc-x-api/utils/simple-lru-cache.js.map +1 -0
  89. package/package.json +4 -2
  90. package/test/icc-x-api/crud/entities-crud-test-interface.js +0 -8
  91. package/test/icc-x-api/crud/entities-crud-test-interface.js.map +1 -1
  92. package/test/icc-x-api/crypto/exchange-data-manager-test.js +75 -93
  93. package/test/icc-x-api/crypto/exchange-data-manager-test.js.map +1 -1
  94. package/test/icc-x-api/crypto/legacy-metadata-migration-test.js.map +1 -1
  95. package/test/icc-x-api/crypto/secure-delegations-manager-test.js +28 -16
  96. package/test/icc-x-api/crypto/secure-delegations-manager-test.js.map +1 -1
  97. package/test/utils/FakeEncryptionKeysManager.d.ts +1 -0
  98. package/test/utils/FakeEncryptionKeysManager.js +11 -0
  99. package/test/utils/FakeEncryptionKeysManager.js.map +1 -1
  100. package/test/utils/FakeExchangeDataApi.d.ts +4 -2
  101. package/test/utils/FakeExchangeDataApi.js +24 -6
  102. package/test/utils/FakeExchangeDataApi.js.map +1 -1
  103. package/test/utils/FakeExchangeDataManager.d.ts +10 -10
  104. package/test/utils/FakeExchangeDataManager.js +12 -22
  105. package/test/utils/FakeExchangeDataManager.js.map +1 -1
  106. package/test/utils/TestApi.js +1 -0
  107. package/test/utils/TestApi.js.map +1 -1
  108. package/icc-api/api/IccArticleApi.d.ts +0 -72
  109. package/icc-api/api/IccArticleApi.js +0 -149
  110. package/icc-api/api/IccArticleApi.js.map +0 -1
  111. package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.d.ts +0 -33
  112. package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.js +0 -141
  113. package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.js.map +0 -1
  114. package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.d.ts +0 -46
  115. package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.js +0 -312
  116. package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.js.map +0 -1
  117. package/icc-x-api/crypto/UserSignatureKeysManager.d.ts +0 -26
  118. package/icc-x-api/crypto/UserSignatureKeysManager.js +0 -78
  119. package/icc-x-api/crypto/UserSignatureKeysManager.js.map +0 -1
  120. package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.d.ts +0 -1
  121. package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.js +0 -393
  122. package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.js.map +0 -1
  123. package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.d.ts +0 -1
  124. package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.js +0 -213
  125. package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.js.map +0 -1
  126. package/test/icc-x-api/crypto/signature-keys-manager-test.d.ts +0 -1
  127. package/test/icc-x-api/crypto/signature-keys-manager-test.js +0 -44
  128. package/test/icc-x-api/crypto/signature-keys-manager-test.js.map +0 -1
  129. package/test/utils/FakeSignatureKeysManager.d.ts +0 -16
  130. package/test/utils/FakeSignatureKeysManager.js +0 -54
  131. package/test/utils/FakeSignatureKeysManager.js.map +0 -1
@@ -8,72 +8,486 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
12
- var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
13
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
15
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
16
- function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
17
- function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
18
- function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
19
- function fulfill(value) { resume("next", value); }
20
- function reject(value) { resume("throw", value); }
21
- function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
22
- };
23
11
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.SecurityMetadataDecryptorChain = void 0;
25
- const SecureDelegation_1 = require("../../icc-api/model/SecureDelegation");
26
- var AccessLevelEnum = SecureDelegation_1.SecureDelegation.AccessLevelEnum;
27
- /**
28
- * @internal this class is meant for internal use only and may be changed without notice.
29
- * Security metadata decryptor which combines other existing decryptors.
30
- */
31
- class SecurityMetadataDecryptorChain {
32
- constructor(decryptors) {
33
- this.decryptors = decryptors;
34
- }
35
- decryptEncryptionKeysOf(typedEntity, dataOwnersHierarchySubset) {
36
- return this.concatenate((d) => d.decryptEncryptionKeysOf(typedEntity, dataOwnersHierarchySubset));
37
- }
38
- decryptOwningEntityIdsOf(typedEntity, dataOwnersHierarchySubset) {
39
- return this.concatenate((d) => d.decryptOwningEntityIdsOf(typedEntity, dataOwnersHierarchySubset));
40
- }
41
- decryptSecretIdsOf(typedEntity, dataOwnersHierarchySubset) {
42
- return this.concatenate((d) => d.decryptSecretIdsOf(typedEntity, dataOwnersHierarchySubset));
43
- }
44
- getEntityAccessLevel(typedEntity, dataOwnersHierarchySubset) {
12
+ exports.SecurityMetadataDecryptor = exports.SecurityMetadataType = void 0;
13
+ const utils_1 = require("../utils");
14
+ const models_1 = require("../../icc-api/model/models");
15
+ var AccessLevelEnum = models_1.SecureDelegation.AccessLevelEnum;
16
+ var SecurityMetadataType;
17
+ (function (SecurityMetadataType) {
18
+ SecurityMetadataType[SecurityMetadataType["SecretId"] = 1] = "SecretId";
19
+ SecurityMetadataType[SecurityMetadataType["EncryptionKey"] = 2] = "EncryptionKey";
20
+ SecurityMetadataType[SecurityMetadataType["OwningEntityId"] = 3] = "OwningEntityId";
21
+ })(SecurityMetadataType = exports.SecurityMetadataType || (exports.SecurityMetadataType = {}));
22
+ class SecurityMetadataDecryptor {
23
+ constructor(exchangeKeysManager, primitives, exchangeData, exchangeDataMap, secureDelegationsEncryption, dataOwnerApi) {
24
+ this.exchangeKeysManager = exchangeKeysManager;
25
+ this.primitives = primitives;
26
+ this.exchangeData = exchangeData;
27
+ this.exchangeDataMap = exchangeDataMap;
28
+ this.secureDelegationsEncryption = secureDelegationsEncryption;
29
+ this.dataOwnerApi = dataOwnerApi;
30
+ }
31
+ decryptLegacyDelegations(entities, dataOwnersHierarchySubset, metadataType) {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ // For legacy delegations there is no advantage in doing stuff in bulk.
34
+ const res = {};
35
+ for (const e of entities) {
36
+ const allDecrypted = yield this.extractFromLegacyDelegations(e, dataOwnersHierarchySubset, metadataType);
37
+ const deduplicatedDecrypted = new Set(allDecrypted.map((x) => x.decrypted));
38
+ res[e.id] = [...deduplicatedDecrypted];
39
+ }
40
+ return res;
41
+ });
42
+ }
43
+ extractFromLegacyDelegations(entity, dataOwnersHierarchySubset, metadataType) {
44
+ var _a, _b, _c;
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ if (!dataOwnersHierarchySubset.length)
47
+ throw new Error("`dataOwnersHierarchySubset` can't be empty");
48
+ let delegations;
49
+ let validateDecrypted = (x) => Promise.resolve(!!x);
50
+ let mapDecrypted = (x) => x;
51
+ switch (metadataType) {
52
+ case SecurityMetadataType.SecretId:
53
+ delegations = (_a = entity.delegations) !== null && _a !== void 0 ? _a : {};
54
+ break;
55
+ case SecurityMetadataType.EncryptionKey:
56
+ delegations = (_b = entity.encryptionKeys) !== null && _b !== void 0 ? _b : {};
57
+ validateDecrypted = (key) => __awaiter(this, void 0, void 0, function* () {
58
+ if (!/^[0-9A-Fa-f\-]+$/g.test(key))
59
+ return false;
60
+ try {
61
+ yield this.primitives.AES.importKey('raw', (0, utils_1.hex2ua)(key.replace(/-/g, '')));
62
+ return true;
63
+ }
64
+ catch (e) {
65
+ console.warn(`Could not import key ${key} as an encryption key.`, e);
66
+ return false;
67
+ }
68
+ });
69
+ mapDecrypted = (key) => key.replace(/-/g, '');
70
+ break;
71
+ case SecurityMetadataType.OwningEntityId:
72
+ delegations = (_c = entity.cryptedForeignKeys) !== null && _c !== void 0 ? _c : {};
73
+ break;
74
+ default:
75
+ throw new Error(`Internal error: invalid SecurityMetadataType ${metadataType}`);
76
+ }
77
+ const delegationsWithOwner = Object.entries(delegations).flatMap(([delegateId, delegations]) => dataOwnersHierarchySubset.some((dataOwnerId) => dataOwnerId === delegateId)
78
+ ? this.populateLegacyDelegationDelegate(delegateId, delegations)
79
+ : this.populateLegacyDelegationDelegate(delegateId, delegations.filter((d) => dataOwnersHierarchySubset.some((dataOwnerId) => d.owner === dataOwnerId))));
80
+ const res = [];
81
+ for (const delegation of delegationsWithOwner) {
82
+ const decrypted = yield this.tryDecryptLegacyDelegation(delegation, (k) => validateDecrypted(k));
83
+ if (decrypted)
84
+ res.push({
85
+ decrypted: mapDecrypted(decrypted),
86
+ dataOwnersWithAccess: delegation.owner ? [delegation.owner, delegation.delegatedTo] : [delegation.delegatedTo],
87
+ });
88
+ }
89
+ return res;
90
+ });
91
+ }
92
+ populateLegacyDelegationDelegate(delegateId, delegations) {
93
+ return delegations.map((d) => (d.delegatedTo === delegateId ? d : Object.assign(Object.assign({}, d), { delegatedTo: delegateId })));
94
+ }
95
+ tryDecryptLegacyDelegation(delegation, validateDecrypted) {
45
96
  return __awaiter(this, void 0, void 0, function* () {
46
- let currMaxLevel = undefined;
47
- for (const d of this.decryptors) {
48
- const currLevel = yield d.getEntityAccessLevel(typedEntity, dataOwnersHierarchySubset);
49
- if (currLevel === AccessLevelEnum.WRITE) {
50
- return currLevel;
97
+ const exchangeKeys = yield this.exchangeKeysManager.getDecryptionExchangeKeysFor(delegation.owner, delegation.delegatedTo);
98
+ for (const key of exchangeKeys) {
99
+ try {
100
+ // Format of encrypted key for any delegation should be entityId:key, but with the merging of entities the entityId might not match the
101
+ // current id. As a checksum we are only verifying that the decrypted bytes can be represented as a string with exactly one ':'.
102
+ // Additionally, we also have a validator that is specific for each type of delegation content (encryption key, secret id, ...)
103
+ const decrypted = (0, utils_1.ua2string)(yield this.primitives.AES.decrypt(key, (0, utils_1.hex2ua)(delegation.key)));
104
+ const decryptedSplit = decrypted.split(':');
105
+ if (decryptedSplit.length === 2) {
106
+ if (yield validateDecrypted(decryptedSplit[1]))
107
+ return decryptedSplit[1];
108
+ }
109
+ else {
110
+ console.warn("Error in the decrypted delegation: content should contain exactly 1 ':', the delegation is ignored.");
111
+ }
51
112
  }
52
- if (currLevel === AccessLevelEnum.READ) {
53
- currMaxLevel = AccessLevelEnum.READ;
113
+ catch (e) {
114
+ // Do nothing: the delegation uses another exchange key owner->delegator
54
115
  }
55
116
  }
56
- return currMaxLevel;
57
117
  });
58
118
  }
59
- hasAnyEncryptionKeys(entity) {
60
- return this.decryptors.some((d) => d.hasAnyEncryptionKeys(entity));
61
- }
62
- concatenate(getGenerator) {
63
- function generator(decryptors) {
64
- return __asyncGenerator(this, arguments, function* generator_1() {
65
- for (const d of decryptors) {
66
- const currGenerator = getGenerator(d);
67
- let next = yield __await(currGenerator.next());
68
- while (!next.done) {
69
- yield yield __await(next.value);
70
- next = yield __await(currGenerator.next());
119
+ decryptSecureDelegationsUsingCache(entities, dataOwnersHierarchySubset, metadataType) {
120
+ var _a, _b, _c, _d;
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ const toSearchById = new Set([]);
123
+ const toSearchByDelegationKey = new Set([]);
124
+ for (const e of entities) {
125
+ for (const [delegationKey, delegation] of Object.entries((_b = (_a = e.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {})) {
126
+ if (!delegation.delegator ||
127
+ !delegation.delegate ||
128
+ dataOwnersHierarchySubset.some((it) => it == delegation.delegator || it == delegation.delegate)) {
129
+ if (delegation.exchangeDataId) {
130
+ toSearchById.add(delegation.exchangeDataId);
131
+ }
132
+ else {
133
+ toSearchByDelegationKey.add(delegationKey);
134
+ }
71
135
  }
72
136
  }
73
- });
137
+ }
138
+ const cachedByExchangeDataId = yield this.exchangeData.getDecryptionDataKeyByIds([...toSearchById], false);
139
+ const cachedByDelegationKey = yield this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash([...toSearchByDelegationKey]);
140
+ const res = {};
141
+ for (const entity of entities) {
142
+ const currEntityRes = new Set([]);
143
+ for (const [delegationKey, delegation] of Object.entries((_d = (_c = entity.securityMetadata) === null || _c === void 0 ? void 0 : _c.secureDelegations) !== null && _d !== void 0 ? _d : {})) {
144
+ const cached = delegation.exchangeDataId ? cachedByExchangeDataId[delegation.exchangeDataId] : cachedByDelegationKey[delegationKey];
145
+ if ((cached === null || cached === void 0 ? void 0 : cached.exchangeKey) &&
146
+ dataOwnersHierarchySubset.some((it) => { var _a, _b; return it == ((_a = cached === null || cached === void 0 ? void 0 : cached.exchangeData) === null || _a === void 0 ? void 0 : _a.delegator) || it == ((_b = cached === null || cached === void 0 ? void 0 : cached.exchangeData) === null || _b === void 0 ? void 0 : _b.delegate); })) {
147
+ ;
148
+ (yield this.decryptSecureDelegationMetadata(delegation, metadataType, cached.exchangeKey)).forEach((decrypted) => currEntityRes.add(decrypted));
149
+ }
150
+ }
151
+ res[entity.id] = [...currEntityRes];
152
+ }
153
+ return res;
154
+ });
155
+ }
156
+ hasSecurityMetadataOfType(delegation, metadataType) {
157
+ var _a, _b, _c;
158
+ switch (metadataType) {
159
+ case SecurityMetadataType.SecretId:
160
+ return ((_a = delegation.secretIds) !== null && _a !== void 0 ? _a : []).length > 0;
161
+ case SecurityMetadataType.EncryptionKey:
162
+ return ((_b = delegation.encryptionKeys) !== null && _b !== void 0 ? _b : []).length > 0;
163
+ case SecurityMetadataType.OwningEntityId:
164
+ return ((_c = delegation.owningEntityIds) !== null && _c !== void 0 ? _c : []).length > 0;
165
+ default:
166
+ throw new Error('Internal error: invalid metadata type');
74
167
  }
75
- return generator(this.decryptors);
168
+ }
169
+ decryptSecureDelegationsUsingKnownExchangeData(entities, dataOwnersHierarchySubset, metadataType) {
170
+ var _a, _b, _c, _d;
171
+ return __awaiter(this, void 0, void 0, function* () {
172
+ const toSearchById = new Set([]);
173
+ for (const e of entities) {
174
+ for (const delegation of Object.values((_b = (_a = e.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {})) {
175
+ if (dataOwnersHierarchySubset.some((it) => it == delegation.delegator || it == delegation.delegate)) {
176
+ if (delegation.exchangeDataId && this.hasSecurityMetadataOfType(delegation, metadataType)) {
177
+ toSearchById.add(delegation.exchangeDataId);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ const retrievedByExchangeDataId = toSearchById.size > 0 ? yield this.exchangeData.getDecryptionDataKeyByIds([...toSearchById], true) : {};
183
+ const res = {};
184
+ for (const entity of entities) {
185
+ const currEntityRes = new Set([]);
186
+ for (const delegation of Object.values((_d = (_c = entity.securityMetadata) === null || _c === void 0 ? void 0 : _c.secureDelegations) !== null && _d !== void 0 ? _d : {})) {
187
+ const currDelegationExchangeData = delegation.exchangeDataId ? retrievedByExchangeDataId[delegation.exchangeDataId] : undefined;
188
+ if (currDelegationExchangeData === null || currDelegationExchangeData === void 0 ? void 0 : currDelegationExchangeData.exchangeKey) {
189
+ ;
190
+ (yield this.decryptSecureDelegationMetadata(delegation, metadataType, currDelegationExchangeData.exchangeKey)).forEach((decrypted) => currEntityRes.add(decrypted));
191
+ }
192
+ }
193
+ res[entity.id] = [...currEntityRes];
194
+ }
195
+ return res;
196
+ });
197
+ }
198
+ decryptSecureDelegationsUsingExchangeDataMap(entities, dataOwnersHierarchySubset, metadataType) {
199
+ var _a, _b, _c, _d;
200
+ return __awaiter(this, void 0, void 0, function* () {
201
+ const toSearchByExchangeDataMap = new Set([]);
202
+ for (const e of entities) {
203
+ for (const [delegationKey, delegation] of Object.entries((_b = (_a = e.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {})) {
204
+ if (dataOwnersHierarchySubset.some((it) => it == delegation.delegator || it == delegation.delegate)) {
205
+ if (!delegation.exchangeDataId && this.hasSecurityMetadataOfType(delegation, metadataType)) {
206
+ toSearchByExchangeDataMap.add(delegationKey);
207
+ }
208
+ }
209
+ }
210
+ }
211
+ const exchangeDataMaps = toSearchByExchangeDataMap.size > 0 ? yield this.exchangeDataMap.getExchangeDataMapBatch([...toSearchByExchangeDataMap]) : [];
212
+ const exchangeDataIdByDelegationKey = {};
213
+ for (const exchangeDataMap of exchangeDataMaps) {
214
+ const decrypted = yield this.secureDelegationsEncryption.decryptExchangeDataId(exchangeDataMap.encryptedExchangeDataIds);
215
+ if (decrypted) {
216
+ exchangeDataIdByDelegationKey[exchangeDataMap.id] = decrypted;
217
+ }
218
+ }
219
+ if (Object.keys(exchangeDataIdByDelegationKey).length == 0)
220
+ return {};
221
+ const retrievedByExchangeDataId = Object.values(exchangeDataIdByDelegationKey).length > 0
222
+ ? yield this.exchangeData.getDecryptionDataKeyByIds([...new Set(Object.values(exchangeDataIdByDelegationKey))], true)
223
+ : {};
224
+ const res = {};
225
+ for (const entity of entities) {
226
+ const currEntityRes = new Set([]);
227
+ for (const [delegationKey, delegation] of Object.entries((_d = (_c = entity.securityMetadata) === null || _c === void 0 ? void 0 : _c.secureDelegations) !== null && _d !== void 0 ? _d : {})) {
228
+ const exchangeDataId = exchangeDataIdByDelegationKey[delegationKey];
229
+ const cached = exchangeDataId ? retrievedByExchangeDataId[exchangeDataId] : undefined;
230
+ if (cached === null || cached === void 0 ? void 0 : cached.exchangeKey) {
231
+ ;
232
+ (yield this.decryptSecureDelegationMetadata(delegation, metadataType, cached.exchangeKey)).forEach((decrypted) => currEntityRes.add(decrypted));
233
+ }
234
+ }
235
+ res[entity.id] = [...currEntityRes];
236
+ }
237
+ return res;
238
+ });
239
+ }
240
+ decryptAll(entity, dataOwnersHierarchySubset, metadataType) {
241
+ return __awaiter(this, void 0, void 0, function* () {
242
+ const allExtractedWithDataOwners = [
243
+ ...(yield this.decryptAllLegacyDelegations(entity, dataOwnersHierarchySubset, metadataType)),
244
+ ...(yield this.decryptAllSecureDelegations(entity, dataOwnersHierarchySubset, metadataType)),
245
+ ];
246
+ return dataOwnersHierarchySubset.map((dataOwner) => {
247
+ const decryptedEntriesForDataOwner = allExtractedWithDataOwners
248
+ .filter((x) => x.dataOwnersWithAccess.some((d) => dataOwner == d))
249
+ .map((x) => x.decrypted);
250
+ return {
251
+ ownerId: dataOwner,
252
+ extracted: [...new Set(decryptedEntriesForDataOwner)],
253
+ };
254
+ });
255
+ });
256
+ }
257
+ decryptAllLegacyDelegations(entity, dataOwnersHierarchySubset, metadataType) {
258
+ return __awaiter(this, void 0, void 0, function* () {
259
+ return this.extractFromLegacyDelegations(entity, dataOwnersHierarchySubset, metadataType);
260
+ });
261
+ }
262
+ decryptAllSecureDelegations(entity, dataOwnersHierarchySubset, metadataType) {
263
+ var _a, _b;
264
+ return __awaiter(this, void 0, void 0, function* () {
265
+ const secureDelegationEntries = Object.entries((_b = (_a = entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {});
266
+ const toSearchByDelegationKey = secureDelegationEntries.flatMap(([delegationKey, delegation]) => {
267
+ if (!delegation.exchangeDataId) {
268
+ return [delegationKey];
269
+ }
270
+ else {
271
+ return [];
272
+ }
273
+ });
274
+ const exchangeDataByDelegationKey = yield this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash(toSearchByDelegationKey);
275
+ const toSearchWithExchangeDataMap = secureDelegationEntries.flatMap(([delegationKey, delegation]) => {
276
+ if (!delegation.exchangeDataId &&
277
+ dataOwnersHierarchySubset.some((it) => delegation.delegate == it || delegation.delegator == it) &&
278
+ !exchangeDataByDelegationKey[delegationKey] &&
279
+ this.hasSecurityMetadataOfType(delegation, metadataType)) {
280
+ return [delegationKey];
281
+ }
282
+ else {
283
+ return [];
284
+ }
285
+ });
286
+ const exchangeDataMaps = toSearchWithExchangeDataMap.length > 0 ? yield this.exchangeDataMap.getExchangeDataMapBatch(toSearchWithExchangeDataMap) : [];
287
+ const exchangeDataIdByDelegationKey = {};
288
+ for (const exchangeDataMap of exchangeDataMaps) {
289
+ const decrypted = yield this.secureDelegationsEncryption.decryptExchangeDataId(exchangeDataMap.encryptedExchangeDataIds);
290
+ if (decrypted) {
291
+ exchangeDataIdByDelegationKey[exchangeDataMap.id] = decrypted;
292
+ }
293
+ }
294
+ const toSearchDirectlyById = secureDelegationEntries.flatMap(([delegationKey, delegation]) => {
295
+ if (delegation.exchangeDataId &&
296
+ dataOwnersHierarchySubset.some((it) => delegation.delegate == it || delegation.delegator == it) &&
297
+ !exchangeDataByDelegationKey[delegationKey] &&
298
+ this.hasSecurityMetadataOfType(delegation, metadataType)) {
299
+ return [delegation.exchangeDataId];
300
+ }
301
+ else {
302
+ return [];
303
+ }
304
+ });
305
+ const allExchangeDataIdToRetrieve = [...new Set([...toSearchDirectlyById, ...Object.values(exchangeDataIdByDelegationKey)])];
306
+ const exchangeDataById = allExchangeDataIdToRetrieve.length > 0 ? yield this.exchangeData.getDecryptionDataKeyByIds(allExchangeDataIdToRetrieve, true) : {};
307
+ const allExtractedWithDataOwners = [];
308
+ for (const [delegationKey, delegation] of secureDelegationEntries) {
309
+ let exchangeData = undefined;
310
+ if (exchangeDataByDelegationKey[delegationKey]) {
311
+ exchangeData = exchangeDataByDelegationKey[delegationKey];
312
+ }
313
+ else if (delegation.exchangeDataId) {
314
+ exchangeData = exchangeDataById[delegation.exchangeDataId];
315
+ }
316
+ else if (exchangeDataIdByDelegationKey[delegationKey]) {
317
+ exchangeData = exchangeDataById[exchangeDataIdByDelegationKey[delegationKey]];
318
+ }
319
+ if (exchangeData && exchangeData.exchangeKey) {
320
+ const decrypted = yield this.decryptSecureDelegationMetadata(delegation, metadataType, exchangeData.exchangeKey);
321
+ for (const d of decrypted) {
322
+ allExtractedWithDataOwners.push({
323
+ decrypted: d,
324
+ dataOwnersWithAccess: [exchangeData.exchangeData.delegator, exchangeData.exchangeData.delegate],
325
+ });
326
+ }
327
+ }
328
+ }
329
+ return allExtractedWithDataOwners;
330
+ });
331
+ }
332
+ getDelegationMemberDetails(typedEntity) {
333
+ var _a, _b;
334
+ return __awaiter(this, void 0, void 0, function* () {
335
+ const res = {};
336
+ // 1. Add all explicit data owners, keep only delegations with at least an anonymous data owner to check later
337
+ let remainingDelegations = Object.entries((_b = (_a = typedEntity.entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {});
338
+ let updatedRemainingDelegations = [];
339
+ for (const delegationEntry of remainingDelegations) {
340
+ const delegation = delegationEntry[1];
341
+ if (delegation.delegator && delegation.delegate) {
342
+ res[delegationEntry[0]] = {
343
+ delegate: delegation.delegate,
344
+ delegator: delegation.delegator,
345
+ fullyExplicit: true,
346
+ accessLevel: delegation.permissions,
347
+ accessControlSecret: undefined,
348
+ };
349
+ }
350
+ else {
351
+ updatedRemainingDelegations.push(delegationEntry);
352
+ }
353
+ }
354
+ remainingDelegations = updatedRemainingDelegations;
355
+ if (!remainingDelegations.length)
356
+ return res;
357
+ updatedRemainingDelegations = [];
358
+ // 2. Attempt to identify the anonymous data owner of remaining delegations by checking if we have the exchange data cached by hash
359
+ // Note: we can find exchange data by hash only if we could successfully decrypt it
360
+ const cachedExchangeData = yield this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash(remainingDelegations.map((d) => d[0]));
361
+ for (const delegationEntry of remainingDelegations) {
362
+ const exchangeDataOfDelegation = cachedExchangeData[delegationEntry[0]];
363
+ if (exchangeDataOfDelegation) {
364
+ res[delegationEntry[0]] = {
365
+ delegate: exchangeDataOfDelegation.exchangeData.delegate,
366
+ delegator: exchangeDataOfDelegation.exchangeData.delegator,
367
+ fullyExplicit: false,
368
+ accessLevel: delegationEntry[1].permissions,
369
+ accessControlSecret: exchangeDataOfDelegation.accessControlSecret,
370
+ };
371
+ }
372
+ else {
373
+ updatedRemainingDelegations.push(delegationEntry);
374
+ }
375
+ }
376
+ remainingDelegations = updatedRemainingDelegations;
377
+ if (!remainingDelegations.length)
378
+ return res;
379
+ updatedRemainingDelegations = [];
380
+ // 3. Attempt to identify the anonymous data owner of remaining delegations between us (or one of our parents) and an anonymous data owner
381
+ const hierarchy = yield this.dataOwnerApi.getCurrentDataOwnerHierarchyIds();
382
+ const remainingExchangeDataMaps = yield this.exchangeDataMap.getExchangeDataMapBatch(remainingDelegations
383
+ .filter(([_, delegation]) => hierarchy.some((x) => x == delegation.delegator || x == delegation.delegate))
384
+ .map(([hash, _]) => hash));
385
+ const exchangeDataIdByDelegationKey = {};
386
+ for (const exchangeDataMap of remainingExchangeDataMaps) {
387
+ if (!!exchangeDataMap.encryptedExchangeDataIds) {
388
+ const decrypted = yield this.secureDelegationsEncryption.decryptExchangeDataId(exchangeDataMap.encryptedExchangeDataIds);
389
+ if (decrypted) {
390
+ exchangeDataIdByDelegationKey[exchangeDataMap.id] = decrypted;
391
+ }
392
+ }
393
+ }
394
+ const exchangeDataByIds = yield this.exchangeData.getDecryptionDataKeyByIds(Object.values(exchangeDataIdByDelegationKey), true);
395
+ for (const [hash, delegation] of remainingDelegations) {
396
+ if (hierarchy.some((x) => x === delegation.delegate || x === delegation.delegator)) {
397
+ const dataId = exchangeDataIdByDelegationKey[hash];
398
+ const exchangeDataInfo = dataId ? exchangeDataByIds[dataId] : undefined;
399
+ if (exchangeDataInfo) {
400
+ res[hash] = {
401
+ delegator: exchangeDataInfo.exchangeData.delegator,
402
+ delegate: exchangeDataInfo.exchangeData.delegate,
403
+ fullyExplicit: false,
404
+ accessLevel: delegation.permissions,
405
+ accessControlSecret: exchangeDataInfo.accessControlSecret,
406
+ };
407
+ }
408
+ else {
409
+ updatedRemainingDelegations.push([hash, delegation]);
410
+ }
411
+ }
412
+ else {
413
+ updatedRemainingDelegations.push([hash, delegation]);
414
+ }
415
+ }
416
+ return Object.assign(Object.assign({}, res), Object.fromEntries(updatedRemainingDelegations.map(([hash, secureDelegation]) => [
417
+ hash,
418
+ {
419
+ delegator: secureDelegation.delegator,
420
+ delegate: secureDelegation.delegate,
421
+ fullyExplicit: false,
422
+ accessLevel: secureDelegation.permissions,
423
+ accessControlSecret: undefined,
424
+ },
425
+ ])));
426
+ });
427
+ }
428
+ decryptSecureDelegationMetadata(delegation, metadataType, key) {
429
+ return __awaiter(this, void 0, void 0, function* () {
430
+ switch (metadataType) {
431
+ case SecurityMetadataType.SecretId:
432
+ return this.secureDelegationsEncryption.decryptSecretIds(delegation, key);
433
+ case SecurityMetadataType.EncryptionKey:
434
+ return this.secureDelegationsEncryption.decryptEncryptionKeys(delegation, key);
435
+ case SecurityMetadataType.OwningEntityId:
436
+ return this.secureDelegationsEncryption.decryptOwningEntityIds(delegation, key);
437
+ default:
438
+ throw new Error(`Internal error: invalid SecurityMetadataType ${metadataType}`);
439
+ }
440
+ });
441
+ }
442
+ getEntityLegacyDelegationAccessLevel(entity, dataOwnersHierarchySubset) {
443
+ var _a;
444
+ return __awaiter(this, void 0, void 0, function* () {
445
+ if (!dataOwnersHierarchySubset.length)
446
+ throw new Error("`dataOwnersHierarchySubset` can't be empty");
447
+ // Legacy delegations provide write access
448
+ if (Object.keys((_a = entity.delegations) !== null && _a !== void 0 ? _a : {}).some((delegate) => dataOwnersHierarchySubset.includes(delegate))) {
449
+ return AccessLevelEnum.WRITE;
450
+ }
451
+ return undefined;
452
+ });
453
+ }
454
+ getEntitySecureDelegationAccessLevel(entity, dataOwnersHierarchySubset) {
455
+ var _a, _b, _c, _d;
456
+ return __awaiter(this, void 0, void 0, function* () {
457
+ if (!dataOwnersHierarchySubset.length)
458
+ throw new Error("`dataOwnersHierarchySubset` can't be empty");
459
+ // If the data owner is explicit all delegations he can access has his id. If the delegator is anonymous all delegations he can access are
460
+ // accessible by hash. No mixed scenario possible.
461
+ let accessibleDelegations = Object.values((_b = (_a = entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {}).filter((secureDelegation) => dataOwnersHierarchySubset.some((dataOwner) => dataOwner === secureDelegation.delegator || dataOwner === secureDelegation.delegate));
462
+ if (!accessibleDelegations.length) {
463
+ const availableCanonicalHashes = Object.keys(yield this.exchangeData.getCachedDecryptionDataKeyByAccessControlHash(Object.keys((_d = (_c = entity.securityMetadata) === null || _c === void 0 ? void 0 : _c.secureDelegations) !== null && _d !== void 0 ? _d : {})));
464
+ accessibleDelegations = availableCanonicalHashes.map((hash) => { var _a, _b; return ((_b = (_a = entity.securityMetadata) === null || _a === void 0 ? void 0 : _a.secureDelegations) !== null && _b !== void 0 ? _b : {})[hash]; });
465
+ }
466
+ const permissions = accessibleDelegations.map((secureDelegation) => secureDelegation.permissions);
467
+ let maxLevel = undefined;
468
+ for (const permission of permissions) {
469
+ if (permission === AccessLevelEnum.WRITE) {
470
+ return AccessLevelEnum.WRITE;
471
+ }
472
+ if (permission === AccessLevelEnum.READ) {
473
+ maxLevel = AccessLevelEnum.READ;
474
+ }
475
+ }
476
+ return maxLevel;
477
+ });
478
+ }
479
+ getEntityAccessLevel(entity, dataOwnersHierarchySubset) {
480
+ return __awaiter(this, void 0, void 0, function* () {
481
+ const legacyAccess = yield this.getEntityLegacyDelegationAccessLevel(entity, dataOwnersHierarchySubset);
482
+ if (legacyAccess != undefined)
483
+ return legacyAccess;
484
+ return this.getEntitySecureDelegationAccessLevel(entity, dataOwnersHierarchySubset);
485
+ });
486
+ }
487
+ hasAnyEncryptionKeys(entity) {
488
+ var _a, _b, _c;
489
+ return Object.keys((_a = entity.encryptionKeys) !== null && _a !== void 0 ? _a : {}).length > 0 || Object.keys((_c = (_b = entity.securityMetadata) === null || _b === void 0 ? void 0 : _b.secureDelegations) !== null && _c !== void 0 ? _c : {}).length > 0;
76
490
  }
77
491
  }
78
- exports.SecurityMetadataDecryptorChain = SecurityMetadataDecryptorChain;
492
+ exports.SecurityMetadataDecryptor = SecurityMetadataDecryptor;
79
493
  //# sourceMappingURL=SecurityMetadataDecryptor.js.map