@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.
- package/icc-api/api/internal/IccExchangeDataApi.d.ts +2 -0
- package/icc-api/api/internal/IccExchangeDataApi.js +10 -0
- package/icc-api/api/internal/IccExchangeDataApi.js.map +1 -1
- package/icc-api/iccApi.d.ts +0 -1
- package/icc-api/iccApi.js +0 -1
- package/icc-api/iccApi.js.map +1 -1
- package/icc-api/index.d.ts +0 -1
- package/icc-api/index.js +0 -1
- package/icc-api/index.js.map +1 -1
- package/icc-x-api/crypto/AccessControlSecretUtils.d.ts +4 -13
- package/icc-x-api/crypto/AccessControlSecretUtils.js +19 -29
- package/icc-x-api/crypto/AccessControlSecretUtils.js.map +1 -1
- package/icc-x-api/crypto/BaseExchangeDataManager.d.ts +8 -3
- package/icc-x-api/crypto/BaseExchangeDataManager.js +45 -10
- package/icc-x-api/crypto/BaseExchangeDataManager.js.map +1 -1
- package/icc-x-api/crypto/BaseExchangeKeysManager.d.ts +2 -3
- package/icc-x-api/crypto/BaseExchangeKeysManager.js +17 -20
- package/icc-x-api/crypto/BaseExchangeKeysManager.js.map +1 -1
- package/icc-x-api/crypto/CryptoPrimitives.d.ts +2 -0
- package/icc-x-api/crypto/CryptoPrimitives.js +3 -0
- package/icc-x-api/crypto/CryptoPrimitives.js.map +1 -1
- package/icc-x-api/crypto/DelegationsDeAnonymization.d.ts +3 -3
- package/icc-x-api/crypto/DelegationsDeAnonymization.js +7 -7
- package/icc-x-api/crypto/DelegationsDeAnonymization.js.map +1 -1
- package/icc-x-api/crypto/ExchangeDataManager.d.ts +19 -29
- package/icc-x-api/crypto/ExchangeDataManager.js +200 -225
- package/icc-x-api/crypto/ExchangeDataManager.js.map +1 -1
- package/icc-x-api/crypto/ExchangeDataMapManager.js +6 -4
- package/icc-x-api/crypto/ExchangeDataMapManager.js.map +1 -1
- package/icc-x-api/crypto/ExchangeKeysManager.d.ts +4 -16
- package/icc-x-api/crypto/ExchangeKeysManager.js +44 -41
- package/icc-x-api/crypto/ExchangeKeysManager.js.map +1 -1
- package/icc-x-api/crypto/ExtendedApisUtils.d.ts +47 -25
- package/icc-x-api/crypto/ExtendedApisUtils.js.map +1 -1
- package/icc-x-api/crypto/ExtendedApisUtilsImpl.d.ts +19 -18
- package/icc-x-api/crypto/ExtendedApisUtilsImpl.js +213 -134
- package/icc-x-api/crypto/ExtendedApisUtilsImpl.js.map +1 -1
- package/icc-x-api/crypto/HMACUtils.d.ts +2 -2
- package/icc-x-api/crypto/HMACUtils.js +3 -4
- package/icc-x-api/crypto/HMACUtils.js.map +1 -1
- package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.d.ts +1 -0
- package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.js +5 -0
- package/icc-x-api/crypto/NativeCryptoPrimitivesBridge.js.map +1 -1
- package/icc-x-api/crypto/SecureDelegationsManager.d.ts +0 -1
- package/icc-x-api/crypto/SecureDelegationsManager.js +17 -49
- package/icc-x-api/crypto/SecureDelegationsManager.js.map +1 -1
- package/icc-x-api/crypto/SecurityMetadataDecryptor.d.ts +59 -90
- package/icc-x-api/crypto/SecurityMetadataDecryptor.js +470 -56
- package/icc-x-api/crypto/SecurityMetadataDecryptor.js.map +1 -1
- package/icc-x-api/crypto/ShamirKeysManager.js +1 -1
- package/icc-x-api/crypto/ShamirKeysManager.js.map +1 -1
- package/icc-x-api/crypto/TransferKeysManager.d.ts +1 -3
- package/icc-x-api/crypto/TransferKeysManager.js +2 -4
- package/icc-x-api/crypto/TransferKeysManager.js.map +1 -1
- package/icc-x-api/icc-accesslog-x-api.d.ts +2 -2
- package/icc-x-api/icc-accesslog-x-api.js +7 -3
- package/icc-x-api/icc-accesslog-x-api.js.map +1 -1
- package/icc-x-api/icc-calendar-item-x-api.js +4 -2
- package/icc-x-api/icc-calendar-item-x-api.js.map +1 -1
- package/icc-x-api/icc-contact-x-api.d.ts +0 -1
- package/icc-x-api/icc-contact-x-api.js +33 -48
- package/icc-x-api/icc-contact-x-api.js.map +1 -1
- package/icc-x-api/icc-crypto-x-api.js +1 -1
- package/icc-x-api/icc-crypto-x-api.js.map +1 -1
- package/icc-x-api/icc-document-x-api.d.ts +2 -2
- package/icc-x-api/icc-document-x-api.js +45 -42
- package/icc-x-api/icc-document-x-api.js.map +1 -1
- package/icc-x-api/icc-form-x-api.js +3 -1
- package/icc-x-api/icc-form-x-api.js.map +1 -1
- package/icc-x-api/icc-helement-x-api.js +4 -4
- package/icc-x-api/icc-helement-x-api.js.map +1 -1
- package/icc-x-api/icc-maintenance-task-x-api.js +4 -2
- package/icc-x-api/icc-maintenance-task-x-api.js.map +1 -1
- package/icc-x-api/icc-message-x-api.js +4 -2
- package/icc-x-api/icc-message-x-api.js.map +1 -1
- package/icc-x-api/icc-patient-x-api.js +5 -7
- package/icc-x-api/icc-patient-x-api.js.map +1 -1
- package/icc-x-api/icc-topic-x-api.js +2 -2
- package/icc-x-api/icc-topic-x-api.js.map +1 -1
- package/icc-x-api/index.d.ts +6 -2
- package/icc-x-api/index.js +16 -20
- package/icc-x-api/index.js.map +1 -1
- package/icc-x-api/utils/crypto-utils.d.ts +6 -4
- package/icc-x-api/utils/crypto-utils.js +27 -6
- package/icc-x-api/utils/crypto-utils.js.map +1 -1
- package/icc-x-api/utils/simple-lru-cache.d.ts +19 -0
- package/icc-x-api/utils/simple-lru-cache.js +90 -0
- package/icc-x-api/utils/simple-lru-cache.js.map +1 -0
- package/package.json +4 -2
- package/test/icc-x-api/crud/entities-crud-test-interface.js +0 -8
- package/test/icc-x-api/crud/entities-crud-test-interface.js.map +1 -1
- package/test/icc-x-api/crypto/exchange-data-manager-test.js +75 -93
- package/test/icc-x-api/crypto/exchange-data-manager-test.js.map +1 -1
- package/test/icc-x-api/crypto/legacy-metadata-migration-test.js.map +1 -1
- package/test/icc-x-api/crypto/secure-delegations-manager-test.js +28 -16
- package/test/icc-x-api/crypto/secure-delegations-manager-test.js.map +1 -1
- package/test/utils/FakeEncryptionKeysManager.d.ts +1 -0
- package/test/utils/FakeEncryptionKeysManager.js +11 -0
- package/test/utils/FakeEncryptionKeysManager.js.map +1 -1
- package/test/utils/FakeExchangeDataApi.d.ts +4 -2
- package/test/utils/FakeExchangeDataApi.js +24 -6
- package/test/utils/FakeExchangeDataApi.js.map +1 -1
- package/test/utils/FakeExchangeDataManager.d.ts +10 -10
- package/test/utils/FakeExchangeDataManager.js +12 -22
- package/test/utils/FakeExchangeDataManager.js.map +1 -1
- package/test/utils/TestApi.js +1 -0
- package/test/utils/TestApi.js.map +1 -1
- package/icc-api/api/IccArticleApi.d.ts +0 -72
- package/icc-api/api/IccArticleApi.js +0 -149
- package/icc-api/api/IccArticleApi.js.map +0 -1
- package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.d.ts +0 -33
- package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.js +0 -141
- package/icc-x-api/crypto/LegacyDelegationSecurityMetadataDecryptor.js.map +0 -1
- package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.d.ts +0 -46
- package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.js +0 -312
- package/icc-x-api/crypto/SecureDelegationsSecurityMetadataDecryptor.js.map +0 -1
- package/icc-x-api/crypto/UserSignatureKeysManager.d.ts +0 -26
- package/icc-x-api/crypto/UserSignatureKeysManager.js +0 -78
- package/icc-x-api/crypto/UserSignatureKeysManager.js.map +0 -1
- package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.d.ts +0 -1
- package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.js +0 -393
- package/test/icc-x-api/crypto/secure-delegations-metadata-decryptor-test.js.map +0 -1
- package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.d.ts +0 -1
- package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.js +0 -213
- package/test/icc-x-api/crypto/security-metadata-decryptor-chain-test.js.map +0 -1
- package/test/icc-x-api/crypto/signature-keys-manager-test.d.ts +0 -1
- package/test/icc-x-api/crypto/signature-keys-manager-test.js +0 -44
- package/test/icc-x-api/crypto/signature-keys-manager-test.js.map +0 -1
- package/test/utils/FakeSignatureKeysManager.d.ts +0 -16
- package/test/utils/FakeSignatureKeysManager.js +0 -54
- package/test/utils/FakeSignatureKeysManager.js.map +0 -1
|
@@ -12,33 +12,32 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.initialiseExchangeDataManagerForCurrentDataOwner = void 0;
|
|
13
13
|
const utils_1 = require("./utils");
|
|
14
14
|
const utils_2 = require("../utils");
|
|
15
|
-
const lru_temporised_async_cache_1 = require("../utils/lru-temporised-async-cache");
|
|
16
|
-
const EntityWithDelegationTypeName_1 = require("../utils/EntityWithDelegationTypeName");
|
|
17
15
|
const CryptoActorStub_1 = require("../../icc-api/model/CryptoActorStub");
|
|
18
16
|
const RSA_1 = require("./RSA");
|
|
17
|
+
const async_mutex_1 = require("async-mutex");
|
|
18
|
+
const simple_lru_cache_1 = require("../utils/simple-lru-cache");
|
|
19
19
|
/**
|
|
20
20
|
* @internal this function is for internal use only and may be changed without notice.
|
|
21
21
|
* Initialises and returns the exchange data manager which is most appropriate for the current data owner.
|
|
22
22
|
*/
|
|
23
|
-
function initialiseExchangeDataManagerForCurrentDataOwner(base, encryptionKeys,
|
|
23
|
+
function initialiseExchangeDataManagerForCurrentDataOwner(base, encryptionKeys, accessControlSecret, cryptoStrategies, dataOwnerApi, primitives, useParentKeys, optionalParameters = {}) {
|
|
24
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
25
|
const currentOwner = CryptoActorStub_1.CryptoActorStubWithType.fromDataOwner(yield dataOwnerApi.getCurrentDataOwner());
|
|
26
26
|
if (cryptoStrategies.dataOwnerRequiresAnonymousDelegation(currentOwner)) {
|
|
27
|
-
const res = new FullyCachedExchangeDataManager(base, encryptionKeys,
|
|
27
|
+
const res = new FullyCachedExchangeDataManager(base, encryptionKeys, accessControlSecret, cryptoStrategies, dataOwnerApi, primitives, useParentKeys);
|
|
28
28
|
yield res.clearOrRepopulateCache();
|
|
29
29
|
return res;
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
|
-
return new LimitedLruCacheExchangeDataManager(base, encryptionKeys,
|
|
32
|
+
return new LimitedLruCacheExchangeDataManager(base, encryptionKeys, accessControlSecret, cryptoStrategies, dataOwnerApi, primitives, useParentKeys, optionalParameters);
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
exports.initialiseExchangeDataManagerForCurrentDataOwner = initialiseExchangeDataManagerForCurrentDataOwner;
|
|
37
37
|
class AbstractExchangeDataManager {
|
|
38
|
-
constructor(base, encryptionKeys,
|
|
38
|
+
constructor(base, encryptionKeys, accessControlSecret, cryptoStrategies, dataOwnerApi, primitives, useParentKeys) {
|
|
39
39
|
this.base = base;
|
|
40
40
|
this.encryptionKeys = encryptionKeys;
|
|
41
|
-
this.signatureKeys = signatureKeys;
|
|
42
41
|
this.accessControlSecret = accessControlSecret;
|
|
43
42
|
this.cryptoStrategies = cryptoStrategies;
|
|
44
43
|
this.dataOwnerApi = dataOwnerApi;
|
|
@@ -48,6 +47,7 @@ class AbstractExchangeDataManager {
|
|
|
48
47
|
decryptData(data) {
|
|
49
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
49
|
const decryptionKeys = this.encryptionKeys.getDecryptionKeys();
|
|
50
|
+
const encryptionKeys = Object.fromEntries(this.encryptionKeys.getSelfVerifiedKeys().map((x) => [x.fingerprint, x.pair.privateKey]));
|
|
51
51
|
const decryptedExchangeKey = (yield this.base.tryDecryptExchangeKeys([data], decryptionKeys)).successfulDecryptions[0];
|
|
52
52
|
if (!decryptedExchangeKey)
|
|
53
53
|
return undefined;
|
|
@@ -65,14 +65,15 @@ class AbstractExchangeDataManager {
|
|
|
65
65
|
decryptedAccessControlSecret,
|
|
66
66
|
decryptedExchangeKey,
|
|
67
67
|
decryptedSharedSignatureKey,
|
|
68
|
-
},
|
|
68
|
+
}, encryptionKeys, true),
|
|
69
69
|
};
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
createNewExchangeData(delegateId, options) {
|
|
73
73
|
return __awaiter(this, void 0, void 0, function* () {
|
|
74
74
|
const encryptionKeys = {};
|
|
75
|
-
this.encryptionKeys.getSelfVerifiedKeys()
|
|
75
|
+
const selfVerifiedKeys = this.encryptionKeys.getSelfVerifiedKeys();
|
|
76
|
+
selfVerifiedKeys.forEach(({ fingerprint, pair }) => {
|
|
76
77
|
encryptionKeys[fingerprint] = pair.publicKey;
|
|
77
78
|
});
|
|
78
79
|
if (delegateId != (yield this.dataOwnerApi.getCurrentDataOwnerId())) {
|
|
@@ -104,8 +105,7 @@ class AbstractExchangeDataManager {
|
|
|
104
105
|
throw new Error('Illegal state: verified keys should contain only keys for OAPE-SHA1 or OAPE-SHA256.');
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
|
-
const
|
|
108
|
-
const newData = yield this.base.createExchangeData(delegateId, { [signatureKey.fingerprint]: signatureKey.keyPair.privateKey }, encryptionKeys, options.newDataId ? { id: options.newDataId } : {});
|
|
108
|
+
const newData = yield this.base.createExchangeData(delegateId, Object.fromEntries(selfVerifiedKeys.map((x) => [x.fingerprint, x.pair.privateKey])), encryptionKeys, options.newDataId ? { id: options.newDataId } : {});
|
|
109
109
|
return {
|
|
110
110
|
exchangeData: newData.exchangeData,
|
|
111
111
|
accessControlSecret: newData.accessControlSecret,
|
|
@@ -122,7 +122,6 @@ class AbstractExchangeDataManager {
|
|
|
122
122
|
if (!newKeyHashVersion)
|
|
123
123
|
throw new Error(`Public key not found for data owner ${otherDataOwner}`);
|
|
124
124
|
const importedNewKey = yield this.primitives.RSA.importKey('spki', (0, utils_2.hex2ua)(newDataOwnerPublicKey), ['encrypt'], newKeyHashVersion);
|
|
125
|
-
const signatureKey = yield this.signatureKeys.getOrCreateSignatureKeyPair();
|
|
126
125
|
const decryptionKeys = this.encryptionKeys.getDecryptionKeys();
|
|
127
126
|
const allExchangeDataToUpdate = self == otherDataOwner
|
|
128
127
|
? yield this.base.getExchangeDataByDelegatorDelegatePair(self, self)
|
|
@@ -143,13 +142,13 @@ class AbstractExchangeDataManager {
|
|
|
143
142
|
clearOrRepopulateCache() {
|
|
144
143
|
throw new Error('Implemented by concrete class');
|
|
145
144
|
}
|
|
146
|
-
getOrCreateEncryptionDataTo(delegateId,
|
|
145
|
+
getOrCreateEncryptionDataTo(delegateId, allowCreationWithoutDelegateKey) {
|
|
147
146
|
throw new Error('Implemented by concrete class');
|
|
148
147
|
}
|
|
149
|
-
getCachedDecryptionDataKeyByAccessControlHash(hashes
|
|
148
|
+
getCachedDecryptionDataKeyByAccessControlHash(hashes) {
|
|
150
149
|
throw new Error('Implemented by concrete class');
|
|
151
150
|
}
|
|
152
|
-
|
|
151
|
+
getDecryptionDataKeyByIds(ids, retrieveIfNotCached) {
|
|
153
152
|
throw new Error('Implemented by concrete class');
|
|
154
153
|
}
|
|
155
154
|
getAccessControlKeysValue(entityType) {
|
|
@@ -162,7 +161,8 @@ class AbstractExchangeDataManager {
|
|
|
162
161
|
class FullyCachedExchangeDataManager extends AbstractExchangeDataManager {
|
|
163
162
|
constructor() {
|
|
164
163
|
super(...arguments);
|
|
165
|
-
this.caches = Promise.resolve({ dataById: {}, hashToId:
|
|
164
|
+
this.caches = Promise.resolve({ dataById: {}, hashToId: {}, delegateToVerifiedEncryptionDataId: {}, entityTypeToAccessControlKeysValue: {} });
|
|
165
|
+
this.createExchangeDataMutex = new async_mutex_1.Mutex();
|
|
166
166
|
}
|
|
167
167
|
clearOrRepopulateCache() {
|
|
168
168
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -170,11 +170,11 @@ class FullyCachedExchangeDataManager extends AbstractExchangeDataManager {
|
|
|
170
170
|
yield this.caches;
|
|
171
171
|
});
|
|
172
172
|
}
|
|
173
|
-
getCachedDecryptionDataKeyByAccessControlHash(hashes
|
|
173
|
+
getCachedDecryptionDataKeyByAccessControlHash(hashes) {
|
|
174
174
|
return __awaiter(this, void 0, void 0, function* () {
|
|
175
175
|
function retrieveByHashesFromCaches(caches) {
|
|
176
176
|
return hashes.reduce((res, hash) => {
|
|
177
|
-
const id = caches.hashToId
|
|
177
|
+
const id = caches.hashToId[hash];
|
|
178
178
|
if (id) {
|
|
179
179
|
const cached = caches.dataById[id];
|
|
180
180
|
if (cached === null || cached === void 0 ? void 0 : cached.decrypted) {
|
|
@@ -188,25 +188,10 @@ class FullyCachedExchangeDataManager extends AbstractExchangeDataManager {
|
|
|
188
188
|
return res;
|
|
189
189
|
}, {});
|
|
190
190
|
}
|
|
191
|
-
|
|
192
|
-
if (Object.keys(retrievedFromHashesCache).length) {
|
|
193
|
-
return retrievedFromHashesCache;
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
this.caches = this.caches.then((caches) => __awaiter(this, void 0, void 0, function* () {
|
|
197
|
-
for (const currData of Object.values(caches.dataById)) {
|
|
198
|
-
if (currData.decrypted) {
|
|
199
|
-
const currDataHashes = yield this.accessControlSecret.secureDelegationKeysFor(currData.decrypted.accessControlSecret, entityType, entitySecretForeignKeys);
|
|
200
|
-
currDataHashes.forEach((hash) => caches.hashToId.set(hash, currData.exchangeData.id));
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return caches;
|
|
204
|
-
}));
|
|
205
|
-
return retrieveByHashesFromCaches(yield this.caches);
|
|
206
|
-
}
|
|
191
|
+
return retrieveByHashesFromCaches(yield this.caches);
|
|
207
192
|
});
|
|
208
193
|
}
|
|
209
|
-
|
|
194
|
+
getCachedEncryptionDataTo(delegateId) {
|
|
210
195
|
return __awaiter(this, void 0, void 0, function* () {
|
|
211
196
|
const caches = yield this.caches;
|
|
212
197
|
const dataId = caches.delegateToVerifiedEncryptionDataId[delegateId];
|
|
@@ -218,48 +203,60 @@ class FullyCachedExchangeDataManager extends AbstractExchangeDataManager {
|
|
|
218
203
|
exchangeKey: cached.decrypted.exchangeKey,
|
|
219
204
|
};
|
|
220
205
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return created;
|
|
206
|
+
else {
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
225
209
|
});
|
|
226
210
|
}
|
|
227
|
-
|
|
211
|
+
getOrCreateEncryptionDataTo(delegateId, allowCreationWithoutDelegateKey) {
|
|
212
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
213
|
+
const initialCached = yield this.getCachedEncryptionDataTo(delegateId);
|
|
214
|
+
if (initialCached)
|
|
215
|
+
return initialCached;
|
|
216
|
+
const release = yield this.createExchangeDataMutex.acquire();
|
|
217
|
+
try {
|
|
218
|
+
const cachedAfterMutex = yield this.getCachedEncryptionDataTo(delegateId);
|
|
219
|
+
if (cachedAfterMutex)
|
|
220
|
+
return cachedAfterMutex;
|
|
221
|
+
const created = yield this.createNewExchangeData(delegateId, { allowNoDelegateKeys: allowCreationWithoutDelegateKey });
|
|
222
|
+
this.cacheData(created.exchangeData, true, {
|
|
223
|
+
accessControlSecret: created.accessControlSecret,
|
|
224
|
+
exchangeKey: created.exchangeKey,
|
|
225
|
+
verified: true,
|
|
226
|
+
});
|
|
227
|
+
return created;
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
release();
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
getDecryptionDataKeyByIds(ids, retrieveIfNotCached) {
|
|
228
235
|
var _a, _b;
|
|
229
236
|
return __awaiter(this, void 0, void 0, function* () {
|
|
230
237
|
const caches = yield this.caches;
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
if (!data)
|
|
242
|
-
throw new Error(`Could not find exchange data with id ${id}`);
|
|
243
|
-
const decrypted = yield this.decryptData(data);
|
|
244
|
-
this.cacheData(data, false, decrypted, entityType, entitySecretForeignKeys);
|
|
245
|
-
return { exchangeData: data, exchangeKey: decrypted === null || decrypted === void 0 ? void 0 : decrypted.exchangeKey, accessControlSecret: decrypted === null || decrypted === void 0 ? void 0 : decrypted.accessControlSecret };
|
|
238
|
+
const res = {};
|
|
239
|
+
for (const id of ids) {
|
|
240
|
+
const data = caches.dataById[id];
|
|
241
|
+
if (data) {
|
|
242
|
+
res[id] = {
|
|
243
|
+
exchangeData: data.exchangeData,
|
|
244
|
+
exchangeKey: (_a = data.decrypted) === null || _a === void 0 ? void 0 : _a.exchangeKey,
|
|
245
|
+
accessControlSecret: (_b = data.decrypted) === null || _b === void 0 ? void 0 : _b.accessControlSecret,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
246
248
|
}
|
|
247
|
-
|
|
248
|
-
return undefined;
|
|
249
|
+
return res;
|
|
249
250
|
});
|
|
250
251
|
}
|
|
251
|
-
cacheData(exchangeData, isNewData, decrypted
|
|
252
|
+
cacheData(exchangeData, isNewData, decrypted) {
|
|
252
253
|
this.caches = this.caches.then((caches) => __awaiter(this, void 0, void 0, function* () {
|
|
253
254
|
caches.dataById[exchangeData.id] = { exchangeData, decrypted };
|
|
254
255
|
if (decrypted) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
hashes.forEach((hash) => {
|
|
260
|
-
caches.hashToId.set(hash, exchangeData.id);
|
|
261
|
-
});
|
|
262
|
-
}
|
|
256
|
+
const hashes = yield this.accessControlSecret.allSecureDelegationKeysFor(decrypted.accessControlSecret);
|
|
257
|
+
hashes.forEach((hash) => {
|
|
258
|
+
caches.hashToId[hash] = exchangeData.id;
|
|
259
|
+
});
|
|
263
260
|
if (decrypted.verified) {
|
|
264
261
|
caches.delegateToVerifiedEncryptionDataId[exchangeData.delegate] = exchangeData.id;
|
|
265
262
|
}
|
|
@@ -275,7 +272,7 @@ class FullyCachedExchangeDataManager extends AbstractExchangeDataManager {
|
|
|
275
272
|
if (!allData)
|
|
276
273
|
throw new Error('Impossible to use fully cached exchange data manager for current data owner.');
|
|
277
274
|
const dataById = {};
|
|
278
|
-
const hashToId =
|
|
275
|
+
const hashToId = {};
|
|
279
276
|
const delegateToVerifiedEncryptionDataId = {};
|
|
280
277
|
for (const currData of allData) {
|
|
281
278
|
const currDecrypted = yield this.decryptData(currData);
|
|
@@ -283,6 +280,11 @@ class FullyCachedExchangeDataManager extends AbstractExchangeDataManager {
|
|
|
283
280
|
if (currDecrypted === null || currDecrypted === void 0 ? void 0 : currDecrypted.verified) {
|
|
284
281
|
delegateToVerifiedEncryptionDataId[currData.delegate] = currData.id;
|
|
285
282
|
}
|
|
283
|
+
if (currDecrypted === null || currDecrypted === void 0 ? void 0 : currDecrypted.accessControlSecret) {
|
|
284
|
+
for (const h of yield this.accessControlSecret.allSecureDelegationKeysFor(currDecrypted.accessControlSecret)) {
|
|
285
|
+
hashToId[h] = currData.id;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
286
288
|
}
|
|
287
289
|
const entityTypeToAccessControlKeysValue = {};
|
|
288
290
|
return { dataById, hashToId, delegateToVerifiedEncryptionDataId, entityTypeToAccessControlKeysValue };
|
|
@@ -307,217 +309,190 @@ class FullyCachedExchangeDataManager extends AbstractExchangeDataManager {
|
|
|
307
309
|
const res = [];
|
|
308
310
|
for (const accessControlSecret of accessControlSecrets) {
|
|
309
311
|
// Usage of sfks in secure delegation key should be configurable: it is not necessary for all users and it has some performance impact
|
|
310
|
-
res.push(yield this.accessControlSecret.secureDelegationKeyFor(accessControlSecret, entityType
|
|
312
|
+
res.push(yield this.accessControlSecret.secureDelegationKeyFor(accessControlSecret, entityType));
|
|
311
313
|
}
|
|
312
314
|
return res;
|
|
313
315
|
});
|
|
314
316
|
}
|
|
315
317
|
}
|
|
316
318
|
class LimitedLruCacheExchangeDataManager extends AbstractExchangeDataManager {
|
|
317
|
-
constructor(base, encryptionKeys,
|
|
319
|
+
constructor(base, encryptionKeys, accessControlSecret, cryptoStrategies, dataOwnerApi, primitives, useParentKeys, optionalParameters) {
|
|
318
320
|
var _a;
|
|
319
|
-
super(base, encryptionKeys,
|
|
321
|
+
super(base, encryptionKeys, accessControlSecret, cryptoStrategies, dataOwnerApi, primitives, useParentKeys);
|
|
322
|
+
this.idToData = new simple_lru_cache_1.SimpleLruCache();
|
|
320
323
|
this.hashToId = new Map();
|
|
321
324
|
this.delegateToVerifiedEncryptionDataId = new Map();
|
|
322
|
-
this.
|
|
325
|
+
this.cacheMutex = new async_mutex_1.Mutex();
|
|
326
|
+
this.maxCachedExchangeData = (_a = optionalParameters.lruCacheSize) !== null && _a !== void 0 ? _a : 2000;
|
|
323
327
|
}
|
|
324
328
|
clearOrRepopulateCache() {
|
|
325
329
|
return __awaiter(this, void 0, void 0, function* () {
|
|
326
|
-
this.
|
|
330
|
+
this.idToData.clear();
|
|
327
331
|
this.hashToId.clear();
|
|
328
332
|
this.delegateToVerifiedEncryptionDataId.clear();
|
|
329
333
|
});
|
|
330
334
|
}
|
|
331
|
-
getCachedDecryptionDataKeyByAccessControlHash(hashes
|
|
335
|
+
getCachedDecryptionDataKeyByAccessControlHash(hashes) {
|
|
332
336
|
return __awaiter(this, void 0, void 0, function* () {
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
337
|
+
const release = yield this.cacheMutex.acquire();
|
|
338
|
+
try {
|
|
339
|
+
const res = {};
|
|
340
|
+
for (const hash of hashes) {
|
|
341
|
+
const dataId = this.hashToId.get(hash);
|
|
342
|
+
if (dataId) {
|
|
343
|
+
const retrieved = this.idToData.getCached(dataId);
|
|
344
|
+
if (!retrieved)
|
|
345
|
+
throw new Error(`Data with id ${dataId} should have been already cached.`);
|
|
346
|
+
if (retrieved.decrypted) {
|
|
347
|
+
res[hash] = {
|
|
348
|
+
exchangeData: retrieved.exchangeData,
|
|
349
|
+
exchangeKey: retrieved.decrypted.exchangeKey,
|
|
350
|
+
accessControlSecret: retrieved.decrypted.accessControlSecret,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
346
353
|
}
|
|
347
354
|
}
|
|
355
|
+
return res;
|
|
348
356
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
secureDelegationKeysForAllEntitiesNoSfkAndSpecificEntitySfksPairs(accessControlSecret, entityType, entitySecretForeignKeys) {
|
|
353
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
354
|
-
const noSfkDelegationKeys = yield Promise.all([...EntityWithDelegationTypeName_1.entityWithDelegationTypeNames].map((t) => this.accessControlSecret.secureDelegationKeyFor(accessControlSecret, t, undefined)));
|
|
355
|
-
if (entityType && (entitySecretForeignKeys === null || entitySecretForeignKeys === void 0 ? void 0 : entitySecretForeignKeys.length)) {
|
|
356
|
-
// Usage of sfks in secure delegation key should be configurable: it is not necessary for all users and it has some performance impact
|
|
357
|
-
// `secureDelegationKeysFor` is currently ignoring the sfks
|
|
358
|
-
return [
|
|
359
|
-
...noSfkDelegationKeys,
|
|
360
|
-
...(yield this.accessControlSecret.secureDelegationKeysFor(accessControlSecret, entityType, entitySecretForeignKeys)),
|
|
361
|
-
];
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
return noSfkDelegationKeys;
|
|
357
|
+
finally {
|
|
358
|
+
release();
|
|
365
359
|
}
|
|
366
360
|
});
|
|
367
361
|
}
|
|
368
|
-
|
|
362
|
+
getDecryptionDataKeyByIds(ids, retrieveIfNotCached) {
|
|
369
363
|
var _a, _b;
|
|
370
364
|
return __awaiter(this, void 0, void 0, function* () {
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
toUpdate.hashes.push(...hashes);
|
|
384
|
-
}
|
|
365
|
+
const release = yield this.cacheMutex.acquire();
|
|
366
|
+
try {
|
|
367
|
+
const res = {};
|
|
368
|
+
const uncached = [];
|
|
369
|
+
for (const id of ids) {
|
|
370
|
+
const cached = this.idToData.getCached(id);
|
|
371
|
+
if (cached) {
|
|
372
|
+
res[id] = {
|
|
373
|
+
exchangeKey: (_a = cached.decrypted) === null || _a === void 0 ? void 0 : _a.exchangeKey,
|
|
374
|
+
accessControlSecret: (_b = cached.decrypted) === null || _b === void 0 ? void 0 : _b.accessControlSecret,
|
|
375
|
+
exchangeData: cached.exchangeData,
|
|
376
|
+
};
|
|
385
377
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
else if (retrieveIfNotCached) {
|
|
395
|
-
return yield this.idToDataCache
|
|
396
|
-
.get(id, () => __awaiter(this, void 0, void 0, function* () {
|
|
397
|
-
return this.cacheJob(() => __awaiter(this, void 0, void 0, function* () {
|
|
398
|
-
const data = yield this.base.getExchangeDataById(id);
|
|
399
|
-
if (!data)
|
|
400
|
-
throw new Error(`Could not find exchange data with id ${id}`);
|
|
378
|
+
else if (retrieveIfNotCached) {
|
|
379
|
+
uncached.push(id);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (uncached.length > 0) {
|
|
383
|
+
const retrieved = yield this.base.getExchangeDataByIds(uncached);
|
|
384
|
+
for (const data of retrieved) {
|
|
401
385
|
const decrypted = yield this.decryptData(data);
|
|
402
386
|
if (decrypted) {
|
|
403
|
-
const hashes = yield this.
|
|
404
|
-
|
|
387
|
+
const hashes = yield this.accessControlSecret.allSecureDelegationKeysFor(decrypted.accessControlSecret);
|
|
388
|
+
this.addToCache({ exchangeData: data, hashes, decrypted });
|
|
405
389
|
}
|
|
406
390
|
else {
|
|
407
|
-
|
|
391
|
+
this.addToCache({ exchangeData: data, hashes: [] });
|
|
408
392
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
393
|
+
res[data.id] = {
|
|
394
|
+
exchangeKey: decrypted === null || decrypted === void 0 ? void 0 : decrypted.exchangeKey,
|
|
395
|
+
accessControlSecret: decrypted === null || decrypted === void 0 ? void 0 : decrypted.accessControlSecret,
|
|
396
|
+
exchangeData: data,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return res;
|
|
401
|
+
}
|
|
402
|
+
finally {
|
|
403
|
+
release();
|
|
412
404
|
}
|
|
413
|
-
else
|
|
414
|
-
return undefined;
|
|
415
405
|
});
|
|
416
406
|
}
|
|
417
|
-
getOrCreateEncryptionDataTo(delegateId,
|
|
407
|
+
getOrCreateEncryptionDataTo(delegateId, allowCreationWithoutDelegateKey) {
|
|
418
408
|
return __awaiter(this, void 0, void 0, function* () {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const cached = yield this.idToDataCache.getIfCachedJob(existingId);
|
|
426
|
-
if (!cached)
|
|
427
|
-
throw new Error(`Illegal state: data with id ${existingId} should have been in cache`);
|
|
428
|
-
if (cached.item.decrypted) {
|
|
429
|
-
return {
|
|
430
|
-
exchangeData: cached.item.exchangeData,
|
|
431
|
-
exchangeKey: cached.item.decrypted.exchangeKey,
|
|
432
|
-
accessControlSecret: cached.item.decrypted.accessControlSecret,
|
|
433
|
-
};
|
|
409
|
+
const release = yield this.cacheMutex.acquire();
|
|
410
|
+
try {
|
|
411
|
+
let existingId = this.delegateToVerifiedEncryptionDataId.get(delegateId);
|
|
412
|
+
if (!existingId) {
|
|
413
|
+
yield this.populateCacheToDelegate(delegateId);
|
|
414
|
+
existingId = this.delegateToVerifiedEncryptionDataId.get(delegateId);
|
|
434
415
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
this.delegateToVerifiedEncryptionDataId.set(delegateId, newDataId);
|
|
441
|
-
const createdAndCachedData = yield this.idToDataCache.get(newDataId, () => this.cacheJob(() => __awaiter(this, void 0, void 0, function* () {
|
|
442
|
-
try {
|
|
443
|
-
const created = yield this.createNewExchangeData(delegateId, { newDataId, allowNoDelegateKeys: allowCreationWithoutDelegateKey });
|
|
444
|
-
const hashes = yield this.secureDelegationKeysForAllEntitiesNoSfkAndSpecificEntitySfksPairs(created.accessControlSecret, entityType, entitySecretForeignKeys);
|
|
416
|
+
if (existingId) {
|
|
417
|
+
const cached = this.idToData.getCached(existingId);
|
|
418
|
+
if (!cached)
|
|
419
|
+
throw new Error(`Illegal state: data with id ${existingId} should have been in cache`);
|
|
420
|
+
if (cached.decrypted) {
|
|
445
421
|
return {
|
|
446
|
-
exchangeData:
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
exchangeKey: created.exchangeKey,
|
|
450
|
-
verified: true,
|
|
451
|
-
},
|
|
452
|
-
hashes,
|
|
422
|
+
exchangeData: cached.exchangeData,
|
|
423
|
+
exchangeKey: cached.decrypted.exchangeKey,
|
|
424
|
+
accessControlSecret: cached.decrypted.accessControlSecret,
|
|
453
425
|
};
|
|
454
426
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
427
|
+
else
|
|
428
|
+
throw new Error(`Illegal state: cached verified data should be decrypted.`);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
const created = yield this.createNewExchangeData(delegateId, {
|
|
432
|
+
allowNoDelegateKeys: allowCreationWithoutDelegateKey,
|
|
433
|
+
});
|
|
434
|
+
const hashes = yield this.accessControlSecret.allSecureDelegationKeysFor(created.accessControlSecret);
|
|
435
|
+
const data = {
|
|
436
|
+
exchangeData: created.exchangeData,
|
|
437
|
+
decrypted: {
|
|
438
|
+
accessControlSecret: created.accessControlSecret,
|
|
439
|
+
exchangeKey: created.exchangeKey,
|
|
440
|
+
verified: true,
|
|
441
|
+
},
|
|
442
|
+
hashes,
|
|
443
|
+
};
|
|
444
|
+
this.addToCache(data);
|
|
445
|
+
return {
|
|
446
|
+
exchangeData: data.exchangeData,
|
|
447
|
+
exchangeKey: data.decrypted.exchangeKey,
|
|
448
|
+
accessControlSecret: data.decrypted.accessControlSecret,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
finally {
|
|
453
|
+
release();
|
|
467
454
|
}
|
|
468
455
|
});
|
|
469
456
|
}
|
|
470
457
|
// Loads and adds to the cache all exchange data from the current data owner to the given delegate. Allows to check if there is already data from
|
|
471
458
|
// the current data owner to the delegate which is good for encryption.
|
|
472
|
-
populateCacheToDelegate(delegateId
|
|
459
|
+
populateCacheToDelegate(delegateId) {
|
|
473
460
|
return __awaiter(this, void 0, void 0, function* () {
|
|
474
461
|
const dataToDelegate = yield this.base.getExchangeDataByDelegatorDelegatePair(yield this.dataOwnerApi.getCurrentDataOwnerId(), delegateId);
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
})));
|
|
486
|
-
})));
|
|
462
|
+
for (const data of dataToDelegate) {
|
|
463
|
+
const decrypted = yield this.decryptData(data);
|
|
464
|
+
if (decrypted) {
|
|
465
|
+
const hashes = yield this.accessControlSecret.allSecureDelegationKeysFor(decrypted.accessControlSecret);
|
|
466
|
+
this.addToCache({ exchangeData: data, hashes, decrypted });
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
this.addToCache({ exchangeData: data, hashes: [] });
|
|
470
|
+
}
|
|
471
|
+
}
|
|
487
472
|
});
|
|
488
473
|
}
|
|
489
|
-
|
|
474
|
+
addToCache(data) {
|
|
490
475
|
var _a;
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
decrypted: info.decrypted,
|
|
500
|
-
};
|
|
501
|
-
return {
|
|
502
|
-
item,
|
|
503
|
-
onEviction: (b) => this.doOnEvictionJob(b, item),
|
|
504
|
-
};
|
|
505
|
-
});
|
|
476
|
+
if (this.idToData.size >= this.maxCachedExchangeData) {
|
|
477
|
+
this.evictOneEntry();
|
|
478
|
+
}
|
|
479
|
+
data.hashes.forEach((hash) => this.hashToId.set(hash, data.exchangeData.id));
|
|
480
|
+
if (((_a = data.decrypted) === null || _a === void 0 ? void 0 : _a.verified) && !this.delegateToVerifiedEncryptionDataId.has(data.exchangeData.delegate)) {
|
|
481
|
+
this.delegateToVerifiedEncryptionDataId.set(data.exchangeData.delegate, data.exchangeData.id);
|
|
482
|
+
}
|
|
483
|
+
this.idToData.set(data.exchangeData.id, data);
|
|
506
484
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
});
|
|
485
|
+
evictOneEntry() {
|
|
486
|
+
const evicted = this.idToData.evictLeastRecentlyUsed();
|
|
487
|
+
evicted.hashes.forEach((hash) => this.hashToId.delete(hash));
|
|
488
|
+
if (this.delegateToVerifiedEncryptionDataId.get(evicted.exchangeData.delegate) === evicted.exchangeData.id) {
|
|
489
|
+
this.delegateToVerifiedEncryptionDataId.delete(evicted.exchangeData.delegate);
|
|
490
|
+
}
|
|
516
491
|
}
|
|
517
|
-
getAccessControlKeysValue(
|
|
492
|
+
getAccessControlKeysValue() {
|
|
518
493
|
return Promise.resolve(undefined);
|
|
519
494
|
}
|
|
520
|
-
getAllDelegationKeys(
|
|
495
|
+
getAllDelegationKeys() {
|
|
521
496
|
return Promise.resolve(undefined);
|
|
522
497
|
}
|
|
523
498
|
}
|