@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
package/src/core/message.ts
CHANGED
|
@@ -12,6 +12,20 @@ import { removeUndefinedProperties } from '@enbox/common';
|
|
|
12
12
|
import { validateJsonSchema } from '../schema-validator.js';
|
|
13
13
|
import { DwnError, DwnErrorCode } from './dwn-error.js';
|
|
14
14
|
|
|
15
|
+
type PermissionGrantInvocation = {
|
|
16
|
+
permissionGrantId?: string;
|
|
17
|
+
permissionGrantIds?: string[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type ValidateSignatureStructureOptions = {
|
|
21
|
+
/**
|
|
22
|
+
* Permission grant invocations are bound to the author signature payload.
|
|
23
|
+
* Owner signatures only prove owner retention/consent and do not repeat
|
|
24
|
+
* the author's grant invocation fields.
|
|
25
|
+
*/
|
|
26
|
+
validatePermissionGrantInvocation?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
15
29
|
/**
|
|
16
30
|
* A class containing utility methods for working with DWN messages.
|
|
17
31
|
*/
|
|
@@ -100,16 +114,17 @@ export class Message {
|
|
|
100
114
|
signer: MessageSigner,
|
|
101
115
|
delegatedGrant?: DataEncodedRecordsWriteMessage,
|
|
102
116
|
permissionGrantId?: string,
|
|
117
|
+
permissionGrantIds?: string[],
|
|
103
118
|
protocolRole?: string
|
|
104
119
|
}): Promise<AuthorizationModel> {
|
|
105
|
-
const { descriptor, signer, delegatedGrant, permissionGrantId, protocolRole } = input;
|
|
120
|
+
const { descriptor, signer, delegatedGrant, permissionGrantId, permissionGrantIds, protocolRole } = input;
|
|
106
121
|
|
|
107
122
|
let delegatedGrantId;
|
|
108
123
|
if (delegatedGrant !== undefined) {
|
|
109
124
|
delegatedGrantId = await Message.getCid(delegatedGrant);
|
|
110
125
|
}
|
|
111
126
|
|
|
112
|
-
const signature = await Message.createSignature(descriptor, signer, { delegatedGrantId, permissionGrantId, protocolRole });
|
|
127
|
+
const signature = await Message.createSignature(descriptor, signer, { delegatedGrantId, permissionGrantId, permissionGrantIds, protocolRole });
|
|
113
128
|
|
|
114
129
|
const authorization: AuthorizationModel = {
|
|
115
130
|
signature
|
|
@@ -129,11 +144,23 @@ export class Message {
|
|
|
129
144
|
public static async createSignature(
|
|
130
145
|
descriptor: Descriptor,
|
|
131
146
|
signer: MessageSigner,
|
|
132
|
-
additionalPayloadProperties?: { delegatedGrantId?: string, permissionGrantId?: string, protocolRole?: string }
|
|
147
|
+
additionalPayloadProperties?: { delegatedGrantId?: string, permissionGrantId?: string, permissionGrantIds?: string[], protocolRole?: string }
|
|
133
148
|
): Promise<GeneralJws> {
|
|
134
149
|
const descriptorCid = await Cid.computeCid(descriptor);
|
|
135
|
-
|
|
136
|
-
|
|
150
|
+
const {
|
|
151
|
+
delegatedGrantId,
|
|
152
|
+
permissionGrantId,
|
|
153
|
+
permissionGrantIds,
|
|
154
|
+
protocolRole
|
|
155
|
+
} = additionalPayloadProperties ?? {};
|
|
156
|
+
const permissionGrantInvocation = Message.normalizePermissionGrantInvocation({ permissionGrantId, permissionGrantIds });
|
|
157
|
+
|
|
158
|
+
const signaturePayload: GenericSignaturePayload = {
|
|
159
|
+
descriptorCid,
|
|
160
|
+
delegatedGrantId,
|
|
161
|
+
protocolRole,
|
|
162
|
+
...permissionGrantInvocation
|
|
163
|
+
};
|
|
137
164
|
removeUndefinedProperties(signaturePayload);
|
|
138
165
|
|
|
139
166
|
const signaturePayloadBytes = Encoder.objectToBytes(signaturePayload);
|
|
@@ -144,6 +171,55 @@ export class Message {
|
|
|
144
171
|
return signature;
|
|
145
172
|
}
|
|
146
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Normalizes permission grant invocation before it is written into a descriptor
|
|
176
|
+
* and signed payload.
|
|
177
|
+
*
|
|
178
|
+
* Direct operation messages use `permissionGrantId`; Messages operations use
|
|
179
|
+
* canonicalized `permissionGrantIds` so a request can invoke a grant set.
|
|
180
|
+
*/
|
|
181
|
+
public static normalizePermissionGrantInvocation(input: PermissionGrantInvocation): PermissionGrantInvocation {
|
|
182
|
+
if (input.permissionGrantId !== undefined && input.permissionGrantIds !== undefined) {
|
|
183
|
+
throw new DwnError(
|
|
184
|
+
DwnErrorCode.MessagePermissionGrantCreateInvocationAmbiguous,
|
|
185
|
+
'permission grant invocation must use either `permissionGrantId` or `permissionGrantIds`, not both'
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (input.permissionGrantId !== undefined) {
|
|
190
|
+
return { permissionGrantId: input.permissionGrantId };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (input.permissionGrantIds === undefined) {
|
|
194
|
+
return {};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const permissionGrantIds = Message.normalizePermissionGrantIds(input);
|
|
198
|
+
return { permissionGrantIds };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Returns the permission grant ID carried by a direct operation signature payload.
|
|
203
|
+
*/
|
|
204
|
+
public static getPermissionGrantId(signaturePayload: GenericSignaturePayload): string | undefined {
|
|
205
|
+
return signaturePayload.permissionGrantId;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Returns all permission grant IDs invoked by a signature payload.
|
|
210
|
+
*
|
|
211
|
+
* Direct Records/Protocols operations carry a single `permissionGrantId`.
|
|
212
|
+
* Messages operations carry `permissionGrantIds`. Generic cleanup and
|
|
213
|
+
* revocation code uses this helper across both wire shapes.
|
|
214
|
+
*/
|
|
215
|
+
public static getPermissionGrantIds(signaturePayload: GenericSignaturePayload): string[] {
|
|
216
|
+
if (signaturePayload.permissionGrantId !== undefined) {
|
|
217
|
+
return [signaturePayload.permissionGrantId];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return signaturePayload.permissionGrantIds ?? [];
|
|
221
|
+
}
|
|
222
|
+
|
|
147
223
|
/**
|
|
148
224
|
* @returns newest message in the array. `undefined` if given array is empty.
|
|
149
225
|
*/
|
|
@@ -227,12 +303,14 @@ export class Message {
|
|
|
227
303
|
* 3. The `descriptorCid` property matches the CID of the message descriptor
|
|
228
304
|
* NOTE: signature is NOT verified.
|
|
229
305
|
* @param payloadJsonSchemaKey The key to look up the JSON schema referenced in `compile-validators.js` and perform payload schema validation on.
|
|
306
|
+
* @param options Additional structural validation controls.
|
|
230
307
|
* @returns the parsed JSON payload object if validation succeeds.
|
|
231
308
|
*/
|
|
232
309
|
public static async validateSignatureStructure(
|
|
233
310
|
messageSignature: GeneralJws,
|
|
234
311
|
messageDescriptor: Descriptor,
|
|
235
312
|
payloadJsonSchemaKey: string = 'GenericSignaturePayload',
|
|
313
|
+
options: ValidateSignatureStructureOptions = {},
|
|
236
314
|
): Promise<GenericSignaturePayload> {
|
|
237
315
|
|
|
238
316
|
if (messageSignature.signatures.length !== 1) {
|
|
@@ -254,6 +332,75 @@ export class Message {
|
|
|
254
332
|
);
|
|
255
333
|
}
|
|
256
334
|
|
|
335
|
+
if (options.validatePermissionGrantInvocation !== false) {
|
|
336
|
+
Message.validatePermissionGrantInvocationMatchesPayload(messageDescriptor, payloadJson);
|
|
337
|
+
}
|
|
338
|
+
|
|
257
339
|
return payloadJson;
|
|
258
340
|
}
|
|
259
|
-
|
|
341
|
+
|
|
342
|
+
private static normalizePermissionGrantIds(input: PermissionGrantInvocation): string[] {
|
|
343
|
+
if (input.permissionGrantIds === undefined) {
|
|
344
|
+
return [];
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (input.permissionGrantIds.length === 0) {
|
|
348
|
+
throw new DwnError(
|
|
349
|
+
DwnErrorCode.MessagePermissionGrantIdsEmpty,
|
|
350
|
+
'`permissionGrantIds` must contain at least one grant ID'
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return [...new Set(input.permissionGrantIds)].sort(lexicographicalCompare);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private static validatePermissionGrantInvocationCanonical(input: PermissionGrantInvocation): string[] {
|
|
358
|
+
if (input.permissionGrantId !== undefined && input.permissionGrantIds !== undefined) {
|
|
359
|
+
throw new DwnError(
|
|
360
|
+
DwnErrorCode.MessagePermissionGrantValidateInvocationAmbiguous,
|
|
361
|
+
'permission grant invocation must use either `permissionGrantId` or `permissionGrantIds`, not both'
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (input.permissionGrantId !== undefined) {
|
|
366
|
+
return [input.permissionGrantId];
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const normalizedPermissionGrantIds = Message.normalizePermissionGrantIds(input);
|
|
370
|
+
|
|
371
|
+
if (input.permissionGrantIds !== undefined && !Message.areStringArraysEqual(input.permissionGrantIds, normalizedPermissionGrantIds)) {
|
|
372
|
+
throw new DwnError(
|
|
373
|
+
DwnErrorCode.MessagePermissionGrantIdsNotCanonical,
|
|
374
|
+
'`permissionGrantIds` must be sorted and deduplicated'
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return normalizedPermissionGrantIds;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
private static validatePermissionGrantInvocationMatchesPayload(
|
|
382
|
+
descriptor: Descriptor & PermissionGrantInvocation,
|
|
383
|
+
signaturePayload: GenericSignaturePayload
|
|
384
|
+
): void {
|
|
385
|
+
if (descriptor.permissionGrantId !== signaturePayload.permissionGrantId) {
|
|
386
|
+
throw new DwnError(
|
|
387
|
+
DwnErrorCode.MessagePermissionGrantDescriptorPayloadMismatch,
|
|
388
|
+
'permission grant invocation in descriptor does not match signature payload'
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const descriptorPermissionGrantIds = Message.validatePermissionGrantInvocationCanonical(descriptor);
|
|
393
|
+
const payloadPermissionGrantIds = Message.validatePermissionGrantInvocationCanonical(signaturePayload);
|
|
394
|
+
|
|
395
|
+
if (!Message.areStringArraysEqual(descriptorPermissionGrantIds, payloadPermissionGrantIds)) {
|
|
396
|
+
throw new DwnError(
|
|
397
|
+
DwnErrorCode.MessagePermissionGrantIdsDescriptorPayloadMismatch,
|
|
398
|
+
'permission grant invocation in descriptor does not match signature payload'
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private static areStringArraysEqual(a: string[], b: string[]): boolean {
|
|
404
|
+
return a.length === b.length && a.every((value, index) => value === b[index]);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
@@ -3,11 +3,14 @@ import type { MessagesPermissionScope } from '../types/permission-types.js';
|
|
|
3
3
|
import type { MessageStore } from '../types/message-store.js';
|
|
4
4
|
import type { PermissionGrant } from '../protocols/permission-grant.js';
|
|
5
5
|
import type { ProtocolsConfigureMessage } from '../types/protocols-types.js';
|
|
6
|
+
import type { ProtocolScope } from '../utils/permission-scope.js';
|
|
6
7
|
import type { DataEncodedRecordsWriteMessage, RecordsDeleteMessage, RecordsWriteMessage } from '../types/records-types.js';
|
|
7
8
|
import type { MessagesReadMessage, MessagesSubscribeMessage, MessagesSyncMessage } from '../types/messages-types.js';
|
|
8
9
|
|
|
9
10
|
import { DwnInterfaceName } from '../enums/dwn-interface-method.js';
|
|
10
11
|
import { GrantAuthorization } from './grant-authorization.js';
|
|
12
|
+
import { isRecordsPrimaryProjectionExcludedProtocol } from './constants.js';
|
|
13
|
+
import { PermissionScopeMatcher } from '../utils/permission-scope.js';
|
|
11
14
|
import { PermissionsProtocol } from '../protocols/permissions.js';
|
|
12
15
|
import { Records } from '../utils/records.js';
|
|
13
16
|
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
@@ -15,6 +18,16 @@ import { DwnError, DwnErrorCode } from './dwn-error.js';
|
|
|
15
18
|
|
|
16
19
|
export class MessagesGrantAuthorization {
|
|
17
20
|
|
|
21
|
+
public static async fetchPermissionGrants(
|
|
22
|
+
tenant: string,
|
|
23
|
+
messageStore: MessageStore,
|
|
24
|
+
permissionGrantIds: string[]
|
|
25
|
+
): Promise<PermissionGrant[]> {
|
|
26
|
+
return Promise.all(
|
|
27
|
+
permissionGrantIds.map(permissionGrantId => PermissionsProtocol.fetchGrant(tenant, messageStore, permissionGrantId))
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
18
31
|
/**
|
|
19
32
|
* Authorizes a MessagesReadMessage using the given permission grant.
|
|
20
33
|
* @param messageStore Used to check if the given grant has been revoked; and to fetch related RecordsWrites if needed.
|
|
@@ -24,23 +37,29 @@ export class MessagesGrantAuthorization {
|
|
|
24
37
|
messageToRead: GenericMessage,
|
|
25
38
|
expectedGrantor: string,
|
|
26
39
|
expectedGrantee: string,
|
|
27
|
-
|
|
40
|
+
permissionGrants: PermissionGrant[],
|
|
28
41
|
messageStore: MessageStore,
|
|
29
42
|
}): Promise<void> {
|
|
30
43
|
const {
|
|
31
|
-
messagesReadMessage, messageToRead, expectedGrantor, expectedGrantee,
|
|
44
|
+
messagesReadMessage, messageToRead, expectedGrantor, expectedGrantee, permissionGrants, messageStore
|
|
32
45
|
} = input;
|
|
33
46
|
|
|
34
|
-
await
|
|
47
|
+
await MessagesGrantAuthorization.performBaseValidationForGrantSet({
|
|
35
48
|
incomingMessage: messagesReadMessage,
|
|
36
49
|
expectedGrantor,
|
|
37
50
|
expectedGrantee,
|
|
38
|
-
|
|
51
|
+
permissionGrants,
|
|
39
52
|
messageStore
|
|
40
53
|
});
|
|
41
54
|
|
|
42
|
-
const
|
|
43
|
-
|
|
55
|
+
for (const permissionGrant of permissionGrants) {
|
|
56
|
+
const scope = permissionGrant.scope as MessagesPermissionScope;
|
|
57
|
+
if (await MessagesGrantAuthorization.isScopeAuthorized(expectedGrantor, messageToRead, scope, messageStore)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
throw new DwnError(DwnErrorCode.MessagesReadVerifyScopeFailed, 'record message failed scope authorization');
|
|
44
63
|
}
|
|
45
64
|
|
|
46
65
|
/**
|
|
@@ -51,98 +70,291 @@ export class MessagesGrantAuthorization {
|
|
|
51
70
|
incomingMessage: MessagesSubscribeMessage | MessagesSyncMessage,
|
|
52
71
|
expectedGrantor: string,
|
|
53
72
|
expectedGrantee: string,
|
|
54
|
-
|
|
73
|
+
permissionGrants: PermissionGrant[],
|
|
55
74
|
messageStore: MessageStore,
|
|
56
75
|
}): Promise<void> {
|
|
57
76
|
const {
|
|
58
|
-
incomingMessage, expectedGrantor, expectedGrantee,
|
|
77
|
+
incomingMessage, expectedGrantor, expectedGrantee, permissionGrants, messageStore
|
|
59
78
|
} = input;
|
|
60
79
|
|
|
61
|
-
await
|
|
80
|
+
await MessagesGrantAuthorization.performBaseValidationForGrantSet({
|
|
62
81
|
incomingMessage,
|
|
63
82
|
expectedGrantor,
|
|
64
83
|
expectedGrantee,
|
|
65
|
-
|
|
84
|
+
permissionGrants,
|
|
66
85
|
messageStore
|
|
67
86
|
});
|
|
68
87
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
const scopes = permissionGrants.map(permissionGrant => permissionGrant.scope as MessagesPermissionScope);
|
|
89
|
+
|
|
90
|
+
if ('action' in incomingMessage.descriptor) {
|
|
91
|
+
MessagesGrantAuthorization.authorizeSyncScope(incomingMessage as MessagesSyncMessage, scopes);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
MessagesGrantAuthorization.authorizeSubscribeScope(incomingMessage as MessagesSubscribeMessage, scopes);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private static authorizeSyncScope(
|
|
99
|
+
syncMessage: MessagesSyncMessage,
|
|
100
|
+
scopes: MessagesPermissionScope[]
|
|
101
|
+
): void {
|
|
102
|
+
const { projectionScopes, protocol } = syncMessage.descriptor;
|
|
103
|
+
|
|
104
|
+
if (projectionScopes === undefined) {
|
|
105
|
+
MessagesGrantAuthorization.authorizeProtocolSyncScope(scopes, protocol);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
MessagesGrantAuthorization.authorizeProjectionScopes(scopes, projectionScopes);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private static authorizeProtocolSyncScope(
|
|
113
|
+
scopes: MessagesPermissionScope[],
|
|
114
|
+
protocol: string | undefined
|
|
115
|
+
): void {
|
|
116
|
+
if (isRecordsPrimaryProjectionExcludedProtocol(protocol)) {
|
|
117
|
+
throw new DwnError(
|
|
118
|
+
DwnErrorCode.MessagesGrantAuthorizationProtocolSyncInfrastructureProtocol,
|
|
119
|
+
`Protocol-scoped MessagesSync cannot authorize infrastructure protocol ${protocol}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!MessagesGrantAuthorization.someScopeMatches(scopes, { protocol })) {
|
|
124
|
+
throw new DwnError(
|
|
125
|
+
DwnErrorCode.MessagesGrantAuthorizationMismatchedProtocol,
|
|
126
|
+
`No permission grant scope matches protocol ${protocol}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private static authorizeProjectionScopes(
|
|
132
|
+
scopes: MessagesPermissionScope[],
|
|
133
|
+
projectionScopes: ProtocolScope[],
|
|
134
|
+
): void {
|
|
135
|
+
for (const projectionScope of projectionScopes) {
|
|
136
|
+
if (isRecordsPrimaryProjectionExcludedProtocol(projectionScope.protocol)) {
|
|
137
|
+
throw new DwnError(
|
|
138
|
+
DwnErrorCode.MessagesGrantAuthorizationProjectionInfrastructureProtocol,
|
|
139
|
+
`Projected MessagesSync cannot authorize infrastructure protocol ${projectionScope.protocol}`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (MessagesGrantAuthorization.someScopeMatches(scopes, projectionScope)) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
throw new DwnError(
|
|
148
|
+
DwnErrorCode.MessagesGrantAuthorizationProjectionScopeMismatch,
|
|
149
|
+
`No permission grant scope matches projection scope ${JSON.stringify(projectionScope)}`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private static authorizeSubscribeScope(
|
|
155
|
+
subscribeMessage: MessagesSubscribeMessage,
|
|
156
|
+
scopes: MessagesPermissionScope[]
|
|
157
|
+
): void {
|
|
158
|
+
const { filters } = subscribeMessage.descriptor;
|
|
159
|
+
|
|
160
|
+
if (filters.length === 0 && !MessagesGrantAuthorization.hasUnscopedGrant(scopes)) {
|
|
161
|
+
throw new DwnError(
|
|
162
|
+
DwnErrorCode.MessagesGrantAuthorizationUnfilteredSubscribeProtocolScope,
|
|
163
|
+
`A protocol-scoped grant cannot authorize an unfiltered subscription`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const filter of filters) {
|
|
168
|
+
if (MessagesGrantAuthorization.someScopeMatches(scopes, { protocol: filter.protocol })) {
|
|
169
|
+
continue;
|
|
93
170
|
}
|
|
171
|
+
|
|
172
|
+
throw new DwnError(
|
|
173
|
+
DwnErrorCode.MessagesGrantAuthorizationSubscribeProtocolMismatch,
|
|
174
|
+
`No permission grant scope matches protocol ${filter.protocol}`
|
|
175
|
+
);
|
|
94
176
|
}
|
|
95
177
|
}
|
|
96
178
|
|
|
179
|
+
private static someScopeMatches(scopes: MessagesPermissionScope[], target: ProtocolScope): boolean {
|
|
180
|
+
return scopes.some(scope => PermissionScopeMatcher.matches(scope, target));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private static hasUnscopedGrant(scopes: MessagesPermissionScope[]): boolean {
|
|
184
|
+
return scopes.some(scope => scope.protocol === undefined);
|
|
185
|
+
}
|
|
186
|
+
|
|
97
187
|
/**
|
|
98
|
-
*
|
|
188
|
+
* Revalidates an already-open delegated MessagesSubscribe grant set at event
|
|
189
|
+
* delivery time. Subscription messages are signed at open time, but grant
|
|
190
|
+
* expiry and revocation must stop future delivery after the grant set becomes
|
|
191
|
+
* invalid.
|
|
99
192
|
*/
|
|
100
|
-
|
|
193
|
+
public static async authorizeSubscribeDelivery(input: {
|
|
194
|
+
messagesSubscribeMessage: MessagesSubscribeMessage,
|
|
195
|
+
expectedGrantor: string,
|
|
196
|
+
expectedGrantee: string,
|
|
197
|
+
permissionGrants: PermissionGrant[],
|
|
198
|
+
messageStore: MessageStore,
|
|
199
|
+
deliveryTimestamp: string,
|
|
200
|
+
}): Promise<void> {
|
|
201
|
+
const {
|
|
202
|
+
messagesSubscribeMessage,
|
|
203
|
+
expectedGrantor,
|
|
204
|
+
expectedGrantee,
|
|
205
|
+
permissionGrants,
|
|
206
|
+
messageStore,
|
|
207
|
+
deliveryTimestamp,
|
|
208
|
+
} = input;
|
|
209
|
+
|
|
210
|
+
const deliveryMessage: MessagesSubscribeMessage = {
|
|
211
|
+
...messagesSubscribeMessage,
|
|
212
|
+
descriptor: {
|
|
213
|
+
...messagesSubscribeMessage.descriptor,
|
|
214
|
+
messageTimestamp: deliveryTimestamp,
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
await MessagesGrantAuthorization.authorizeSubscribeOrSync({
|
|
219
|
+
incomingMessage: deliveryMessage,
|
|
220
|
+
expectedGrantor,
|
|
221
|
+
expectedGrantee,
|
|
222
|
+
permissionGrants,
|
|
223
|
+
messageStore,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Performs base validation on every invoked grant. The grant set is all-or-nothing:
|
|
229
|
+
* unresolved, revoked, expired, or interface/method-mismatched grants fail the request.
|
|
230
|
+
*/
|
|
231
|
+
private static async performBaseValidationForGrantSet(input: {
|
|
232
|
+
incomingMessage: MessagesReadMessage | MessagesSubscribeMessage | MessagesSyncMessage,
|
|
233
|
+
expectedGrantor: string,
|
|
234
|
+
expectedGrantee: string,
|
|
235
|
+
permissionGrants: PermissionGrant[],
|
|
236
|
+
messageStore: MessageStore,
|
|
237
|
+
}): Promise<void> {
|
|
238
|
+
const {
|
|
239
|
+
incomingMessage, expectedGrantor, expectedGrantee, permissionGrants, messageStore
|
|
240
|
+
} = input;
|
|
241
|
+
|
|
242
|
+
for (const permissionGrant of permissionGrants) {
|
|
243
|
+
await GrantAuthorization.performBaseValidation({
|
|
244
|
+
incomingMessage,
|
|
245
|
+
expectedGrantor,
|
|
246
|
+
expectedGrantee,
|
|
247
|
+
permissionGrant,
|
|
248
|
+
messageStore
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Determines whether the given record is inside a grant scope.
|
|
255
|
+
*/
|
|
256
|
+
private static async isScopeAuthorized(
|
|
101
257
|
tenant: string,
|
|
102
258
|
messageToGet: GenericMessage,
|
|
103
259
|
incomingScope: MessagesPermissionScope,
|
|
104
260
|
messageStore: MessageStore,
|
|
105
|
-
): Promise<
|
|
261
|
+
): Promise<boolean> {
|
|
106
262
|
if (incomingScope.protocol === undefined) {
|
|
107
|
-
|
|
108
|
-
return;
|
|
263
|
+
return true;
|
|
109
264
|
}
|
|
110
265
|
|
|
111
266
|
if (messageToGet.descriptor.interface === DwnInterfaceName.Records) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
267
|
+
return MessagesGrantAuthorization.isRecordsMessageScopeAuthorized(
|
|
268
|
+
tenant,
|
|
269
|
+
messageToGet as RecordsWriteMessage | RecordsDeleteMessage,
|
|
270
|
+
incomingScope,
|
|
271
|
+
messageStore
|
|
272
|
+
);
|
|
273
|
+
}
|
|
116
274
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
275
|
+
if (messageToGet.descriptor.interface === DwnInterfaceName.Protocols) {
|
|
276
|
+
return MessagesGrantAuthorization.isProtocolsConfigureScopeAuthorized(
|
|
277
|
+
messageToGet as ProtocolsConfigureMessage,
|
|
278
|
+
incomingScope
|
|
279
|
+
);
|
|
280
|
+
}
|
|
121
281
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// get the permission scope from the permission message
|
|
125
|
-
const permissionScope = await PermissionsProtocol.getScopeFromPermissionRecord(
|
|
126
|
-
tenant,
|
|
127
|
-
messageStore,
|
|
128
|
-
recordsWriteMessage as DataEncodedRecordsWriteMessage
|
|
129
|
-
);
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
130
284
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
285
|
+
private static async isRecordsMessageScopeAuthorized(
|
|
286
|
+
tenant: string,
|
|
287
|
+
recordsMessage: RecordsWriteMessage | RecordsDeleteMessage,
|
|
288
|
+
incomingScope: MessagesPermissionScope,
|
|
289
|
+
messageStore: MessageStore,
|
|
290
|
+
): Promise<boolean> {
|
|
291
|
+
const recordsWriteMessage = await MessagesGrantAuthorization.getAssociatedRecordsWrite(
|
|
292
|
+
tenant,
|
|
293
|
+
recordsMessage,
|
|
294
|
+
messageStore
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
if (recordsWriteMessage.descriptor.protocol === PermissionsProtocol.uri) {
|
|
298
|
+
return MessagesGrantAuthorization.isPermissionRecordScopeAuthorized(
|
|
299
|
+
tenant,
|
|
300
|
+
recordsWriteMessage,
|
|
301
|
+
incomingScope,
|
|
302
|
+
messageStore
|
|
303
|
+
);
|
|
144
304
|
}
|
|
145
305
|
|
|
146
|
-
|
|
306
|
+
return PermissionScopeMatcher.matches(incomingScope, MessagesGrantAuthorization.getRecordsScopeTarget(recordsWriteMessage));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private static async isPermissionRecordScopeAuthorized(
|
|
310
|
+
tenant: string,
|
|
311
|
+
recordsWriteMessage: RecordsWriteMessage,
|
|
312
|
+
incomingScope: MessagesPermissionScope,
|
|
313
|
+
messageStore: MessageStore,
|
|
314
|
+
): Promise<boolean> {
|
|
315
|
+
if (MessagesGrantAuthorization.isSubtreeScope(incomingScope)) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const permissionScope = await PermissionsProtocol.getScopeFromPermissionRecord(
|
|
320
|
+
tenant,
|
|
321
|
+
messageStore,
|
|
322
|
+
recordsWriteMessage as DataEncodedRecordsWriteMessage
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
return PermissionsProtocol.hasProtocolScope(permissionScope)
|
|
326
|
+
&& PermissionScopeMatcher.matches(incomingScope, permissionScope);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private static isProtocolsConfigureScopeAuthorized(
|
|
330
|
+
protocolsConfigureMessage: ProtocolsConfigureMessage,
|
|
331
|
+
incomingScope: MessagesPermissionScope
|
|
332
|
+
): boolean {
|
|
333
|
+
// A delegate with any Messages.Read grant inside a protocol needs that
|
|
334
|
+
// protocol definition to interpret and validate the records it can read.
|
|
335
|
+
return incomingScope.protocol !== undefined &&
|
|
336
|
+
incomingScope.protocol === protocolsConfigureMessage.descriptor.definition.protocol;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
private static async getAssociatedRecordsWrite(
|
|
340
|
+
tenant: string,
|
|
341
|
+
recordsMessage: RecordsWriteMessage | RecordsDeleteMessage,
|
|
342
|
+
messageStore: MessageStore,
|
|
343
|
+
): Promise<RecordsWriteMessage> {
|
|
344
|
+
if (Records.isRecordsWrite(recordsMessage)) {
|
|
345
|
+
return recordsMessage;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return RecordsWrite.fetchNewestRecordsWrite(messageStore, tenant, recordsMessage.descriptor.recordId);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private static getRecordsScopeTarget(recordsWriteMessage: RecordsWriteMessage): ProtocolScope {
|
|
352
|
+
const { protocol, protocolPath } = recordsWriteMessage.descriptor;
|
|
353
|
+
const { contextId } = recordsWriteMessage;
|
|
354
|
+
return { protocol, protocolPath, contextId };
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private static isSubtreeScope(scope: MessagesPermissionScope): boolean {
|
|
358
|
+
return scope.protocolPath !== undefined || scope.contextId !== undefined;
|
|
147
359
|
}
|
|
148
|
-
}
|
|
360
|
+
}
|