@enbox/dwn-sdk-js 0.3.7 → 0.3.8
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/dist/browser.mjs +8 -8
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +2591 -1435
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/constants.js +20 -0
- package/dist/esm/src/core/constants.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +24 -1
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +4 -4
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/core/message.js +89 -4
- package/dist/esm/src/core/message.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +147 -55
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +76 -0
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/records-grant-authorization.js +40 -15
- package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
- package/dist/esm/src/handlers/messages-read.js +5 -5
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +109 -7
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/messages-sync.js +341 -96
- package/dist/esm/src/handlers/messages-sync.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +81 -2
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +30 -0
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +3 -2
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +30 -0
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +3 -2
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +31 -0
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +3 -2
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +2 -0
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/messages-read.js +6 -3
- package/dist/esm/src/interfaces/messages-read.js.map +1 -1
- package/dist/esm/src/interfaces/messages-subscribe.js +6 -3
- package/dist/esm/src/interfaces/messages-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/messages-sync.js +17 -3
- package/dist/esm/src/interfaces/messages-sync.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +5 -2
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-query.js +8 -4
- package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-count.js +5 -0
- package/dist/esm/src/interfaces/records-count.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +6 -2
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-query.js +5 -0
- package/dist/esm/src/interfaces/records-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-read.js +6 -3
- package/dist/esm/src/interfaces/records-read.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +5 -0
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +6 -3
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +28 -7
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/sync/records-projection.js +228 -0
- package/dist/esm/src/sync/records-projection.js.map +1 -0
- package/dist/esm/src/types/message-types.js.map +1 -1
- package/dist/esm/src/types/permission-types.js.map +1 -1
- package/dist/esm/src/utils/permission-scope.js +37 -0
- package/dist/esm/src/utils/permission-scope.js.map +1 -0
- package/dist/esm/tests/core/grant-authorization.spec.js +26 -3
- package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/records-grant-authorization.spec.js +117 -0
- package/dist/esm/tests/core/records-grant-authorization.spec.js.map +1 -0
- package/dist/esm/tests/features/permissions.spec.js +126 -0
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-read.spec.js +345 -12
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +326 -9
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-sync.spec.js +1053 -7
- package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +361 -0
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +75 -2
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +73 -0
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +75 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/messages-get.spec.js +107 -5
- package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-configure.spec.js +13 -0
- package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-delete.spec.js +12 -0
- package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-query.spec.js +10 -0
- package/dist/esm/tests/interfaces/records-query.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-subscribe.spec.js +10 -0
- package/dist/esm/tests/interfaces/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +33 -0
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/sync/records-projection.spec.js +245 -0
- package/dist/esm/tests/sync/records-projection.spec.js.map +1 -0
- package/dist/esm/tests/test-suite.js +2 -0
- package/dist/esm/tests/test-suite.js.map +1 -1
- package/dist/esm/tests/utils/permission-scope.spec.js +66 -0
- package/dist/esm/tests/utils/permission-scope.spec.js.map +1 -0
- package/dist/esm/tests/utils/test-data-generator.js +5 -2
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/constants.d.ts +13 -0
- package/dist/types/src/core/constants.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +24 -1
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/grant-authorization.d.ts +1 -2
- package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/message.d.ts +41 -1
- package/dist/types/src/core/message.d.ts.map +1 -1
- package/dist/types/src/core/messages-grant-authorization.d.ts +36 -4
- package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts +12 -0
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/records-grant-authorization.d.ts +6 -0
- package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-subscribe.d.ts +2 -1
- package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-sync.d.ts +31 -0
- package/dist/types/src/handlers/messages-sync.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts +3 -0
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/records-count.d.ts +4 -0
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts +4 -0
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +6 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/messages-read.d.ts +1 -1
- package/dist/types/src/interfaces/messages-read.d.ts.map +1 -1
- package/dist/types/src/interfaces/messages-subscribe.d.ts +1 -1
- package/dist/types/src/interfaces/messages-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/messages-sync.d.ts +4 -1
- package/dist/types/src/interfaces/messages-sync.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-query.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-count.d.ts +1 -0
- package/dist/types/src/interfaces/records-count.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-query.d.ts +1 -0
- package/dist/types/src/interfaces/records-query.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-read.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts +1 -0
- package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/protocols/permissions.d.ts +2 -0
- package/dist/types/src/protocols/permissions.d.ts.map +1 -1
- package/dist/types/src/sync/records-projection.d.ts +98 -0
- package/dist/types/src/sync/records-projection.d.ts.map +1 -0
- package/dist/types/src/types/message-types.d.ts +1 -0
- package/dist/types/src/types/message-types.d.ts.map +1 -1
- package/dist/types/src/types/messages-types.d.ts +21 -3
- package/dist/types/src/types/messages-types.d.ts.map +1 -1
- package/dist/types/src/types/permission-types.d.ts +4 -0
- package/dist/types/src/types/permission-types.d.ts.map +1 -1
- package/dist/types/src/types/records-types.d.ts +4 -0
- package/dist/types/src/types/records-types.d.ts.map +1 -1
- package/dist/types/src/types/subscriptions.d.ts +18 -3
- package/dist/types/src/types/subscriptions.d.ts.map +1 -1
- package/dist/types/src/utils/permission-scope.d.ts +29 -0
- package/dist/types/src/utils/permission-scope.d.ts.map +1 -0
- package/dist/types/tests/core/records-grant-authorization.spec.d.ts +2 -0
- package/dist/types/tests/core/records-grant-authorization.spec.d.ts.map +1 -0
- package/dist/types/tests/features/permissions.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/sync/records-projection.spec.d.ts +2 -0
- package/dist/types/tests/sync/records-projection.spec.d.ts.map +1 -0
- package/dist/types/tests/test-suite.d.ts.map +1 -1
- package/dist/types/tests/utils/permission-scope.spec.d.ts +2 -0
- package/dist/types/tests/utils/permission-scope.spec.d.ts.map +1 -0
- package/dist/types/tests/utils/test-data-generator.d.ts +5 -2
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/constants.ts +24 -0
- package/src/core/dwn-error.ts +24 -1
- package/src/core/grant-authorization.ts +7 -5
- package/src/core/message.ts +153 -6
- package/src/core/messages-grant-authorization.ts +282 -70
- package/src/core/protocol-authorization.ts +130 -0
- package/src/core/records-grant-authorization.ts +64 -21
- package/src/handlers/messages-read.ts +7 -5
- package/src/handlers/messages-subscribe.ts +149 -9
- package/src/handlers/messages-sync.ts +593 -102
- package/src/handlers/protocols-configure.ts +103 -2
- package/src/handlers/records-count.ts +33 -0
- package/src/handlers/records-delete.ts +3 -2
- package/src/handlers/records-query.ts +33 -0
- package/src/handlers/records-read.ts +3 -2
- package/src/handlers/records-subscribe.ts +34 -0
- package/src/handlers/records-write.ts +3 -2
- package/src/index.ts +7 -3
- package/src/interfaces/messages-read.ts +8 -5
- package/src/interfaces/messages-subscribe.ts +12 -9
- package/src/interfaces/messages-sync.ts +33 -12
- package/src/interfaces/protocols-configure.ts +8 -4
- package/src/interfaces/protocols-query.ts +13 -9
- package/src/interfaces/records-count.ts +7 -0
- package/src/interfaces/records-delete.ts +9 -5
- package/src/interfaces/records-query.ts +7 -0
- package/src/interfaces/records-read.ts +6 -3
- package/src/interfaces/records-subscribe.ts +7 -0
- package/src/interfaces/records-write.ts +25 -17
- package/src/protocols/permissions.ts +47 -9
- package/src/sync/records-projection.ts +328 -0
- package/src/types/message-types.ts +1 -0
- package/src/types/messages-types.ts +23 -3
- package/src/types/permission-types.ts +5 -1
- package/src/types/records-types.ts +5 -1
- package/src/types/subscriptions.ts +19 -3
- package/src/utils/permission-scope.ts +55 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GenericMessageReply } from '../types/message-types.js';
|
|
2
2
|
import type { MessageStore } from '../types//message-store.js';
|
|
3
|
+
import type { RecordsWriteMessage } from '../types/records-types.js';
|
|
3
4
|
import type { HandlerDependencies, MethodHandler } from '../types/method-handler.js';
|
|
4
5
|
import type { ProtocolDefinition, ProtocolRuleSet, ProtocolsConfigureMessage } from '../types/protocols-types.js';
|
|
5
6
|
|
|
@@ -7,12 +8,34 @@ import { authenticate } from '../core/auth.js';
|
|
|
7
8
|
import { Message } from '../core/message.js';
|
|
8
9
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
9
10
|
import { PermissionsProtocol } from '../protocols/permissions.js';
|
|
11
|
+
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
10
12
|
import { ProtocolsConfigure } from '../interfaces/protocols-configure.js';
|
|
11
13
|
import { ProtocolsGrantAuthorization } from '../core/protocols-grant-authorization.js';
|
|
14
|
+
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
15
|
+
import { StorageController } from '../store/storage-controller.js';
|
|
12
16
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
13
17
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
14
18
|
import { getRuleSetAtPath, parseCrossProtocolRef } from '../utils/protocols.js';
|
|
15
19
|
|
|
20
|
+
type StoredInitialWriteConfigValidity = 'valid' | 'invalid' | 'unknown';
|
|
21
|
+
|
|
22
|
+
const STORED_INITIAL_WRITE_CONFIG_INVALID_CODES = new Set<string>([
|
|
23
|
+
DwnErrorCode.ProtocolAuthorizationEncryptionRequired,
|
|
24
|
+
DwnErrorCode.ProtocolAuthorizationIncorrectDataFormat,
|
|
25
|
+
DwnErrorCode.ProtocolAuthorizationInitialWriteRevalidationNotInitial,
|
|
26
|
+
DwnErrorCode.ProtocolAuthorizationInvalidSchema,
|
|
27
|
+
DwnErrorCode.ProtocolAuthorizationInvalidType,
|
|
28
|
+
DwnErrorCode.ProtocolAuthorizationMaxSizeInvalid,
|
|
29
|
+
DwnErrorCode.ProtocolAuthorizationMinSizeInvalid,
|
|
30
|
+
DwnErrorCode.ProtocolAuthorizationMissingRuleSet,
|
|
31
|
+
DwnErrorCode.ProtocolAuthorizationSquashNotEnabled,
|
|
32
|
+
DwnErrorCode.ProtocolAuthorizationSquashNotInitialWrite,
|
|
33
|
+
DwnErrorCode.ProtocolAuthorizationStoredInitialWriteActionNotAllowed,
|
|
34
|
+
DwnErrorCode.ProtocolAuthorizationStoredInitialWriteActionRulesNotFound,
|
|
35
|
+
DwnErrorCode.ProtocolAuthorizationStoredInitialWriteRoleMissingRecipient,
|
|
36
|
+
DwnErrorCode.ProtocolAuthorizationTagsInvalidSchema,
|
|
37
|
+
]);
|
|
38
|
+
|
|
16
39
|
export class ProtocolsConfigureHandler implements MethodHandler {
|
|
17
40
|
|
|
18
41
|
constructor(private readonly deps: HandlerDependencies) { }
|
|
@@ -115,6 +138,8 @@ export class ProtocolsConfigureHandler implements MethodHandler {
|
|
|
115
138
|
}
|
|
116
139
|
}
|
|
117
140
|
|
|
141
|
+
await this.purgeRecordsInvalidatedByProtocolConfig(tenant, message.descriptor.definition.protocol);
|
|
142
|
+
|
|
118
143
|
return messageReply;
|
|
119
144
|
};
|
|
120
145
|
|
|
@@ -142,8 +167,9 @@ export class ProtocolsConfigureHandler implements MethodHandler {
|
|
|
142
167
|
|
|
143
168
|
if (protocolConfigure.author === tenant) {
|
|
144
169
|
return;
|
|
145
|
-
} else if (protocolConfigure.author !== undefined && protocolConfigure.signaturePayload
|
|
146
|
-
const
|
|
170
|
+
} else if (protocolConfigure.author !== undefined && Message.getPermissionGrantId(protocolConfigure.signaturePayload!) !== undefined) {
|
|
171
|
+
const permissionGrantId = Message.getPermissionGrantId(protocolConfigure.signaturePayload!)!;
|
|
172
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
147
173
|
await ProtocolsGrantAuthorization.authorizeConfigure({
|
|
148
174
|
protocolsConfigureMessage : protocolConfigure.message,
|
|
149
175
|
expectedGrantor : tenant,
|
|
@@ -156,6 +182,81 @@ export class ProtocolsConfigureHandler implements MethodHandler {
|
|
|
156
182
|
}
|
|
157
183
|
}
|
|
158
184
|
|
|
185
|
+
private async purgeRecordsInvalidatedByProtocolConfig(tenant: string, protocol: string): Promise<void> {
|
|
186
|
+
const dataStore = this.deps.dataStore;
|
|
187
|
+
const stateIndex = this.deps.stateIndex;
|
|
188
|
+
if (dataStore === undefined || stateIndex === undefined) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const { messages } = await this.deps.messageStore.query(tenant, [{
|
|
193
|
+
interface : DwnInterfaceName.Records,
|
|
194
|
+
method : DwnMethodName.Write,
|
|
195
|
+
protocol,
|
|
196
|
+
}]);
|
|
197
|
+
|
|
198
|
+
const checkedRecordIds = new Set<string>();
|
|
199
|
+
for (const message of messages) {
|
|
200
|
+
const recordsWriteMessage = message as RecordsWriteMessage;
|
|
201
|
+
if (checkedRecordIds.has(recordsWriteMessage.recordId)) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const isInitialWrite = await RecordsWrite.isInitialWrite(recordsWriteMessage);
|
|
206
|
+
if (!isInitialWrite) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
checkedRecordIds.add(recordsWriteMessage.recordId);
|
|
211
|
+
|
|
212
|
+
const validity = await this.getStoredInitialWriteConfigValidity(tenant, recordsWriteMessage);
|
|
213
|
+
if (validity !== 'invalid') {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const { messages: recordMessages } = await this.deps.messageStore.query(tenant, [{
|
|
218
|
+
interface : DwnInterfaceName.Records,
|
|
219
|
+
recordId : recordsWriteMessage.recordId,
|
|
220
|
+
}]);
|
|
221
|
+
if (recordMessages.length === 0) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// A DWN cannot synthesize a valid RecordsDelete on behalf of the record author.
|
|
226
|
+
// This repair therefore performs a local hard purge of only the invalid initial
|
|
227
|
+
// record. Descendants are evaluated independently so valid child records are not
|
|
228
|
+
// destroyed as collateral.
|
|
229
|
+
await StorageController.purgeRecordMessages(
|
|
230
|
+
tenant, recordMessages, this.deps.messageStore, dataStore, stateIndex
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private async getStoredInitialWriteConfigValidity(
|
|
236
|
+
tenant: string,
|
|
237
|
+
message: RecordsWriteMessage,
|
|
238
|
+
): Promise<StoredInitialWriteConfigValidity> {
|
|
239
|
+
try {
|
|
240
|
+
const recordsWrite = await RecordsWrite.parse(message);
|
|
241
|
+
// Stored records were authenticated when admitted. Reconciliation should not make
|
|
242
|
+
// record retention depend on fresh DID resolution availability or mutable dependency state.
|
|
243
|
+
await ProtocolAuthorization.validateStoredInitialWrite(
|
|
244
|
+
tenant, recordsWrite, this.deps.messageStore, this.deps.coreProtocols
|
|
245
|
+
);
|
|
246
|
+
return 'valid';
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (ProtocolsConfigureHandler.isStoredInitialWriteConfigInvalidError(error)) {
|
|
249
|
+
return 'invalid';
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return 'unknown';
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private static isStoredInitialWriteConfigInvalidError(error: unknown): boolean {
|
|
257
|
+
return error instanceof DwnError && STORED_INITIAL_WRITE_CONFIG_INVALID_CODES.has(error.code);
|
|
258
|
+
}
|
|
259
|
+
|
|
159
260
|
/**
|
|
160
261
|
* Validates composition dependencies at install time:
|
|
161
262
|
* 1. All `uses` protocols must already be installed for the tenant.
|
|
@@ -7,9 +7,11 @@ import type { RecordsCountMessage, RecordsCountReply } from '../types/records-ty
|
|
|
7
7
|
import { authenticate } from '../core/auth.js';
|
|
8
8
|
import { Message } from '../core/message.js';
|
|
9
9
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
10
|
+
import { PermissionsProtocol } from '../protocols/permissions.js';
|
|
10
11
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
11
12
|
import { Records } from '../utils/records.js';
|
|
12
13
|
import { RecordsCount } from '../interfaces/records-count.js';
|
|
14
|
+
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
13
15
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
14
16
|
|
|
15
17
|
export class RecordsCountHandler implements MethodHandler {
|
|
@@ -90,6 +92,10 @@ export class RecordsCountHandler implements MethodHandler {
|
|
|
90
92
|
filters.push(RecordsCountHandler.buildUnpublishedProtocolAuthorizedRecordsFilter(recordsCount));
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
if (Message.getPermissionGrantId(recordsCount.signaturePayload!) !== undefined) {
|
|
96
|
+
filters.push(RecordsCountHandler.buildUnpublishedPermissionGrantAuthorizedRecordsFilter(recordsCount));
|
|
97
|
+
}
|
|
98
|
+
|
|
93
99
|
if (Records.shouldBuildUnpublishedRecipientFilter(filter, recordsCount.author!)) {
|
|
94
100
|
filters.push(RecordsCountHandler.buildUnpublishedRecordsForCountAuthorFilter(recordsCount));
|
|
95
101
|
}
|
|
@@ -146,6 +152,20 @@ export class RecordsCountHandler implements MethodHandler {
|
|
|
146
152
|
};
|
|
147
153
|
}
|
|
148
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Creates a filter for unpublished records authorized by a permission grant.
|
|
157
|
+
*/
|
|
158
|
+
private static buildUnpublishedPermissionGrantAuthorizedRecordsFilter(recordsCount: RecordsCount): Filter {
|
|
159
|
+
const { filter } = recordsCount.message.descriptor;
|
|
160
|
+
return {
|
|
161
|
+
...Records.convertFilter(filter),
|
|
162
|
+
interface : DwnInterfaceName.Records,
|
|
163
|
+
method : DwnMethodName.Write,
|
|
164
|
+
isLatestBaseState : true,
|
|
165
|
+
published : false
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
149
169
|
/**
|
|
150
170
|
* Creates a filter for only unpublished records where the author is the same as the count author.
|
|
151
171
|
*/
|
|
@@ -175,6 +195,19 @@ export class RecordsCountHandler implements MethodHandler {
|
|
|
175
195
|
await recordsCount.authorizeDelegate(messageStore);
|
|
176
196
|
}
|
|
177
197
|
|
|
198
|
+
const permissionGrantId = Message.getPermissionGrantId(recordsCount.signaturePayload!);
|
|
199
|
+
if (permissionGrantId !== undefined) {
|
|
200
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
201
|
+
await RecordsGrantAuthorization.authorizeQueryOrSubscribe({
|
|
202
|
+
incomingMessage : recordsCount.message,
|
|
203
|
+
expectedGrantor : tenant,
|
|
204
|
+
expectedGrantee : recordsCount.author!,
|
|
205
|
+
permissionGrant,
|
|
206
|
+
messageStore,
|
|
207
|
+
});
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
178
211
|
// NOTE: not all RecordsCount messages require protocol authorization even if the filter includes protocol-related fields,
|
|
179
212
|
// this is because we dynamically filter out records that the caller is not authorized to see.
|
|
180
213
|
// Currently only run protocol authorization if message deliberately invokes a protocol role.
|
|
@@ -110,8 +110,9 @@ export class RecordsDeleteHandler implements MethodHandler {
|
|
|
110
110
|
|
|
111
111
|
if (recordsDelete.author === tenant) {
|
|
112
112
|
return;
|
|
113
|
-
} else if (recordsDelete.author !== undefined && recordsDelete.signaturePayload
|
|
114
|
-
const
|
|
113
|
+
} else if (recordsDelete.author !== undefined && Message.getPermissionGrantId(recordsDelete.signaturePayload!) !== undefined) {
|
|
114
|
+
const permissionGrantId = Message.getPermissionGrantId(recordsDelete.signaturePayload!)!;
|
|
115
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
115
116
|
await RecordsGrantAuthorization.authorizeDelete({
|
|
116
117
|
recordsDeleteMessage : recordsDelete.message,
|
|
117
118
|
recordsWriteToDelete : recordsWrite.message,
|
|
@@ -9,8 +9,10 @@ import { authenticate } from '../core/auth.js';
|
|
|
9
9
|
import { DateSort } from '../types/records-types.js';
|
|
10
10
|
import { Message } from '../core/message.js';
|
|
11
11
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
12
|
+
import { PermissionsProtocol } from '../protocols/permissions.js';
|
|
12
13
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
13
14
|
import { Records } from '../utils/records.js';
|
|
15
|
+
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
14
16
|
import { RecordsQuery } from '../interfaces/records-query.js';
|
|
15
17
|
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
16
18
|
import { SortDirection } from '../types/query-types.js';
|
|
@@ -162,6 +164,10 @@ export class RecordsQueryHandler implements MethodHandler {
|
|
|
162
164
|
filters.push(RecordsQueryHandler.buildUnpublishedProtocolAuthorizedRecordsFilter(recordsQuery));
|
|
163
165
|
}
|
|
164
166
|
|
|
167
|
+
if (Message.getPermissionGrantId(recordsQuery.signaturePayload!) !== undefined) {
|
|
168
|
+
filters.push(RecordsQueryHandler.buildUnpublishedPermissionGrantAuthorizedRecordsFilter(recordsQuery));
|
|
169
|
+
}
|
|
170
|
+
|
|
165
171
|
if (Records.shouldBuildUnpublishedRecipientFilter(filter, recordsQuery.author!)) {
|
|
166
172
|
filters.push(RecordsQueryHandler.buildUnpublishedRecordsForQueryAuthorFilter(recordsQuery));
|
|
167
173
|
}
|
|
@@ -226,6 +232,20 @@ export class RecordsQueryHandler implements MethodHandler {
|
|
|
226
232
|
};
|
|
227
233
|
}
|
|
228
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Creates a filter for unpublished records authorized by a permission grant.
|
|
237
|
+
*/
|
|
238
|
+
private static buildUnpublishedPermissionGrantAuthorizedRecordsFilter(recordsQuery: RecordsQuery): Filter {
|
|
239
|
+
const { dateSort, filter } = recordsQuery.message.descriptor;
|
|
240
|
+
return {
|
|
241
|
+
...Records.convertFilter(filter, dateSort),
|
|
242
|
+
interface : DwnInterfaceName.Records,
|
|
243
|
+
method : DwnMethodName.Write,
|
|
244
|
+
isLatestBaseState : true,
|
|
245
|
+
published : false
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
229
249
|
/**
|
|
230
250
|
* Creates a filter for only unpublished records where the author is the same as the query author.
|
|
231
251
|
*/
|
|
@@ -256,6 +276,19 @@ export class RecordsQueryHandler implements MethodHandler {
|
|
|
256
276
|
await recordsQuery.authorizeDelegate(messageStore);
|
|
257
277
|
}
|
|
258
278
|
|
|
279
|
+
const permissionGrantId = Message.getPermissionGrantId(recordsQuery.signaturePayload!);
|
|
280
|
+
if (permissionGrantId !== undefined) {
|
|
281
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
282
|
+
await RecordsGrantAuthorization.authorizeQueryOrSubscribe({
|
|
283
|
+
incomingMessage : recordsQuery.message,
|
|
284
|
+
expectedGrantor : tenant,
|
|
285
|
+
expectedGrantee : recordsQuery.author!,
|
|
286
|
+
permissionGrant,
|
|
287
|
+
messageStore,
|
|
288
|
+
});
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
259
292
|
// NOTE: not all RecordsQuery messages require protocol authorization even if the filter includes protocol-related fields,
|
|
260
293
|
// this is because we dynamically filter out records that the caller is not authorized to see.
|
|
261
294
|
// Currently only run protocol authorization if message deliberately invokes a protocol role.
|
|
@@ -182,8 +182,9 @@ export class RecordsReadHandler implements MethodHandler {
|
|
|
182
182
|
) {
|
|
183
183
|
// The recipient or author of a message may always read it
|
|
184
184
|
return;
|
|
185
|
-
} else if (recordsRead.author !== undefined && recordsRead.signaturePayload
|
|
186
|
-
const
|
|
185
|
+
} else if (recordsRead.author !== undefined && Message.getPermissionGrantId(recordsRead.signaturePayload!) !== undefined) {
|
|
186
|
+
const permissionGrantId = Message.getPermissionGrantId(recordsRead.signaturePayload!)!;
|
|
187
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
187
188
|
await RecordsGrantAuthorization.authorizeRead({
|
|
188
189
|
recordsReadMessage : recordsRead.message,
|
|
189
190
|
recordsWriteMessageToBeRead : matchedRecordsWrite.message,
|
|
@@ -10,8 +10,10 @@ import { authenticate } from '../core/auth.js';
|
|
|
10
10
|
import { DateSort } from '../types/records-types.js';
|
|
11
11
|
import { Message } from '../core/message.js';
|
|
12
12
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
13
|
+
import { PermissionsProtocol } from '../protocols/permissions.js';
|
|
13
14
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
14
15
|
import { Records } from '../utils/records.js';
|
|
16
|
+
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
15
17
|
import { RecordsSubscribe } from '../interfaces/records-subscribe.js';
|
|
16
18
|
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
17
19
|
import { SortDirection } from '../types/query-types.js';
|
|
@@ -218,6 +220,15 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
218
220
|
});
|
|
219
221
|
}
|
|
220
222
|
|
|
223
|
+
if (Message.getPermissionGrantId(recordsSubscribe.signaturePayload!) !== undefined) {
|
|
224
|
+
filters.push({
|
|
225
|
+
...Records.convertFilter(filter),
|
|
226
|
+
interface : DwnInterfaceName.Records,
|
|
227
|
+
method : [DwnMethodName.Write, DwnMethodName.Delete],
|
|
228
|
+
published : false,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
221
232
|
if (Records.shouldBuildUnpublishedRecipientFilter(filter, recordsSubscribe.author!)) {
|
|
222
233
|
filters.push({
|
|
223
234
|
...Records.convertFilter(filter),
|
|
@@ -293,6 +304,16 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
293
304
|
});
|
|
294
305
|
}
|
|
295
306
|
|
|
307
|
+
if (Message.getPermissionGrantId(recordsSubscribe.signaturePayload!) !== undefined) {
|
|
308
|
+
filters.push({
|
|
309
|
+
...Records.convertFilter(filter, dateSort),
|
|
310
|
+
interface : DwnInterfaceName.Records,
|
|
311
|
+
method : DwnMethodName.Write,
|
|
312
|
+
isLatestBaseState : true,
|
|
313
|
+
published : false,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
296
317
|
if (Records.shouldBuildUnpublishedRecipientFilter(filter, recordsSubscribe.author!)) {
|
|
297
318
|
filters.push({
|
|
298
319
|
...Records.convertFilter(filter, dateSort),
|
|
@@ -335,6 +356,19 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
335
356
|
await recordsSubscribe.authorizeDelegate(messageStore);
|
|
336
357
|
}
|
|
337
358
|
|
|
359
|
+
const permissionGrantId = Message.getPermissionGrantId(recordsSubscribe.signaturePayload!);
|
|
360
|
+
if (permissionGrantId !== undefined) {
|
|
361
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
362
|
+
await RecordsGrantAuthorization.authorizeQueryOrSubscribe({
|
|
363
|
+
incomingMessage : recordsSubscribe.message,
|
|
364
|
+
expectedGrantor : tenant,
|
|
365
|
+
expectedGrantee : recordsSubscribe.author!,
|
|
366
|
+
permissionGrant,
|
|
367
|
+
messageStore,
|
|
368
|
+
});
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
338
372
|
// NOTE: not all RecordsSubscribe messages require protocol authorization even if the filter includes protocol-related fields,
|
|
339
373
|
// this is because we dynamically filter out records that the caller is not authorized to see.
|
|
340
374
|
// Currently only run protocol authorization if message deliberately invokes a protocol role.
|
|
@@ -515,8 +515,9 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
515
515
|
} else if (recordsWrite.author === tenant) {
|
|
516
516
|
// if author is the same as the target tenant, we can directly grant access
|
|
517
517
|
return;
|
|
518
|
-
} else if (recordsWrite.author !== undefined && recordsWrite.signaturePayload
|
|
519
|
-
const
|
|
518
|
+
} else if (recordsWrite.author !== undefined && Message.getPermissionGrantId(recordsWrite.signaturePayload!) !== undefined) {
|
|
519
|
+
const permissionGrantId = Message.getPermissionGrantId(recordsWrite.signaturePayload!)!;
|
|
520
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
520
521
|
await RecordsGrantAuthorization.authorizeWrite({
|
|
521
522
|
recordsWriteMessage : recordsWrite.message,
|
|
522
523
|
expectedGrantor : tenant,
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// export everything that we want to be consumable
|
|
2
2
|
export type { DwnConfig } from './dwn.js';
|
|
3
|
-
export type { EventListener, EventLog, EventLogEntry, EventLogReadOptions, EventLogReadResult, EventLogSubscribeOptions, EventSubscription, MessageEvent, ProgressGapInfo, ProgressGapReason, ProgressToken, SubscriptionEose, SubscriptionEvent, SubscriptionListener, SubscriptionMessage, SubscriptionReply } from './types/subscriptions.js';
|
|
3
|
+
export type { EventListener, EventLog, EventLogEntry, EventLogReadOptions, EventLogReadResult, EventLogSubscribeOptions, EventSubscription, MessageEvent, ProgressGapInfo, ProgressGapReason, ProgressToken, SubscriptionEose, SubscriptionError, SubscriptionEvent, SubscriptionListener, SubscriptionMessage, SubscriptionReply } from './types/subscriptions.js';
|
|
4
4
|
export type { AuthorizationModel, Descriptor, DelegatedGrantRecordsWriteMessage, GenericMessage, GenericMessageReply, GenericSignaturePayload, MessageSort, MessageSubscription, Pagination, QueryResultEntry, Status } from './types/message-types.js';
|
|
5
|
-
export type { MessagesFilter, MessagesReadMessage, MessagesReadReply, MessagesReadReplyEntry, MessagesReadDescriptor, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessagesSubscribeMessageOptions, MessagesSyncAction, MessagesSyncDescriptor, MessagesSyncDiffEntry, MessagesSyncMessage, MessagesSyncReply } from './types/messages-types.js';
|
|
5
|
+
export type { MessagesFilter, MessagesReadMessage, MessagesReadReply, MessagesReadReplyEntry, MessagesReadDescriptor, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessagesSubscribeMessageOptions, MessagesSyncAction, MessagesSyncDependencyClass, MessagesSyncDependencyEntry, MessagesSyncDescriptor, MessagesSyncDiffEntry, MessagesSyncMessage, MessagesSyncReply } from './types/messages-types.js';
|
|
6
6
|
export type { GT, LT, Filter, FilterValue, KeyValues, EqualFilter, OneOfFilter, RangeFilter, RangeCriterion, PaginationCursor, QueryOptions, RangeValue, StartsWithFilter } from './types/query-types.js';
|
|
7
7
|
export type { ProtocolsConfigureDescriptor, ProtocolDefinition, ProtocolTypes, ProtocolRuleSet, ProtocolsQueryFilter, ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply, ProtocolActionRule, ProtocolDeliveryStrategy, ProtocolPathEncryption, ProtocolsQueryDescriptor, ProtocolRecordLimitDefinition, ProtocolSizeDefinition, ProtocolTagsDefinition, ProtocolTagSchema, ProtocolType, ProtocolUses } from './types/protocols-types.js';
|
|
8
8
|
export { ProtocolRecordLimitStrategy } from './types/protocols-types.js';
|
|
@@ -51,6 +51,8 @@ export { PermissionGrant } from './protocols/permission-grant.js';
|
|
|
51
51
|
export { PermissionRequest } from './protocols/permission-request.js';
|
|
52
52
|
export { PermissionsProtocol } from './protocols/permissions.js';
|
|
53
53
|
export type { PermissionGrantCreateOptions, PermissionRequestCreateOptions, PermissionRevocationCreateOptions } from './protocols/permissions.js';
|
|
54
|
+
export { PermissionScopeMatcher } from './utils/permission-scope.js';
|
|
55
|
+
export type { ProtocolScope } from './utils/permission-scope.js';
|
|
54
56
|
export { PrivateKeySigner } from './utils/private-key-signer.js';
|
|
55
57
|
export type { PrivateKeySignerOptions } from './utils/private-key-signer.js';
|
|
56
58
|
export { Protocols, parseCrossProtocolRef, isCrossProtocolRef, getRuleSetAtPath } from './utils/protocols.js';
|
|
@@ -101,8 +103,10 @@ export { SMTStoreLevel } from './smt/smt-store-level.js';
|
|
|
101
103
|
export { SMTStoreMemory } from './smt/smt-store-memory.js';
|
|
102
104
|
export type { Hash, SMTNode, SMTInternalNode, SMTLeafNode, SMTProof, SMTDiffResult, SMTNodeStore } from './types/smt-types.js';
|
|
103
105
|
export { hashChildren, hashEquals, hashKey, hashLeaf, hashToHex, hexToHash, getBit, initDefaultHashes, getDefaultHashes, SMT_DEPTH, ZERO_HASH } from './smt/smt-utils.js';
|
|
106
|
+
export { RECORDS_PROJECTION_ROOT_VERSION, RecordsProjection } from './sync/records-projection.js';
|
|
107
|
+
export type { NormalizedRecordsProjectionScope, RecordsProjectionInput, RecordsProjectionScope, RecordsProjectionSnapshot, RecordsProjectionTreeInput } from './sync/records-projection.js';
|
|
104
108
|
|
|
105
109
|
// test library exports
|
|
106
110
|
export type { GenerateFromRecordsWriteInput, GenerateFromRecordsWriteOut, GenerateGrantCreateInput, GenerateGrantCreateOutput, GenerateMessagesReadInput, GenerateMessagesReadOutput, GenerateMessagesSubscribeInput, GenerateMessagesSubscribeOutput, GenerateProtocolsConfigureInput, GenerateProtocolsConfigureOutput, GenerateProtocolsQueryInput, GenerateProtocolsQueryOutput, GenerateRecordsCountInput, GenerateRecordsCountOutput, GenerateRecordsDeleteInput, GenerateRecordsDeleteOutput, GenerateRecordsQueryInput, GenerateRecordsQueryOutput, GenerateRecordsSubscribeInput, GenerateRecordsSubscribeOutput, GenerateRecordsWriteInput, GenerateRecordsWriteOutput, Persona } from '../tests/utils/test-data-generator.js';
|
|
107
111
|
export { TestDataGenerator } from '../tests/utils/test-data-generator.js';
|
|
108
|
-
export { Poller } from '../tests/utils/poller.js';
|
|
112
|
+
export { Poller } from '../tests/utils/poller.js';
|
|
@@ -12,7 +12,7 @@ export type MessagesReadOptions = {
|
|
|
12
12
|
messageCid: string;
|
|
13
13
|
signer: MessageSigner;
|
|
14
14
|
messageTimestamp?: string;
|
|
15
|
-
|
|
15
|
+
permissionGrantIds?: string[];
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
export class MessagesRead extends AbstractMessage<MessagesReadMessage> {
|
|
@@ -27,19 +27,22 @@ export class MessagesRead extends AbstractMessage<MessagesReadMessage> {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
public static async create(options: MessagesReadOptions): Promise<MessagesRead> {
|
|
30
|
-
const { signer
|
|
30
|
+
const { signer } = options;
|
|
31
|
+
const permissionGrantInvocation = Message.normalizePermissionGrantInvocation({
|
|
32
|
+
permissionGrantIds: options.permissionGrantIds
|
|
33
|
+
});
|
|
31
34
|
|
|
32
35
|
const descriptor: MessagesReadDescriptor = {
|
|
33
36
|
interface : DwnInterfaceName.Messages,
|
|
34
37
|
method : DwnMethodName.Read,
|
|
35
38
|
messageCid : options.messageCid,
|
|
36
39
|
messageTimestamp : options.messageTimestamp ?? Time.getCurrentTimestamp(),
|
|
37
|
-
...
|
|
40
|
+
...permissionGrantInvocation,
|
|
38
41
|
};
|
|
39
42
|
const authorization = await Message.createAuthorization({
|
|
40
43
|
descriptor,
|
|
41
44
|
signer,
|
|
42
|
-
|
|
45
|
+
...permissionGrantInvocation,
|
|
43
46
|
});
|
|
44
47
|
const message = { descriptor, authorization };
|
|
45
48
|
|
|
@@ -61,4 +64,4 @@ export class MessagesRead extends AbstractMessage<MessagesReadMessage> {
|
|
|
61
64
|
throw new DwnError(DwnErrorCode.MessagesReadInvalidCid, `${messageCid} is not a valid CID`);
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
|
-
}
|
|
67
|
+
}
|
|
@@ -15,7 +15,7 @@ export type MessagesSubscribeOptions = {
|
|
|
15
15
|
signer: MessageSigner;
|
|
16
16
|
messageTimestamp?: string;
|
|
17
17
|
filters?: MessagesFilter[];
|
|
18
|
-
|
|
18
|
+
permissionGrantIds?: string[];
|
|
19
19
|
/**
|
|
20
20
|
* Progress token to resume from. When provided, catch-up events are replayed
|
|
21
21
|
* from the EventLog and an EOSE marker is delivered before live events.
|
|
@@ -47,22 +47,25 @@ export class MessagesSubscribe extends AbstractMessage<MessagesSubscribeMessage>
|
|
|
47
47
|
options: MessagesSubscribeOptions
|
|
48
48
|
): Promise<MessagesSubscribe> {
|
|
49
49
|
const currentTime = Time.getCurrentTimestamp();
|
|
50
|
+
const permissionGrantInvocation = Message.normalizePermissionGrantInvocation({
|
|
51
|
+
permissionGrantIds: options.permissionGrantIds
|
|
52
|
+
});
|
|
50
53
|
|
|
51
54
|
const descriptor: MessagesSubscribeDescriptor = {
|
|
52
|
-
interface
|
|
53
|
-
method
|
|
54
|
-
filters
|
|
55
|
-
messageTimestamp
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
interface : DwnInterfaceName.Messages,
|
|
56
|
+
method : DwnMethodName.Subscribe,
|
|
57
|
+
filters : options.filters ?? [],
|
|
58
|
+
messageTimestamp : options.messageTimestamp ?? currentTime,
|
|
59
|
+
cursor : options.cursor,
|
|
60
|
+
...permissionGrantInvocation,
|
|
58
61
|
};
|
|
59
62
|
|
|
60
63
|
removeUndefinedProperties(descriptor);
|
|
61
|
-
const {
|
|
64
|
+
const { signer } = options;
|
|
62
65
|
const authorization = await Message.createAuthorization({
|
|
63
66
|
descriptor,
|
|
64
67
|
signer,
|
|
65
|
-
|
|
68
|
+
...permissionGrantInvocation
|
|
66
69
|
});
|
|
67
70
|
|
|
68
71
|
const message: MessagesSubscribeMessage = { descriptor, authorization };
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import type { MessageSigner } from '../types/signer.js';
|
|
2
|
+
import type { RecordsProjectionScope } from '../sync/records-projection.js';
|
|
2
3
|
import type { MessagesSyncAction, MessagesSyncDescriptor, MessagesSyncMessage } from '../types/messages-types.js';
|
|
3
4
|
|
|
4
5
|
import { AbstractMessage } from '../core/abstract-message.js';
|
|
5
6
|
import { Message } from '../core/message.js';
|
|
7
|
+
import { RECORDS_PROJECTION_ROOT_VERSION } from '../sync/records-projection.js';
|
|
6
8
|
import { removeUndefinedProperties } from '@enbox/common';
|
|
7
9
|
import { Time } from '../utils/time.js';
|
|
8
10
|
import { validateProtocolUrlNormalized } from '../utils/url.js';
|
|
11
|
+
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
9
12
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
10
13
|
|
|
11
14
|
export type MessagesSyncOptions = {
|
|
12
15
|
signer : MessageSigner;
|
|
13
16
|
action : MessagesSyncAction;
|
|
14
17
|
protocol? : string;
|
|
18
|
+
projectionRootVersion?: string;
|
|
19
|
+
projectionScopes?: RecordsProjectionScope[];
|
|
15
20
|
prefix? : string;
|
|
16
21
|
messageTimestamp? : string;
|
|
17
|
-
|
|
22
|
+
permissionGrantIds? : string[];
|
|
18
23
|
/** For `action: 'diff'`: client's subtree hashes at `depth`. */
|
|
19
24
|
hashes? : Record<string, string>;
|
|
20
25
|
/** For `action: 'diff'`: bit depth at which hashes were computed. */
|
|
@@ -30,30 +35,46 @@ export class MessagesSync extends AbstractMessage<MessagesSyncMessage> {
|
|
|
30
35
|
if (message.descriptor.protocol !== undefined) {
|
|
31
36
|
validateProtocolUrlNormalized(message.descriptor.protocol);
|
|
32
37
|
}
|
|
38
|
+
if (message.descriptor.projectionRootVersion !== undefined &&
|
|
39
|
+
message.descriptor.projectionRootVersion !== RECORDS_PROJECTION_ROOT_VERSION) {
|
|
40
|
+
throw new DwnError(
|
|
41
|
+
DwnErrorCode.MessagesSyncUnsupportedProjectionRootVersion,
|
|
42
|
+
`Unsupported projection root version ${message.descriptor.projectionRootVersion}`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
for (const scope of message.descriptor.projectionScopes ?? []) {
|
|
46
|
+
validateProtocolUrlNormalized(scope.protocol);
|
|
47
|
+
}
|
|
33
48
|
|
|
34
49
|
return new MessagesSync(message);
|
|
35
50
|
}
|
|
36
51
|
|
|
37
52
|
public static async create(options: MessagesSyncOptions): Promise<MessagesSync> {
|
|
53
|
+
const permissionGrantInvocation = Message.normalizePermissionGrantInvocation({
|
|
54
|
+
permissionGrantIds: options.permissionGrantIds
|
|
55
|
+
});
|
|
56
|
+
|
|
38
57
|
const descriptor: MessagesSyncDescriptor = {
|
|
39
|
-
interface
|
|
40
|
-
method
|
|
41
|
-
messageTimestamp
|
|
42
|
-
action
|
|
43
|
-
protocol
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
interface : DwnInterfaceName.Messages,
|
|
59
|
+
method : DwnMethodName.Sync,
|
|
60
|
+
messageTimestamp : options.messageTimestamp ?? Time.getCurrentTimestamp(),
|
|
61
|
+
action : options.action,
|
|
62
|
+
protocol : options.protocol,
|
|
63
|
+
projectionRootVersion : options.projectionRootVersion,
|
|
64
|
+
projectionScopes : options.projectionScopes,
|
|
65
|
+
prefix : options.prefix,
|
|
66
|
+
hashes : options.hashes,
|
|
67
|
+
depth : options.depth,
|
|
68
|
+
...permissionGrantInvocation,
|
|
48
69
|
};
|
|
49
70
|
|
|
50
71
|
removeUndefinedProperties(descriptor);
|
|
51
72
|
|
|
52
|
-
const {
|
|
73
|
+
const { signer } = options;
|
|
53
74
|
const authorization = await Message.createAuthorization({
|
|
54
75
|
descriptor,
|
|
55
76
|
signer,
|
|
56
|
-
|
|
77
|
+
...permissionGrantInvocation
|
|
57
78
|
});
|
|
58
79
|
|
|
59
80
|
const message = { descriptor, authorization };
|
|
@@ -40,19 +40,23 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
public static async create(options: ProtocolsConfigureOptions): Promise<ProtocolsConfigure> {
|
|
43
|
+
const permissionGrantInvocation = Message.normalizePermissionGrantInvocation({
|
|
44
|
+
permissionGrantId: options.permissionGrantId,
|
|
45
|
+
});
|
|
46
|
+
|
|
43
47
|
const descriptor: ProtocolsConfigureDescriptor = {
|
|
44
48
|
interface : DwnInterfaceName.Protocols,
|
|
45
49
|
method : DwnMethodName.Configure,
|
|
46
50
|
messageTimestamp : options.messageTimestamp ?? Time.getCurrentTimestamp(),
|
|
47
51
|
definition : ProtocolsConfigure.normalizeDefinition(options.definition),
|
|
48
|
-
...
|
|
52
|
+
...permissionGrantInvocation,
|
|
49
53
|
};
|
|
50
54
|
|
|
51
55
|
const authorization = await Message.createAuthorization({
|
|
52
56
|
descriptor,
|
|
53
|
-
signer
|
|
54
|
-
delegatedGrant
|
|
55
|
-
|
|
57
|
+
signer : options.signer,
|
|
58
|
+
delegatedGrant : options.delegatedGrant,
|
|
59
|
+
...permissionGrantInvocation
|
|
56
60
|
});
|
|
57
61
|
const message = { descriptor, authorization };
|
|
58
62
|
|
|
@@ -36,13 +36,16 @@ export class ProtocolsQuery extends AbstractMessage<ProtocolsQueryMessage> {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
public static async create(options: ProtocolsQueryOptions): Promise<ProtocolsQuery> {
|
|
39
|
+
const permissionGrantInvocation = Message.normalizePermissionGrantInvocation({
|
|
40
|
+
permissionGrantId: options.permissionGrantId,
|
|
41
|
+
});
|
|
39
42
|
|
|
40
43
|
const descriptor: ProtocolsQueryDescriptor = {
|
|
41
|
-
interface
|
|
42
|
-
method
|
|
43
|
-
messageTimestamp
|
|
44
|
-
filter
|
|
45
|
-
|
|
44
|
+
interface : DwnInterfaceName.Protocols,
|
|
45
|
+
method : DwnMethodName.Query,
|
|
46
|
+
messageTimestamp : options.messageTimestamp ?? Time.getCurrentTimestamp(),
|
|
47
|
+
filter : options.filter ? ProtocolsQuery.normalizeFilter(options.filter) : undefined,
|
|
48
|
+
...permissionGrantInvocation,
|
|
46
49
|
};
|
|
47
50
|
|
|
48
51
|
// delete all descriptor properties that are `undefined` else the code will encounter the following IPLD issue when attempting to generate CID:
|
|
@@ -54,8 +57,8 @@ export class ProtocolsQuery extends AbstractMessage<ProtocolsQueryMessage> {
|
|
|
54
57
|
if (options.signer !== undefined) {
|
|
55
58
|
authorization = await Message.createAuthorization({
|
|
56
59
|
descriptor,
|
|
57
|
-
signer
|
|
58
|
-
|
|
60
|
+
signer: options.signer,
|
|
61
|
+
...permissionGrantInvocation
|
|
59
62
|
});
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -78,8 +81,9 @@ export class ProtocolsQuery extends AbstractMessage<ProtocolsQueryMessage> {
|
|
|
78
81
|
// if author is the same as the target tenant, we can directly grant access
|
|
79
82
|
if (this.author === tenant) {
|
|
80
83
|
return;
|
|
81
|
-
} else if (this.author !== undefined && this.signaturePayload
|
|
82
|
-
const
|
|
84
|
+
} else if (this.author !== undefined && Message.getPermissionGrantId(this.signaturePayload!) !== undefined) {
|
|
85
|
+
const permissionGrantId = Message.getPermissionGrantId(this.signaturePayload!)!;
|
|
86
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId);
|
|
83
87
|
await ProtocolsGrantAuthorization.authorizeQuery({
|
|
84
88
|
expectedGrantor : tenant,
|
|
85
89
|
expectedGrantee : this.author,
|