@enbox/dwn-sdk-js 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +135 -0
- package/dist/browser.mjs.map +7 -0
- package/dist/esm/generated/precompiled-validators.js +640 -510
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/auth.js +6 -1
- package/dist/esm/src/core/auth.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +3 -0
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +4 -0
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/dwn.js +14 -0
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +13 -0
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +121 -66
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +1 -1
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +1 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +1 -0
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +2 -0
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +28 -45
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js +9 -1
- package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
- package/dist/esm/src/smt/smt-utils.js +1 -1
- package/dist/esm/src/smt/smt-utils.js.map +1 -1
- package/dist/esm/src/types/records-types.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +221 -78
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/hd-key.js +6 -7
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +12 -10
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/records.js +33 -44
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +26 -21
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/records-tags.spec.js +5 -5
- package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +120 -2
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +25 -26
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +103 -0
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +124 -10
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/messages-get.spec.js +3 -2
- package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +43 -34
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +4 -4
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-callbacks.spec.js +21 -24
- package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption.spec.js +69 -66
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/filters.spec.js +1 -0
- package/dist/esm/tests/utils/filters.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +28 -7
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/auth.d.ts +3 -1
- package/dist/types/src/core/auth.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +3 -0
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/dwn.d.ts +12 -0
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +17 -28
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +4 -4
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-delete.d.ts +4 -0
- package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts +4 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +23 -53
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/jose/jws/general/verifier.d.ts.map +1 -1
- package/dist/types/src/types/encryption-types.d.ts +9 -8
- package/dist/types/src/types/encryption-types.d.ts.map +1 -1
- package/dist/types/src/types/protocols-types.d.ts +65 -16
- package/dist/types/src/types/protocols-types.d.ts.map +1 -1
- package/dist/types/src/types/records-types.d.ts +7 -26
- package/dist/types/src/types/records-types.d.ts.map +1 -1
- package/dist/types/src/utils/encryption.d.ts +157 -28
- package/dist/types/src/utils/encryption.d.ts.map +1 -1
- package/dist/types/src/utils/hd-key.d.ts +2 -3
- package/dist/types/src/utils/hd-key.d.ts.map +1 -1
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +3 -4
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
- package/dist/types/tests/utils/test-data-generator.d.ts +7 -0
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/package.json +10 -21
- package/src/core/auth.ts +12 -1
- package/src/core/dwn-error.ts +3 -0
- package/src/core/protocol-authorization.ts +8 -0
- package/src/dwn.ts +15 -0
- package/src/handlers/protocols-configure.ts +4 -4
- package/src/handlers/records-delete.ts +12 -0
- package/src/handlers/records-subscribe.ts +174 -75
- package/src/handlers/records-write.ts +1 -1
- package/src/index.ts +4 -4
- package/src/interfaces/protocols-configure.ts +5 -5
- package/src/interfaces/records-delete.ts +9 -3
- package/src/interfaces/records-subscribe.ts +6 -1
- package/src/interfaces/records-write.ts +33 -105
- package/src/jose/jws/general/verifier.ts +11 -1
- package/src/smt/smt-utils.ts +1 -1
- package/src/types/encryption-types.ts +9 -8
- package/src/types/protocols-types.ts +72 -18
- package/src/types/records-types.ts +7 -29
- package/src/utils/encryption.ts +346 -88
- package/src/utils/hd-key.ts +9 -10
- package/src/utils/protocols.ts +15 -13
- package/src/utils/records.ts +47 -55
- package/dist/bundles/dwn.js +0 -151
|
@@ -4,7 +4,7 @@ import type { GenericMessageReply } from '../types/message-types.js';
|
|
|
4
4
|
import type { MessageStore } from '../types//message-store.js';
|
|
5
5
|
import type { MethodHandler } from '../types/method-handler.js';
|
|
6
6
|
import type { StateIndex } from '../types/state-index.js';
|
|
7
|
-
import type { ProtocolDefinition, ProtocolsConfigureMessage } from '../types/protocols-types.js';
|
|
7
|
+
import type { ProtocolDefinition, ProtocolRuleSet, ProtocolsConfigureMessage } from '../types/protocols-types.js';
|
|
8
8
|
|
|
9
9
|
import { authenticate } from '../core/auth.js';
|
|
10
10
|
import { Message } from '../core/message.js';
|
|
@@ -187,7 +187,7 @@ export class ProtocolsConfigureHandler implements MethodHandler {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
// Walk the structure and validate all $ref paths and cross-protocol role references
|
|
190
|
-
ProtocolsConfigureHandler.validateRefsAndRolesRecursively(definition.structure, '', referencedDefinitions);
|
|
190
|
+
ProtocolsConfigureHandler.validateRefsAndRolesRecursively(definition.structure as ProtocolRuleSet, '', referencedDefinitions);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
/**
|
|
@@ -218,7 +218,7 @@ export class ProtocolsConfigureHandler implements MethodHandler {
|
|
|
218
218
|
* - Cross-protocol `role` references point to valid `$role: true` paths in the referenced protocol
|
|
219
219
|
*/
|
|
220
220
|
private static validateRefsAndRolesRecursively(
|
|
221
|
-
ruleSet:
|
|
221
|
+
ruleSet: ProtocolRuleSet,
|
|
222
222
|
protocolPath: string,
|
|
223
223
|
referencedDefinitions: Map<string, ProtocolDefinition>
|
|
224
224
|
): void {
|
|
@@ -227,7 +227,7 @@ export class ProtocolsConfigureHandler implements MethodHandler {
|
|
|
227
227
|
continue;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
const childRuleSet = ruleSet[key];
|
|
230
|
+
const childRuleSet = ruleSet[key] as ProtocolRuleSet;
|
|
231
231
|
const childProtocolPath = protocolPath === '' ? key : `${protocolPath}/${key}`;
|
|
232
232
|
|
|
233
233
|
// Validate $ref path exists in the referenced protocol
|
|
@@ -9,9 +9,11 @@ import { authenticate } from '../core/auth.js';
|
|
|
9
9
|
import { DwnInterfaceName } from '../enums/dwn-interface-method.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';
|
|
14
15
|
import { RecordsDelete } from '../interfaces/records-delete.js';
|
|
16
|
+
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
15
17
|
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
16
18
|
import { ResumableTaskName } from '../core/resumable-task-manager.js';
|
|
17
19
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
@@ -112,6 +114,16 @@ export class RecordsDeleteHandler implements MethodHandler {
|
|
|
112
114
|
|
|
113
115
|
if (recordsDelete.author === tenant) {
|
|
114
116
|
return;
|
|
117
|
+
} else if (recordsDelete.author !== undefined && recordsDelete.signaturePayload!.permissionGrantId !== undefined) {
|
|
118
|
+
const permissionGrant = await PermissionsProtocol.fetchGrant(tenant, messageStore, recordsDelete.signaturePayload!.permissionGrantId);
|
|
119
|
+
await RecordsGrantAuthorization.authorizeDelete({
|
|
120
|
+
recordsDeleteMessage : recordsDelete.message,
|
|
121
|
+
recordsWriteToDelete : recordsWrite.message,
|
|
122
|
+
expectedGrantor : tenant,
|
|
123
|
+
expectedGrantee : recordsDelete.author,
|
|
124
|
+
permissionGrant,
|
|
125
|
+
messageStore,
|
|
126
|
+
});
|
|
115
127
|
} else if (recordsWrite.message.descriptor.protocol !== undefined) {
|
|
116
128
|
await ProtocolAuthorization.authorizeDelete(tenant, recordsDelete, recordsWrite, messageStore);
|
|
117
129
|
} else {
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import type { DidResolver } from '@enbox/dids';
|
|
2
|
-
import type {
|
|
2
|
+
import type { MessageSort } from '../types/message-types.js';
|
|
3
3
|
import type { MessageStore } from '../types//message-store.js';
|
|
4
4
|
import type { MethodHandler } from '../types/method-handler.js';
|
|
5
5
|
import type { EventListener, EventStream } from '../types/subscriptions.js';
|
|
6
|
-
import type {
|
|
6
|
+
import type { Filter, PaginationCursor } from '../types/query-types.js';
|
|
7
|
+
import type { RecordEvent, RecordsQueryReplyEntry, RecordsSubscribeMessage, RecordsSubscribeReply, RecordSubscriptionHandler } from '../types/records-types.js';
|
|
7
8
|
|
|
8
9
|
import { authenticate } from '../core/auth.js';
|
|
10
|
+
import { DateSort } from '../types/records-types.js';
|
|
9
11
|
import { FilterUtility } from '../utils/filter.js';
|
|
10
12
|
import { Message } from '../core/message.js';
|
|
11
13
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
12
14
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
13
15
|
import { Records } from '../utils/records.js';
|
|
14
16
|
import { RecordsSubscribe } from '../interfaces/records-subscribe.js';
|
|
17
|
+
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
18
|
+
import { SortDirection } from '../types/query-types.js';
|
|
15
19
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
16
20
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
17
21
|
|
|
@@ -42,11 +46,13 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
42
46
|
return messageReplyFromError(e, 400);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
let
|
|
49
|
+
let eventFilters: Filter[] = [];
|
|
50
|
+
let queryFilters: Filter[] = [];
|
|
51
|
+
|
|
46
52
|
// if this is an anonymous subscribe and the filter supports published records, subscribe to only published records
|
|
47
53
|
if (Records.filterIncludesPublishedRecords(recordsSubscribe.message.descriptor.filter) && recordsSubscribe.author === undefined) {
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
eventFilters = [RecordsSubscribeHandler.buildPublishedEventFilter(recordsSubscribe)];
|
|
55
|
+
queryFilters = [RecordsSubscribeHandler.buildPublishedQueryFilter(recordsSubscribe)];
|
|
50
56
|
// delete the undefined authorization property else the code will encounter the following IPLD issue when attempting to generate CID:
|
|
51
57
|
// Error: `undefined` is not supported by the IPLD Data Model and cannot be encoded
|
|
52
58
|
delete message.authorization;
|
|
@@ -60,138 +66,231 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
if (recordsSubscribe.author === tenant) {
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
eventFilters = RecordsSubscribeHandler.buildOwnerEventFilters(recordsSubscribe);
|
|
70
|
+
queryFilters = RecordsSubscribeHandler.buildOwnerQueryFilters(recordsSubscribe);
|
|
65
71
|
} else {
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
eventFilters = RecordsSubscribeHandler.buildNonOwnerEventFilters(recordsSubscribe);
|
|
73
|
+
queryFilters = RecordsSubscribeHandler.buildNonOwnerQueryFilters(recordsSubscribe);
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
76
|
|
|
77
|
+
// Step 1: Register event listener FIRST to ensure no events are missed between query and subscribe
|
|
71
78
|
const listener: EventListener = (eventTenant, event, eventIndexes):void => {
|
|
72
|
-
if (tenant === eventTenant && FilterUtility.matchAnyFilter(eventIndexes,
|
|
73
|
-
// the filters check for interface and method
|
|
74
|
-
// if matched the message is either a `RecordsWriteMessage` or `RecordsDeleteMessage` so we cast the event to a `RecordEvent`
|
|
79
|
+
if (tenant === eventTenant && FilterUtility.matchAnyFilter(eventIndexes, eventFilters)) {
|
|
75
80
|
subscriptionHandler(event as RecordEvent);
|
|
76
81
|
}
|
|
77
82
|
};
|
|
78
83
|
|
|
79
84
|
const messageCid = await Message.getCid(message);
|
|
80
85
|
const subscription = await this.eventStream.subscribe(tenant, messageCid, listener);
|
|
86
|
+
|
|
87
|
+
// Step 2: Query for initial snapshot of matching records
|
|
88
|
+
let entries: RecordsQueryReplyEntry[];
|
|
89
|
+
let cursor: PaginationCursor | undefined;
|
|
90
|
+
try {
|
|
91
|
+
const { dateSort, pagination } = recordsSubscribe.message.descriptor;
|
|
92
|
+
const messageSort = RecordsSubscribeHandler.convertDateSort(dateSort);
|
|
93
|
+
const queryResult = await this.messageStore.query(tenant, queryFilters, messageSort, pagination);
|
|
94
|
+
entries = queryResult.messages as RecordsQueryReplyEntry[];
|
|
95
|
+
cursor = queryResult.cursor;
|
|
96
|
+
|
|
97
|
+
// attach initialWrite for non-initial writes
|
|
98
|
+
for (const entry of entries) {
|
|
99
|
+
if (!await RecordsWrite.isInitialWrite(entry)) {
|
|
100
|
+
const initialWriteResult = await this.messageStore.query(
|
|
101
|
+
tenant,
|
|
102
|
+
[{ recordId: entry.recordId, isLatestBaseState: false, method: DwnMethodName.Write }]
|
|
103
|
+
);
|
|
104
|
+
const initialWrite = initialWriteResult.messages[0] as RecordsQueryReplyEntry;
|
|
105
|
+
delete initialWrite.encodedData;
|
|
106
|
+
entry.initialWrite = initialWrite;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
// if the query fails, close the subscription and return the error
|
|
111
|
+
await subscription.close();
|
|
112
|
+
return messageReplyFromError(error, 500);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Step 3: Return subscription + initial entries + cursor
|
|
81
116
|
return {
|
|
82
117
|
status: { code: 200, detail: 'OK' },
|
|
83
|
-
subscription
|
|
118
|
+
subscription,
|
|
119
|
+
entries,
|
|
120
|
+
cursor
|
|
84
121
|
};
|
|
85
122
|
}
|
|
86
123
|
|
|
87
124
|
/**
|
|
88
|
-
*
|
|
125
|
+
* Convert an incoming DateSort to a sort type accepted by MessageStore.
|
|
126
|
+
* Defaults to `dateCreated` ascending if no sort is supplied.
|
|
89
127
|
*/
|
|
90
|
-
private static
|
|
91
|
-
|
|
128
|
+
private static convertDateSort(dateSort?: DateSort): MessageSort {
|
|
129
|
+
switch (dateSort) {
|
|
130
|
+
case DateSort.CreatedAscending:
|
|
131
|
+
return { dateCreated: SortDirection.Ascending };
|
|
132
|
+
case DateSort.CreatedDescending:
|
|
133
|
+
return { dateCreated: SortDirection.Descending };
|
|
134
|
+
case DateSort.PublishedAscending:
|
|
135
|
+
return { datePublished: SortDirection.Ascending };
|
|
136
|
+
case DateSort.PublishedDescending:
|
|
137
|
+
return { datePublished: SortDirection.Descending };
|
|
138
|
+
case DateSort.UpdatedAscending:
|
|
139
|
+
return { messageTimestamp: SortDirection.Ascending };
|
|
140
|
+
case DateSort.UpdatedDescending:
|
|
141
|
+
return { messageTimestamp: SortDirection.Descending };
|
|
142
|
+
default:
|
|
143
|
+
return { dateCreated: SortDirection.Ascending };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// =============================================
|
|
148
|
+
// Event filters (for live subscription)
|
|
149
|
+
// These match Write+Delete and do NOT use isLatestBaseState
|
|
150
|
+
// =============================================
|
|
92
151
|
|
|
93
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Build event filters for owner: all matching Write+Delete events.
|
|
154
|
+
*/
|
|
155
|
+
private static buildOwnerEventFilters(recordsSubscribe: RecordsSubscribe): Filter[] {
|
|
156
|
+
const { filter } = recordsSubscribe.message.descriptor;
|
|
157
|
+
return [{
|
|
94
158
|
...Records.convertFilter(filter),
|
|
95
159
|
interface : DwnInterfaceName.Records,
|
|
96
|
-
method : [
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
return [ subscribeFilter ];
|
|
160
|
+
method : [DwnMethodName.Write, DwnMethodName.Delete],
|
|
161
|
+
}];
|
|
100
162
|
}
|
|
101
163
|
|
|
102
164
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* Filters can support emitting messages for both published and unpublished records,
|
|
106
|
-
* as well as explicitly only published or only unpublished records.
|
|
107
|
-
*
|
|
108
|
-
* A) BOTH published and unpublished:
|
|
109
|
-
* 1. published records; and
|
|
110
|
-
* 2. unpublished records intended for the subscription author (where `recipient` is the subscription author); and
|
|
111
|
-
* 3. unpublished records authorized by a protocol rule.
|
|
112
|
-
*
|
|
113
|
-
* B) PUBLISHED:
|
|
114
|
-
* 1. only published records;
|
|
115
|
-
*
|
|
116
|
-
* C) UNPUBLISHED:
|
|
117
|
-
* 1. unpublished records intended for the subscription author (where `recipient` is the subscription author); and
|
|
118
|
-
* 2. unpublished records authorized by a protocol rule.
|
|
165
|
+
* Build event filters for non-owner with visibility rules.
|
|
119
166
|
*/
|
|
120
|
-
private static
|
|
121
|
-
|
|
122
|
-
): Promise<Filter[]> {
|
|
123
|
-
const filters:Filter[] = [];
|
|
167
|
+
private static buildNonOwnerEventFilters(recordsSubscribe: RecordsSubscribe): Filter[] {
|
|
168
|
+
const filters: Filter[] = [];
|
|
124
169
|
const { filter } = recordsSubscribe.message.descriptor;
|
|
125
170
|
if (Records.filterIncludesPublishedRecords(filter)) {
|
|
126
|
-
filters.push(RecordsSubscribeHandler.
|
|
171
|
+
filters.push(RecordsSubscribeHandler.buildPublishedEventFilter(recordsSubscribe));
|
|
127
172
|
}
|
|
128
173
|
|
|
129
174
|
if (Records.filterIncludesUnpublishedRecords(filter)) {
|
|
130
175
|
if (Records.shouldBuildUnpublishedAuthorFilter(filter, recordsSubscribe.author!)) {
|
|
131
|
-
filters.push(
|
|
176
|
+
filters.push({
|
|
177
|
+
...Records.convertFilter(filter),
|
|
178
|
+
author : recordsSubscribe.author!,
|
|
179
|
+
interface : DwnInterfaceName.Records,
|
|
180
|
+
method : [DwnMethodName.Write, DwnMethodName.Delete],
|
|
181
|
+
published : false,
|
|
182
|
+
});
|
|
132
183
|
}
|
|
133
184
|
|
|
134
185
|
if (Records.shouldProtocolAuthorize(recordsSubscribe.signaturePayload!)) {
|
|
135
|
-
filters.push(
|
|
186
|
+
filters.push({
|
|
187
|
+
...Records.convertFilter(filter),
|
|
188
|
+
interface : DwnInterfaceName.Records,
|
|
189
|
+
method : [DwnMethodName.Write, DwnMethodName.Delete],
|
|
190
|
+
published : false,
|
|
191
|
+
});
|
|
136
192
|
}
|
|
137
193
|
|
|
138
194
|
if (Records.shouldBuildUnpublishedRecipientFilter(filter, recordsSubscribe.author!)) {
|
|
139
|
-
filters.push(
|
|
195
|
+
filters.push({
|
|
196
|
+
...Records.convertFilter(filter),
|
|
197
|
+
interface : DwnInterfaceName.Records,
|
|
198
|
+
method : [DwnMethodName.Write, DwnMethodName.Delete],
|
|
199
|
+
recipient : recordsSubscribe.author!,
|
|
200
|
+
published : false,
|
|
201
|
+
});
|
|
140
202
|
}
|
|
141
203
|
}
|
|
142
204
|
return filters;
|
|
143
205
|
}
|
|
144
206
|
|
|
145
207
|
/**
|
|
146
|
-
*
|
|
208
|
+
* Build a published-only event filter (Write+Delete).
|
|
147
209
|
*/
|
|
148
|
-
private static
|
|
210
|
+
private static buildPublishedEventFilter(recordsSubscribe: RecordsSubscribe): Filter {
|
|
149
211
|
return {
|
|
150
212
|
...Records.convertFilter(recordsSubscribe.message.descriptor.filter),
|
|
151
213
|
interface : DwnInterfaceName.Records,
|
|
152
|
-
method : [
|
|
214
|
+
method : [DwnMethodName.Write, DwnMethodName.Delete],
|
|
153
215
|
published : true,
|
|
154
216
|
};
|
|
155
217
|
}
|
|
156
218
|
|
|
219
|
+
// =============================================
|
|
220
|
+
// Query filters (for initial snapshot)
|
|
221
|
+
// These match Write only and use isLatestBaseState: true
|
|
222
|
+
// =============================================
|
|
223
|
+
|
|
157
224
|
/**
|
|
158
|
-
*
|
|
225
|
+
* Build query filters for owner: latest writes matching the filter.
|
|
159
226
|
*/
|
|
160
|
-
private static
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
...Records.convertFilter(
|
|
164
|
-
interface
|
|
165
|
-
method
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
};
|
|
227
|
+
private static buildOwnerQueryFilters(recordsSubscribe: RecordsSubscribe): Filter[] {
|
|
228
|
+
const { dateSort, filter } = recordsSubscribe.message.descriptor;
|
|
229
|
+
return [{
|
|
230
|
+
...Records.convertFilter(filter, dateSort),
|
|
231
|
+
interface : DwnInterfaceName.Records,
|
|
232
|
+
method : DwnMethodName.Write,
|
|
233
|
+
isLatestBaseState : true,
|
|
234
|
+
}];
|
|
169
235
|
}
|
|
170
236
|
|
|
171
237
|
/**
|
|
172
|
-
*
|
|
173
|
-
* Validation that `protocol` and other required protocol-related fields occurs before this method.
|
|
238
|
+
* Build query filters for non-owner with visibility rules.
|
|
174
239
|
*/
|
|
175
|
-
private static
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
240
|
+
private static buildNonOwnerQueryFilters(recordsSubscribe: RecordsSubscribe): Filter[] {
|
|
241
|
+
const filters: Filter[] = [];
|
|
242
|
+
const { dateSort, filter } = recordsSubscribe.message.descriptor;
|
|
243
|
+
if (Records.filterIncludesPublishedRecords(filter)) {
|
|
244
|
+
filters.push(RecordsSubscribeHandler.buildPublishedQueryFilter(recordsSubscribe));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (Records.filterIncludesUnpublishedRecords(filter)) {
|
|
248
|
+
if (Records.shouldBuildUnpublishedAuthorFilter(filter, recordsSubscribe.author!)) {
|
|
249
|
+
filters.push({
|
|
250
|
+
...Records.convertFilter(filter, dateSort),
|
|
251
|
+
author : recordsSubscribe.author!,
|
|
252
|
+
interface : DwnInterfaceName.Records,
|
|
253
|
+
method : DwnMethodName.Write,
|
|
254
|
+
isLatestBaseState : true,
|
|
255
|
+
published : false,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (Records.shouldProtocolAuthorize(recordsSubscribe.signaturePayload!)) {
|
|
260
|
+
filters.push({
|
|
261
|
+
...Records.convertFilter(filter, dateSort),
|
|
262
|
+
interface : DwnInterfaceName.Records,
|
|
263
|
+
method : DwnMethodName.Write,
|
|
264
|
+
isLatestBaseState : true,
|
|
265
|
+
published : false,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (Records.shouldBuildUnpublishedRecipientFilter(filter, recordsSubscribe.author!)) {
|
|
270
|
+
filters.push({
|
|
271
|
+
...Records.convertFilter(filter, dateSort),
|
|
272
|
+
interface : DwnInterfaceName.Records,
|
|
273
|
+
method : DwnMethodName.Write,
|
|
274
|
+
recipient : recordsSubscribe.author!,
|
|
275
|
+
isLatestBaseState : true,
|
|
276
|
+
published : false,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return filters;
|
|
182
281
|
}
|
|
183
282
|
|
|
184
283
|
/**
|
|
185
|
-
*
|
|
284
|
+
* Build a published-only query filter (latest writes).
|
|
186
285
|
*/
|
|
187
|
-
private static
|
|
188
|
-
|
|
286
|
+
private static buildPublishedQueryFilter(recordsSubscribe: RecordsSubscribe): Filter {
|
|
287
|
+
const { dateSort, filter } = recordsSubscribe.message.descriptor;
|
|
189
288
|
return {
|
|
190
|
-
...Records.convertFilter(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
289
|
+
...Records.convertFilter(filter, dateSort),
|
|
290
|
+
interface : DwnInterfaceName.Records,
|
|
291
|
+
method : DwnMethodName.Write,
|
|
292
|
+
published : true,
|
|
293
|
+
isLatestBaseState : true,
|
|
195
294
|
};
|
|
196
295
|
}
|
|
197
296
|
|
|
@@ -53,7 +53,7 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
53
53
|
|
|
54
54
|
// authentication & authorization
|
|
55
55
|
try {
|
|
56
|
-
await authenticate(message.authorization, this.didResolver);
|
|
56
|
+
await authenticate(message.authorization, this.didResolver, message.attestation);
|
|
57
57
|
await RecordsWriteHandler.authorizeRecordsWrite(tenant, recordsWrite, this.messageStore);
|
|
58
58
|
} catch (e) {
|
|
59
59
|
return messageReplyFromError(e, 401);
|
package/src/index.ts
CHANGED
|
@@ -4,8 +4,8 @@ export type { EventListener, EventStream, EventSubscription, MessageEvent, Subsc
|
|
|
4
4
|
export type { AuthorizationModel, Descriptor, DelegatedGrantRecordsWriteMessage, GenericMessage, GenericMessageReply, GenericSignaturePayload, MessageSort, MessageSubscription, Pagination, QueryResultEntry, Status } from './types/message-types.js';
|
|
5
5
|
export type { MessagesFilter, MessagesReadMessage as MessagesReadMessage, MessagesReadReply as MessagesReadReply, MessagesReadReplyEntry as MessagesReadReplyEntry, MessagesReadDescriptor, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessageSubscriptionHandler, MessagesSubscribeMessageOptions, MessagesSyncAction, MessagesSyncDescriptor, 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
|
-
export type { ProtocolsConfigureDescriptor, ProtocolDefinition, ProtocolTypes, ProtocolRuleSet, ProtocolsQueryFilter, ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply, ProtocolActionRule, ProtocolPathEncryption, ProtocolsQueryDescriptor, ProtocolType, ProtocolUses } from './types/protocols-types.js';
|
|
8
|
-
export type { DataEncodedRecordsWriteMessage,
|
|
7
|
+
export type { ProtocolsConfigureDescriptor, ProtocolDefinition, ProtocolTypes, ProtocolRuleSet, ProtocolsQueryFilter, ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply, ProtocolActionRule, ProtocolPathEncryption, ProtocolsQueryDescriptor, ProtocolSizeDefinition, ProtocolTagsDefinition, ProtocolTagSchema, ProtocolType, ProtocolUses } from './types/protocols-types.js';
|
|
8
|
+
export type { DataEncodedRecordsWriteMessage, RecordsCountDescriptor, RecordsCountMessage, RecordsCountReply, RecordsDeleteMessage, RecordsFilter, RecordsQueryMessage, RecordsQueryReply, RecordsQueryReplyEntry, RecordsReadMessage, RecordsReadReply, RecordsSubscribeDescriptor, RecordsSubscribeMessage, RecordsSubscribeReply, RecordSubscriptionHandler, RecordsWriteDescriptor, RecordsWriteTags, RecordsWriteTagValue, RecordsWriteMessage, RecordsWriteSignaturePayload, RecordsDeleteDescriptor, RecordsQueryDescriptor, RecordsReadDescriptor, RecordsSubscribeMessageOptions, RecordsWriteMessageOptions, InternalRecordsWriteMessage, RecordEvent, RecordsWriteTagsFilter } from './types/records-types.js';
|
|
9
9
|
export type { GeneralJws, SignatureEntry } from './types/jws-types.js';
|
|
10
10
|
export { authenticate } from './core/auth.js';
|
|
11
11
|
export { AllowAllTenantGate } from './core/tenant-gate.js';
|
|
@@ -28,8 +28,8 @@ export { DwnInterfaceName, DwnMethodName } from './enums/dwn-interface-method.js
|
|
|
28
28
|
export { Encoder } from './utils/encoder.js';
|
|
29
29
|
export { MessagesSubscribe as MessagesSubscribe } from './interfaces/messages-subscribe.js';
|
|
30
30
|
export type { MessagesSubscribeOptions as MessagesSubscribeOptions } from './interfaces/messages-subscribe.js';
|
|
31
|
-
export { Encryption,
|
|
32
|
-
export type {
|
|
31
|
+
export { Encryption, ContentEncryptionAlgorithm, KeyAgreementAlgorithm } from './utils/encryption.js';
|
|
32
|
+
export type { JweEncryption, JweRecipient, JweRecipientHeader, JweProtectedHeader, JweKeyUnwrapPayload } from './utils/encryption.js';
|
|
33
33
|
export { RecordsWrite } from './interfaces/records-write.js';
|
|
34
34
|
export type { EncryptionInput, KeyEncryptionInput, RecordsWriteOptions, CreateFromOptions } from './interfaces/records-write.js';
|
|
35
35
|
export { executeUnlessAborted } from './utils/abort.js';
|
|
@@ -143,11 +143,11 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
143
143
|
const recordTypes = Object.keys(definition.types);
|
|
144
144
|
|
|
145
145
|
// gather all roles (local roles only — cross-protocol roles are validated by alias existence)
|
|
146
|
-
const roles = ProtocolsConfigure.fetchAllRolePathsRecursively('', definition.structure, []);
|
|
146
|
+
const roles = ProtocolsConfigure.fetchAllRolePathsRecursively('', definition.structure as ProtocolRuleSet, []);
|
|
147
147
|
|
|
148
148
|
// validate the entire rule set structure recursively
|
|
149
149
|
ProtocolsConfigure.validateRuleSetRecursively({
|
|
150
|
-
ruleSet : definition.structure,
|
|
150
|
+
ruleSet : definition.structure as ProtocolRuleSet,
|
|
151
151
|
ruleSetProtocolPath : '',
|
|
152
152
|
recordTypes,
|
|
153
153
|
roles,
|
|
@@ -172,7 +172,7 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
172
172
|
continue;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
const childRuleSet = ruleSet[recordType];
|
|
175
|
+
const childRuleSet = ruleSet[recordType] as ProtocolRuleSet;
|
|
176
176
|
|
|
177
177
|
let childRuleSetProtocolPath;
|
|
178
178
|
if (ruleSetProtocolPath === '') {
|
|
@@ -233,7 +233,7 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
233
233
|
for (const tag in tagProperties) {
|
|
234
234
|
const tagSchemaDefinition = tagProperties[tag];
|
|
235
235
|
|
|
236
|
-
if (!ajv.validateSchema(tagSchemaDefinition)) {
|
|
236
|
+
if (!ajv.validateSchema(tagSchemaDefinition as Record<string, unknown>)) {
|
|
237
237
|
const schemaError = ajv.errorsText(ajv.errors, { dataVar: `${ruleSetProtocolPath}/$tags/${tag}` });
|
|
238
238
|
throw new DwnError(DwnErrorCode.ProtocolsConfigureInvalidTagSchema, `tags schema validation error: ${schemaError}`);
|
|
239
239
|
}
|
|
@@ -376,7 +376,7 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
376
376
|
continue;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
const childRuleSet = ruleSet[recordType];
|
|
379
|
+
const childRuleSet = ruleSet[recordType] as ProtocolRuleSet;
|
|
380
380
|
|
|
381
381
|
// A structure key whose rule set has `$ref` does not need to be in the local `types` map —
|
|
382
382
|
// the type comes from the referenced protocol. All other keys must be in `types`.
|
|
@@ -23,6 +23,11 @@ export type RecordsDeleteOptions = {
|
|
|
23
23
|
*/
|
|
24
24
|
prune?: boolean
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* The ID of the permission grant authorizing this delete.
|
|
28
|
+
*/
|
|
29
|
+
permissionGrantId?: string;
|
|
30
|
+
|
|
26
31
|
/**
|
|
27
32
|
* The delegated grant to sign on behalf of the logical author, which is the grantor (`grantedBy`) of the delegated grant.
|
|
28
33
|
*/
|
|
@@ -64,9 +69,10 @@ export class RecordsDelete extends AbstractMessage<RecordsDeleteMessage> {
|
|
|
64
69
|
|
|
65
70
|
const authorization = await Message.createAuthorization({
|
|
66
71
|
descriptor,
|
|
67
|
-
signer
|
|
68
|
-
protocolRole
|
|
69
|
-
|
|
72
|
+
signer : options.signer,
|
|
73
|
+
protocolRole : options.protocolRole,
|
|
74
|
+
permissionGrantId : options.permissionGrantId,
|
|
75
|
+
delegatedGrant : options.delegatedGrant
|
|
70
76
|
});
|
|
71
77
|
const message: RecordsDeleteMessage = { descriptor, authorization };
|
|
72
78
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MessageSigner } from '../types/signer.js';
|
|
2
2
|
import type { MessageStore } from '../types/message-store.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { Pagination } from '../types/message-types.js';
|
|
4
|
+
import type { DataEncodedRecordsWriteMessage, DateSort, RecordsFilter, RecordsSubscribeDescriptor, RecordsSubscribeMessage } from '../types/records-types.js';
|
|
4
5
|
|
|
5
6
|
import { AbstractMessage } from '../core/abstract-message.js';
|
|
6
7
|
import { Message } from '../core/message.js';
|
|
@@ -16,6 +17,8 @@ import { validateProtocolUrlNormalized, validateSchemaUrlNormalized } from '../u
|
|
|
16
17
|
export type RecordsSubscribeOptions = {
|
|
17
18
|
messageTimestamp?: string;
|
|
18
19
|
filter: RecordsFilter;
|
|
20
|
+
dateSort?: DateSort;
|
|
21
|
+
pagination?: Pagination;
|
|
19
22
|
signer?: MessageSigner;
|
|
20
23
|
protocolRole?: string;
|
|
21
24
|
|
|
@@ -63,6 +66,8 @@ export class RecordsSubscribe extends AbstractMessage<RecordsSubscribeMessage> {
|
|
|
63
66
|
method : DwnMethodName.Subscribe,
|
|
64
67
|
messageTimestamp : options.messageTimestamp ?? Time.getCurrentTimestamp(),
|
|
65
68
|
filter : Records.normalizeFilter(options.filter),
|
|
69
|
+
dateSort : options.dateSort,
|
|
70
|
+
pagination : options.pagination,
|
|
66
71
|
};
|
|
67
72
|
|
|
68
73
|
// delete all descriptor properties that are `undefined` else the code will encounter the following IPLD issue when attempting to generate CID:
|