mindoodb 0.0.85 → 0.0.88
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 +6 -2
- package/README.md +6 -4
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +2 -1
- package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +151 -12
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -1
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +340 -24
- package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js.map +1 -1
- package/dist/browser/index.mjs +14 -0
- 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 +95 -10
- package/dist/core/BaseMindooDB.d.ts.map +1 -1
- package/dist/core/BaseMindooDB.js +441 -98
- package/dist/core/BaseMindooDB.js.map +1 -1
- package/dist/core/BaseMindooTenant.d.ts +43 -0
- package/dist/core/BaseMindooTenant.d.ts.map +1 -1
- package/dist/core/BaseMindooTenant.js +157 -6
- package/dist/core/BaseMindooTenant.js.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.d.ts +103 -0
- package/dist/core/BaseMindooTenantDirectory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantDirectory.js +371 -8
- package/dist/core/BaseMindooTenantDirectory.js.map +1 -1
- package/dist/core/BaseMindooTenantFactory.d.ts.map +1 -1
- package/dist/core/BaseMindooTenantFactory.js +2 -1
- package/dist/core/BaseMindooTenantFactory.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/MindooDBServerAdmin.d.ts.map +1 -1
- package/dist/core/MindooDBServerAdmin.js +2 -1
- package/dist/core/MindooDBServerAdmin.js.map +1 -1
- package/dist/core/accesscontrol/directoryProjection.d.ts.map +1 -1
- package/dist/core/accesscontrol/directoryProjection.js +19 -0
- package/dist/core/accesscontrol/directoryProjection.js.map +1 -1
- package/dist/core/accesscontrol/evaluate.d.ts +14 -0
- package/dist/core/accesscontrol/evaluate.d.ts.map +1 -1
- package/dist/core/accesscontrol/evaluate.js +42 -1
- package/dist/core/accesscontrol/evaluate.js.map +1 -1
- package/dist/core/accesscontrol/types.d.ts +88 -4
- package/dist/core/accesscontrol/types.d.ts.map +1 -1
- package/dist/core/accesscontrol/types.js +114 -1
- package/dist/core/accesscontrol/types.js.map +1 -1
- package/dist/core/appendonlystores/network/AuthenticationService.d.ts +14 -0
- package/dist/core/appendonlystores/network/AuthenticationService.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/AuthenticationService.js +27 -7
- package/dist/core/appendonlystores/network/AuthenticationService.js.map +1 -1
- package/dist/core/appendonlystores/network/IrohNetworkTransport.d.ts.map +1 -1
- package/dist/core/appendonlystores/network/IrohNetworkTransport.js +12 -0
- package/dist/core/appendonlystores/network/IrohNetworkTransport.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/RpcContentAddressedStore.d.ts +6 -0
- package/dist/core/appendonlystores/rpc/RpcContentAddressedStore.d.ts.map +1 -1
- package/dist/core/appendonlystores/rpc/RpcContentAddressedStore.js +20 -1
- package/dist/core/appendonlystores/rpc/RpcContentAddressedStore.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 +7 -0
- package/dist/core/appendonlystores/sqlite/SqliteContentAddressedStore.d.ts.map +1 -1
- package/dist/core/appendonlystores/sqlite/SqliteContentAddressedStore.js +39 -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/appendonlystores/syncStores.d.ts.map +1 -1
- package/dist/core/appendonlystores/syncStores.js +25 -5
- package/dist/core/appendonlystores/syncStores.js.map +1 -1
- package/dist/core/appendonlystores/types.d.ts +7 -1
- package/dist/core/appendonlystores/types.d.ts.map +1 -1
- package/dist/core/appendonlystores/types.js +1 -0
- package/dist/core/appendonlystores/types.js.map +1 -1
- package/dist/core/builtinDbInvariants.d.ts +49 -0
- package/dist/core/builtinDbInvariants.d.ts.map +1 -1
- package/dist/core/builtinDbInvariants.js +86 -1
- package/dist/core/builtinDbInvariants.js.map +1 -1
- package/dist/core/crypto/AuthChallenge.d.ts +68 -0
- package/dist/core/crypto/AuthChallenge.d.ts.map +1 -0
- package/dist/core/crypto/AuthChallenge.js +118 -0
- package/dist/core/crypto/AuthChallenge.js.map +1 -0
- package/dist/core/crypto/DomainStatement.d.ts +5 -3
- package/dist/core/crypto/DomainStatement.d.ts.map +1 -1
- package/dist/core/crypto/DomainStatement.js +5 -3
- package/dist/core/crypto/DomainStatement.js.map +1 -1
- package/dist/core/crypto/encryptedFields.d.ts +11 -0
- package/dist/core/crypto/encryptedFields.d.ts.map +1 -1
- package/dist/core/crypto/encryptedFields.js +18 -0
- package/dist/core/crypto/encryptedFields.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/index.d.ts +3 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +17 -6
- package/dist/core/index.js.map +1 -1
- package/dist/core/query/executeQuery.d.ts.map +1 -1
- package/dist/core/query/executeQuery.js +5 -1
- package/dist/core/query/executeQuery.js.map +1 -1
- package/dist/core/query/executeQueryInclude.d.ts.map +1 -1
- package/dist/core/query/executeQueryInclude.js +2 -0
- package/dist/core/query/executeQueryInclude.js.map +1 -1
- package/dist/core/query/queryView.d.ts.map +1 -1
- package/dist/core/query/queryView.js +5 -1
- package/dist/core/query/queryView.js.map +1 -1
- package/dist/core/types.d.ts +204 -10
- 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/userkeys/index.d.ts +1 -0
- package/dist/core/userkeys/index.d.ts.map +1 -1
- package/dist/core/userkeys/index.js +5 -1
- package/dist/core/userkeys/index.js.map +1 -1
- package/dist/core/userkeys/sealedValues.d.ts +54 -0
- package/dist/core/userkeys/sealedValues.d.ts.map +1 -0
- package/dist/core/userkeys/sealedValues.js +67 -0
- package/dist/core/userkeys/sealedValues.js.map +1 -0
- 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/dynamicImportInterop.d.ts +10 -0
- package/dist/core/utils/dynamicImportInterop.d.ts.map +1 -0
- package/dist/core/utils/dynamicImportInterop.js +22 -0
- package/dist/core/utils/dynamicImportInterop.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/appendonlystores/BasicOnDiskContentAddressedStore.d.ts.map +1 -1
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.js +7 -0
- package/dist/node/appendonlystores/BasicOnDiskContentAddressedStore.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 +164 -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 +227 -0
- package/dist/server/SystemAdminAuth.js.map +1 -0
- package/dist/server/TenantManager.d.ts +366 -0
- package/dist/server/TenantManager.d.ts.map +1 -0
- package/dist/server/TenantManager.js +1416 -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 +1410 -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 +207 -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 +1072 -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
|
@@ -63,6 +63,44 @@ export interface BuiltinWriteDecision {
|
|
|
63
63
|
allowed: boolean;
|
|
64
64
|
reason: string;
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Prefixes of **personal databases**: `<prefix><grantDocId>` belongs to the
|
|
68
|
+
* person whose `grantaccess` document has that id (docs/accesscontrol.md
|
|
69
|
+
* §6.11). Built in, like the `directory` and `userdirectory` invariants:
|
|
70
|
+
*
|
|
71
|
+
* - read and sync only for the devices on that grant, identities whose grant
|
|
72
|
+
* lists the prefix in `accessPrefixes` (a service such as the mail gateway
|
|
73
|
+
* that serves every person's outbox), and the tenant admin,
|
|
74
|
+
* - deposit (push of sealed creates only, §6.10) only for identities whose
|
|
75
|
+
* grant lists the prefix in `depositPrefixes`,
|
|
76
|
+
*
|
|
77
|
+
* whatever a configured policy says; a policy can add prefixes
|
|
78
|
+
* (`personalDatabasePrefixes`) and can deny more, never allow more.
|
|
79
|
+
*
|
|
80
|
+
* `mmail_` — MindooMail's mailbox (`mmail_${user.persondocid}` in Haven); the
|
|
81
|
+
* mail gateway deposits incoming mail.
|
|
82
|
+
* `mmailout_` — MindooMail's outbox: the person writes outgoing mail, the mail
|
|
83
|
+
* gateway (accessPrefixes) reads it, sends it and writes status documents.
|
|
84
|
+
*/
|
|
85
|
+
export declare const BUILTIN_PERSONAL_DATABASE_PREFIXES: readonly ["mmail_", "mmailout_"];
|
|
86
|
+
/**
|
|
87
|
+
* Default document-id prefixes a depositor may use in a built-in personal
|
|
88
|
+
* database (docs/accesscontrol.md §6.11): deposits into a mailbox are MindooMail
|
|
89
|
+
* messages (`memo_…`), so documents of other kinds (events, status, folders)
|
|
90
|
+
* there are always the owner's own. A grant's `depositDocIdPrefixes` overrides
|
|
91
|
+
* this per database prefix.
|
|
92
|
+
*/
|
|
93
|
+
export declare const BUILTIN_PERSONAL_DEPOSIT_DOC_ID_PREFIXES: Readonly<Record<string, readonly string[]>>;
|
|
94
|
+
/** A valid personal-database prefix: lowercase letters and digits, ending in `_`. */
|
|
95
|
+
export declare const PERSONAL_DATABASE_PREFIX_REGEX: RegExp;
|
|
96
|
+
/**
|
|
97
|
+
* The owner of a personal database: the matching prefix and the grant id
|
|
98
|
+
* that follows it, or `null` when `dbId` is not a personal database.
|
|
99
|
+
*/
|
|
100
|
+
export declare function personalDatabaseOwner(dbId: string, extraPrefixes?: readonly string[]): {
|
|
101
|
+
prefix: string;
|
|
102
|
+
grantDocId: string;
|
|
103
|
+
} | null;
|
|
66
104
|
export declare function hasBuiltinWriteInvariant(dbId: string): boolean;
|
|
67
105
|
export declare function evaluateBuiltinWrite(input: BuiltinWriteInput): BuiltinWriteDecision;
|
|
68
106
|
/**
|
|
@@ -89,4 +127,15 @@ export declare function shouldSkipLoadedEntry(input: {
|
|
|
89
127
|
docId?: string;
|
|
90
128
|
creatorUsernameHash?: string | null;
|
|
91
129
|
}): boolean;
|
|
130
|
+
/** Document-id prefix of a purge request inside a personal database. */
|
|
131
|
+
export declare const PURGE_REQUEST_ID_PREFIX = "purgereq_";
|
|
132
|
+
/** `form` of a purge request document. */
|
|
133
|
+
export declare const PURGE_REQUEST_FORM = "purgerequest";
|
|
134
|
+
/** Whether `docId` is a purge request of a personal database. */
|
|
135
|
+
export declare function isPurgeRequestDocId(docId: string): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* The document ids a purge request names, from its decrypted `doc_create`
|
|
138
|
+
* payload (`$publicinfos`), or null when the payload is not a purge request.
|
|
139
|
+
*/
|
|
140
|
+
export declare function purgeRequestDocIdsFromCreateBytes(changeBytes: Uint8Array): string[] | null;
|
|
92
141
|
//# sourceMappingURL=builtinDbInvariants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtinDbInvariants.d.ts","sourceRoot":"","sources":["../../src/core/builtinDbInvariants.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,CAAC;AAE1G;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,mCAAoC,CAAC;AAE1E,kEAAkE;AAClE,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAGtF;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,cAAc,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,oBAAoB,CAqEnF;AA4ED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAgBxF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAc7E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,OAAO,CAsCV"}
|
|
1
|
+
{"version":3,"file":"builtinDbInvariants.d.ts","sourceRoot":"","sources":["../../src/core/builtinDbInvariants.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,CAAC;AAE1G;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,mCAAoC,CAAC;AAE1E,kEAAkE;AAClE,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAGtF;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,cAAc,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kCAAkC,kCAAmC,CAAC;AAEnF;;;;;;GAMG;AACH,eAAO,MAAM,wCAAwC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAEhG,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,8BAA8B,QAAsB,CAAC;AAElE;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,aAAa,GAAE,SAAS,MAAM,EAAO,GACpC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAO/C;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,oBAAoB,CAqEnF;AA4ED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAgBxF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAc7E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,OAAO,CAsCV;AAMD,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,cAAc,CAAC;AACnD,0CAA0C;AAC1C,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,WAAW,EAAE,UAAU,GAAG,MAAM,EAAE,GAAG,IAAI,CAkB1F"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PERSONAL_DOC_ID_PREFIXES = void 0;
|
|
3
|
+
exports.PURGE_REQUEST_FORM = exports.PURGE_REQUEST_ID_PREFIX = exports.PERSONAL_DATABASE_PREFIX_REGEX = exports.BUILTIN_PERSONAL_DEPOSIT_DOC_ID_PREFIXES = exports.BUILTIN_PERSONAL_DATABASE_PREFIXES = exports.PERSONAL_DOC_ID_PREFIXES = void 0;
|
|
4
4
|
exports.isPersonalUserdirectoryDocId = isPersonalUserdirectoryDocId;
|
|
5
|
+
exports.personalDatabaseOwner = personalDatabaseOwner;
|
|
5
6
|
exports.hasBuiltinWriteInvariant = hasBuiltinWriteInvariant;
|
|
6
7
|
exports.evaluateBuiltinWrite = evaluateBuiltinWrite;
|
|
7
8
|
exports.usernameHashFromCreateChangeBytes = usernameHashFromCreateChangeBytes;
|
|
8
9
|
exports.entryTypeToBuiltinOp = entryTypeToBuiltinOp;
|
|
9
10
|
exports.shouldSkipLoadedEntry = shouldSkipLoadedEntry;
|
|
11
|
+
exports.isPurgeRequestDocId = isPurgeRequestDocId;
|
|
12
|
+
exports.purgeRequestDocIdsFromCreateBytes = purgeRequestDocIdsFromCreateBytes;
|
|
10
13
|
const automerge_adapter_1 = require("./automerge-adapter");
|
|
11
14
|
const DirectoryStateNode_1 = require("./accesscontrol/DirectoryStateNode");
|
|
12
15
|
const types_1 = require("./types");
|
|
@@ -34,6 +37,50 @@ function isPersonalUserdirectoryDocId(docId) {
|
|
|
34
37
|
return false;
|
|
35
38
|
return exports.PERSONAL_DOC_ID_PREFIXES.some((prefix) => docId.startsWith(prefix));
|
|
36
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Prefixes of **personal databases**: `<prefix><grantDocId>` belongs to the
|
|
42
|
+
* person whose `grantaccess` document has that id (docs/accesscontrol.md
|
|
43
|
+
* §6.11). Built in, like the `directory` and `userdirectory` invariants:
|
|
44
|
+
*
|
|
45
|
+
* - read and sync only for the devices on that grant, identities whose grant
|
|
46
|
+
* lists the prefix in `accessPrefixes` (a service such as the mail gateway
|
|
47
|
+
* that serves every person's outbox), and the tenant admin,
|
|
48
|
+
* - deposit (push of sealed creates only, §6.10) only for identities whose
|
|
49
|
+
* grant lists the prefix in `depositPrefixes`,
|
|
50
|
+
*
|
|
51
|
+
* whatever a configured policy says; a policy can add prefixes
|
|
52
|
+
* (`personalDatabasePrefixes`) and can deny more, never allow more.
|
|
53
|
+
*
|
|
54
|
+
* `mmail_` — MindooMail's mailbox (`mmail_${user.persondocid}` in Haven); the
|
|
55
|
+
* mail gateway deposits incoming mail.
|
|
56
|
+
* `mmailout_` — MindooMail's outbox: the person writes outgoing mail, the mail
|
|
57
|
+
* gateway (accessPrefixes) reads it, sends it and writes status documents.
|
|
58
|
+
*/
|
|
59
|
+
exports.BUILTIN_PERSONAL_DATABASE_PREFIXES = ["mmail_", "mmailout_"];
|
|
60
|
+
/**
|
|
61
|
+
* Default document-id prefixes a depositor may use in a built-in personal
|
|
62
|
+
* database (docs/accesscontrol.md §6.11): deposits into a mailbox are MindooMail
|
|
63
|
+
* messages (`memo_…`), so documents of other kinds (events, status, folders)
|
|
64
|
+
* there are always the owner's own. A grant's `depositDocIdPrefixes` overrides
|
|
65
|
+
* this per database prefix.
|
|
66
|
+
*/
|
|
67
|
+
exports.BUILTIN_PERSONAL_DEPOSIT_DOC_ID_PREFIXES = {
|
|
68
|
+
mmail_: ["memo_"],
|
|
69
|
+
};
|
|
70
|
+
/** A valid personal-database prefix: lowercase letters and digits, ending in `_`. */
|
|
71
|
+
exports.PERSONAL_DATABASE_PREFIX_REGEX = /^[a-z][a-z0-9]*_$/;
|
|
72
|
+
/**
|
|
73
|
+
* The owner of a personal database: the matching prefix and the grant id
|
|
74
|
+
* that follows it, or `null` when `dbId` is not a personal database.
|
|
75
|
+
*/
|
|
76
|
+
function personalDatabaseOwner(dbId, extraPrefixes = []) {
|
|
77
|
+
for (const prefix of [...exports.BUILTIN_PERSONAL_DATABASE_PREFIXES, ...extraPrefixes]) {
|
|
78
|
+
if (dbId.startsWith(prefix) && dbId.length > prefix.length) {
|
|
79
|
+
return { prefix, grantDocId: dbId.slice(prefix.length) };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
37
84
|
function hasBuiltinWriteInvariant(dbId) {
|
|
38
85
|
return dbId === types_1.DIRECTORY_DB_ID || dbId === types_1.USER_DIRECTORY_DB_ID;
|
|
39
86
|
}
|
|
@@ -250,4 +297,42 @@ function shouldSkipLoadedEntry(input) {
|
|
|
250
297
|
}
|
|
251
298
|
return false;
|
|
252
299
|
}
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
// Hard delete in personal databases (docs/accesscontrol.md §6.11, "Purge")
|
|
302
|
+
// ---------------------------------------------------------------------------
|
|
303
|
+
/** Document-id prefix of a purge request inside a personal database. */
|
|
304
|
+
exports.PURGE_REQUEST_ID_PREFIX = "purgereq_";
|
|
305
|
+
/** `form` of a purge request document. */
|
|
306
|
+
exports.PURGE_REQUEST_FORM = "purgerequest";
|
|
307
|
+
/** Whether `docId` is a purge request of a personal database. */
|
|
308
|
+
function isPurgeRequestDocId(docId) {
|
|
309
|
+
return docId.startsWith(exports.PURGE_REQUEST_ID_PREFIX);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* The document ids a purge request names, from its decrypted `doc_create`
|
|
313
|
+
* payload (`$publicinfos`), or null when the payload is not a purge request.
|
|
314
|
+
*/
|
|
315
|
+
function purgeRequestDocIdsFromCreateBytes(changeBytes) {
|
|
316
|
+
const fromRecord = (record) => {
|
|
317
|
+
if (!record || record.form !== exports.PURGE_REQUEST_FORM || !Array.isArray(record.docIds))
|
|
318
|
+
return null;
|
|
319
|
+
const ids = record.docIds.map((id) => String(id)).filter((id) => id.length > 0);
|
|
320
|
+
return ids.length > 0 ? ids : null;
|
|
321
|
+
};
|
|
322
|
+
try {
|
|
323
|
+
const [doc] = automerge_adapter_1.Automerge.applyChanges(automerge_adapter_1.Automerge.init(), [changeBytes]);
|
|
324
|
+
const ids = fromRecord(JSON.parse(JSON.stringify(doc)));
|
|
325
|
+
if (ids)
|
|
326
|
+
return ids;
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
// Payload may be a full Automerge document rather than a change.
|
|
330
|
+
}
|
|
331
|
+
try {
|
|
332
|
+
return fromRecord(JSON.parse(JSON.stringify(automerge_adapter_1.Automerge.load(changeBytes))));
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
253
338
|
//# sourceMappingURL=builtinDbInvariants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtinDbInvariants.js","sourceRoot":"","sources":["../../src/core/builtinDbInvariants.ts"],"names":[],"mappings":";;;AA+CA,oEAGC;
|
|
1
|
+
{"version":3,"file":"builtinDbInvariants.js","sourceRoot":"","sources":["../../src/core/builtinDbInvariants.ts"],"names":[],"mappings":";;;AA+CA,oEAGC;AAmED,sDAUC;AAED,4DAEC;AAED,oDAqEC;AAkFD,8EAgBC;AAED,oDAcC;AAQD,sDA+CC;AAYD,kDAEC;AAMD,8EAkBC;AAzZD,2DAAgD;AAChD,2EAAsE;AACtE,mCAAgE;AAyBhE;;;;;;;;;;;;;;;;GAgBG;AACU,QAAA,wBAAwB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC;AAE1E,kEAAkE;AAClE,SAAgB,4BAA4B,CAAC,KAAgC;IAC3E,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,gCAAwB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7E,CAAC;AA4BD;;;;;;;;;;;;;;;;;;GAkBG;AACU,QAAA,kCAAkC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAU,CAAC;AAEnF;;;;;;GAMG;AACU,QAAA,wCAAwC,GAAgD;IACnG,MAAM,EAAE,CAAC,OAAO,CAAC;CAClB,CAAC;AAEF,qFAAqF;AACxE,QAAA,8BAA8B,GAAG,mBAAmB,CAAC;AAElE;;;GAGG;AACH,SAAgB,qBAAqB,CACnC,IAAY,EACZ,gBAAmC,EAAE;IAErC,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,0CAAkC,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC;QAC/E,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC3D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,wBAAwB,CAAC,IAAY;IACnD,OAAO,IAAI,KAAK,uBAAe,IAAI,IAAI,KAAK,4BAAoB,CAAC;AACnE,CAAC;AAED,SAAgB,oBAAoB,CAAC,KAAwB;IAC3D,IAAI,KAAK,CAAC,IAAI,KAAK,uBAAe,EAAE,CAAC;QACnC,IAAI,CAAC,IAAA,qCAAgB,EAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,yDAAyD,EAAE,CAAC;QAC/F,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;IAC5D,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,4BAAoB,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,IAAA,qCAAgB,EAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;QACxE,IAAI,4BAA4B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,OAAO,wBAAwB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,KAAK,CAAC,EAAE,KAAK,YAAY,EAAE,CAAC;YAC9B,OAAO,OAAO;gBACZ,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,4BAA4B,EAAE;gBACzD,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,0CAA0C,EAAE,CAAC;QAC7E,CAAC;QACD,IAAI,KAAK,CAAC,EAAE,KAAK,cAAc,EAAE,CAAC;YAChC,IAAI,OAAO;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;YAC9E,IACE,KAAK,CAAC,oBAAoB;gBAC1B,KAAK,CAAC,kBAAkB;gBACxB,KAAK,CAAC,oBAAoB,KAAK,KAAK,CAAC,kBAAkB,EACvD,CAAC;gBACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;YACnE,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,wEAAwE;aACjF,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,EAAE,KAAK,YAAY,EAAE,CAAC;YAC9B,IAAI,OAAO;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC;YAC5E,IACE,KAAK,CAAC,oBAAoB;gBAC1B,KAAK,CAAC,kBAAkB;gBACxB,KAAK,CAAC,oBAAoB,KAAK,KAAK,CAAC,kBAAkB,EACvD,CAAC;gBACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;YAChE,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,sEAAsE;aAC/E,CAAC;QACJ,CAAC;QACD,0EAA0E;QAC1E,yEAAyE;QACzE,wEAAwE;QACxE,IACE,KAAK,CAAC,oBAAoB;YAC1B,KAAK,CAAC,kBAAkB;YACxB,KAAK,CAAC,oBAAoB,KAAK,KAAK,CAAC,kBAAkB,EACvD,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC;QACjE,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,0DAA0D,EAAE,CAAC;QAChG,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC;YAChC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,6DAA6D,EAAE,CAAC;QACnG,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;YAC9B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,+CAA+C,EAAE,CAAC;QACrF,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,kDAAkD,EAAE,CAAC;IACxF,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;AAC3D,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,wBAAwB,CAC/B,KAAwB,EACxB,OAAgB;IAEhB,MAAM,OAAO,GAAG,OAAO,CACrB,KAAK,CAAC,mBAAmB;QACvB,KAAK,CAAC,kBAAkB;QACxB,KAAK,CAAC,mBAAmB,KAAK,KAAK,CAAC,kBAAkB,CACzD,CAAC;IACF,IAAI,KAAK,CAAC,EAAE,KAAK,YAAY,EAAE,CAAC;QAC9B,wEAAwE;QACxE,qEAAqE;QACrE,2CAA2C;QAC3C,IAAI,OAAO,IAAI,KAAK,CAAC,kBAAkB,EAAE,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC;QACpE,CAAC;QACD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,4DAA4D;SACrE,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,EAAE,KAAK,YAAY,IAAI,KAAK,CAAC,EAAE,KAAK,cAAc,EAAE,CAAC;QAC7D,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,gCAAgC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAC/E,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,gCAAgC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAC/E,CAAC;QACD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,0DACN,KAAK,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UACzC,sBAAsB;SACvB,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,qCAAqC,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,4DAA4D;SACrE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,8DAA8D;SACvE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;QAC9B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,+CAA+C,EAAE,CAAC;IACrF,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,sEAAsE;KAC/E,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,GAA4B;IAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC;IAChC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACH,SAAgB,iCAAiC,CAAC,WAAuB;IACvE,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,GAAG,6BAAS,CAAC,YAAY,CAClC,6BAAS,CAAC,IAAI,EAA2B,EACzC,CAAC,WAAW,CAAC,CACd,CAAC;QACF,MAAM,UAAU,GAAG,sBAAsB,CAAC,GAA8B,CAAC,CAAC;QAC1E,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;IACD,IAAI,CAAC;QACH,OAAO,sBAAsB,CAAC,6BAAS,CAAC,IAAI,CAA0B,WAAW,CAAC,CAAC,CAAC;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,oBAAoB,CAAC,SAAiB;IACpD,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,YAAY;YACf,OAAO,YAAY,CAAC;QACtB,KAAK,YAAY,CAAC;QAClB,KAAK,cAAc;YACjB,OAAO,YAAY,CAAC;QACtB,KAAK,YAAY;YACf,OAAO,YAAY,CAAC;QACtB,KAAK,cAAc;YACjB,OAAO,cAAc,CAAC;QACxB;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,qBAAqB,CAAC,KASrC;IACC,IAAI,KAAK,CAAC,IAAI,KAAK,uBAAe,EAAE,CAAC;QACnC,OAAO,CAAC,IAAA,qCAAgB,EAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,4BAAoB,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,IAAA,qCAAgB,EAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;QACxE,IAAI,4BAA4B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,uEAAuE;YACvE,wEAAwE;YACxE,uEAAuE;YACvE,sEAAsE;YACtE,uEAAuE;YACvE,wEAAwE;YACxE,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY;gBAAE,OAAO,KAAK,CAAC;YACnD,MAAM,WAAW,GACf,KAAK,CAAC,SAAS,KAAK,YAAY,IAAI,KAAK,CAAC,SAAS,KAAK,cAAc,CAAC;YACzE,IAAI,OAAO;gBAAE,OAAO,CAAC,WAAW,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,mBAAmB,IAAI,CAAC,KAAK,CAAC,kBAAkB;gBAAE,OAAO,KAAK,CAAC;YAC1E,OAAO,KAAK,CAAC,mBAAmB,KAAK,KAAK,CAAC,kBAAkB,CAAC;QAChE,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;YACrC,OAAO,CAAC,OAAO,CAAC;QAClB,CAAC;QACD,sEAAsE;QACtE,wEAAwE;QACxE,IAAI,KAAK,CAAC,SAAS,KAAK,YAAY,IAAI,KAAK,CAAC,SAAS,KAAK,cAAc,EAAE,CAAC;YAC3E,IAAI,CAAC,OAAO;gBAAE,OAAO,KAAK,CAAC;YAC3B,IACE,KAAK,CAAC,oBAAoB;gBAC1B,KAAK,CAAC,kBAAkB;gBACxB,KAAK,CAAC,oBAAoB,KAAK,KAAK,CAAC,kBAAkB,EACvD,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,2EAA2E;AAC3E,8EAA8E;AAE9E,wEAAwE;AAC3D,QAAA,uBAAuB,GAAG,WAAW,CAAC;AACnD,0CAA0C;AAC7B,QAAA,kBAAkB,GAAG,cAAc,CAAC;AAEjD,iEAAiE;AACjE,SAAgB,mBAAmB,CAAC,KAAa;IAC/C,OAAO,KAAK,CAAC,UAAU,CAAC,+BAAuB,CAAC,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,SAAgB,iCAAiC,CAAC,WAAuB;IACvE,MAAM,UAAU,GAAG,CAAC,MAAsC,EAAmB,EAAE;QAC7E,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,0BAAkB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QAChG,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChF,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACrC,CAAC,CAAC;IACF,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,GAAG,6BAAS,CAAC,YAAY,CAAC,6BAAS,CAAC,IAAI,EAA2B,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QAC/F,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAA4B,CAAC,CAAC;QACnF,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;IACD,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,6BAAS,CAAC,IAAI,CAA0B,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a client signs when it answers a login challenge, and what a server
|
|
3
|
+
* accepts back.
|
|
4
|
+
*
|
|
5
|
+
* Every login in MindooDB is challenge/response with an Ed25519 key: a user's
|
|
6
|
+
* device key against a tenant server (sync, Iroh), the system admin key, a
|
|
7
|
+
* server's key against a peer server, and device discovery. Those keys sign
|
|
8
|
+
* other things too — store entries (`EntrySignature.ts`), app seals
|
|
9
|
+
* (`DomainStatement.ts`), witness receipts — so the bytes a challenge makes
|
|
10
|
+
* the key sign must never be one of those.
|
|
11
|
+
*
|
|
12
|
+
* Until v2 the client signed the challenge string as it came. The side that
|
|
13
|
+
* issues the challenge is the side the client is logging in to — a server, or
|
|
14
|
+
* on Iroh a peer device — so whoever ran it could send any string and get a
|
|
15
|
+
* signature over its UTF-8 bytes. The entry layout is expressible as UTF-8,
|
|
16
|
+
* which made that a way to obtain a valid author signature over a forged entry.
|
|
17
|
+
*
|
|
18
|
+
* ## The two challenge forms
|
|
19
|
+
*
|
|
20
|
+
* - **v2** (`mindoodb-auth-challenge/v2:<uuid>`): issued by current servers.
|
|
21
|
+
* The client signs `utf8("mindoodb-auth/v2") || 0x00 || utf8(challenge)`,
|
|
22
|
+
* a domain no other signer in MindooDB uses.
|
|
23
|
+
* - **legacy** (a bare UUID): issued by servers that predate v2. The client
|
|
24
|
+
* signs the UUID's bytes as before. A UUID starts with a hex digit, so it
|
|
25
|
+
* cannot be an entry layout (version byte `0x01`) or a domain statement
|
|
26
|
+
* (`mindoodb-…`).
|
|
27
|
+
*
|
|
28
|
+
* A client refuses to sign anything else. That alone closes the attack against
|
|
29
|
+
* a hostile server or peer, whatever version it runs.
|
|
30
|
+
*
|
|
31
|
+
* ## Transition
|
|
32
|
+
*
|
|
33
|
+
* Clients that predate v2 sign whatever string they get, so they answer a v2
|
|
34
|
+
* challenge with a raw signature over it. Servers accept that as long as
|
|
35
|
+
* `acceptLegacySignatures` is on (the default) — it is still safe, because the
|
|
36
|
+
* server chose the bytes. Switch it off once no old clients remain.
|
|
37
|
+
*/
|
|
38
|
+
/** Prefix of a v2 challenge. Not a signing domain: the client adds its own. */
|
|
39
|
+
export declare const AUTH_CHALLENGE_V2_PREFIX = "mindoodb-auth-challenge/v2:";
|
|
40
|
+
/** Domain a v2 challenge response is signed under. */
|
|
41
|
+
export declare const AUTH_CHALLENGE_SIGNING_DOMAIN = "mindoodb-auth/v2";
|
|
42
|
+
/** A fresh v2 challenge, for a server to hand out. */
|
|
43
|
+
export declare function issueAuthChallenge(): string;
|
|
44
|
+
/** Which form `challenge` is in, or null when a client must not sign it. */
|
|
45
|
+
export declare function authChallengeForm(challenge: unknown): "v2" | "legacy" | null;
|
|
46
|
+
/**
|
|
47
|
+
* The bytes a client signs to answer `challenge`. Throws for anything that is
|
|
48
|
+
* neither a v2 challenge nor a bare UUID — the server or peer sending it is
|
|
49
|
+
* either broken or trying to get a signature over bytes of its choosing.
|
|
50
|
+
*/
|
|
51
|
+
export declare function authChallengeSigningBytes(challenge: string): Uint8Array<ArrayBuffer>;
|
|
52
|
+
/**
|
|
53
|
+
* The byte strings a server accepts a signature over, for a challenge it
|
|
54
|
+
* issued itself: the v2 domain form, plus the raw string from clients that
|
|
55
|
+
* predate v2 while `acceptLegacySignatures` is on. A legacy (bare UUID)
|
|
56
|
+
* challenge only ever had the raw form.
|
|
57
|
+
*/
|
|
58
|
+
export declare function authChallengeVerificationInputs(challenge: string, options?: {
|
|
59
|
+
acceptLegacySignatures?: boolean;
|
|
60
|
+
}): Uint8Array<ArrayBuffer>[];
|
|
61
|
+
/**
|
|
62
|
+
* Verify a challenge response against an imported Ed25519 public key, trying
|
|
63
|
+
* each form {@link authChallengeVerificationInputs} allows.
|
|
64
|
+
*/
|
|
65
|
+
export declare function verifyAuthChallengeSignature(subtle: SubtleCrypto, publicKey: CryptoKey, challenge: string, signature: Uint8Array, options?: {
|
|
66
|
+
acceptLegacySignatures?: boolean;
|
|
67
|
+
}): Promise<boolean>;
|
|
68
|
+
//# sourceMappingURL=AuthChallenge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthChallenge.d.ts","sourceRoot":"","sources":["../../../src/core/crypto/AuthChallenge.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AAEtE,sDAAsD;AACtD,eAAO,MAAM,6BAA6B,qBAAqB,CAAC;AAMhE,sDAAsD;AACtD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAQ5E;AAYD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAYpF;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAO,GACjD,UAAU,CAAC,WAAW,CAAC,EAAE,CAM3B;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,UAAU,EACrB,OAAO,GAAE;IAAE,sBAAsB,CAAC,EAAE,OAAO,CAAA;CAAO,GACjD,OAAO,CAAC,OAAO,CAAC,CAWlB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AUTH_CHALLENGE_SIGNING_DOMAIN = exports.AUTH_CHALLENGE_V2_PREFIX = void 0;
|
|
4
|
+
exports.issueAuthChallenge = issueAuthChallenge;
|
|
5
|
+
exports.authChallengeForm = authChallengeForm;
|
|
6
|
+
exports.authChallengeSigningBytes = authChallengeSigningBytes;
|
|
7
|
+
exports.authChallengeVerificationInputs = authChallengeVerificationInputs;
|
|
8
|
+
exports.verifyAuthChallengeSignature = verifyAuthChallengeSignature;
|
|
9
|
+
const idGeneration_1 = require("../utils/idGeneration");
|
|
10
|
+
/**
|
|
11
|
+
* What a client signs when it answers a login challenge, and what a server
|
|
12
|
+
* accepts back.
|
|
13
|
+
*
|
|
14
|
+
* Every login in MindooDB is challenge/response with an Ed25519 key: a user's
|
|
15
|
+
* device key against a tenant server (sync, Iroh), the system admin key, a
|
|
16
|
+
* server's key against a peer server, and device discovery. Those keys sign
|
|
17
|
+
* other things too — store entries (`EntrySignature.ts`), app seals
|
|
18
|
+
* (`DomainStatement.ts`), witness receipts — so the bytes a challenge makes
|
|
19
|
+
* the key sign must never be one of those.
|
|
20
|
+
*
|
|
21
|
+
* Until v2 the client signed the challenge string as it came. The side that
|
|
22
|
+
* issues the challenge is the side the client is logging in to — a server, or
|
|
23
|
+
* on Iroh a peer device — so whoever ran it could send any string and get a
|
|
24
|
+
* signature over its UTF-8 bytes. The entry layout is expressible as UTF-8,
|
|
25
|
+
* which made that a way to obtain a valid author signature over a forged entry.
|
|
26
|
+
*
|
|
27
|
+
* ## The two challenge forms
|
|
28
|
+
*
|
|
29
|
+
* - **v2** (`mindoodb-auth-challenge/v2:<uuid>`): issued by current servers.
|
|
30
|
+
* The client signs `utf8("mindoodb-auth/v2") || 0x00 || utf8(challenge)`,
|
|
31
|
+
* a domain no other signer in MindooDB uses.
|
|
32
|
+
* - **legacy** (a bare UUID): issued by servers that predate v2. The client
|
|
33
|
+
* signs the UUID's bytes as before. A UUID starts with a hex digit, so it
|
|
34
|
+
* cannot be an entry layout (version byte `0x01`) or a domain statement
|
|
35
|
+
* (`mindoodb-…`).
|
|
36
|
+
*
|
|
37
|
+
* A client refuses to sign anything else. That alone closes the attack against
|
|
38
|
+
* a hostile server or peer, whatever version it runs.
|
|
39
|
+
*
|
|
40
|
+
* ## Transition
|
|
41
|
+
*
|
|
42
|
+
* Clients that predate v2 sign whatever string they get, so they answer a v2
|
|
43
|
+
* challenge with a raw signature over it. Servers accept that as long as
|
|
44
|
+
* `acceptLegacySignatures` is on (the default) — it is still safe, because the
|
|
45
|
+
* server chose the bytes. Switch it off once no old clients remain.
|
|
46
|
+
*/
|
|
47
|
+
/** Prefix of a v2 challenge. Not a signing domain: the client adds its own. */
|
|
48
|
+
exports.AUTH_CHALLENGE_V2_PREFIX = "mindoodb-auth-challenge/v2:";
|
|
49
|
+
/** Domain a v2 challenge response is signed under. */
|
|
50
|
+
exports.AUTH_CHALLENGE_SIGNING_DOMAIN = "mindoodb-auth/v2";
|
|
51
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
52
|
+
const textEncoder = new TextEncoder();
|
|
53
|
+
/** A fresh v2 challenge, for a server to hand out. */
|
|
54
|
+
function issueAuthChallenge() {
|
|
55
|
+
return `${exports.AUTH_CHALLENGE_V2_PREFIX}${(0, idGeneration_1.generateRandomUuid)()}`;
|
|
56
|
+
}
|
|
57
|
+
/** Which form `challenge` is in, or null when a client must not sign it. */
|
|
58
|
+
function authChallengeForm(challenge) {
|
|
59
|
+
if (typeof challenge !== "string") {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (challenge.startsWith(exports.AUTH_CHALLENGE_V2_PREFIX)) {
|
|
63
|
+
return UUID_PATTERN.test(challenge.slice(exports.AUTH_CHALLENGE_V2_PREFIX.length)) ? "v2" : null;
|
|
64
|
+
}
|
|
65
|
+
return UUID_PATTERN.test(challenge) ? "legacy" : null;
|
|
66
|
+
}
|
|
67
|
+
function domainBytes(challenge) {
|
|
68
|
+
const prefix = textEncoder.encode(exports.AUTH_CHALLENGE_SIGNING_DOMAIN);
|
|
69
|
+
const body = textEncoder.encode(challenge);
|
|
70
|
+
const out = new Uint8Array(prefix.byteLength + 1 + body.byteLength);
|
|
71
|
+
out.set(prefix, 0);
|
|
72
|
+
out[prefix.byteLength] = 0x00;
|
|
73
|
+
out.set(body, prefix.byteLength + 1);
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The bytes a client signs to answer `challenge`. Throws for anything that is
|
|
78
|
+
* neither a v2 challenge nor a bare UUID — the server or peer sending it is
|
|
79
|
+
* either broken or trying to get a signature over bytes of its choosing.
|
|
80
|
+
*/
|
|
81
|
+
function authChallengeSigningBytes(challenge) {
|
|
82
|
+
const form = authChallengeForm(challenge);
|
|
83
|
+
if (form === "v2") {
|
|
84
|
+
return domainBytes(challenge);
|
|
85
|
+
}
|
|
86
|
+
if (form === "legacy") {
|
|
87
|
+
return textEncoder.encode(challenge);
|
|
88
|
+
}
|
|
89
|
+
throw new Error("Refusing to sign a login challenge in an unknown format. "
|
|
90
|
+
+ "The server or peer is not a MindooDB server, or is misbehaving.");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The byte strings a server accepts a signature over, for a challenge it
|
|
94
|
+
* issued itself: the v2 domain form, plus the raw string from clients that
|
|
95
|
+
* predate v2 while `acceptLegacySignatures` is on. A legacy (bare UUID)
|
|
96
|
+
* challenge only ever had the raw form.
|
|
97
|
+
*/
|
|
98
|
+
function authChallengeVerificationInputs(challenge, options = {}) {
|
|
99
|
+
const raw = textEncoder.encode(challenge);
|
|
100
|
+
if (authChallengeForm(challenge) !== "v2") {
|
|
101
|
+
return [raw];
|
|
102
|
+
}
|
|
103
|
+
return options.acceptLegacySignatures === false ? [domainBytes(challenge)] : [domainBytes(challenge), raw];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Verify a challenge response against an imported Ed25519 public key, trying
|
|
107
|
+
* each form {@link authChallengeVerificationInputs} allows.
|
|
108
|
+
*/
|
|
109
|
+
async function verifyAuthChallengeSignature(subtle, publicKey, challenge, signature, options = {}) {
|
|
110
|
+
const signatureBytes = signature.buffer.slice(signature.byteOffset, signature.byteOffset + signature.byteLength);
|
|
111
|
+
for (const message of authChallengeVerificationInputs(challenge, options)) {
|
|
112
|
+
if (await subtle.verify({ name: "Ed25519" }, publicKey, signatureBytes, message)) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=AuthChallenge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthChallenge.js","sourceRoot":"","sources":["../../../src/core/crypto/AuthChallenge.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,9 +14,11 @@
|
|
|
14
14
|
*
|
|
15
15
|
* and `domain` must come from {@link SIGNING_DOMAINS}. Because every allowed
|
|
16
16
|
* domain starts with an ASCII letter while the entry layout starts with its
|
|
17
|
-
* version byte `0x01`,
|
|
18
|
-
* `
|
|
19
|
-
*
|
|
17
|
+
* version byte `0x01`, the two cannot overlap. Login challenges are signed
|
|
18
|
+
* under their own domain `mindoodb-auth/v2`, or — against servers older than
|
|
19
|
+
* that — only when they are a bare UUID (`crypto/AuthChallenge.ts`), so they
|
|
20
|
+
* stay out of both spaces too. The `0x00` separator stops one domain from
|
|
21
|
+
* being a prefix of another.
|
|
20
22
|
*/
|
|
21
23
|
/**
|
|
22
24
|
* Every purpose an app may request a signature for. Deliberately a closed list:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DomainStatement.d.ts","sourceRoot":"","sources":["../../../src/core/crypto/DomainStatement.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"DomainStatement.d.ts","sourceRoot":"","sources":["../../../src/core/crypto/DomainStatement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe;IAC1B,gFAAgF;;EAEvE,CAAC;AAEZ,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAInF,+DAA+D;AAC/D,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,MAAM,EAAE,MAAM;CAM3B;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,aAAa,CAE9E;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAI1F;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,CAa3F"}
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
*
|
|
16
16
|
* and `domain` must come from {@link SIGNING_DOMAINS}. Because every allowed
|
|
17
17
|
* domain starts with an ASCII letter while the entry layout starts with its
|
|
18
|
-
* version byte `0x01`,
|
|
19
|
-
* `
|
|
20
|
-
*
|
|
18
|
+
* version byte `0x01`, the two cannot overlap. Login challenges are signed
|
|
19
|
+
* under their own domain `mindoodb-auth/v2`, or — against servers older than
|
|
20
|
+
* that — only when they are a bare UUID (`crypto/AuthChallenge.ts`), so they
|
|
21
|
+
* stay out of both spaces too. The `0x00` separator stops one domain from
|
|
22
|
+
* being a prefix of another.
|
|
21
23
|
*/
|
|
22
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
25
|
exports.InvalidSigningDomainError = exports.MAX_DOMAIN_STATEMENT_BYTES = exports.SIGNING_DOMAINS = void 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DomainStatement.js","sourceRoot":"","sources":["../../../src/core/crypto/DomainStatement.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"DomainStatement.js","sourceRoot":"","sources":["../../../src/core/crypto/DomainStatement.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;AA2BH,wDAEC;AAED,gEAIC;AAQD,8DAaC;AAtDD;;;GAGG;AACU,QAAA,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,gFAAgF;IAChF,OAAO,EAAE,kBAAkB;CACnB,CAAC,CAAC;AAIZ,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,uBAAe,CAAC,CAAC,CAAC;AAErF,+DAA+D;AAClD,QAAA,0BAA0B,GAAG,GAAG,GAAG,IAAI,CAAC;AAErD,MAAa,yBAA0B,SAAQ,KAAK;IAClD,YAAY,MAAc;QACxB,KAAK,CACH,IAAI,MAAM,wDAAwD,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5G,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAPD,8DAOC;AAED,SAAgB,sBAAsB,CAAC,MAAc;IACnD,OAAO,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,0BAA0B,CAAC,MAAc;IACvD,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,yBAAyB,CAAC,MAAc,EAAE,SAAqB;IAC7E,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,SAAS,CAAC,UAAU,GAAG,kCAA0B,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,wBAAwB,SAAS,CAAC,UAAU,eAAe,kCAA0B,GAAG,CACzF,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IACzE,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACnB,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAC9B,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAC1C,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
export interface EncryptedFieldDecryptor {
|
|
7
7
|
decryptPayload(encryptedPayload: Uint8Array, decryptionKeyId: string): Promise<Uint8Array>;
|
|
8
8
|
}
|
|
9
|
+
/** Minimal encryptor surface for {@link encryptEncryptedField} (a subset of `MindooTenant`). */
|
|
10
|
+
export interface EncryptedFieldEncryptor {
|
|
11
|
+
encryptPayload(payload: Uint8Array, decryptionKeyId: string): Promise<Uint8Array>;
|
|
12
|
+
}
|
|
9
13
|
/**
|
|
10
14
|
* Resolves the symmetric key id for an `_encrypted` field following the
|
|
11
15
|
* `<field>_encrypted` / `<field>_encrypted_key` naming convention.
|
|
@@ -14,6 +18,13 @@ export interface EncryptedFieldDecryptor {
|
|
|
14
18
|
* field on the document -> the tenant default key (`"default"`).
|
|
15
19
|
*/
|
|
16
20
|
export declare function getEncryptedFieldKeyId(data: Record<string, unknown>, encryptedFieldName: string, override?: string | null): string;
|
|
21
|
+
/**
|
|
22
|
+
* Encrypts UTF-8 `plaintext` for an `_encrypted` field with the symmetric key
|
|
23
|
+
* `keyId` (default: the tenant `default` key), the counterpart of
|
|
24
|
+
* {@link decryptEncryptedField}. Store a non-default `keyId` in the
|
|
25
|
+
* `<field>_key` companion field so readers find it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function encryptEncryptedField(encryptor: EncryptedFieldEncryptor, plaintext: string, keyId?: string): Promise<string>;
|
|
17
28
|
/**
|
|
18
29
|
* Decrypts a base64 `_encrypted` field to its UTF-8 plaintext.
|
|
19
30
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryptedFields.d.ts","sourceRoot":"","sources":["../../../src/core/crypto/encryptedFields.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5F;AAKD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,CASR;AAYD;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,uBAAuB,EAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,kBAAkB,EAAE,MAAM,EAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB"}
|
|
1
|
+
{"version":3,"file":"encryptedFields.d.ts","sourceRoot":"","sources":["../../../src/core/crypto/encryptedFields.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5F;AAED,gGAAgG;AAChG,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACnF;AAKD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,CASR;AAWD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,uBAAuB,EAClC,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAA8B,GACpC,OAAO,CAAC,MAAM,CAAC,CAEjB;AAYD;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,uBAAuB,EAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,kBAAkB,EAAE,MAAM,EAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getEncryptedFieldKeyId = getEncryptedFieldKeyId;
|
|
4
|
+
exports.encryptEncryptedField = encryptEncryptedField;
|
|
4
5
|
exports.decryptEncryptedField = decryptEncryptedField;
|
|
5
6
|
const types_1 = require("../types");
|
|
6
7
|
/** Suffix of the companion field naming the key id of an `_encrypted` field. */
|
|
@@ -22,6 +23,23 @@ function getEncryptedFieldKeyId(data, encryptedFieldName, override) {
|
|
|
22
23
|
}
|
|
23
24
|
return types_1.DEFAULT_TENANT_KEY_ID;
|
|
24
25
|
}
|
|
26
|
+
/** Encodes bytes as base64. */
|
|
27
|
+
function uint8ArrayToBase64(bytes) {
|
|
28
|
+
let binary = "";
|
|
29
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
30
|
+
binary += String.fromCharCode(bytes[i]);
|
|
31
|
+
}
|
|
32
|
+
return btoa(binary);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Encrypts UTF-8 `plaintext` for an `_encrypted` field with the symmetric key
|
|
36
|
+
* `keyId` (default: the tenant `default` key), the counterpart of
|
|
37
|
+
* {@link decryptEncryptedField}. Store a non-default `keyId` in the
|
|
38
|
+
* `<field>_key` companion field so readers find it.
|
|
39
|
+
*/
|
|
40
|
+
async function encryptEncryptedField(encryptor, plaintext, keyId = types_1.DEFAULT_TENANT_KEY_ID) {
|
|
41
|
+
return uint8ArrayToBase64(await encryptor.encryptPayload(new TextEncoder().encode(plaintext), keyId));
|
|
42
|
+
}
|
|
25
43
|
/** Decodes a base64 string into bytes. */
|
|
26
44
|
function base64ToUint8Array(base64) {
|
|
27
45
|
const binary = atob(base64);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryptedFields.js","sourceRoot":"","sources":["../../../src/core/crypto/encryptedFields.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"encryptedFields.js","sourceRoot":"","sources":["../../../src/core/crypto/encryptedFields.ts"],"names":[],"mappings":";;AA0BA,wDAaC;AAiBD,sDAMC;AAqBD,sDAkBC;AArGD,oCAAiD;AAgBjD,gFAAgF;AAChF,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC;;;;;;GAMG;AACH,SAAgB,sBAAsB,CACpC,IAA6B,EAC7B,kBAA0B,EAC1B,QAAwB;IAExB,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QACpD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,kBAAkB,GAAG,gBAAgB,EAAE,CAAC,CAAC;IACnE,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACtD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,6BAAqB,CAAC;AAC/B,CAAC;AAED,+BAA+B;AAC/B,SAAS,kBAAkB,CAAC,KAAiB;IAC3C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,qBAAqB,CACzC,SAAkC,EAClC,SAAiB,EACjB,QAAgB,6BAAqB;IAErC,OAAO,kBAAkB,CAAC,MAAM,SAAS,CAAC,cAAc,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACxG,CAAC;AAED,0CAA0C;AAC1C,SAAS,kBAAkB,CAAC,MAAc;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,qBAAqB,CACzC,SAAkC,EAClC,IAA6B,EAC7B,kBAA0B,EAC1B,aAA6B;IAE7B,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,UAAU,EAAE,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,EAAE,aAAa,CAAC,CAAC;IAC9E,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACnE,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -71,6 +71,14 @@ export declare const VIEW_CONTEXT_OPERATIONS: ReadonlySet<string>;
|
|
|
71
71
|
export declare function getFieldValue(source: Record<string, unknown>, path: string): unknown;
|
|
72
72
|
export declare function expressionToNumber(value: unknown): number | null;
|
|
73
73
|
export declare function expressionToBoolean(value: unknown): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Ordering for `gt`/`gte`/`lt`/`lte`. Numbers compare numerically (a numeric
|
|
76
|
+
* string next to a number counts as a number) and dates by time (an ISO
|
|
77
|
+
* string next to a date counts as a date); everything else, including a
|
|
78
|
+
* missing value, compares as strings, so `10 > 9` holds and `"10" > "9"`
|
|
79
|
+
* stays a string comparison.
|
|
80
|
+
*/
|
|
81
|
+
export declare function compareOrdered(a: unknown, b: unknown): number;
|
|
74
82
|
/**
|
|
75
83
|
* Evaluates an expression against a document plus the current view/value
|
|
76
84
|
* context. This is the runtime counterpart of the builder and parser.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluateExpression.d.ts","sourceRoot":"","sources":["../../../src/core/expressions/evaluateExpression.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"evaluateExpression.d.ts","sourceRoot":"","sources":["../../../src/core/expressions/evaluateExpression.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ exports.EXPRESSION_KINDS = exports.VIEW_CONTEXT_OPERATIONS = void 0;
|
|
|
4
4
|
exports.getFieldValue = getFieldValue;
|
|
5
5
|
exports.expressionToNumber = expressionToNumber;
|
|
6
6
|
exports.expressionToBoolean = expressionToBoolean;
|
|
7
|
+
exports.compareOrdered = compareOrdered;
|
|
7
8
|
exports.evaluateExpression = evaluateExpression;
|
|
8
9
|
exports.findUnknownExpressionNode = findUnknownExpressionNode;
|
|
9
10
|
exports.collectDecryptRequests = collectDecryptRequests;
|
|
@@ -61,6 +62,30 @@ function expressionToBoolean(value) {
|
|
|
61
62
|
}
|
|
62
63
|
return Boolean(value);
|
|
63
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Ordering for `gt`/`gte`/`lt`/`lte`. Numbers compare numerically (a numeric
|
|
67
|
+
* string next to a number counts as a number) and dates by time (an ISO
|
|
68
|
+
* string next to a date counts as a date); everything else, including a
|
|
69
|
+
* missing value, compares as strings, so `10 > 9` holds and `"10" > "9"`
|
|
70
|
+
* stays a string comparison.
|
|
71
|
+
*/
|
|
72
|
+
function compareOrdered(a, b) {
|
|
73
|
+
if (a instanceof Date || b instanceof Date) {
|
|
74
|
+
const ta = toDate(a)?.getTime();
|
|
75
|
+
const tb = toDate(b)?.getTime();
|
|
76
|
+
if (ta !== undefined && tb !== undefined)
|
|
77
|
+
return ta - tb;
|
|
78
|
+
}
|
|
79
|
+
else if (typeof a === "number" || typeof b === "number") {
|
|
80
|
+
const na = expressionToNumber(a);
|
|
81
|
+
const nb = expressionToNumber(b);
|
|
82
|
+
if (na !== null && nb !== null)
|
|
83
|
+
return na - nb;
|
|
84
|
+
}
|
|
85
|
+
const sa = String(a ?? "");
|
|
86
|
+
const sb = String(b ?? "");
|
|
87
|
+
return sa < sb ? -1 : sa > sb ? 1 : 0;
|
|
88
|
+
}
|
|
64
89
|
function toDate(value) {
|
|
65
90
|
if (value instanceof Date) {
|
|
66
91
|
return Number.isNaN(value.getTime()) ? null : value;
|
|
@@ -159,13 +184,13 @@ function evaluateOperation(expression, context) {
|
|
|
159
184
|
case "neq":
|
|
160
185
|
return args[0] !== args[1];
|
|
161
186
|
case "gt":
|
|
162
|
-
return
|
|
187
|
+
return compareOrdered(args[0], args[1]) > 0;
|
|
163
188
|
case "gte":
|
|
164
|
-
return
|
|
189
|
+
return compareOrdered(args[0], args[1]) >= 0;
|
|
165
190
|
case "lt":
|
|
166
|
-
return
|
|
191
|
+
return compareOrdered(args[0], args[1]) < 0;
|
|
167
192
|
case "lte":
|
|
168
|
-
return
|
|
193
|
+
return compareOrdered(args[0], args[1]) <= 0;
|
|
169
194
|
case "and":
|
|
170
195
|
return args.every((value) => expressionToBoolean(value));
|
|
171
196
|
case "or":
|