mindoodb 0.0.3 → 0.0.5
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/README-server.md +1030 -0
- package/README.md +14 -26
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts +27 -0
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +270 -121
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -1
- package/dist/appendonlystores/network/HttpTransport.d.ts +15 -0
- package/dist/appendonlystores/network/HttpTransport.d.ts.map +1 -1
- package/dist/appendonlystores/network/HttpTransport.js +235 -10
- package/dist/appendonlystores/network/HttpTransport.js.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +5 -0
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +40 -4
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js.map +1 -1
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.d.ts +10 -3
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.d.ts.map +1 -1
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.js +138 -13
- package/dist/browser/appendonlystores/IndexedDBContentAddressedStore.js.map +1 -1
- package/dist/browser/cache/IndexedDBLocalCacheStore.d.ts +21 -0
- package/dist/browser/cache/IndexedDBLocalCacheStore.d.ts.map +1 -0
- package/dist/browser/cache/IndexedDBLocalCacheStore.js +106 -0
- package/dist/browser/cache/IndexedDBLocalCacheStore.js.map +1 -0
- package/dist/browser/index.d.ts +3 -0
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +9 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/core/BaseMindooDB.d.ts +108 -13
- package/dist/core/BaseMindooDB.d.ts.map +1 -1
- package/dist/core/BaseMindooDB.js +1268 -292
- package/dist/core/BaseMindooDB.js.map +1 -1
- package/dist/core/BaseMindooTenant.d.ts +31 -1
- package/dist/core/BaseMindooTenant.d.ts.map +1 -1
- package/dist/core/BaseMindooTenant.js +212 -129
- package/dist/core/BaseMindooTenant.js.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.d.ts +13 -10
- package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.js +134 -27
- package/dist/core/BaseMindooTenantDirectory.js.map +1 -1
- package/dist/core/BaseMindooTenantFactory.d.ts +5 -1
- package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantFactory.js +46 -69
- package/dist/core/BaseMindooTenantFactory.js.map +1 -1
- package/dist/core/MindooDBServerAdmin.d.ts +241 -0
- package/dist/core/MindooDBServerAdmin.d.ts.map +1 -0
- package/dist/core/MindooDBServerAdmin.js +401 -0
- package/dist/core/MindooDBServerAdmin.js.map +1 -0
- package/dist/core/appendonlystores/AttachmentReadPlanner.d.ts +22 -0
- package/dist/core/appendonlystores/AttachmentReadPlanner.d.ts.map +1 -0
- package/dist/core/appendonlystores/AttachmentReadPlanner.js +124 -0
- package/dist/core/appendonlystores/AttachmentReadPlanner.js.map +1 -0
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts +10 -4
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.d.ts.map +1 -1
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.js +44 -9
- package/dist/core/appendonlystores/InMemoryContentAddressedStore.js.map +1 -1
- package/dist/core/appendonlystores/MaterializationPlanner.d.ts +84 -0
- package/dist/core/appendonlystores/MaterializationPlanner.d.ts.map +1 -0
- package/dist/core/appendonlystores/MaterializationPlanner.js +326 -0
- package/dist/core/appendonlystores/MaterializationPlanner.js.map +1 -0
- package/dist/core/appendonlystores/network/NetworkTransport.d.ts +33 -0
- package/dist/core/appendonlystores/network/NetworkTransport.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/types.d.ts +35 -0
- package/dist/core/appendonlystores/network/types.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/types.js +2 -0
- package/dist/core/appendonlystores/network/types.js.map +1 -1
- package/dist/core/appendonlystores/types.d.ts +174 -3
- package/dist/core/appendonlystores/types.d.ts.map +1 -1
- package/dist/core/cache/CacheManager.d.ts +75 -0
- package/dist/core/cache/CacheManager.d.ts.map +1 -0
- package/dist/core/cache/CacheManager.js +101 -0
- package/dist/core/cache/CacheManager.js.map +1 -0
- package/dist/core/cache/EncryptedLocalCacheStore.d.ts +41 -0
- package/dist/core/cache/EncryptedLocalCacheStore.d.ts.map +1 -0
- package/dist/core/cache/EncryptedLocalCacheStore.js +120 -0
- package/dist/core/cache/EncryptedLocalCacheStore.js.map +1 -0
- package/dist/core/cache/LocalCacheStore.d.ts +50 -0
- package/dist/core/cache/LocalCacheStore.d.ts.map +1 -0
- package/dist/core/cache/LocalCacheStore.js +39 -0
- package/dist/core/cache/LocalCacheStore.js.map +1 -0
- package/dist/core/crypto/privateKeyEncryption.d.ts +5 -0
- package/dist/core/crypto/privateKeyEncryption.d.ts.map +1 -0
- package/dist/core/crypto/privateKeyEncryption.js +87 -0
- package/dist/core/crypto/privateKeyEncryption.js.map +1 -0
- package/dist/core/index.d.ts +13 -6
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +13 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.d.ts +4 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js +39 -11
- package/dist/core/indexing/virtualviews/MindooDBVirtualViewDataProvider.js.map +1 -1
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.d.ts +1 -0
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.js +3 -0
- package/dist/core/indexing/virtualviews/ViewEntrySortKeyComparator.js.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualView.d.ts +43 -0
- package/dist/core/indexing/virtualviews/VirtualView.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualView.js +173 -0
- package/dist/core/indexing/virtualviews/VirtualView.js.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.d.ts +7 -0
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.d.ts.map +1 -1
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.js +28 -0
- package/dist/core/indexing/virtualviews/VirtualViewEntryData.js.map +1 -1
- package/dist/core/keys/KeyBag.d.ts +38 -14
- package/dist/core/keys/KeyBag.d.ts.map +1 -1
- package/dist/core/keys/KeyBag.js +102 -76
- package/dist/core/keys/KeyBag.js.map +1 -1
- package/dist/core/keys/KeyContext.d.ts +3 -3
- package/dist/core/keys/KeyContext.d.ts.map +1 -1
- package/dist/core/keys/KeyContext.js +10 -4
- package/dist/core/keys/KeyContext.js.map +1 -1
- package/dist/core/types.d.ts +341 -22
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +7 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils/idGeneration.d.ts.map +1 -1
- package/dist/core/utils/idGeneration.js +37 -3
- package/dist/core/utils/idGeneration.js.map +1 -1
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts +31 -7
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.d.ts.map +1 -1
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js +139 -17
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js.map +1 -1
- package/dist/node/attachments/writeAttachmentToFile.d.ts +15 -0
- package/dist/node/attachments/writeAttachmentToFile.d.ts.map +1 -0
- package/dist/node/attachments/writeAttachmentToFile.js +73 -0
- package/dist/node/attachments/writeAttachmentToFile.js.map +1 -0
- package/dist/node/cache/FileSystemLocalCacheStore.d.ts +17 -0
- package/dist/node/cache/FileSystemLocalCacheStore.d.ts.map +1 -0
- package/dist/node/cache/FileSystemLocalCacheStore.js +128 -0
- package/dist/node/cache/FileSystemLocalCacheStore.js.map +1 -0
- package/dist/node/cli/change-identity-password.d.ts +7 -0
- package/dist/node/cli/change-identity-password.d.ts.map +1 -0
- package/dist/node/cli/change-identity-password.js +67 -0
- package/dist/node/cli/change-identity-password.js.map +1 -0
- package/dist/node/cli/cli-utils.d.ts +16 -0
- package/dist/node/cli/cli-utils.d.ts.map +1 -0
- package/dist/node/cli/cli-utils.js +113 -0
- package/dist/node/cli/cli-utils.js.map +1 -0
- package/dist/node/cli/identity-export-public.d.ts +4 -0
- package/dist/node/cli/identity-export-public.d.ts.map +1 -0
- package/dist/node/cli/identity-export-public.js +55 -0
- package/dist/node/cli/identity-export-public.js.map +1 -0
- package/dist/node/cli/identity-info.d.ts +4 -0
- package/dist/node/cli/identity-info.d.ts.map +1 -0
- package/dist/node/cli/identity-info.js +57 -0
- package/dist/node/cli/identity-info.js.map +1 -0
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +4 -1
- package/dist/node/index.js.map +1 -1
- package/dist/node/server/CapabilityMatcher.d.ts +45 -0
- package/dist/node/server/CapabilityMatcher.d.ts.map +1 -0
- package/dist/node/server/CapabilityMatcher.js +117 -0
- package/dist/node/server/CapabilityMatcher.js.map +1 -0
- package/dist/node/server/MindooDBServer.d.ts +94 -0
- package/dist/node/server/MindooDBServer.d.ts.map +1 -0
- package/dist/node/server/MindooDBServer.js +1256 -0
- package/dist/node/server/MindooDBServer.js.map +1 -0
- package/dist/node/server/ServerSync.d.ts +41 -0
- package/dist/node/server/ServerSync.d.ts.map +1 -0
- package/dist/node/server/ServerSync.js +187 -0
- package/dist/node/server/ServerSync.js.map +1 -0
- package/dist/node/server/StoreFactory.d.ts +45 -0
- package/dist/node/server/StoreFactory.d.ts.map +1 -0
- package/dist/node/server/StoreFactory.js +89 -0
- package/dist/node/server/StoreFactory.js.map +1 -0
- package/dist/node/server/SystemAdminAuth.d.ts +65 -0
- package/dist/node/server/SystemAdminAuth.d.ts.map +1 -0
- package/dist/node/server/SystemAdminAuth.js +200 -0
- package/dist/node/server/SystemAdminAuth.js.map +1 -0
- package/dist/node/server/SystemIpAllowlist.d.ts +21 -0
- package/dist/node/server/SystemIpAllowlist.d.ts.map +1 -0
- package/dist/node/server/SystemIpAllowlist.js +210 -0
- package/dist/node/server/SystemIpAllowlist.js.map +1 -0
- package/dist/node/server/TenantManager.d.ts +100 -0
- package/dist/node/server/TenantManager.d.ts.map +1 -0
- package/dist/node/server/TenantManager.js +615 -0
- package/dist/node/server/TenantManager.js.map +1 -0
- package/dist/node/server/add-to-network.d.ts +20 -0
- package/dist/node/server/add-to-network.d.ts.map +1 -0
- package/dist/node/server/add-to-network.js +275 -0
- package/dist/node/server/add-to-network.js.map +1 -0
- package/dist/node/server/config.d.ts +51 -0
- package/dist/node/server/config.d.ts.map +1 -0
- package/dist/node/server/config.js +218 -0
- package/dist/node/server/config.js.map +1 -0
- package/dist/node/server/resolveServerPassword.d.ts +7 -0
- package/dist/node/server/resolveServerPassword.d.ts.map +1 -0
- package/dist/node/server/resolveServerPassword.js +25 -0
- package/dist/node/server/resolveServerPassword.js.map +1 -0
- package/dist/node/server/server.d.ts +22 -0
- package/dist/node/server/server.d.ts.map +1 -0
- package/dist/node/server/server.js +225 -0
- package/dist/node/server/server.js.map +1 -0
- package/dist/node/server/serverinit.d.ts +21 -0
- package/dist/node/server/serverinit.d.ts.map +1 -0
- package/dist/node/server/serverinit.js +317 -0
- package/dist/node/server/serverinit.js.map +1 -0
- package/dist/node/server/types.d.ts +167 -0
- package/dist/node/server/types.d.ts.map +1 -0
- package/dist/node/server/types.js +24 -0
- package/dist/node/server/types.js.map +1 -0
- package/dist/node/server/validation.d.ts +47 -0
- package/dist/node/server/validation.d.ts.map +1 -0
- package/dist/node/server/validation.js +114 -0
- package/dist/node/server/validation.js.map +1 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.d.ts +48 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.d.ts.map +1 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.js +113 -0
- package/dist/reactnative/cache/MMKVLocalCacheStore.js.map +1 -0
- package/dist/reactnative/index.d.ts +1 -0
- package/dist/reactnative/index.d.ts.map +1 -1
- package/dist/reactnative/index.js +4 -1
- package/dist/reactnative/index.js.map +1 -1
- package/package.json +15 -3
|
@@ -5,9 +5,13 @@ const types_1 = require("./types");
|
|
|
5
5
|
const BaseMindooDB_1 = require("./BaseMindooDB");
|
|
6
6
|
const BaseMindooTenantDirectory_1 = require("./BaseMindooTenantDirectory");
|
|
7
7
|
const MindooDocSigner_1 = require("./crypto/MindooDocSigner");
|
|
8
|
+
const RSAEncryption_1 = require("./crypto/RSAEncryption");
|
|
9
|
+
const privateKeyEncryption_1 = require("./crypto/privateKeyEncryption");
|
|
8
10
|
const errors_1 = require("./errors");
|
|
9
11
|
const logging_1 = require("./logging");
|
|
10
12
|
const MindooURI_1 = require("./uri/MindooURI");
|
|
13
|
+
const EncryptedLocalCacheStore_1 = require("./cache/EncryptedLocalCacheStore");
|
|
14
|
+
const CacheManager_1 = require("./cache/CacheManager");
|
|
11
15
|
/**
|
|
12
16
|
* BaseMindooTenant is a platform-agnostic implementation of MindooTenant
|
|
13
17
|
* that works in both browser and server environments.
|
|
@@ -23,9 +27,12 @@ const MindooURI_1 = require("./uri/MindooURI");
|
|
|
23
27
|
* - PBKDF2 key derivation (for password-based key derivation)
|
|
24
28
|
*/
|
|
25
29
|
class BaseMindooTenant {
|
|
26
|
-
constructor(factory, tenantId, administrationPublicKey, administrationEncryptionPublicKey, currentUser, currentUserPassword, keyBag, storeFactory, cryptoAdapter, logger, additionalTrustedKeys) {
|
|
30
|
+
constructor(factory, tenantId, administrationPublicKey, administrationEncryptionPublicKey, currentUser, currentUserPassword, keyBag, storeFactory, cryptoAdapter, logger, additionalTrustedKeys, localCacheStore) {
|
|
27
31
|
this.databaseCache = new Map();
|
|
28
32
|
this.directoryCache = null;
|
|
33
|
+
this.remoteStoreCache = new Map();
|
|
34
|
+
// Local cache support
|
|
35
|
+
this.cacheManager = null;
|
|
29
36
|
this.factory = factory;
|
|
30
37
|
this.tenantId = tenantId;
|
|
31
38
|
this.administrationPublicKey = administrationPublicKey;
|
|
@@ -47,6 +54,11 @@ class BaseMindooTenant {
|
|
|
47
54
|
this.logger =
|
|
48
55
|
logger ||
|
|
49
56
|
new logging_1.MindooLogger((0, logging_1.getDefaultLogLevel)(), `Tenant:${tenantId}`, true);
|
|
57
|
+
// Set up cache if a local cache store is provided
|
|
58
|
+
if (localCacheStore) {
|
|
59
|
+
const encryptedStore = new EncryptedLocalCacheStore_1.EncryptedLocalCacheStore(localCacheStore, currentUserPassword, this.cryptoAdapter, this.logger.createChild("EncryptedCache"));
|
|
60
|
+
this.cacheManager = new CacheManager_1.CacheManager(encryptedStore, undefined, this.logger.createChild("CacheManager"));
|
|
61
|
+
}
|
|
50
62
|
}
|
|
51
63
|
/**
|
|
52
64
|
* Initialize the tenant.
|
|
@@ -57,6 +69,22 @@ class BaseMindooTenant {
|
|
|
57
69
|
const keyCount = (await this.keyBag.listKeys()).length;
|
|
58
70
|
this.logger.info(`Tenant initialized with ${keyCount} keys in KeyBag`);
|
|
59
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Get the CacheManager for this tenant (null if caching is disabled).
|
|
74
|
+
*/
|
|
75
|
+
getCacheManager() {
|
|
76
|
+
return this.cacheManager;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Flush and dispose the cache manager.
|
|
80
|
+
* Should be called when the tenant is being closed.
|
|
81
|
+
*/
|
|
82
|
+
async disposeCacheManager() {
|
|
83
|
+
if (this.cacheManager) {
|
|
84
|
+
await this.cacheManager.dispose();
|
|
85
|
+
this.cacheManager = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
60
88
|
getCryptoAdapter() {
|
|
61
89
|
return this.cryptoAdapter;
|
|
62
90
|
}
|
|
@@ -100,9 +128,9 @@ class BaseMindooTenant {
|
|
|
100
128
|
}
|
|
101
129
|
else {
|
|
102
130
|
this.logger.debug(`Resolving tenant encryption key from KeyBag`);
|
|
103
|
-
const tenantKey = await this.keyBag.get("
|
|
131
|
+
const tenantKey = await this.keyBag.get("doc", this.tenantId, types_1.DEFAULT_TENANT_KEY_ID);
|
|
104
132
|
if (!tenantKey) {
|
|
105
|
-
throw new errors_1.SymmetricKeyNotFoundError(`
|
|
133
|
+
throw new errors_1.SymmetricKeyNotFoundError(`doc:${this.tenantId}:${types_1.DEFAULT_TENANT_KEY_ID}`);
|
|
106
134
|
}
|
|
107
135
|
symmetricKey = tenantKey;
|
|
108
136
|
this.decryptedTenantKeyCache = symmetricKey;
|
|
@@ -112,7 +140,7 @@ class BaseMindooTenant {
|
|
|
112
140
|
else {
|
|
113
141
|
this.logger.debug(`Getting named key from KeyBag: ${decryptionKeyId}`);
|
|
114
142
|
// Get the decrypted key from KeyBag
|
|
115
|
-
const decryptedKey = await this.keyBag.get("doc", decryptionKeyId);
|
|
143
|
+
const decryptedKey = await this.keyBag.get("doc", this.tenantId, decryptionKeyId);
|
|
116
144
|
if (!decryptedKey) {
|
|
117
145
|
throw new errors_1.SymmetricKeyNotFoundError(decryptionKeyId);
|
|
118
146
|
}
|
|
@@ -210,9 +238,9 @@ class BaseMindooTenant {
|
|
|
210
238
|
symmetricKey = this.decryptedTenantKeyCache;
|
|
211
239
|
}
|
|
212
240
|
else {
|
|
213
|
-
const tenantKey = await this.keyBag.get("
|
|
241
|
+
const tenantKey = await this.keyBag.get("doc", this.tenantId, types_1.DEFAULT_TENANT_KEY_ID);
|
|
214
242
|
if (!tenantKey) {
|
|
215
|
-
throw new errors_1.SymmetricKeyNotFoundError(`
|
|
243
|
+
throw new errors_1.SymmetricKeyNotFoundError(`doc:${this.tenantId}:${types_1.DEFAULT_TENANT_KEY_ID}`);
|
|
216
244
|
}
|
|
217
245
|
symmetricKey = tenantKey;
|
|
218
246
|
this.decryptedTenantKeyCache = symmetricKey;
|
|
@@ -220,7 +248,7 @@ class BaseMindooTenant {
|
|
|
220
248
|
}
|
|
221
249
|
else {
|
|
222
250
|
// Get the decrypted key from KeyBag
|
|
223
|
-
const decryptedKey = await this.keyBag.get("doc", decryptionKeyId);
|
|
251
|
+
const decryptedKey = await this.keyBag.get("doc", this.tenantId, decryptionKeyId);
|
|
224
252
|
if (!decryptedKey) {
|
|
225
253
|
throw new errors_1.SymmetricKeyNotFoundError(decryptionKeyId);
|
|
226
254
|
}
|
|
@@ -326,12 +354,31 @@ class BaseMindooTenant {
|
|
|
326
354
|
}
|
|
327
355
|
return this.directoryCache;
|
|
328
356
|
}
|
|
357
|
+
async assertCurrentUserCanOpenDB(id) {
|
|
358
|
+
if (id === "directory") {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const currentUser = await this.getCurrentUserId();
|
|
362
|
+
if (currentUser.userSigningPublicKey === this.getAdministrationPublicKey()) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const directory = await this.openDirectory();
|
|
366
|
+
const registeredUser = await directory.getUserPublicKeys(currentUser.username);
|
|
367
|
+
const hasMatchingGrant = registeredUser?.signingPublicKey === currentUser.userSigningPublicKey &&
|
|
368
|
+
registeredUser?.encryptionPublicKey === currentUser.userEncryptionPublicKey;
|
|
369
|
+
if (hasMatchingGrant) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
this.logger.warn(`Denied database open for ungranted user ${currentUser.username} on database ${id}`);
|
|
373
|
+
throw new Error(`User "${currentUser.username}" does not have tenant access yet; the tenant admin must grant access first.`);
|
|
374
|
+
}
|
|
329
375
|
async openDB(id, options) {
|
|
330
376
|
// Enforce admin-only mode for directory database - this is a security invariant
|
|
331
377
|
// The directory database must only accept entries signed by the admin key
|
|
332
378
|
const effectiveOptions = id === "directory"
|
|
333
379
|
? { ...options, adminOnlyDb: true }
|
|
334
380
|
: options ?? {};
|
|
381
|
+
await this.assertCurrentUserCanOpenDB(id);
|
|
335
382
|
// Return cached database if it exists
|
|
336
383
|
const cached = this.databaseCache.get(id);
|
|
337
384
|
if (cached) {
|
|
@@ -342,11 +389,14 @@ class BaseMindooTenant {
|
|
|
342
389
|
return cached;
|
|
343
390
|
}
|
|
344
391
|
// Extract store options and DB-specific options
|
|
345
|
-
const { adminOnlyDb, attachmentConfig, ...storeOptions } = effectiveOptions;
|
|
392
|
+
const { adminOnlyDb, attachmentConfig, documentCacheConfig, snapshotConfig, performanceCallback, ...storeOptions } = effectiveOptions;
|
|
346
393
|
// Create the database stores using the factory
|
|
347
394
|
const { docStore, attachmentStore } = this.storeFactory.createStore(id, storeOptions);
|
|
348
395
|
const dbLogger = this.logger.createChild("BaseMindooDB");
|
|
349
|
-
const db = new BaseMindooDB_1.BaseMindooDB(this, docStore, attachmentStore, attachmentConfig, adminOnlyDb ?? false, dbLogger);
|
|
396
|
+
const db = new BaseMindooDB_1.BaseMindooDB(this, docStore, attachmentStore, attachmentConfig, documentCacheConfig, snapshotConfig, adminOnlyDb ?? false, dbLogger, performanceCallback);
|
|
397
|
+
if (this.cacheManager) {
|
|
398
|
+
db.setCacheManager(this.cacheManager);
|
|
399
|
+
}
|
|
350
400
|
await db.initialize();
|
|
351
401
|
// Cache the database for future use
|
|
352
402
|
this.databaseCache.set(id, db);
|
|
@@ -384,12 +434,12 @@ class BaseMindooTenant {
|
|
|
384
434
|
};
|
|
385
435
|
await directory.registerUser(publicUserId, options.adminSigningKey, options.adminPassword);
|
|
386
436
|
// 2. Export the tenant key encrypted with the share password
|
|
387
|
-
const encryptedTenantKey = await this.keyBag.encryptAndExportKey("
|
|
437
|
+
const encryptedTenantKey = await this.keyBag.encryptAndExportKey("doc", this.tenantId, types_1.DEFAULT_TENANT_KEY_ID, options.sharePassword);
|
|
388
438
|
if (!encryptedTenantKey) {
|
|
389
439
|
throw new Error(`Failed to export tenant key for tenant "${this.tenantId}"`);
|
|
390
440
|
}
|
|
391
441
|
// 3. Export the $publicinfos key encrypted with the share password
|
|
392
|
-
const encryptedPublicInfosKey = await this.keyBag.encryptAndExportKey("doc", types_1.PUBLIC_INFOS_KEY_ID, options.sharePassword);
|
|
442
|
+
const encryptedPublicInfosKey = await this.keyBag.encryptAndExportKey("doc", this.tenantId, types_1.PUBLIC_INFOS_KEY_ID, options.sharePassword);
|
|
393
443
|
if (!encryptedPublicInfosKey) {
|
|
394
444
|
throw new Error(`Failed to export $publicinfos key`);
|
|
395
445
|
}
|
|
@@ -415,23 +465,59 @@ class BaseMindooTenant {
|
|
|
415
465
|
}
|
|
416
466
|
/**
|
|
417
467
|
* Publish (register) this tenant on a MindooDB server.
|
|
468
|
+
*
|
|
469
|
+
* When `systemAdminUser` + `systemAdminPassword` are provided the method
|
|
470
|
+
* performs a challenge/response handshake against `/system/auth/*` to
|
|
471
|
+
* obtain a JWT, then calls `POST /system/tenants/:tenantId`.
|
|
418
472
|
*/
|
|
419
473
|
async publishToServer(serverUrl, options) {
|
|
420
474
|
console.log(`[publishToServer] Publishing tenant "${this.tenantId}" to server: ${serverUrl}`);
|
|
421
475
|
this.logger.info(`Publishing tenant "${this.tenantId}" to server: ${serverUrl}`);
|
|
476
|
+
const baseUrl = serverUrl.replace(/\/$/, "");
|
|
422
477
|
// Export the $publicinfos key so the server can read the directory DB
|
|
423
|
-
const publicInfosKeyBytes = await this.keyBag.get("doc", types_1.PUBLIC_INFOS_KEY_ID);
|
|
478
|
+
const publicInfosKeyBytes = await this.keyBag.get("doc", this.tenantId, types_1.PUBLIC_INFOS_KEY_ID);
|
|
424
479
|
if (!publicInfosKeyBytes) {
|
|
425
480
|
throw new Error(`Cannot publish to server: $publicinfos key not found in KeyBag`);
|
|
426
481
|
}
|
|
427
|
-
|
|
428
|
-
// Build the registration request
|
|
482
|
+
// Build the registration request body
|
|
429
483
|
const requestBody = {
|
|
430
|
-
tenantId: this.tenantId,
|
|
431
484
|
adminSigningPublicKey: this.administrationPublicKey,
|
|
432
485
|
adminEncryptionPublicKey: this.administrationEncryptionPublicKey,
|
|
433
|
-
publicInfosKey: publicInfosKeyBase64,
|
|
434
486
|
};
|
|
487
|
+
try {
|
|
488
|
+
const serverInfoResponse = await fetch(`${baseUrl}/.well-known/mindoodb-server-info`, {
|
|
489
|
+
headers: {
|
|
490
|
+
Accept: "application/json",
|
|
491
|
+
},
|
|
492
|
+
});
|
|
493
|
+
let serverInfoBody = null;
|
|
494
|
+
try {
|
|
495
|
+
serverInfoBody = await serverInfoResponse.json();
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
serverInfoBody = null;
|
|
499
|
+
}
|
|
500
|
+
if (!serverInfoResponse.ok) {
|
|
501
|
+
throw new Error(typeof serverInfoBody?.error === "string"
|
|
502
|
+
? serverInfoBody.error
|
|
503
|
+
: `Could not read ${baseUrl}/.well-known/mindoodb-server-info (HTTP ${serverInfoResponse.status}).`);
|
|
504
|
+
}
|
|
505
|
+
if (!serverInfoBody
|
|
506
|
+
|| typeof serverInfoBody !== "object"
|
|
507
|
+
|| Array.isArray(serverInfoBody)
|
|
508
|
+
|| typeof serverInfoBody.encryptionPublicKey !== "string") {
|
|
509
|
+
throw new Error("The server returned an invalid .well-known payload.");
|
|
510
|
+
}
|
|
511
|
+
const rsaEncryption = new RSAEncryption_1.RSAEncryption(this.cryptoAdapter);
|
|
512
|
+
requestBody.encryptedPublicInfosKey = this.uint8ArrayToBase64(await rsaEncryption.encrypt(publicInfosKeyBytes, serverInfoBody.encryptionPublicKey));
|
|
513
|
+
}
|
|
514
|
+
catch (error) {
|
|
515
|
+
console.warn("[publishToServer] Falling back to raw publicInfosKey transport:", error);
|
|
516
|
+
requestBody.publicInfosKey = this.uint8ArrayToBase64(publicInfosKeyBytes);
|
|
517
|
+
}
|
|
518
|
+
if (options?.adminUsername) {
|
|
519
|
+
requestBody.adminUsername = options.adminUsername;
|
|
520
|
+
}
|
|
435
521
|
// Add users if provided
|
|
436
522
|
if (options?.registerUsers && options.registerUsers.length > 0) {
|
|
437
523
|
requestBody.users = options.registerUsers.map((u) => ({
|
|
@@ -440,15 +526,16 @@ class BaseMindooTenant {
|
|
|
440
526
|
encryptionPublicKey: u.userEncryptionPublicKey,
|
|
441
527
|
}));
|
|
442
528
|
}
|
|
443
|
-
//
|
|
529
|
+
// Authenticate as system admin via challenge/response
|
|
444
530
|
const headers = {
|
|
445
531
|
"Content-Type": "application/json",
|
|
446
532
|
};
|
|
447
|
-
if (options?.
|
|
448
|
-
|
|
533
|
+
if (options?.systemAdminUser && options?.systemAdminPassword) {
|
|
534
|
+
const token = await this.authenticateAsSystemAdmin(baseUrl, options.systemAdminUser, options.systemAdminPassword);
|
|
535
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
449
536
|
}
|
|
450
|
-
// POST to
|
|
451
|
-
const url = `${
|
|
537
|
+
// POST to /system/tenants/:tenantId
|
|
538
|
+
const url = `${baseUrl}/system/tenants/${encodeURIComponent(this.tenantId)}`;
|
|
452
539
|
const response = await fetch(url, {
|
|
453
540
|
method: "POST",
|
|
454
541
|
headers,
|
|
@@ -461,31 +548,90 @@ class BaseMindooTenant {
|
|
|
461
548
|
console.log(`[publishToServer] ✓ Tenant "${this.tenantId}" published to server successfully`);
|
|
462
549
|
this.logger.info(`Tenant "${this.tenantId}" published to server successfully`);
|
|
463
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
* Perform system admin challenge/response auth and return a JWT token.
|
|
553
|
+
*/
|
|
554
|
+
async authenticateAsSystemAdmin(baseUrl, adminUser, adminPassword) {
|
|
555
|
+
const subtle = this.cryptoAdapter.getSubtle();
|
|
556
|
+
// Decrypt the admin's signing private key
|
|
557
|
+
const signingKeyBuffer = await this.decryptPrivateKey(adminUser.userSigningKeyPair.privateKey, adminPassword, "signing");
|
|
558
|
+
const signingKey = await subtle.importKey("pkcs8", signingKeyBuffer, { name: "Ed25519" }, false, ["sign"]);
|
|
559
|
+
// Step 1: Request challenge from server
|
|
560
|
+
const challengeRes = await fetch(`${baseUrl}/system/auth/challenge`, {
|
|
561
|
+
method: "POST",
|
|
562
|
+
headers: { "Content-Type": "application/json" },
|
|
563
|
+
body: JSON.stringify({
|
|
564
|
+
username: adminUser.username,
|
|
565
|
+
publicsignkey: adminUser.userSigningKeyPair.publicKey,
|
|
566
|
+
}),
|
|
567
|
+
});
|
|
568
|
+
if (!challengeRes.ok) {
|
|
569
|
+
const errorBody = await challengeRes.text();
|
|
570
|
+
throw new Error(`System admin challenge failed (HTTP ${challengeRes.status}): ${errorBody}`);
|
|
571
|
+
}
|
|
572
|
+
const { challenge } = (await challengeRes.json());
|
|
573
|
+
// Step 2: Sign the challenge
|
|
574
|
+
const messageBytes = new TextEncoder().encode(challenge);
|
|
575
|
+
const signatureBuffer = await subtle.sign({ name: "Ed25519" }, signingKey, messageBytes);
|
|
576
|
+
const signatureBase64 = this.uint8ArrayToBase64(new Uint8Array(signatureBuffer));
|
|
577
|
+
// Step 3: Authenticate
|
|
578
|
+
const authRes = await fetch(`${baseUrl}/system/auth/authenticate`, {
|
|
579
|
+
method: "POST",
|
|
580
|
+
headers: { "Content-Type": "application/json" },
|
|
581
|
+
body: JSON.stringify({ challenge, signature: signatureBase64 }),
|
|
582
|
+
});
|
|
583
|
+
if (!authRes.ok) {
|
|
584
|
+
const errorBody = await authRes.text();
|
|
585
|
+
throw new Error(`System admin authentication failed (HTTP ${authRes.status}): ${errorBody}`);
|
|
586
|
+
}
|
|
587
|
+
const result = (await authRes.json());
|
|
588
|
+
if (!result.success || !result.token) {
|
|
589
|
+
throw new Error(`System admin authentication failed: ${result.error || "unknown error"}`);
|
|
590
|
+
}
|
|
591
|
+
return result.token;
|
|
592
|
+
}
|
|
464
593
|
/**
|
|
465
594
|
* Create a remote store connected to a MindooDB server, ready for sync.
|
|
466
595
|
*/
|
|
467
596
|
async connectToServer(serverUrl, dbId) {
|
|
468
597
|
console.log(`[connectToServer] Connecting to server: ${serverUrl}, db: ${dbId}`);
|
|
469
598
|
this.logger.info(`Connecting to server: ${serverUrl}, db: ${dbId}`);
|
|
470
|
-
|
|
471
|
-
const
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
599
|
+
const normalizedServerUrl = serverUrl.replace(/\/$/, "");
|
|
600
|
+
const cacheKey = `${normalizedServerUrl}::${dbId}`;
|
|
601
|
+
const cachedStore = this.remoteStoreCache.get(cacheKey);
|
|
602
|
+
if (cachedStore) {
|
|
603
|
+
this.logger.debug(`Reusing cached remote store for ${normalizedServerUrl}, db: ${dbId}`);
|
|
604
|
+
return cachedStore;
|
|
605
|
+
}
|
|
606
|
+
const remoteStorePromise = (async () => {
|
|
607
|
+
// Lazy-import network modules to avoid circular dependencies and keep core lightweight
|
|
608
|
+
const { HttpTransport } = await import("../appendonlystores/network/HttpTransport.js");
|
|
609
|
+
const { ClientNetworkContentAddressedStore } = await import("../appendonlystores/network/ClientNetworkContentAddressedStore.js");
|
|
610
|
+
// Create the HTTP transport
|
|
611
|
+
const baseUrl = `${normalizedServerUrl}/${this.tenantId}`;
|
|
612
|
+
const transport = new HttpTransport({
|
|
613
|
+
baseUrl,
|
|
614
|
+
tenantId: this.tenantId,
|
|
615
|
+
dbId,
|
|
616
|
+
}, this.logger.createChild("HttpTransport"));
|
|
617
|
+
// Get the current user's decrypted signing key
|
|
618
|
+
const signingKey = await this.getDecryptedSigningKey();
|
|
619
|
+
// Get the current user's decrypted RSA encryption private key (for decrypting entries)
|
|
620
|
+
const decryptedEncryptionKey = await this.getDecryptedEncryptionKey();
|
|
621
|
+
// Create the client network store
|
|
622
|
+
const store = new ClientNetworkContentAddressedStore(dbId, transport, this.cryptoAdapter, this.currentUser.username, signingKey, decryptedEncryptionKey, this.logger.createChild(`ClientNetworkStore:${dbId}`));
|
|
623
|
+
console.log(`[connectToServer] ✓ Connected to server for db "${dbId}"`);
|
|
624
|
+
this.logger.info(`Connected to server for db "${dbId}"`);
|
|
625
|
+
return store;
|
|
626
|
+
})();
|
|
627
|
+
this.remoteStoreCache.set(cacheKey, remoteStorePromise);
|
|
628
|
+
try {
|
|
629
|
+
return await remoteStorePromise;
|
|
630
|
+
}
|
|
631
|
+
catch (error) {
|
|
632
|
+
this.remoteStoreCache.delete(cacheKey);
|
|
633
|
+
throw error;
|
|
634
|
+
}
|
|
489
635
|
}
|
|
490
636
|
/**
|
|
491
637
|
* Internal method to get the decrypted signing key for the current user.
|
|
@@ -538,104 +684,22 @@ class BaseMindooTenant {
|
|
|
538
684
|
this.logger.debug(`decryptPrivateKey: Starting decryption with saltString: ${saltString}`);
|
|
539
685
|
this.logger.debug(`decryptPrivateKey: Password length: ${password.length}`);
|
|
540
686
|
this.logger.debug(`decryptPrivateKey: EncryptedKey iterations: ${encryptedKey.iterations}`);
|
|
541
|
-
|
|
542
|
-
// Decode base64 strings
|
|
543
|
-
this.logger.debug(`decryptPrivateKey: Decoding base64 strings`);
|
|
544
|
-
let ciphertext;
|
|
545
|
-
let iv;
|
|
546
|
-
let tag;
|
|
547
|
-
let saltBytes;
|
|
687
|
+
this.logger.debug(`decryptPrivateKey: Delegating PBKDF2 + AES-GCM work to shared helper`);
|
|
548
688
|
try {
|
|
549
|
-
|
|
550
|
-
iv = this.base64ToUint8Array(encryptedKey.iv);
|
|
551
|
-
tag = this.base64ToUint8Array(encryptedKey.tag);
|
|
552
|
-
saltBytes = this.base64ToUint8Array(encryptedKey.salt);
|
|
553
|
-
this.logger.debug(`decryptPrivateKey: Decoded - ciphertext: ${ciphertext.length} bytes, iv: ${iv.length} bytes, tag: ${tag.length} bytes, salt: ${saltBytes.length} bytes`);
|
|
554
|
-
}
|
|
555
|
-
catch (error) {
|
|
556
|
-
this.logger.error(`decryptPrivateKey: Error decoding base64:`, error);
|
|
557
|
-
throw error;
|
|
558
|
-
}
|
|
559
|
-
// Derive key from password using PBKDF2
|
|
560
|
-
// Combine the stored salt bytes with the salt string for additional security
|
|
561
|
-
// This ensures different key types (signing, encryption, etc.) use different derived keys
|
|
562
|
-
// even if they share the same password
|
|
563
|
-
this.logger.debug(`decryptPrivateKey: Combining salt with saltString`);
|
|
564
|
-
const saltStringBytes = new TextEncoder().encode(saltString);
|
|
565
|
-
const combinedSalt = new Uint8Array(saltBytes.length + saltStringBytes.length);
|
|
566
|
-
combinedSalt.set(saltBytes);
|
|
567
|
-
combinedSalt.set(saltStringBytes, saltBytes.length);
|
|
568
|
-
this.logger.debug(`decryptPrivateKey: Combined salt length: ${combinedSalt.length} bytes`);
|
|
569
|
-
this.logger.debug(`decryptPrivateKey: Importing password key for PBKDF2`);
|
|
570
|
-
let passwordKey;
|
|
571
|
-
try {
|
|
572
|
-
passwordKey = await subtle.importKey("raw", new TextEncoder().encode(password), "PBKDF2", false, ["deriveBits", "deriveKey"]);
|
|
573
|
-
this.logger.debug(`decryptPrivateKey: Successfully imported password key`);
|
|
574
|
-
}
|
|
575
|
-
catch (error) {
|
|
576
|
-
this.logger.error(`decryptPrivateKey: Error importing password key:`, error);
|
|
577
|
-
throw error;
|
|
578
|
-
}
|
|
579
|
-
this.logger.debug(`decryptPrivateKey: Deriving key with PBKDF2 (iterations: ${encryptedKey.iterations})`);
|
|
580
|
-
let derivedKey;
|
|
581
|
-
try {
|
|
582
|
-
derivedKey = await subtle.deriveKey({
|
|
583
|
-
name: "PBKDF2",
|
|
584
|
-
salt: combinedSalt,
|
|
585
|
-
iterations: encryptedKey.iterations,
|
|
586
|
-
hash: "SHA-256",
|
|
587
|
-
}, passwordKey, {
|
|
588
|
-
name: "AES-GCM",
|
|
589
|
-
length: 256,
|
|
590
|
-
}, false, ["decrypt"]);
|
|
591
|
-
this.logger.debug(`decryptPrivateKey: Successfully derived key`);
|
|
592
|
-
}
|
|
593
|
-
catch (error) {
|
|
594
|
-
this.logger.error(`decryptPrivateKey: Error deriving key:`, error);
|
|
595
|
-
throw error;
|
|
596
|
-
}
|
|
597
|
-
// Combine ciphertext and tag (GCM authentication tag is separate)
|
|
598
|
-
// AES-GCM expects the tag to be appended to the ciphertext
|
|
599
|
-
this.logger.debug(`decryptPrivateKey: Combining ciphertext and tag`);
|
|
600
|
-
const encryptedData = new Uint8Array(ciphertext.length + tag.length);
|
|
601
|
-
encryptedData.set(ciphertext);
|
|
602
|
-
encryptedData.set(tag, ciphertext.length);
|
|
603
|
-
this.logger.debug(`decryptPrivateKey: Combined encrypted data length: ${encryptedData.length} bytes`);
|
|
604
|
-
// Decrypt the private key
|
|
605
|
-
this.logger.debug(`decryptPrivateKey: Decrypting with AES-GCM`);
|
|
606
|
-
this.logger.debug(`decryptPrivateKey: IV length: ${iv.length} bytes (expected: 12 for AES-GCM)`);
|
|
607
|
-
this.logger.debug(`decryptPrivateKey: Tag length: ${tag.length} bytes (expected: 16 for 128-bit tag)`);
|
|
608
|
-
this.logger.debug(`decryptPrivateKey: Ciphertext length: ${ciphertext.length} bytes`);
|
|
609
|
-
let decrypted;
|
|
610
|
-
try {
|
|
611
|
-
// Create a new ArrayBuffer to ensure we have the correct buffer without any offset issues
|
|
612
|
-
const encryptedBuffer = new Uint8Array(encryptedData).buffer;
|
|
613
|
-
this.logger.debug(`decryptPrivateKey: Encrypted buffer size: ${encryptedBuffer.byteLength} bytes`);
|
|
614
|
-
decrypted = await subtle.decrypt({
|
|
615
|
-
name: "AES-GCM",
|
|
616
|
-
iv: new Uint8Array(iv), // Create a new Uint8Array to ensure proper buffer
|
|
617
|
-
tagLength: 128,
|
|
618
|
-
}, derivedKey, encryptedBuffer);
|
|
689
|
+
const decrypted = await (0, privateKeyEncryption_1.decryptPrivateKey)(this.cryptoAdapter, encryptedKey, password, saltString);
|
|
619
690
|
this.logger.debug(`decryptPrivateKey: Successfully decrypted, result length: ${decrypted.byteLength} bytes`);
|
|
691
|
+
return decrypted;
|
|
620
692
|
}
|
|
621
693
|
catch (error) {
|
|
622
694
|
this.logger.error(`decryptPrivateKey: Error during decryption:`, error);
|
|
623
695
|
this.logger.error(`decryptPrivateKey: Error details:`, {
|
|
624
696
|
errorName: error instanceof Error ? error.name : typeof error,
|
|
625
697
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
626
|
-
ivLength: iv.length,
|
|
627
|
-
tagLength: tag.length,
|
|
628
|
-
ciphertextLength: ciphertext.length,
|
|
629
|
-
encryptedDataLength: encryptedData.length,
|
|
630
698
|
iterations: encryptedKey.iterations,
|
|
631
|
-
saltString
|
|
632
|
-
encryptedDataByteOffset: encryptedData.byteOffset,
|
|
633
|
-
encryptedDataByteLength: encryptedData.byteLength,
|
|
634
|
-
encryptedDataBufferLength: encryptedData.buffer.byteLength,
|
|
699
|
+
saltString,
|
|
635
700
|
});
|
|
636
701
|
throw error;
|
|
637
702
|
}
|
|
638
|
-
return decrypted;
|
|
639
703
|
}
|
|
640
704
|
/**
|
|
641
705
|
* Helper method to convert base64 string to Uint8Array
|
|
@@ -682,6 +746,25 @@ class BaseMindooTenant {
|
|
|
682
746
|
}
|
|
683
747
|
return bytes.buffer;
|
|
684
748
|
}
|
|
749
|
+
/**
|
|
750
|
+
* Check whether the symmetric key for the given key ID is available in the KeyBag.
|
|
751
|
+
* This is a lightweight probe that does not perform any crypto operations.
|
|
752
|
+
*
|
|
753
|
+
* @param decryptionKeyId The key ID ("default" or a named key ID)
|
|
754
|
+
* @returns true if the key can be resolved, false otherwise
|
|
755
|
+
*/
|
|
756
|
+
async hasDecryptionKey(decryptionKeyId) {
|
|
757
|
+
try {
|
|
758
|
+
await this.getSymmetricKey(decryptionKeyId);
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
761
|
+
catch (error) {
|
|
762
|
+
if (error instanceof errors_1.SymmetricKeyNotFoundError) {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
throw error;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
685
768
|
/**
|
|
686
769
|
* Get the symmetric key for a given key ID.
|
|
687
770
|
* This is a protected helper method that can be used by subclasses.
|
|
@@ -695,9 +778,9 @@ class BaseMindooTenant {
|
|
|
695
778
|
if (this.decryptedTenantKeyCache) {
|
|
696
779
|
return this.decryptedTenantKeyCache;
|
|
697
780
|
}
|
|
698
|
-
const tenantKey = await this.keyBag.get("
|
|
781
|
+
const tenantKey = await this.keyBag.get("doc", this.tenantId, types_1.DEFAULT_TENANT_KEY_ID);
|
|
699
782
|
if (!tenantKey) {
|
|
700
|
-
throw new errors_1.SymmetricKeyNotFoundError(`
|
|
783
|
+
throw new errors_1.SymmetricKeyNotFoundError(`doc:${this.tenantId}:${types_1.DEFAULT_TENANT_KEY_ID}`);
|
|
701
784
|
}
|
|
702
785
|
const symmetricKey = tenantKey;
|
|
703
786
|
this.decryptedTenantKeyCache = symmetricKey;
|
|
@@ -705,7 +788,7 @@ class BaseMindooTenant {
|
|
|
705
788
|
}
|
|
706
789
|
else {
|
|
707
790
|
// Get the decrypted key from KeyBag
|
|
708
|
-
const decryptedKey = await this.keyBag.get("doc", decryptionKeyId);
|
|
791
|
+
const decryptedKey = await this.keyBag.get("doc", this.tenantId, decryptionKeyId);
|
|
709
792
|
if (!decryptedKey) {
|
|
710
793
|
throw new errors_1.SymmetricKeyNotFoundError(decryptionKeyId);
|
|
711
794
|
}
|