mindoodb 0.0.85 → 0.0.86
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 +1 -0
- package/README.md +6 -4
- package/dist/cloudflare/DurableObjectSql.d.ts +56 -0
- package/dist/cloudflare/DurableObjectSql.d.ts.map +1 -0
- package/dist/cloudflare/DurableObjectSql.js +180 -0
- package/dist/cloudflare/DurableObjectSql.js.map +1 -0
- package/dist/cloudflare/MindooDatabaseObject.d.ts +86 -0
- package/dist/cloudflare/MindooDatabaseObject.d.ts.map +1 -0
- package/dist/cloudflare/MindooDatabaseObject.js +614 -0
- package/dist/cloudflare/MindooDatabaseObject.js.map +1 -0
- package/dist/cloudflare/MindooServerObject.d.ts +63 -0
- package/dist/cloudflare/MindooServerObject.d.ts.map +1 -0
- package/dist/cloudflare/MindooServerObject.js +521 -0
- package/dist/cloudflare/MindooServerObject.js.map +1 -0
- package/dist/cloudflare/WorkersCryptoAdapter.d.ts +7 -0
- package/dist/cloudflare/WorkersCryptoAdapter.d.ts.map +1 -0
- package/dist/cloudflare/WorkersCryptoAdapter.js +14 -0
- package/dist/cloudflare/WorkersCryptoAdapter.js.map +1 -0
- package/dist/cloudflare/host.d.ts +49 -0
- package/dist/cloudflare/host.d.ts.map +1 -0
- package/dist/cloudflare/host.js +104 -0
- package/dist/cloudflare/host.js.map +1 -0
- package/dist/cloudflare/http.d.ts +91 -0
- package/dist/cloudflare/http.d.ts.map +1 -0
- package/dist/cloudflare/http.js +266 -0
- package/dist/cloudflare/http.js.map +1 -0
- package/dist/cloudflare/index.d.ts +12 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +20 -0
- package/dist/cloudflare/index.js.map +1 -0
- package/dist/cloudflare/storeRpc.d.ts +22 -0
- package/dist/cloudflare/storeRpc.d.ts.map +1 -0
- package/dist/cloudflare/storeRpc.js +85 -0
- package/dist/cloudflare/storeRpc.js.map +1 -0
- package/dist/cloudflare/types.d.ts +101 -0
- package/dist/cloudflare/types.d.ts.map +1 -0
- package/dist/cloudflare/types.js +10 -0
- package/dist/cloudflare/types.js.map +1 -0
- package/dist/cloudflare/worker.d.ts +25 -0
- package/dist/cloudflare/worker.d.ts.map +1 -0
- package/dist/cloudflare/worker.js +170 -0
- package/dist/cloudflare/worker.js.map +1 -0
- package/dist/core/BaseMindooDB.d.ts +28 -1
- package/dist/core/BaseMindooDB.d.ts.map +1 -1
- package/dist/core/BaseMindooDB.js +180 -86
- package/dist/core/BaseMindooDB.js.map +1 -1
- package/dist/core/BaseMindooTenant.d.ts +14 -0
- package/dist/core/BaseMindooTenant.d.ts.map +1 -1
- package/dist/core/BaseMindooTenant.js +46 -0
- package/dist/core/BaseMindooTenant.js.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.d.ts +10 -0
- package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.js +79 -8
- package/dist/core/BaseMindooTenantDirectory.js.map +1 -1
- package/dist/core/ChangeDocDraft.d.ts +133 -0
- package/dist/core/ChangeDocDraft.d.ts.map +1 -0
- package/dist/core/ChangeDocDraft.js +492 -0
- package/dist/core/ChangeDocDraft.js.map +1 -0
- package/dist/core/appendonlystores/network/AuthenticationService.d.ts +8 -0
- package/dist/core/appendonlystores/network/AuthenticationService.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/AuthenticationService.js +19 -0
- package/dist/core/appendonlystores/network/AuthenticationService.js.map +1 -1
- package/dist/core/appendonlystores/network/IrohStreamIO.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/IrohStreamIO.js +3 -23
- package/dist/core/appendonlystores/network/IrohStreamIO.js.map +1 -1
- package/dist/core/appendonlystores/rpc/storeRpcCodec.d.ts.map +1 -1
- package/dist/core/appendonlystores/rpc/storeRpcCodec.js +3 -23
- package/dist/core/appendonlystores/rpc/storeRpcCodec.js.map +1 -1
- package/dist/core/appendonlystores/sqlite/SqliteContentAddressedStore.d.ts.map +1 -1
- package/dist/core/appendonlystores/sqlite/SqliteContentAddressedStore.js +21 -30
- package/dist/core/appendonlystores/sqlite/SqliteContentAddressedStore.js.map +1 -1
- package/dist/core/appendonlystores/sqlite/SqliteDriver.d.ts +37 -1
- package/dist/core/appendonlystores/sqlite/SqliteDriver.d.ts.map +1 -1
- package/dist/core/appendonlystores/sqlite/SqliteDriver.js +99 -40
- package/dist/core/appendonlystores/sqlite/SqliteDriver.js.map +1 -1
- package/dist/core/expressions/evaluateExpression.d.ts +8 -0
- package/dist/core/expressions/evaluateExpression.d.ts.map +1 -1
- package/dist/core/expressions/evaluateExpression.js +29 -4
- package/dist/core/expressions/evaluateExpression.js.map +1 -1
- package/dist/core/expressions/metadata.js +4 -4
- package/dist/core/expressions/metadata.js.map +1 -1
- package/dist/core/types.d.ts +61 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/uri/MindooURI.d.ts.map +1 -1
- package/dist/core/uri/MindooURI.js +3 -24
- package/dist/core/uri/MindooURI.js.map +1 -1
- package/dist/core/utils/base64.d.ts +17 -0
- package/dist/core/utils/base64.d.ts.map +1 -0
- package/dist/core/utils/base64.js +54 -0
- package/dist/core/utils/base64.js.map +1 -0
- package/dist/core/utils/idGeneration.d.ts.map +1 -1
- package/dist/core/utils/idGeneration.js +14 -3
- package/dist/core/utils/idGeneration.js.map +1 -1
- package/dist/node/server/FsServerDataStore.d.ts +23 -0
- package/dist/node/server/FsServerDataStore.d.ts.map +1 -0
- package/dist/node/server/FsServerDataStore.js +59 -0
- package/dist/node/server/FsServerDataStore.js.map +1 -0
- package/dist/node/server/IrohServerEndpoint.d.ts +1 -1
- package/dist/node/server/IrohServerEndpoint.d.ts.map +1 -1
- package/dist/node/server/IrohServerRpc.d.ts +5 -5
- package/dist/node/server/IrohServerRpc.d.ts.map +1 -1
- package/dist/node/server/IrohServerRpc.js +1 -1
- package/dist/node/server/IrohServerRpc.js.map +1 -1
- package/dist/node/server/MindooDBServer.d.ts +29 -150
- package/dist/node/server/MindooDBServer.d.ts.map +1 -1
- package/dist/node/server/MindooDBServer.js +160 -1573
- package/dist/node/server/MindooDBServer.js.map +1 -1
- package/dist/node/server/PurgedDocRegistry.d.ts +4 -27
- package/dist/node/server/PurgedDocRegistry.d.ts.map +1 -1
- package/dist/node/server/PurgedDocRegistry.js +6 -83
- package/dist/node/server/PurgedDocRegistry.js.map +1 -1
- package/dist/node/server/StoreFactory.d.ts +1 -1
- package/dist/node/server/StoreFactory.d.ts.map +1 -1
- package/dist/node/server/TenantManager.d.ts +16 -284
- package/dist/node/server/TenantManager.d.ts.map +1 -1
- package/dist/node/server/TenantManager.js +35 -1168
- package/dist/node/server/TenantManager.js.map +1 -1
- package/dist/node/server/add-to-network.js +1 -1
- package/dist/node/server/add-to-network.js.map +1 -1
- package/dist/node/server/config.d.ts +11 -15
- package/dist/node/server/config.d.ts.map +1 -1
- package/dist/node/server/config.js +30 -245
- package/dist/node/server/config.js.map +1 -1
- package/dist/node/server/expressAdapter.d.ts +23 -0
- package/dist/node/server/expressAdapter.d.ts.map +1 -0
- package/dist/node/server/expressAdapter.js +108 -0
- package/dist/node/server/expressAdapter.js.map +1 -0
- package/dist/node/server/nativeIrohStreamIO.d.ts +1 -1
- package/dist/node/server/nativeIrohStreamIO.d.ts.map +1 -1
- package/dist/node/server/peer/FileClusterAuditStorage.d.ts +16 -0
- package/dist/node/server/peer/FileClusterAuditStorage.d.ts.map +1 -0
- package/dist/node/server/peer/FileClusterAuditStorage.js +39 -0
- package/dist/node/server/peer/FileClusterAuditStorage.js.map +1 -0
- package/dist/node/server/peer/IrohPeerLink.d.ts +1 -1
- package/dist/node/server/peer/IrohPeerLink.d.ts.map +1 -1
- package/dist/node/server/peer/routes.d.ts +10 -44
- package/dist/node/server/peer/routes.d.ts.map +1 -1
- package/dist/node/server/peer/routes.js +33 -275
- package/dist/node/server/peer/routes.js.map +1 -1
- package/dist/node/server/resolveServerPassword.js +1 -1
- package/dist/node/server/resolveServerPassword.js.map +1 -1
- package/dist/node/server/server.js +1 -1
- package/dist/node/server/server.js.map +1 -1
- package/dist/node/server/serverinit.js +1 -1
- package/dist/node/server/serverinit.js.map +1 -1
- package/dist/server/CapabilityMatcher.d.ts +60 -0
- package/dist/server/CapabilityMatcher.d.ts.map +1 -0
- package/dist/server/CapabilityMatcher.js +138 -0
- package/dist/server/CapabilityMatcher.js.map +1 -0
- package/dist/server/DeviceDiscoveryService.d.ts +36 -0
- package/dist/server/DeviceDiscoveryService.d.ts.map +1 -0
- package/dist/server/DeviceDiscoveryService.js +165 -0
- package/dist/server/DeviceDiscoveryService.js.map +1 -0
- package/dist/server/PurgedDocRegistry.d.ts +35 -0
- package/dist/server/PurgedDocRegistry.d.ts.map +1 -0
- package/dist/server/PurgedDocRegistry.js +90 -0
- package/dist/server/PurgedDocRegistry.js.map +1 -0
- package/dist/server/ServerDataStore.d.ts +67 -0
- package/dist/server/ServerDataStore.d.ts.map +1 -0
- package/dist/server/ServerDataStore.js +88 -0
- package/dist/server/ServerDataStore.js.map +1 -0
- package/dist/server/SyncEventBus.d.ts +39 -0
- package/dist/server/SyncEventBus.d.ts.map +1 -0
- package/dist/server/SyncEventBus.js +41 -0
- package/dist/server/SyncEventBus.js.map +1 -0
- package/dist/server/SystemAdminAuth.d.ts +82 -0
- package/dist/server/SystemAdminAuth.d.ts.map +1 -0
- package/dist/server/SystemAdminAuth.js +228 -0
- package/dist/server/SystemAdminAuth.js.map +1 -0
- package/dist/server/TenantManager.d.ts +330 -0
- package/dist/server/TenantManager.d.ts.map +1 -0
- package/dist/server/TenantManager.js +1186 -0
- package/dist/server/TenantManager.js.map +1 -0
- package/dist/server/http/MindooDBServerCore.d.ts +313 -0
- package/dist/server/http/MindooDBServerCore.d.ts.map +1 -0
- package/dist/server/http/MindooDBServerCore.js +1403 -0
- package/dist/server/http/MindooDBServerCore.js.map +1 -0
- package/dist/server/http/types.d.ts +89 -0
- package/dist/server/http/types.d.ts.map +1 -0
- package/dist/server/http/types.js +29 -0
- package/dist/server/http/types.js.map +1 -0
- package/dist/server/index.d.ts +32 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +76 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/peer/ClusterAuditLog.d.ts +71 -0
- package/dist/server/peer/ClusterAuditLog.d.ts.map +1 -0
- package/dist/server/peer/ClusterAuditLog.js +81 -0
- package/dist/server/peer/ClusterAuditLog.js.map +1 -0
- package/dist/server/peer/ClusterJobRunner.d.ts +43 -0
- package/dist/server/peer/ClusterJobRunner.d.ts.map +1 -0
- package/dist/server/peer/ClusterJobRunner.js +119 -0
- package/dist/server/peer/ClusterJobRunner.js.map +1 -0
- package/dist/server/peer/ClusterManager.d.ts +149 -0
- package/dist/server/peer/ClusterManager.d.ts.map +1 -0
- package/dist/server/peer/ClusterManager.js +292 -0
- package/dist/server/peer/ClusterManager.js.map +1 -0
- package/dist/server/peer/PeerAuthService.d.ts +69 -0
- package/dist/server/peer/PeerAuthService.d.ts.map +1 -0
- package/dist/server/peer/PeerAuthService.js +208 -0
- package/dist/server/peer/PeerAuthService.js.map +1 -0
- package/dist/server/peer/PeerReplicator.d.ts +303 -0
- package/dist/server/peer/PeerReplicator.d.ts.map +1 -0
- package/dist/server/peer/PeerReplicator.js +1071 -0
- package/dist/server/peer/PeerReplicator.js.map +1 -0
- package/dist/server/peer/clusterHttp.d.ts +113 -0
- package/dist/server/peer/clusterHttp.d.ts.map +1 -0
- package/dist/server/peer/clusterHttp.js +290 -0
- package/dist/server/peer/clusterHttp.js.map +1 -0
- package/dist/server/peer/types.d.ts +244 -0
- package/dist/server/peer/types.d.ts.map +1 -0
- package/dist/server/peer/types.js +189 -0
- package/dist/server/peer/types.js.map +1 -0
- package/dist/server/rateLimits.d.ts +119 -0
- package/dist/server/rateLimits.d.ts.map +1 -0
- package/dist/server/rateLimits.js +159 -0
- package/dist/server/rateLimits.js.map +1 -0
- package/dist/server/serverConfig.d.ts +37 -0
- package/dist/server/serverConfig.d.ts.map +1 -0
- package/dist/server/serverConfig.js +251 -0
- package/dist/server/serverConfig.js.map +1 -0
- package/dist/server/timestampProxy.d.ts +129 -0
- package/dist/server/timestampProxy.d.ts.map +1 -0
- package/dist/server/timestampProxy.js +361 -0
- package/dist/server/timestampProxy.js.map +1 -0
- package/dist/server/types.d.ts +267 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +56 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/validation.d.ts +43 -0
- package/dist/server/validation.d.ts.map +1 -0
- package/dist/server/validation.js +104 -0
- package/dist/server/validation.js.map +1 -0
- package/package.json +9 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* System admin authentication service.
|
|
4
|
+
*
|
|
5
|
+
* Reuses the existing `AuthenticationService` by providing a
|
|
6
|
+
* `SystemAdminDirectory` adapter that derives user lookup data from
|
|
7
|
+
* the capabilities section of `config.json` rather than a tenant
|
|
8
|
+
* directory. Challenges require both username and publicsignkey so
|
|
9
|
+
* the issued JWT can carry both fields for capability matching.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SystemAdminAuthService = void 0;
|
|
13
|
+
const idGeneration_1 = require("../core/utils/idGeneration");
|
|
14
|
+
const serverConfig_1 = require("./serverConfig");
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// SystemAdminAuthService
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
class SystemAdminAuthService {
|
|
19
|
+
constructor(cryptoAdapter, config, options) {
|
|
20
|
+
this.challenges = new Map();
|
|
21
|
+
this.cryptoAdapter = cryptoAdapter;
|
|
22
|
+
this.principals = (0, serverConfig_1.extractAllPrincipals)(config);
|
|
23
|
+
this.allowTenantCreationWildcardPrincipal =
|
|
24
|
+
(0, serverConfig_1.hasTenantCreationWildcardPrincipal)(config);
|
|
25
|
+
this.isTenantAdminSigningKey = options?.isTenantAdminSigningKey;
|
|
26
|
+
this.jwtSecret =
|
|
27
|
+
options?.jwtSecret ?? cryptoAdapter.getRandomValues(new Uint8Array(32));
|
|
28
|
+
this.challengeExpirationMs = options?.challengeExpirationMs ?? 5 * 60 * 1000;
|
|
29
|
+
this.tokenExpirationMs = options?.tokenExpirationMs ?? 60 * 60 * 1000;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Hot-swap the principal list from a new config.
|
|
33
|
+
* In-flight challenges and existing JWTs remain valid (same HMAC secret);
|
|
34
|
+
* removed principals will fail the CapabilityMatcher check on their next request.
|
|
35
|
+
*/
|
|
36
|
+
reloadPrincipals(config) {
|
|
37
|
+
this.principals = (0, serverConfig_1.extractAllPrincipals)(config);
|
|
38
|
+
this.allowTenantCreationWildcardPrincipal =
|
|
39
|
+
(0, serverConfig_1.hasTenantCreationWildcardPrincipal)(config);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generate a challenge for a system admin.
|
|
43
|
+
* Both `username` and `publicsignkey` are required so we can bind
|
|
44
|
+
* the issued JWT to a specific keypair.
|
|
45
|
+
*/
|
|
46
|
+
async generateChallenge(username, publicsignkey) {
|
|
47
|
+
const normalizedUsername = username.toLowerCase();
|
|
48
|
+
const found = this.principals.some((p) => p.username.toLowerCase() === normalizedUsername &&
|
|
49
|
+
p.publicsignkey === publicsignkey);
|
|
50
|
+
if (!found &&
|
|
51
|
+
!this.allowTenantCreationWildcardPrincipal &&
|
|
52
|
+
!this.isTenantAdminSigningKey?.(publicsignkey)) {
|
|
53
|
+
throw new Error("Unknown system admin principal");
|
|
54
|
+
}
|
|
55
|
+
const challenge = (0, idGeneration_1.generateRandomUuid)();
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
this.challenges.set(challenge, {
|
|
58
|
+
challenge,
|
|
59
|
+
username,
|
|
60
|
+
publicsignkey,
|
|
61
|
+
createdAt: now,
|
|
62
|
+
expiresAt: now + this.challengeExpirationMs,
|
|
63
|
+
used: false,
|
|
64
|
+
});
|
|
65
|
+
this.cleanupExpiredChallenges();
|
|
66
|
+
this.evictChallengesOverCap();
|
|
67
|
+
return challenge;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Verify a signed challenge and return a JWT containing both
|
|
71
|
+
* `sub` (username) and `publicsignkey`.
|
|
72
|
+
*/
|
|
73
|
+
async authenticate(challenge, signature) {
|
|
74
|
+
const stored = this.challenges.get(challenge);
|
|
75
|
+
if (!stored) {
|
|
76
|
+
return { success: false, error: "Challenge not found or expired" };
|
|
77
|
+
}
|
|
78
|
+
if (Date.now() > stored.expiresAt) {
|
|
79
|
+
this.challenges.delete(challenge);
|
|
80
|
+
return { success: false, error: "Challenge expired" };
|
|
81
|
+
}
|
|
82
|
+
if (stored.used) {
|
|
83
|
+
return { success: false, error: "Challenge already used" };
|
|
84
|
+
}
|
|
85
|
+
stored.used = true;
|
|
86
|
+
const isValid = await this.verifySignature(challenge, signature, stored.publicsignkey);
|
|
87
|
+
if (!isValid) {
|
|
88
|
+
return { success: false, error: "Invalid signature" };
|
|
89
|
+
}
|
|
90
|
+
const token = await this.generateToken(stored.username, stored.publicsignkey);
|
|
91
|
+
return { success: true, token };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Validate and decode a system admin JWT.
|
|
95
|
+
*/
|
|
96
|
+
async validateToken(token) {
|
|
97
|
+
const parts = token.split(".");
|
|
98
|
+
if (parts.length !== 3)
|
|
99
|
+
return null;
|
|
100
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
101
|
+
try {
|
|
102
|
+
// Pin the JWT algorithm to HS256 (audit, Low: alg pinning): reject any
|
|
103
|
+
// other declared `alg` to block algorithm-confusion attacks.
|
|
104
|
+
const header = JSON.parse(this.base64UrlDecode(headerB64));
|
|
105
|
+
if (header.alg !== "HS256")
|
|
106
|
+
return null;
|
|
107
|
+
const subtle = this.cryptoAdapter.getSubtle();
|
|
108
|
+
const signingKey = await subtle.importKey("raw", this.jwtSecret.buffer, { name: "HMAC", hash: "SHA-256" }, false, ["verify"]);
|
|
109
|
+
const dataToVerify = new TextEncoder().encode(`${headerB64}.${payloadB64}`);
|
|
110
|
+
const sig = this.base64UrlToUint8Array(signatureB64);
|
|
111
|
+
const isValid = await subtle.verify("HMAC", signingKey, sig.buffer.slice(sig.byteOffset, sig.byteOffset + sig.byteLength), dataToVerify.buffer);
|
|
112
|
+
if (!isValid)
|
|
113
|
+
return null;
|
|
114
|
+
const payload = JSON.parse(this.base64UrlDecode(payloadB64));
|
|
115
|
+
const now = Math.floor(Date.now() / 1000);
|
|
116
|
+
if (payload.exp < now)
|
|
117
|
+
return null;
|
|
118
|
+
return payload;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// -----------------------------------------------------------------------
|
|
125
|
+
// Private helpers
|
|
126
|
+
// -----------------------------------------------------------------------
|
|
127
|
+
async verifySignature(message, signature, publicKeyPem) {
|
|
128
|
+
const subtle = this.cryptoAdapter.getSubtle();
|
|
129
|
+
try {
|
|
130
|
+
const pemContents = publicKeyPem
|
|
131
|
+
.replace(/-----BEGIN PUBLIC KEY-----/g, "")
|
|
132
|
+
.replace(/-----END PUBLIC KEY-----/g, "")
|
|
133
|
+
.replace(/\s/g, "");
|
|
134
|
+
const keyData = this.base64ToUint8Array(pemContents);
|
|
135
|
+
const publicKey = await subtle.importKey("spki", keyData.buffer, { name: "Ed25519" }, false, ["verify"]);
|
|
136
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
137
|
+
return await subtle.verify({ name: "Ed25519" }, publicKey, signature.buffer.slice(signature.byteOffset, signature.byteOffset + signature.byteLength), messageBytes.buffer);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async generateToken(username, publicsignkey) {
|
|
144
|
+
const subtle = this.cryptoAdapter.getSubtle();
|
|
145
|
+
const now = Math.floor(Date.now() / 1000);
|
|
146
|
+
const payload = {
|
|
147
|
+
sub: username,
|
|
148
|
+
publicsignkey,
|
|
149
|
+
iat: now,
|
|
150
|
+
exp: now + Math.floor(this.tokenExpirationMs / 1000),
|
|
151
|
+
};
|
|
152
|
+
const header = { alg: "HS256", typ: "JWT" };
|
|
153
|
+
const headerB64 = this.base64UrlEncode(JSON.stringify(header));
|
|
154
|
+
const payloadB64 = this.base64UrlEncode(JSON.stringify(payload));
|
|
155
|
+
const signingKey = await subtle.importKey("raw", this.jwtSecret.buffer, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
156
|
+
const dataToSign = new TextEncoder().encode(`${headerB64}.${payloadB64}`);
|
|
157
|
+
const signature = await subtle.sign("HMAC", signingKey, dataToSign.buffer);
|
|
158
|
+
const signatureB64 = this.uint8ArrayToBase64Url(new Uint8Array(signature));
|
|
159
|
+
return `${headerB64}.${payloadB64}.${signatureB64}`;
|
|
160
|
+
}
|
|
161
|
+
cleanupExpiredChallenges() {
|
|
162
|
+
const now = Date.now();
|
|
163
|
+
for (const [key, ch] of this.challenges) {
|
|
164
|
+
if (ch.expiresAt < now) {
|
|
165
|
+
this.challenges.delete(key);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Bound the challenge map (DoS guard): if still over the cap after expiry
|
|
171
|
+
* cleanup, drop the oldest entries (Map preserves insertion order).
|
|
172
|
+
*/
|
|
173
|
+
evictChallengesOverCap() {
|
|
174
|
+
let overflow = this.challenges.size - SystemAdminAuthService.MAX_CHALLENGES;
|
|
175
|
+
if (overflow <= 0)
|
|
176
|
+
return;
|
|
177
|
+
for (const key of this.challenges.keys()) {
|
|
178
|
+
if (overflow-- <= 0)
|
|
179
|
+
break;
|
|
180
|
+
this.challenges.delete(key);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Base64 utilities
|
|
184
|
+
base64UrlEncode(str) {
|
|
185
|
+
const base64 = btoa(str);
|
|
186
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
187
|
+
}
|
|
188
|
+
base64UrlDecode(str) {
|
|
189
|
+
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
190
|
+
while (base64.length % 4)
|
|
191
|
+
base64 += "=";
|
|
192
|
+
return atob(base64);
|
|
193
|
+
}
|
|
194
|
+
uint8ArrayToBase64Url(bytes) {
|
|
195
|
+
let binary = "";
|
|
196
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
197
|
+
binary += String.fromCharCode(bytes[i]);
|
|
198
|
+
}
|
|
199
|
+
const base64 = btoa(binary);
|
|
200
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
201
|
+
}
|
|
202
|
+
base64UrlToUint8Array(str) {
|
|
203
|
+
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
204
|
+
while (base64.length % 4)
|
|
205
|
+
base64 += "=";
|
|
206
|
+
const binary = atob(base64);
|
|
207
|
+
const bytes = new Uint8Array(binary.length);
|
|
208
|
+
for (let i = 0; i < binary.length; i++) {
|
|
209
|
+
bytes[i] = binary.charCodeAt(i);
|
|
210
|
+
}
|
|
211
|
+
return bytes;
|
|
212
|
+
}
|
|
213
|
+
base64ToUint8Array(base64) {
|
|
214
|
+
const binary = atob(base64);
|
|
215
|
+
const bytes = new Uint8Array(binary.length);
|
|
216
|
+
for (let i = 0; i < binary.length; i++) {
|
|
217
|
+
bytes[i] = binary.charCodeAt(i);
|
|
218
|
+
}
|
|
219
|
+
return bytes;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
exports.SystemAdminAuthService = SystemAdminAuthService;
|
|
223
|
+
/**
|
|
224
|
+
* Hard cap on outstanding challenges (DoS guard). Challenge creation is
|
|
225
|
+
* unauthenticated, so bound the map and evict oldest-first on overflow.
|
|
226
|
+
*/
|
|
227
|
+
SystemAdminAuthService.MAX_CHALLENGES = 10000;
|
|
228
|
+
//# sourceMappingURL=SystemAdminAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SystemAdminAuth.js","sourceRoot":"","sources":["../../src/server/SystemAdminAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TenantManager handles loading, caching, and registration of tenants.
|
|
3
|
+
*
|
|
4
|
+
* Uses a global server identity (one per server, not per tenant) for
|
|
5
|
+
* authenticating with remote servers and opening tenant directories.
|
|
6
|
+
*
|
|
7
|
+
* When a tenant has a $publicinfos key (sent during publishToServer), the
|
|
8
|
+
* manager creates a real BaseMindooTenant for directory reading. User
|
|
9
|
+
* authentication is then validated against the admin-signed directory DB
|
|
10
|
+
* rather than a static JSON config.
|
|
11
|
+
*
|
|
12
|
+
* When no $publicinfos key is available, a SimpleMindooDirectory backed
|
|
13
|
+
* by config.json users[] is used as a fallback (useful for tests).
|
|
14
|
+
*
|
|
15
|
+
* A CompositeMindooDirectory wraps whichever directory source is used and
|
|
16
|
+
* also checks the global trusted-servers list, enabling server-to-server
|
|
17
|
+
* auth without servers being in each tenant's user directory.
|
|
18
|
+
*/
|
|
19
|
+
import { AuthenticationService } from "../core/appendonlystores/network/AuthenticationService";
|
|
20
|
+
import { ServerNetworkContentAddressedStore } from "../appendonlystores/network/ServerNetworkContentAddressedStore";
|
|
21
|
+
import type { ServerPeerTokenResolver, ServerTrustedWitnessResolver } from "../appendonlystores/network/ServerNetworkContentAddressedStore";
|
|
22
|
+
import type { WitnessSigner } from "../core/crypto/WitnessReceipt";
|
|
23
|
+
import type { TimestampProvider } from "../core/accesscontrol/timestamp/TimestampProvider";
|
|
24
|
+
import type { MindooTenant, MindooTenantDirectory, ContentAddressedStore, DirectoryUserLookup } from "../core/types";
|
|
25
|
+
import { StoreKind } from "../core/types";
|
|
26
|
+
import type { PrivateUserId } from "../core/userid";
|
|
27
|
+
import type { CryptoAdapter } from "../core/crypto/CryptoAdapter";
|
|
28
|
+
import type { ServerDataStore, ServerStoreProvider, TenantStoreFactory } from "./ServerDataStore";
|
|
29
|
+
import type { TenantConfig, TenantContext, RegisterTenantRequest, TrustedServer } from "./types";
|
|
30
|
+
export interface LoadedTenant {
|
|
31
|
+
context: TenantContext;
|
|
32
|
+
storeFactory: TenantStoreFactory;
|
|
33
|
+
authService: AuthenticationService;
|
|
34
|
+
directory: MindooTenantDirectory;
|
|
35
|
+
mindooTenant?: MindooTenant;
|
|
36
|
+
serverStores: Map<string, ServerNetworkContentAddressedStore>;
|
|
37
|
+
}
|
|
38
|
+
export interface RegisterTenantResult {
|
|
39
|
+
context: TenantContext;
|
|
40
|
+
created: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare class SimpleMindooDirectory implements Pick<MindooTenantDirectory, "getUserPublicKeys" | "isUserRevoked" | "validatePublicSigningKey" | "getUserBySigningPublicKey"> {
|
|
43
|
+
/** Canonical index: entries are identified by their signing public key. */
|
|
44
|
+
private usersByKey;
|
|
45
|
+
/**
|
|
46
|
+
* Backward-compat index by documentation-only username, populated only for
|
|
47
|
+
* config entries that carry a `username`. Lets legacy username-based
|
|
48
|
+
* challenges keep resolving; `username` is never required.
|
|
49
|
+
*/
|
|
50
|
+
private usersByUsername;
|
|
51
|
+
private revokedUsers;
|
|
52
|
+
private adminSigningPublicKey;
|
|
53
|
+
constructor(config: TenantConfig);
|
|
54
|
+
getUserPublicKeys(username: string): Promise<{
|
|
55
|
+
signingPublicKey: string;
|
|
56
|
+
encryptionPublicKey: string;
|
|
57
|
+
} | null>;
|
|
58
|
+
getUserBySigningPublicKey(publicKey: string): Promise<DirectoryUserLookup | null>;
|
|
59
|
+
private toLookup;
|
|
60
|
+
isUserRevoked(username: string): Promise<boolean>;
|
|
61
|
+
validatePublicSigningKey(publicKey: string, _opts?: {
|
|
62
|
+
forceRefresh?: boolean;
|
|
63
|
+
}): Promise<boolean>;
|
|
64
|
+
}
|
|
65
|
+
export interface TenantManagerOptions {
|
|
66
|
+
/** Server identity, trusted servers, key bag and tenant configs. */
|
|
67
|
+
dataStore: ServerDataStore;
|
|
68
|
+
/** Content-addressed stores of every tenant database. */
|
|
69
|
+
storeProvider: ServerStoreProvider;
|
|
70
|
+
cryptoAdapter: CryptoAdapter;
|
|
71
|
+
/** Unlocks the server identity's private keys and the server key bag. */
|
|
72
|
+
serverPassword?: string;
|
|
73
|
+
/**
|
|
74
|
+
* HMAC secret for a tenant's sync tokens. Without it every loaded tenant
|
|
75
|
+
* gets a random secret, so tokens die with the process — fine for one
|
|
76
|
+
* server process, wrong for a host that spreads one tenant over several
|
|
77
|
+
* instances which must accept each other's tokens.
|
|
78
|
+
*/
|
|
79
|
+
jwtSecretForTenant?: (tenantId: string) => Promise<Uint8Array>;
|
|
80
|
+
/**
|
|
81
|
+
* Source of a tenant's `$publicinfos` keys when they are not kept in this
|
|
82
|
+
* manager's own `server.keybag` (e.g. a host instance that serves one
|
|
83
|
+
* tenant database and gets the keys from a central registry).
|
|
84
|
+
*/
|
|
85
|
+
publicInfosKeysResolver?: (tenantId: string) => Promise<Uint8Array[]>;
|
|
86
|
+
}
|
|
87
|
+
export interface ExecutePendingPurgesOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Only purge in these databases; requests for other databases stay
|
|
90
|
+
* unprocessed in this manager's registry. For hosts that serve a subset of
|
|
91
|
+
* a tenant's databases per instance.
|
|
92
|
+
*/
|
|
93
|
+
dbIds?: ReadonlySet<string>;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* TenantManager is responsible for:
|
|
97
|
+
* - Loading the global server identity and trusted servers
|
|
98
|
+
* - Loading tenant configurations from disk
|
|
99
|
+
* - Caching loaded tenants
|
|
100
|
+
* - Registering new tenants
|
|
101
|
+
* - Managing tenant stores and authentication services
|
|
102
|
+
* - Creating a real MindooDB tenant for directory reading (when keys available)
|
|
103
|
+
* - Runtime management of trusted servers
|
|
104
|
+
*/
|
|
105
|
+
export declare class TenantManager {
|
|
106
|
+
private readonly dataStore;
|
|
107
|
+
private readonly storeProvider;
|
|
108
|
+
private serverPassword;
|
|
109
|
+
private cryptoAdapter;
|
|
110
|
+
private readonly jwtSecretForTenant;
|
|
111
|
+
private readonly publicInfosKeysResolver;
|
|
112
|
+
private loadedTenants;
|
|
113
|
+
private serverIdentity;
|
|
114
|
+
private trustedServers;
|
|
115
|
+
/** Lazily-built, cached witness signer (server's Ed25519 signing identity). */
|
|
116
|
+
private witnessSigner;
|
|
117
|
+
/** Lazily-imported RSA private key for peer replication (see getServerEncryptionPrivateKey). */
|
|
118
|
+
private serverEncryptionPrivateKey;
|
|
119
|
+
/** Peer wiring handed down to every server store; see setPeerAccessControl. */
|
|
120
|
+
private peerAccessControl;
|
|
121
|
+
/** Per-tenant persistent registry of executed purges (docs/accesscontrol.md §13). */
|
|
122
|
+
private purgedDocRegistries;
|
|
123
|
+
/** In-flight purge executions, keyed by normalized tenant id (serializes runs). */
|
|
124
|
+
private purgeInFlight;
|
|
125
|
+
constructor(options: TenantManagerOptions);
|
|
126
|
+
getServerIdentity(): PrivateUserId | null;
|
|
127
|
+
getServerPublicInfo(): TrustedServer | null;
|
|
128
|
+
/**
|
|
129
|
+
* Teach every server store how to recognise a trusted peer.
|
|
130
|
+
*
|
|
131
|
+
* `MindooDBServer` calls this once at startup. Two hooks, both required for
|
|
132
|
+
* peer replication to be correct:
|
|
133
|
+
*
|
|
134
|
+
* - `peerTokenResolver` lets a peer's cluster-level JWT through the tenant
|
|
135
|
+
* sync routes. A peer holds no per-tenant grant, so without it the mirror
|
|
136
|
+
* would need a second replication protocol; with it the peer reuses the
|
|
137
|
+
* client one and the store skips the per-user gates that do not apply to a
|
|
138
|
+
* full replica.
|
|
139
|
+
* - `trustedWitnessResolver` decides whose witness receipts may be preserved
|
|
140
|
+
* instead of re-stamped (convergence invariant 3). Without it a replicated
|
|
141
|
+
* entry would get a fresh `receivedAt` on every hop and "trusted time"
|
|
142
|
+
* would mean "time it reached the last server".
|
|
143
|
+
*
|
|
144
|
+
* Must be called before the first {@link getServerStore}, since stores are
|
|
145
|
+
* cached per tenant and database.
|
|
146
|
+
*/
|
|
147
|
+
setPeerAccessControl(options: {
|
|
148
|
+
peerTokenResolver?: ServerPeerTokenResolver;
|
|
149
|
+
trustedWitnessResolver?: ServerTrustedWitnessResolver;
|
|
150
|
+
}): void;
|
|
151
|
+
/**
|
|
152
|
+
* Database ids this server holds for a tenant (on Node, the directories in
|
|
153
|
+
* `{dataDir}/{tenantId}/stores`). Used by peer replication to mirror every
|
|
154
|
+
* database rather than a configured subset.
|
|
155
|
+
*/
|
|
156
|
+
listDatabases(tenantId: string): string[];
|
|
157
|
+
/**
|
|
158
|
+
* The server's own RSA private key, imported for decryption.
|
|
159
|
+
*
|
|
160
|
+
* Peer replication needs it because the remote wraps transported entries to
|
|
161
|
+
* this server's `encryptionPublicKey` (the one in its `trusted-servers.json`),
|
|
162
|
+
* exactly as it would wrap them for a client.
|
|
163
|
+
*/
|
|
164
|
+
getServerEncryptionPrivateKey(): Promise<CryptoKey | undefined>;
|
|
165
|
+
/**
|
|
166
|
+
* Build (and cache) the server's witness identity used to stamp receipts on
|
|
167
|
+
* accepted entries (docs/accesscontrol.md §5.3). Returns undefined when the
|
|
168
|
+
* server identity or its unlock password is unavailable, in which case the
|
|
169
|
+
* server runs in pre-access-control mode (no stamping, no Tier 1 advertised).
|
|
170
|
+
*/
|
|
171
|
+
getWitnessSigner(): Promise<WitnessSigner | undefined>;
|
|
172
|
+
/**
|
|
173
|
+
* Build the trusted-time provider that stamps receipts on accepted entries
|
|
174
|
+
* (docs/accesscontrol.md §5.3, §13). v1 wraps the server's Ed25519 witness
|
|
175
|
+
* identity; returns undefined when no witness signer is available, leaving the
|
|
176
|
+
* server in pre-access-control mode.
|
|
177
|
+
*/
|
|
178
|
+
getTimestampProvider(): Promise<TimestampProvider | undefined>;
|
|
179
|
+
listTrustedServers(): TrustedServer[];
|
|
180
|
+
addTrustedServer(server: TrustedServer): void;
|
|
181
|
+
/**
|
|
182
|
+
* Add or replace a trusted server by name.
|
|
183
|
+
*
|
|
184
|
+
* Peer CRUD needs an upsert: `addTrustedServer` throws on an existing name,
|
|
185
|
+
* which is right for `add-to-network` (a silent overwrite of a peer's keys
|
|
186
|
+
* would be a trust change disguised as a config edit) but wrong for the admin
|
|
187
|
+
* API, where changing a peer's url or role is the common case.
|
|
188
|
+
*/
|
|
189
|
+
saveTrustedServer(server: TrustedServer): void;
|
|
190
|
+
removeTrustedServer(name: string): boolean;
|
|
191
|
+
private persistTrustedServers;
|
|
192
|
+
private loadServerKeyBag;
|
|
193
|
+
private createServerKeyBag;
|
|
194
|
+
private saveServerKeyBag;
|
|
195
|
+
private bytesToBase64;
|
|
196
|
+
private mergeUniqueKeys;
|
|
197
|
+
private computePublicInfosFingerprint;
|
|
198
|
+
/**
|
|
199
|
+
* The data-store key of a tenant's directory. Tenant ids reach this from
|
|
200
|
+
* request paths, so anything that could address another key is refused.
|
|
201
|
+
*/
|
|
202
|
+
private tenantKey;
|
|
203
|
+
private tenantConfigKey;
|
|
204
|
+
private readTenantConfig;
|
|
205
|
+
private writeTenantConfig;
|
|
206
|
+
private decryptEncryptedPublicInfosKey;
|
|
207
|
+
private resolveIncomingPublicInfosKey;
|
|
208
|
+
private getStoredPublicInfosKeys;
|
|
209
|
+
private persistTenantPublicInfosKey;
|
|
210
|
+
/**
|
|
211
|
+
* All stored `$publicinfos` AES key versions for a tenant from `server.keybag`.
|
|
212
|
+
* Empty when the tenant was never published or the server keybag is locked.
|
|
213
|
+
*/
|
|
214
|
+
getPublicInfosKeysForTenant(tenantId: string): Promise<Uint8Array[]>;
|
|
215
|
+
listTenantPublicInfosFingerprints(tenantId: string): Promise<string[]>;
|
|
216
|
+
registerTenant(request: RegisterTenantRequest): Promise<RegisterTenantResult>;
|
|
217
|
+
getTenant(tenantId: string): Promise<LoadedTenant>;
|
|
218
|
+
tenantExists(tenantId: string): boolean;
|
|
219
|
+
/**
|
|
220
|
+
* Read the tenant's registered admin signing key without fully loading the
|
|
221
|
+
* tenant. Returns `null` if the tenant is missing or the config is unreadable.
|
|
222
|
+
*/
|
|
223
|
+
getTenantAdminSigningPublicKey(tenantId: string): string | null;
|
|
224
|
+
/**
|
|
225
|
+
* True when `publicsignkey` is the registered tenant-admin signing key for
|
|
226
|
+
* `tenantId` (PEM whitespace-insensitive).
|
|
227
|
+
*/
|
|
228
|
+
isTenantAdminSigningKeyFor(tenantId: string, publicsignkey: string): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* True when `publicsignkey` is the registered admin signing key of any
|
|
231
|
+
* tenant on this server. Used to issue a system JWT so that admin can
|
|
232
|
+
* DELETE their own tenant; other `/system/*` routes stay capability-gated.
|
|
233
|
+
*/
|
|
234
|
+
isRegisteredTenantAdminSigningKey(publicsignkey: string): boolean;
|
|
235
|
+
listTenants(): string[];
|
|
236
|
+
/**
|
|
237
|
+
* Update operator-owned fields of an existing tenant configuration.
|
|
238
|
+
* Only the fields present in `updates` are overwritten.
|
|
239
|
+
*/
|
|
240
|
+
updateTenantConfig(tenantId: string, updates: Partial<Pick<TenantConfig, "defaultStoreType">>): void;
|
|
241
|
+
removeTenant(tenantId: string): Promise<void>;
|
|
242
|
+
getServerStore(tenantId: string, dbId: string, storeKind: StoreKind): Promise<ServerNetworkContentAddressedStore>;
|
|
243
|
+
/**
|
|
244
|
+
* Build a Tier 1 evaluator closure for a server store, or undefined when the
|
|
245
|
+
* directory cannot evaluate access (e.g. config-based directory without the
|
|
246
|
+
* access-control state chain). The closure resolves `$author` for non-create
|
|
247
|
+
* ops by reading the document's `doc_create` entry creator key from the local
|
|
248
|
+
* store (metadata only, no decryption) and comparing it to the change author.
|
|
249
|
+
*/
|
|
250
|
+
/**
|
|
251
|
+
* The witness's Tier 1 gate. The evaluation itself is shared with the peer
|
|
252
|
+
* listener, which has to run it for entries that never reach a witness at
|
|
253
|
+
* all — see `core/accesscontrol/tier1Evaluator.ts`.
|
|
254
|
+
*/
|
|
255
|
+
private buildTier1Evaluator;
|
|
256
|
+
/**
|
|
257
|
+
* Builtin `userdirectory` write invariant: admin may create/delete, only the
|
|
258
|
+
* owning person may change. `username_hash` is read from the decrypted
|
|
259
|
+
* `doc_create` payload (`$publicinfos`). Personal documents are sealed to
|
|
260
|
+
* their owner and therefore undecryptable here, so they are owned by whoever
|
|
261
|
+
* signed their `doc_create` — `resolveCreatorSigningKey` answers that from
|
|
262
|
+
* the entry chain alone.
|
|
263
|
+
*/
|
|
264
|
+
private buildUserdirectoryWriteContext;
|
|
265
|
+
private findCreateEntry;
|
|
266
|
+
/**
|
|
267
|
+
* Build a database-open evaluator closure for a server store, or undefined
|
|
268
|
+
* when the directory cannot evaluate the database-open policy (e.g. a
|
|
269
|
+
* config-based directory without the access-control state chain). When the
|
|
270
|
+
* tenant policy is `"directory-restricted"`, this rejects sync for any
|
|
271
|
+
* database id that is not in the allowlist; `"directory"` is always allowed
|
|
272
|
+
* and the tenant admin is exempt (resolved from the principal signing key).
|
|
273
|
+
*/
|
|
274
|
+
private buildDbAccessEvaluator;
|
|
275
|
+
/**
|
|
276
|
+
* Build a remote-wipe resolver closure for a server store, or undefined when
|
|
277
|
+
* the directory does not support wipe directives (docs/accesscontrol.md §6.5).
|
|
278
|
+
* Maps a wipe-targeted signing key to the admin-signed grant document id so
|
|
279
|
+
* the server can serve only that document to the targeted device.
|
|
280
|
+
*/
|
|
281
|
+
private buildWipeGrantDocIdResolver;
|
|
282
|
+
/**
|
|
283
|
+
* Build a per-user revoked-key blacklist resolver for a server store, or
|
|
284
|
+
* undefined when the directory cannot resolve revoked keys (e.g. a
|
|
285
|
+
* config-based directory). Maps the authenticated principal's signing key to
|
|
286
|
+
* the set of decryption key ids revoked for them at the directory head
|
|
287
|
+
* (docs/accesscontrol.md §13).
|
|
288
|
+
*/
|
|
289
|
+
private buildRevokedKeyResolver;
|
|
290
|
+
getStore(tenantId: string, dbId: string, storeKind: StoreKind): Promise<ContentAddressedStore>;
|
|
291
|
+
/**
|
|
292
|
+
* Documents purged from `dbId` on this server (the persistent purge
|
|
293
|
+
* registry). Peer pull replication refuses their entries.
|
|
294
|
+
*/
|
|
295
|
+
getPurgedDocIds(tenantId: string, dbId: string): ReadonlySet<string>;
|
|
296
|
+
/** The (lazily-loaded, cached) purge registry for a tenant. */
|
|
297
|
+
private getPurgedDocRegistry;
|
|
298
|
+
/**
|
|
299
|
+
* Execute any not-yet-processed document-history purge requests for a tenant
|
|
300
|
+
* (docs/accesscontrol.md §13). Reads the admin-signed purge requests from the
|
|
301
|
+
* tenant directory (server-readable `$publicinfos` envelope), physically
|
|
302
|
+
* purges each requested document's history from the tenant's `docs` and
|
|
303
|
+
* `attachments` stores, and records the purge in the persistent registry so
|
|
304
|
+
* (a) it is never executed twice and (b) re-pushes of the purged docs are
|
|
305
|
+
* rejected at sync time.
|
|
306
|
+
*
|
|
307
|
+
* No-op when the server cannot read the directory (config-based fallback, or
|
|
308
|
+
* the directory does not expose the purge reader). Runs are serialized per
|
|
309
|
+
* tenant; concurrent callers share the in-flight promise.
|
|
310
|
+
*/
|
|
311
|
+
executePendingPurges(tenantId: string, options?: ExecutePendingPurgesOptions): Promise<void>;
|
|
312
|
+
private executePendingPurgesInternal;
|
|
313
|
+
/**
|
|
314
|
+
* Purge one document from a database's docs and attachment stores. Attachment
|
|
315
|
+
* chunks still referenced by another document are kept (see
|
|
316
|
+
* `purgeDocumentHistory.ts`). Failures are logged, never thrown.
|
|
317
|
+
*/
|
|
318
|
+
private purgeDocumentFromDatabase;
|
|
319
|
+
getAuthService(tenantId: string): Promise<AuthenticationService>;
|
|
320
|
+
getCryptoAdapter(): CryptoAdapter;
|
|
321
|
+
reloadTenant(tenantId: string): Promise<LoadedTenant>;
|
|
322
|
+
clearCache(): void;
|
|
323
|
+
private loadTenant;
|
|
324
|
+
/**
|
|
325
|
+
* Create a real BaseMindooTenant for directory reading using the global
|
|
326
|
+
* server identity.
|
|
327
|
+
*/
|
|
328
|
+
private createDirectoryTenant;
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=TenantManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TenantManager.d.ts","sourceRoot":"","sources":["../../src/server/TenantManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,EAAE,kCAAkC,EAAE,MAAM,gEAAgE,CAAC;AACpH,OAAO,KAAK,EAMV,uBAAuB,EACvB,4BAA4B,EAC7B,MAAM,gEAAgE,CAAC;AAGxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAO3F,OAAO,KAAK,EACV,YAAY,EACZ,qBAAqB,EACrB,qBAAqB,EAMrB,mBAAmB,EAGpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,SAAS,EAEV,MAAM,eAAe,CAAC;AAOvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAGlE,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,qBAAqB,EAErB,aAAa,EACd,MAAM,SAAS,CAAC;AAMjB,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,YAAY,EAAE,kBAAkB,CAAC;IACjC,WAAW,EAAE,qBAAqB,CAAC;IACnC,SAAS,EAAE,qBAAqB,CAAC;IACjC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,kCAAkC,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAoBD,qBAAa,qBAAsB,YAAW,IAAI,CAChD,qBAAqB,EACnB,mBAAmB,GACnB,eAAe,GACf,0BAA0B,GAC1B,2BAA2B,CAC9B;IACC,2EAA2E;IAC3E,OAAO,CAAC,UAAU,CAAsC;IACxD;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,qBAAqB,CAAS;gBAE1B,MAAM,EAAE,YAAY;IAe1B,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QACjD,gBAAgB,EAAE,MAAM,CAAC;QACzB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,GAAG,IAAI,CAAC;IAeH,yBAAyB,CAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAetC,OAAO,CAAC,QAAQ;IAeV,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjD,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,GACjC,OAAO,CAAC,OAAO,CAAC;CAgBpB;AAsSD,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,SAAS,EAAE,eAAe,CAAC;IAC3B,yDAAyD;IACzD,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6C;IAChF,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAkD;IAC1F,OAAO,CAAC,aAAa,CAAwC;IAE7D,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,cAAc,CAAuB;IAC7C,+EAA+E;IAC/E,OAAO,CAAC,aAAa,CAA4B;IACjD,gGAAgG;IAChG,OAAO,CAAC,0BAA0B,CAAwB;IAC1D,+EAA+E;IAC/E,OAAO,CAAC,iBAAiB,CAGlB;IACP,qFAAqF;IACrF,OAAO,CAAC,mBAAmB,CAA6C;IACxE,mFAAmF;IACnF,OAAO,CAAC,aAAa,CAAyC;gBAElD,OAAO,EAAE,oBAAoB;IAmCzC,iBAAiB,IAAI,aAAa,GAAG,IAAI;IAIzC,mBAAmB,IAAI,aAAa,GAAG,IAAI;IAW3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,oBAAoB,CAAC,OAAO,EAAE;QAC5B,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;QAC5C,sBAAsB,CAAC,EAAE,4BAA4B,CAAC;KACvD,GAAG,IAAI;IAIR;;;;OAIG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAIzC;;;;;;OAMG;IACG,6BAA6B,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAsBrE;;;;;OAKG;IACG,gBAAgB,IAAI,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IA0B5D;;;;;OAKG;IACG,oBAAoB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAUpE,kBAAkB,IAAI,aAAa,EAAE;IAIrC,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAY7C;;;;;;;OAOG;IACH,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAa9C,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAW1C,OAAO,CAAC,qBAAqB;YAOf,gBAAgB;YAiBhB,kBAAkB;YAgBlB,gBAAgB;IAI9B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,eAAe;YAcT,6BAA6B;IAW3C;;;OAGG;IACH,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,iBAAiB;YAOX,8BAA8B;YAqC9B,6BAA6B;YAgB7B,wBAAwB;YAoBxB,2BAA2B;IAoBzC;;;OAGG;IACG,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIpE,iCAAiC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiBtE,cAAc,CAClB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC;IAwD1B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAcxD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKvC;;;OAGG;IACH,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAoB/D;;;OAGG;IACH,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO;IAK5E;;;;OAIG;IACH,iCAAiC,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IASjE,WAAW,IAAI,MAAM,EAAE;IAOvB;;;OAGG;IACH,kBAAkB,CAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC,GACvD,IAAI;IAgBD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4B7C,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,kCAAkC,CAAC;IAqE9C;;;;;;OAMG;IACH;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAU3B;;;;;;;OAOG;IACH,OAAO,CAAC,8BAA8B;YA8BxB,eAAe;IAkB7B;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAkB9B;;;;;OAKG;IACH,OAAO,CAAC,2BAA2B;IASnC;;;;;;OAMG;IACH,OAAO,CAAC,uBAAuB;IAgBzB,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,qBAAqB,CAAC;IAKjC;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;IAIpE,+DAA+D;IAC/D,OAAO,CAAC,oBAAoB;IAa5B;;;;;;;;;;;;OAYG;IACG,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,IAAI,CAAC;YAWF,4BAA4B;IAwF1C;;;;OAIG;YACW,yBAAyB;IAqBjC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAKtE,gBAAgB,IAAI,aAAa;IAI3B,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAM3D,UAAU,IAAI,IAAI;YASJ,UAAU;IAyFxB;;;OAGG;YACW,qBAAqB;CA6CpC"}
|