@enbox/dwn-sdk-js 0.0.5 → 0.0.7
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 +1 -2
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/abstract-message.js +4 -0
- package/dist/esm/src/core/abstract-message.js.map +1 -1
- package/dist/esm/src/core/auth.js +22 -33
- package/dist/esm/src/core/auth.js.map +1 -1
- package/dist/esm/src/core/dwn-constant.js +7 -7
- package/dist/esm/src/core/dwn-constant.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +1 -0
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +37 -52
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/core/message.js +85 -116
- package/dist/esm/src/core/message.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +63 -78
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +266 -0
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -0
- package/dist/esm/src/core/protocol-authorization-validation.js +254 -0
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -0
- package/dist/esm/src/core/protocol-authorization.js +122 -740
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/protocols-grant-authorization.js +24 -38
- package/dist/esm/src/core/protocols-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/record-chain.js +64 -0
- package/dist/esm/src/core/record-chain.js.map +1 -0
- package/dist/esm/src/core/records-grant-authorization.js +55 -72
- package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/resumable-task-manager.js +50 -65
- package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
- package/dist/esm/src/core/tenant-gate.js +2 -13
- package/dist/esm/src/core/tenant-gate.js.map +1 -1
- package/dist/esm/src/dwn.js +69 -86
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/event-stream/event-emitter-stream.js +17 -31
- package/dist/esm/src/event-stream/event-emitter-stream.js.map +1 -1
- package/dist/esm/src/handlers/messages-read.js +67 -77
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +51 -61
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/messages-sync.js +75 -85
- package/dist/esm/src/handlers/messages-sync.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +135 -155
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/protocols-query.js +52 -51
- package/dist/esm/src/handlers/protocols-query.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +96 -82
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +78 -88
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +116 -101
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +124 -131
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +150 -103
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +250 -259
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/interfaces/messages-read.js +24 -32
- package/dist/esm/src/interfaces/messages-read.js.map +1 -1
- package/dist/esm/src/interfaces/messages-subscribe.js +27 -41
- package/dist/esm/src/interfaces/messages-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/messages-sync.js +26 -40
- package/dist/esm/src/interfaces/messages-sync.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +63 -63
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-query.js +55 -68
- package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-count.js +50 -66
- package/dist/esm/src/interfaces/records-count.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +45 -55
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-query.js +60 -76
- package/dist/esm/src/interfaces/records-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-read.js +51 -67
- package/dist/esm/src/interfaces/records-read.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +52 -68
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write-query.js +102 -0
- package/dist/esm/src/interfaces/records-write-query.js.map +1 -0
- package/dist/esm/src/interfaces/records-write-signing.js +92 -0
- package/dist/esm/src/interfaces/records-write-signing.js.map +1 -0
- package/dist/esm/src/interfaces/records-write.js +407 -602
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/jose/algorithms/signing/ed25519.js +10 -19
- package/dist/esm/src/jose/algorithms/signing/ed25519.js.map +1 -1
- package/dist/esm/src/jose/jws/general/builder.js +23 -35
- package/dist/esm/src/jose/jws/general/builder.js.map +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js +56 -69
- package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
- package/dist/esm/src/protocols/permission-grant.js +44 -15
- package/dist/esm/src/protocols/permission-grant.js.map +1 -1
- package/dist/esm/src/protocols/permission-request.js +29 -15
- package/dist/esm/src/protocols/permission-request.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +216 -226
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/smt/smt-store-level.js +42 -64
- package/dist/esm/src/smt/smt-store-level.js.map +1 -1
- package/dist/esm/src/smt/smt-store-memory.js +19 -45
- package/dist/esm/src/smt/smt-store-memory.js.map +1 -1
- package/dist/esm/src/smt/smt-utils.js +28 -45
- package/dist/esm/src/smt/smt-utils.js.map +1 -1
- package/dist/esm/src/smt/sparse-merkle-tree.js +426 -471
- package/dist/esm/src/smt/sparse-merkle-tree.js.map +1 -1
- package/dist/esm/src/state-index/state-index-level.js +115 -150
- package/dist/esm/src/state-index/state-index-level.js.map +1 -1
- package/dist/esm/src/store/blockstore-level.js +54 -156
- package/dist/esm/src/store/blockstore-level.js.map +1 -1
- package/dist/esm/src/store/blockstore-mock.js +48 -153
- package/dist/esm/src/store/blockstore-mock.js.map +1 -1
- package/dist/esm/src/store/data-store-level.js +59 -99
- package/dist/esm/src/store/data-store-level.js.map +1 -1
- package/dist/esm/src/store/index-level-compound.js +246 -0
- package/dist/esm/src/store/index-level-compound.js.map +1 -0
- package/dist/esm/src/store/index-level.js +295 -713
- package/dist/esm/src/store/index-level.js.map +1 -1
- package/dist/esm/src/store/level-wrapper.js +143 -244
- package/dist/esm/src/store/level-wrapper.js.map +1 -1
- package/dist/esm/src/store/message-store-level.js +71 -94
- package/dist/esm/src/store/message-store-level.js.map +1 -1
- package/dist/esm/src/store/resumable-task-store-level.js +62 -101
- package/dist/esm/src/store/resumable-task-store-level.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +129 -144
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/utils/abort.js +8 -19
- package/dist/esm/src/utils/abort.js.map +1 -1
- package/dist/esm/src/utils/array.js +15 -49
- package/dist/esm/src/utils/array.js.map +1 -1
- package/dist/esm/src/utils/cid.js +29 -77
- package/dist/esm/src/utils/cid.js.map +1 -1
- package/dist/esm/src/utils/data-stream.js +37 -65
- package/dist/esm/src/utils/data-stream.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +136 -162
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/filter.js +1 -12
- package/dist/esm/src/utils/filter.js.map +1 -1
- package/dist/esm/src/utils/hd-key.js +45 -63
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/jws.js +9 -20
- package/dist/esm/src/utils/jws.js.map +1 -1
- package/dist/esm/src/utils/memory-cache.js +12 -23
- package/dist/esm/src/utils/memory-cache.js.map +1 -1
- package/dist/esm/src/utils/messages.js +9 -3
- package/dist/esm/src/utils/messages.js.map +1 -1
- package/dist/esm/src/utils/private-key-signer.js +9 -17
- package/dist/esm/src/utils/private-key-signer.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +62 -70
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/records.js +108 -140
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/src/utils/secp256k1.js +60 -96
- package/dist/esm/src/utils/secp256k1.js.map +1 -1
- package/dist/esm/src/utils/secp256r1.js +54 -71
- package/dist/esm/src/utils/secp256r1.js.map +1 -1
- package/dist/esm/src/utils/time.js +5 -18
- package/dist/esm/src/utils/time.js.map +1 -1
- package/dist/esm/src/utils/url.js +3 -3
- package/dist/esm/src/utils/url.js.map +1 -1
- package/dist/esm/tests/core/auth.spec.js +3 -12
- package/dist/esm/tests/core/auth.spec.js.map +1 -1
- package/dist/esm/tests/core/message.spec.js +50 -59
- package/dist/esm/tests/core/message.spec.js.map +1 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js +9 -18
- package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
- package/dist/esm/tests/dwn.spec.js +45 -58
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/event-stream/event-emitter-stream.spec.js +24 -33
- package/dist/esm/tests/event-stream/event-emitter-stream.spec.js.map +1 -1
- package/dist/esm/tests/event-stream/event-stream.spec.js +46 -55
- package/dist/esm/tests/event-stream/event-stream.spec.js.map +1 -1
- package/dist/esm/tests/features/author-delegated-grant.spec.js +326 -343
- package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-delegated-grant.spec.js +153 -169
- package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-signature.spec.js +67 -78
- package/dist/esm/tests/features/owner-signature.spec.js.map +1 -1
- package/dist/esm/tests/features/permissions.spec.js +446 -181
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +346 -356
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-create-action.spec.js +42 -51
- package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-delete-action.spec.js +94 -103
- package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-update-action.spec.js +105 -114
- package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -1
- package/dist/esm/tests/features/records-prune.spec.js +175 -191
- package/dist/esm/tests/features/records-prune.spec.js.map +1 -1
- package/dist/esm/tests/features/records-tags.spec.js +441 -460
- package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
- package/dist/esm/tests/features/resumable-tasks.spec.js +82 -91
- package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-read.spec.js +206 -207
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +145 -154
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-sync.spec.js +174 -183
- package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +244 -238
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-query.spec.js +156 -169
- package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +93 -102
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +252 -264
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +917 -988
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +553 -568
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +269 -278
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +1057 -1082
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/messages-get.spec.js +39 -48
- package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/messages-subscribe.spec.js +4 -13
- package/dist/esm/tests/interfaces/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-configure.spec.js +212 -88
- package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-query.spec.js +8 -17
- package/dist/esm/tests/interfaces/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-delete.spec.js +8 -17
- package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-query.spec.js +20 -29
- package/dist/esm/tests/interfaces/records-query.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-read.spec.js +42 -51
- package/dist/esm/tests/interfaces/records-read.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-subscribe.spec.js +16 -25
- package/dist/esm/tests/interfaces/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +152 -165
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/jose/jws/general.spec.js +36 -45
- package/dist/esm/tests/jose/jws/general.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permission-grant.spec.js +44 -50
- package/dist/esm/tests/protocols/permission-grant.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permission-request.spec.js +23 -32
- package/dist/esm/tests/protocols/permission-request.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permissions.spec.js +49 -55
- package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/aggregator.spec.js +124 -135
- package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/deleted-record.spec.js +23 -32
- package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +52 -61
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/nested-roles.spec.js +63 -73
- package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/subscriptions.spec.js +377 -333
- package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -1
- package/dist/esm/tests/smt/smt-store-level.spec.js +76 -87
- package/dist/esm/tests/smt/smt-store-level.spec.js.map +1 -1
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js +344 -353
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js.map +1 -1
- package/dist/esm/tests/state-index/state-index-level.spec.js +117 -126
- package/dist/esm/tests/state-index/state-index-level.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-level.spec.js +44 -99
- package/dist/esm/tests/store/blockstore-level.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-mock.spec.js +40 -120
- package/dist/esm/tests/store/blockstore-mock.spec.js.map +1 -1
- package/dist/esm/tests/store/data-store-level.spec.js +86 -95
- package/dist/esm/tests/store/data-store-level.spec.js.map +1 -1
- package/dist/esm/tests/store/index-level.spec.js +404 -414
- package/dist/esm/tests/store/index-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store-level.spec.js +13 -22
- package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store.spec.js +229 -238
- package/dist/esm/tests/store/message-store.spec.js.map +1 -1
- package/dist/esm/tests/test-event-stream.js +3 -3
- package/dist/esm/tests/test-event-stream.js.map +1 -1
- package/dist/esm/tests/test-stores.js +16 -13
- package/dist/esm/tests/test-stores.js.map +1 -1
- package/dist/esm/tests/test-suite.js +2 -11
- package/dist/esm/tests/test-suite.js.map +1 -1
- package/dist/esm/tests/utils/cid.spec.js +24 -33
- package/dist/esm/tests/utils/cid.spec.js.map +1 -1
- package/dist/esm/tests/utils/data-stream.spec.js +48 -57
- package/dist/esm/tests/utils/data-stream.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-callbacks.spec.js +45 -54
- package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption.spec.js +291 -44
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/filters.spec.js +46 -55
- package/dist/esm/tests/utils/filters.spec.js.map +1 -1
- package/dist/esm/tests/utils/hd-key.spec.js +10 -19
- package/dist/esm/tests/utils/hd-key.spec.js.map +1 -1
- package/dist/esm/tests/utils/jws.spec.js +3 -12
- package/dist/esm/tests/utils/jws.spec.js.map +1 -1
- package/dist/esm/tests/utils/memory-cache.spec.js +9 -18
- package/dist/esm/tests/utils/memory-cache.spec.js.map +1 -1
- package/dist/esm/tests/utils/messages.spec.js +6 -15
- package/dist/esm/tests/utils/messages.spec.js.map +1 -1
- package/dist/esm/tests/utils/poller.js +22 -33
- package/dist/esm/tests/utils/poller.js.map +1 -1
- package/dist/esm/tests/utils/private-key-signer.spec.js +15 -24
- package/dist/esm/tests/utils/private-key-signer.spec.js.map +1 -1
- package/dist/esm/tests/utils/records.spec.js +10 -19
- package/dist/esm/tests/utils/records.spec.js.map +1 -1
- package/dist/esm/tests/utils/secp256k1.spec.js +16 -25
- package/dist/esm/tests/utils/secp256k1.spec.js.map +1 -1
- package/dist/esm/tests/utils/secp256r1.spec.js +18 -27
- package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +414 -468
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/definitions.spec.js +2 -11
- package/dist/esm/tests/validation/json-schemas/definitions.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js +4 -13
- package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js +8 -17
- package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js +3 -12
- package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +4 -13
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js +2 -11
- package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-read.spec.js +2 -11
- package/dist/esm/tests/validation/json-schemas/records/records-read.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +7 -16
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
- package/dist/types/src/core/protocol-authorization-action.d.ts +42 -0
- package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -0
- package/dist/types/src/core/protocol-authorization-validation.d.ts +60 -0
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -0
- package/dist/types/src/core/protocol-authorization.d.ts +10 -100
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/record-chain.d.ts +24 -0
- package/dist/types/src/core/record-chain.d.ts.map +1 -0
- package/dist/types/src/handlers/records-write.d.ts +2 -1
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write-query.d.ts +33 -0
- package/dist/types/src/interfaces/records-write-query.d.ts.map +1 -0
- package/dist/types/src/interfaces/records-write-signing.d.ts +35 -0
- package/dist/types/src/interfaces/records-write-signing.d.ts.map +1 -0
- package/dist/types/src/interfaces/records-write.d.ts +10 -44
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/store/index-level-compound.d.ts +70 -0
- package/dist/types/src/store/index-level-compound.d.ts.map +1 -0
- package/dist/types/src/store/index-level.d.ts +0 -58
- package/dist/types/src/store/index-level.d.ts.map +1 -1
- package/dist/types/src/utils/protocols.d.ts +5 -0
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +3 -1
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/tests/features/permissions.spec.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/core/protocol-authorization-action.ts +377 -0
- package/src/core/protocol-authorization-validation.ts +391 -0
- package/src/core/protocol-authorization.ts +60 -849
- package/src/core/record-chain.ts +99 -0
- package/src/handlers/records-read.ts +1 -1
- package/src/handlers/records-write.ts +37 -21
- package/src/interfaces/protocols-configure.ts +33 -5
- package/src/interfaces/records-write-query.ts +139 -0
- package/src/interfaces/records-write-signing.ts +143 -0
- package/src/interfaces/records-write.ts +49 -221
- package/src/store/index-level-compound.ts +324 -0
- package/src/store/index-level.ts +24 -306
- package/src/utils/protocols.ts +8 -0
- package/src/utils/records.ts +9 -15
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import chatProtocolDefinition from '../vectors/protocol-definitions/chat.json' with { type: 'json' };
|
|
11
2
|
import emailProtocolDefinition from '../vectors/protocol-definitions/email.json' with { type: 'json' };
|
|
12
3
|
import friendRoleProtocolDefinition from '../vectors/protocol-definitions/friend-role.json' with { type: 'json' };
|
|
@@ -46,7 +37,7 @@ export function testRecordsReadHandler() {
|
|
|
46
37
|
describe('functional tests', () => {
|
|
47
38
|
// important to follow the `before` and `after` pattern to initialize and clean the stores in tests
|
|
48
39
|
// so that different test suites can reuse the same backend store for testing
|
|
49
|
-
beforeAll(() =>
|
|
40
|
+
beforeAll(async () => {
|
|
50
41
|
didResolver = new UniversalResolver({ didResolvers: [DidKey] });
|
|
51
42
|
const stores = TestStores.get();
|
|
52
43
|
messageStore = stores.messageStore;
|
|
@@ -54,152 +45,150 @@ export function testRecordsReadHandler() {
|
|
|
54
45
|
resumableTaskStore = stores.resumableTaskStore;
|
|
55
46
|
stateIndex = stores.stateIndex;
|
|
56
47
|
eventStream = TestEventStream.get();
|
|
57
|
-
dwn =
|
|
58
|
-
})
|
|
59
|
-
beforeEach(() =>
|
|
48
|
+
dwn = await Dwn.create({ didResolver, messageStore, dataStore, stateIndex, eventStream, resumableTaskStore });
|
|
49
|
+
});
|
|
50
|
+
beforeEach(async () => {
|
|
60
51
|
// clean up before each test rather than after so that a test does not depend on other tests to do the clean up
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
})
|
|
66
|
-
afterAll(() =>
|
|
67
|
-
|
|
68
|
-
})
|
|
69
|
-
it('should allow tenant to RecordsRead their own record', () =>
|
|
70
|
-
|
|
71
|
-
const alice = yield TestDataGenerator.generateDidKeyPersona();
|
|
52
|
+
await messageStore.clear();
|
|
53
|
+
await dataStore.clear();
|
|
54
|
+
await resumableTaskStore.clear();
|
|
55
|
+
await stateIndex.clear();
|
|
56
|
+
});
|
|
57
|
+
afterAll(async () => {
|
|
58
|
+
await dwn.close();
|
|
59
|
+
});
|
|
60
|
+
it('should allow tenant to RecordsRead their own record', async () => {
|
|
61
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
72
62
|
// insert data
|
|
73
|
-
const { message, dataStream, dataBytes } =
|
|
74
|
-
const writeReply =
|
|
63
|
+
const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: alice });
|
|
64
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
75
65
|
expect(writeReply.status.code).toBe(202);
|
|
76
66
|
// testing RecordsRead
|
|
77
|
-
const recordsRead =
|
|
67
|
+
const recordsRead = await RecordsRead.create({
|
|
78
68
|
filter: {
|
|
79
69
|
recordId: message.recordId,
|
|
80
70
|
},
|
|
81
71
|
signer: Jws.createSigner(alice)
|
|
82
72
|
});
|
|
83
|
-
const readReply =
|
|
73
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
84
74
|
expect(readReply.status.code).toBe(200);
|
|
85
75
|
expect(readReply.entry.recordsWrite).toBeDefined();
|
|
86
|
-
expect(
|
|
87
|
-
expect(
|
|
88
|
-
const dataFetched =
|
|
76
|
+
expect(readReply.entry.recordsWrite?.authorization).toEqual(message.authorization);
|
|
77
|
+
expect(readReply.entry.recordsWrite?.descriptor).toEqual(message.descriptor);
|
|
78
|
+
const dataFetched = await DataStream.toBytes(readReply.entry.data);
|
|
89
79
|
expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes)).toBe(true);
|
|
90
|
-
})
|
|
91
|
-
it('should not allow non-tenant to RecordsRead a record', () =>
|
|
92
|
-
const alice =
|
|
80
|
+
});
|
|
81
|
+
it('should not allow non-tenant to RecordsRead a record', async () => {
|
|
82
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
93
83
|
// insert data
|
|
94
|
-
const { message, dataStream } =
|
|
95
|
-
const writeReply =
|
|
84
|
+
const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice });
|
|
85
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
96
86
|
expect(writeReply.status.code).toBe(202);
|
|
97
87
|
// testing RecordsRead
|
|
98
|
-
const bob =
|
|
99
|
-
const recordsRead =
|
|
88
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
89
|
+
const recordsRead = await RecordsRead.create({
|
|
100
90
|
filter: {
|
|
101
91
|
recordId: message.recordId,
|
|
102
92
|
},
|
|
103
93
|
signer: Jws.createSigner(bob)
|
|
104
94
|
});
|
|
105
|
-
const readReply =
|
|
95
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
106
96
|
expect(readReply.status.code).toBe(401);
|
|
107
|
-
})
|
|
108
|
-
it('should allow reading of data that is published without `authorization`', () =>
|
|
109
|
-
const alice =
|
|
97
|
+
});
|
|
98
|
+
it('should allow reading of data that is published without `authorization`', async () => {
|
|
99
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
110
100
|
// insert public data
|
|
111
|
-
const { message, dataStream, dataBytes } =
|
|
112
|
-
const writeReply =
|
|
101
|
+
const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true });
|
|
102
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
113
103
|
expect(writeReply.status.code).toBe(202);
|
|
114
104
|
// testing public RecordsRead
|
|
115
|
-
const recordsRead =
|
|
105
|
+
const recordsRead = await RecordsRead.create({
|
|
116
106
|
filter: {
|
|
117
107
|
recordId: message.recordId
|
|
118
108
|
}
|
|
119
109
|
});
|
|
120
110
|
expect(recordsRead.author).toBeUndefined(); // making sure no author/authorization is created
|
|
121
|
-
const readReply =
|
|
111
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
122
112
|
expect(readReply.status.code).toBe(200);
|
|
123
|
-
const dataFetched =
|
|
113
|
+
const dataFetched = await DataStream.toBytes(readReply.entry.data);
|
|
124
114
|
expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes)).toBe(true);
|
|
125
|
-
})
|
|
126
|
-
it('should allow an authenticated user to RecordRead data that is published', () =>
|
|
127
|
-
const alice =
|
|
115
|
+
});
|
|
116
|
+
it('should allow an authenticated user to RecordRead data that is published', async () => {
|
|
117
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
128
118
|
// insert public data
|
|
129
|
-
const { message, dataStream, dataBytes } =
|
|
130
|
-
const writeReply =
|
|
119
|
+
const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true });
|
|
120
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
131
121
|
expect(writeReply.status.code).toBe(202);
|
|
132
122
|
// testing public RecordsRead
|
|
133
|
-
const bob =
|
|
134
|
-
const recordsRead =
|
|
123
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
124
|
+
const recordsRead = await RecordsRead.create({
|
|
135
125
|
filter: {
|
|
136
126
|
recordId: message.recordId,
|
|
137
127
|
},
|
|
138
128
|
signer: Jws.createSigner(bob)
|
|
139
129
|
});
|
|
140
|
-
const readReply =
|
|
130
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
141
131
|
expect(readReply.status.code).toBe(200);
|
|
142
|
-
const dataFetched =
|
|
132
|
+
const dataFetched = await DataStream.toBytes(readReply.entry.data);
|
|
143
133
|
expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes)).toBe(true);
|
|
144
|
-
})
|
|
145
|
-
it('should allow a non-tenant to read RecordsRead data they have received', () =>
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
const bob = yield TestDataGenerator.generateDidKeyPersona();
|
|
134
|
+
});
|
|
135
|
+
it('should allow a non-tenant to read RecordsRead data they have received', async () => {
|
|
136
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
137
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
149
138
|
// Alice inserts data with Bob as recipient
|
|
150
|
-
const { message, dataStream, dataBytes } =
|
|
139
|
+
const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({
|
|
151
140
|
author: alice,
|
|
152
141
|
recipient: bob.did,
|
|
153
142
|
});
|
|
154
|
-
const writeReply =
|
|
143
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
155
144
|
expect(writeReply.status.code).toBe(202);
|
|
156
145
|
// Bob reads the data that Alice sent him
|
|
157
|
-
const recordsRead =
|
|
146
|
+
const recordsRead = await RecordsRead.create({
|
|
158
147
|
filter: {
|
|
159
148
|
recordId: message.recordId,
|
|
160
149
|
},
|
|
161
150
|
signer: Jws.createSigner(bob)
|
|
162
151
|
});
|
|
163
|
-
const readReply =
|
|
152
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
164
153
|
expect(readReply.status.code).toBe(200);
|
|
165
154
|
expect(readReply.entry.recordsWrite).toBeDefined();
|
|
166
|
-
expect(
|
|
167
|
-
const dataFetched =
|
|
155
|
+
expect(readReply.entry.recordsWrite?.descriptor).toBeDefined();
|
|
156
|
+
const dataFetched = await DataStream.toBytes(readReply.entry.data);
|
|
168
157
|
expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes)).toBe(true);
|
|
169
|
-
})
|
|
170
|
-
it('should return 400 when fetching initial write for a deleted record fails', () =>
|
|
171
|
-
const alice =
|
|
158
|
+
});
|
|
159
|
+
it('should return 400 when fetching initial write for a deleted record fails', async () => {
|
|
160
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
172
161
|
// Write a record
|
|
173
|
-
const { message: writeMessage, dataStream } =
|
|
174
|
-
const writeReply =
|
|
162
|
+
const { message: writeMessage, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice });
|
|
163
|
+
const writeReply = await dwn.processMessage(alice.did, writeMessage, { dataStream });
|
|
175
164
|
expect(writeReply.status.code).toBe(202);
|
|
176
165
|
// Delete the record
|
|
177
|
-
const recordsDelete =
|
|
166
|
+
const recordsDelete = await RecordsDelete.create({
|
|
178
167
|
signer: Jws.createSigner(alice),
|
|
179
168
|
recordId: writeMessage.recordId
|
|
180
169
|
});
|
|
181
|
-
const deleteReply =
|
|
170
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
182
171
|
expect(deleteReply.status.code).toBe(202);
|
|
183
172
|
// Stub the messageStore.query method to simulate failure in fetching initial write
|
|
184
173
|
const queryStub = sinon.stub(dwn['messageStore'], 'query');
|
|
185
174
|
queryStub.onFirstCall().resolves({ messages: [recordsDelete.message] });
|
|
186
175
|
queryStub.onSecondCall().resolves({ messages: [] }); // Simulate no initial write found
|
|
187
176
|
// Attempt to read the deleted record
|
|
188
|
-
const recordsRead =
|
|
177
|
+
const recordsRead = await RecordsRead.create({
|
|
189
178
|
filter: { recordId: writeMessage.recordId },
|
|
190
179
|
signer: Jws.createSigner(alice)
|
|
191
180
|
});
|
|
192
|
-
const readReply =
|
|
181
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
193
182
|
// Verify the response
|
|
194
183
|
expect(readReply.status.code).toBe(400);
|
|
195
184
|
expect(readReply.status.detail).toContain(DwnErrorCode.RecordsReadInitialWriteNotFound);
|
|
196
185
|
// Restore the original messageStore.query method
|
|
197
186
|
queryStub.restore();
|
|
198
|
-
})
|
|
199
|
-
it('should return 401 when a non-author attempts to read the initial write of a deleted record', () =>
|
|
200
|
-
const alice =
|
|
201
|
-
const bob =
|
|
202
|
-
const carol =
|
|
187
|
+
});
|
|
188
|
+
it('should return 401 when a non-author attempts to read the initial write of a deleted record', async () => {
|
|
189
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
190
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
191
|
+
const carol = await TestDataGenerator.generateDidKeyPersona();
|
|
203
192
|
// Alice installs a protocol that allows anyone to write
|
|
204
193
|
const protocolDefinition = {
|
|
205
194
|
published: true,
|
|
@@ -216,42 +205,41 @@ export function testRecordsReadHandler() {
|
|
|
216
205
|
}
|
|
217
206
|
}
|
|
218
207
|
};
|
|
219
|
-
const configureProtocol =
|
|
208
|
+
const configureProtocol = await TestDataGenerator.generateProtocolsConfigure({
|
|
220
209
|
author: alice,
|
|
221
210
|
protocolDefinition: protocolDefinition,
|
|
222
211
|
});
|
|
223
|
-
const configureProtocolReply =
|
|
212
|
+
const configureProtocolReply = await dwn.processMessage(alice.did, configureProtocol.message);
|
|
224
213
|
expect(configureProtocolReply.status.code).toBe(202);
|
|
225
214
|
// Bob writes a record to Alice's DWN
|
|
226
|
-
const { message: writeMessage, dataStream } =
|
|
215
|
+
const { message: writeMessage, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
227
216
|
author: bob,
|
|
228
217
|
protocol: protocolDefinition.protocol,
|
|
229
218
|
protocolPath: 'foo'
|
|
230
219
|
});
|
|
231
|
-
const writeReply =
|
|
220
|
+
const writeReply = await dwn.processMessage(alice.did, writeMessage, { dataStream });
|
|
232
221
|
expect(writeReply.status.code).toBe(202);
|
|
233
222
|
// Bob deletes the record
|
|
234
|
-
const recordsDelete =
|
|
223
|
+
const recordsDelete = await RecordsDelete.create({
|
|
235
224
|
signer: Jws.createSigner(bob),
|
|
236
225
|
recordId: writeMessage.recordId
|
|
237
226
|
});
|
|
238
|
-
const deleteReply =
|
|
227
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
239
228
|
expect(deleteReply.status.code).toBe(202);
|
|
240
229
|
// Carol attempts to read the deleted record
|
|
241
|
-
const recordsRead =
|
|
230
|
+
const recordsRead = await RecordsRead.create({
|
|
242
231
|
filter: { recordId: writeMessage.recordId },
|
|
243
232
|
signer: Jws.createSigner(carol)
|
|
244
233
|
});
|
|
245
|
-
const readReply =
|
|
234
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
246
235
|
// Verify the response
|
|
247
236
|
expect(readReply.status.code).toBe(401);
|
|
248
237
|
expect(readReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
|
|
249
|
-
})
|
|
250
|
-
it('should allow a non-tenant to read RecordsRead data they have authored', () =>
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
const carol = yield TestDataGenerator.generateDidKeyPersona();
|
|
238
|
+
});
|
|
239
|
+
it('should allow a non-tenant to read RecordsRead data they have authored', async () => {
|
|
240
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
241
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
242
|
+
const carol = await TestDataGenerator.generateDidKeyPersona();
|
|
255
243
|
// Alice installs a protocol that allows anyone to write foo record
|
|
256
244
|
const protocolDefinition = {
|
|
257
245
|
published: true,
|
|
@@ -268,76 +256,75 @@ export function testRecordsReadHandler() {
|
|
|
268
256
|
}
|
|
269
257
|
}
|
|
270
258
|
};
|
|
271
|
-
const configureProtocol =
|
|
259
|
+
const configureProtocol = await TestDataGenerator.generateProtocolsConfigure({
|
|
272
260
|
author: alice,
|
|
273
261
|
protocolDefinition: protocolDefinition,
|
|
274
262
|
});
|
|
275
|
-
const configureProtocolReply =
|
|
263
|
+
const configureProtocolReply = await dwn.processMessage(alice.did, configureProtocol.message);
|
|
276
264
|
expect(configureProtocolReply.status.code).toBe(202);
|
|
277
265
|
// Bob writes a foo record to Alice's DWN
|
|
278
|
-
const { message, dataStream, dataBytes } =
|
|
266
|
+
const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({
|
|
279
267
|
author: bob,
|
|
280
268
|
protocol: protocolDefinition.protocol,
|
|
281
269
|
protocolPath: 'foo',
|
|
282
270
|
});
|
|
283
|
-
const writeReply =
|
|
271
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
284
272
|
expect(writeReply.status.code).toBe(202);
|
|
285
273
|
// Bob reads the record he sent to Alice from Alice's DWN
|
|
286
|
-
const recordsRead =
|
|
274
|
+
const recordsRead = await RecordsRead.create({
|
|
287
275
|
filter: {
|
|
288
276
|
recordId: message.recordId,
|
|
289
277
|
},
|
|
290
278
|
signer: Jws.createSigner(bob)
|
|
291
279
|
});
|
|
292
|
-
const readReply =
|
|
280
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
293
281
|
expect(readReply.status.code).toBe(200);
|
|
294
282
|
expect(readReply.entry.recordsWrite).toBeDefined();
|
|
295
|
-
expect(
|
|
296
|
-
const dataFetched =
|
|
283
|
+
expect(readReply.entry.recordsWrite?.descriptor).toBeDefined();
|
|
284
|
+
const dataFetched = await DataStream.toBytes(readReply.entry.data);
|
|
297
285
|
expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes)).toBe(true);
|
|
298
286
|
// carol attempts to read Bob's record
|
|
299
|
-
const carolRecordsRead =
|
|
287
|
+
const carolRecordsRead = await RecordsRead.create({
|
|
300
288
|
filter: {
|
|
301
289
|
recordId: message.recordId,
|
|
302
290
|
},
|
|
303
291
|
signer: Jws.createSigner(carol)
|
|
304
292
|
});
|
|
305
|
-
const carolReadReply =
|
|
293
|
+
const carolReadReply = await dwn.processMessage(alice.did, carolRecordsRead.message);
|
|
306
294
|
expect(carolReadReply.status.code).toBe(401);
|
|
307
|
-
})
|
|
308
|
-
it('should include `initialWrite` property if RecordsWrite is not initial write', () =>
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
const
|
|
312
|
-
const writeReply = yield dwn.processMessage(alice.did, write.message, { dataStream: write.dataStream });
|
|
295
|
+
});
|
|
296
|
+
it('should include `initialWrite` property if RecordsWrite is not initial write', async () => {
|
|
297
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
298
|
+
const write = await TestDataGenerator.generateRecordsWrite({ author: alice, published: false });
|
|
299
|
+
const writeReply = await dwn.processMessage(alice.did, write.message, { dataStream: write.dataStream });
|
|
313
300
|
expect(writeReply.status.code).toBe(202);
|
|
314
301
|
// write an update to the record
|
|
315
|
-
const write2 =
|
|
316
|
-
const write2Reply =
|
|
302
|
+
const write2 = await RecordsWrite.createFrom({ recordsWriteMessage: write.message, published: true, signer: Jws.createSigner(alice) });
|
|
303
|
+
const write2Reply = await dwn.processMessage(alice.did, write2.message);
|
|
317
304
|
expect(write2Reply.status.code).toBe(202);
|
|
318
305
|
// make sure result returned now has `initialWrite` property
|
|
319
|
-
const messageData =
|
|
320
|
-
const reply =
|
|
306
|
+
const messageData = await RecordsRead.create({ filter: { recordId: write.message.recordId }, signer: Jws.createSigner(alice) });
|
|
307
|
+
const reply = await dwn.processMessage(alice.did, messageData.message);
|
|
321
308
|
expect(reply.status.code).toBe(200);
|
|
322
309
|
expect(reply.entry.initialWrite).toBeDefined();
|
|
323
|
-
expect(
|
|
324
|
-
})
|
|
310
|
+
expect(reply.entry.initialWrite?.recordId).toBe(write.message.recordId);
|
|
311
|
+
});
|
|
325
312
|
describe('protocol based reads', () => {
|
|
326
|
-
it('should allow read with allow-anyone rule', () =>
|
|
313
|
+
it('should allow read with allow-anyone rule', async () => {
|
|
327
314
|
// scenario: Alice writes an image to her DWN, then Bob reads the image because he is "anyone".
|
|
328
|
-
const alice =
|
|
329
|
-
const bob =
|
|
315
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
316
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
330
317
|
const protocolDefinition = socialMediaProtocolDefinition;
|
|
331
318
|
// Install social-media protocol on Alice's DWN
|
|
332
|
-
const protocolsConfig =
|
|
319
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
333
320
|
author: alice,
|
|
334
321
|
protocolDefinition
|
|
335
322
|
});
|
|
336
|
-
const protocolsConfigureReply =
|
|
323
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
337
324
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
338
325
|
// Alice writes image to her DWN
|
|
339
326
|
const encodedImage = new TextEncoder().encode('cafe-aesthetic.jpg');
|
|
340
|
-
const imageRecordsWrite =
|
|
327
|
+
const imageRecordsWrite = await TestDataGenerator.generateRecordsWrite({
|
|
341
328
|
author: alice,
|
|
342
329
|
protocol: protocolDefinition.protocol,
|
|
343
330
|
protocolPath: 'image', // this comes from `types` in protocol definition
|
|
@@ -346,32 +333,32 @@ export function testRecordsReadHandler() {
|
|
|
346
333
|
data: encodedImage,
|
|
347
334
|
recipient: alice.did
|
|
348
335
|
});
|
|
349
|
-
const imageReply =
|
|
336
|
+
const imageReply = await dwn.processMessage(alice.did, imageRecordsWrite.message, { dataStream: imageRecordsWrite.dataStream });
|
|
350
337
|
expect(imageReply.status.code).toBe(202);
|
|
351
338
|
// Bob (anyone) reads the image that Alice wrote
|
|
352
|
-
const imageRecordsRead =
|
|
339
|
+
const imageRecordsRead = await RecordsRead.create({
|
|
353
340
|
filter: {
|
|
354
341
|
recordId: imageRecordsWrite.message.recordId,
|
|
355
342
|
},
|
|
356
343
|
signer: Jws.createSigner(bob)
|
|
357
344
|
});
|
|
358
|
-
const imageReadReply =
|
|
345
|
+
const imageReadReply = await dwn.processMessage(alice.did, imageRecordsRead.message);
|
|
359
346
|
expect(imageReadReply.status.code).toBe(200);
|
|
360
|
-
})
|
|
361
|
-
it('should not allow anonymous reads when there is no allow-anyone rule', () =>
|
|
347
|
+
});
|
|
348
|
+
it('should not allow anonymous reads when there is no allow-anyone rule', async () => {
|
|
362
349
|
// scenario: Alice's writes a record to a protocol. An anonymous read his Alice's DWN and is rejected
|
|
363
350
|
// because there is not an allow-anyone rule.
|
|
364
|
-
const alice =
|
|
351
|
+
const alice = await TestDataGenerator.generatePersona();
|
|
365
352
|
const protocolDefinition = emailProtocolDefinition;
|
|
366
353
|
TestStubGenerator.stubDidResolver(didResolver, [alice]);
|
|
367
|
-
const protocolsConfig =
|
|
354
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
368
355
|
author: alice,
|
|
369
356
|
protocolDefinition
|
|
370
357
|
});
|
|
371
|
-
const protocolsConfigureReply =
|
|
358
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
372
359
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
373
360
|
// Alice writes a message to the minimal protocol
|
|
374
|
-
const recordsWrite =
|
|
361
|
+
const recordsWrite = await TestDataGenerator.generateRecordsWrite({
|
|
375
362
|
author: alice,
|
|
376
363
|
protocol: protocolDefinition.protocol,
|
|
377
364
|
protocolPath: 'email',
|
|
@@ -379,36 +366,36 @@ export function testRecordsReadHandler() {
|
|
|
379
366
|
dataFormat: protocolDefinition.types.email.dataFormats[0],
|
|
380
367
|
data: new TextEncoder().encode('foo')
|
|
381
368
|
});
|
|
382
|
-
const recordsWriteReply =
|
|
369
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream: recordsWrite.dataStream });
|
|
383
370
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
384
371
|
// Anonymous tries and fails to read Alice's message
|
|
385
|
-
const recordsRead =
|
|
372
|
+
const recordsRead = await RecordsRead.create({
|
|
386
373
|
filter: {
|
|
387
374
|
recordId: recordsWrite.message.recordId,
|
|
388
375
|
}
|
|
389
376
|
});
|
|
390
|
-
const recordsReadReply =
|
|
377
|
+
const recordsReadReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
391
378
|
expect(recordsReadReply.status.code).toBe(401);
|
|
392
379
|
expect(recordsReadReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
|
|
393
|
-
})
|
|
380
|
+
});
|
|
394
381
|
describe('recipient rules', () => {
|
|
395
|
-
it('should allow read with ancestor recipient rule', () =>
|
|
382
|
+
it('should allow read with ancestor recipient rule', async () => {
|
|
396
383
|
// scenario: Alice sends an email to Bob, then Bob reads the email.
|
|
397
384
|
// ImposterBob tries and fails to read the email.
|
|
398
|
-
const alice =
|
|
399
|
-
const bob =
|
|
400
|
-
const imposterBob =
|
|
385
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
386
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
387
|
+
const imposterBob = await TestDataGenerator.generateDidKeyPersona();
|
|
401
388
|
const protocolDefinition = emailProtocolDefinition;
|
|
402
389
|
// Install email protocol on Alice's DWN
|
|
403
|
-
const protocolsConfig =
|
|
390
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
404
391
|
author: alice,
|
|
405
392
|
protocolDefinition,
|
|
406
393
|
});
|
|
407
|
-
const protocolsConfigureReply =
|
|
394
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
408
395
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
409
396
|
// Alice writes an email with Bob as recipient
|
|
410
397
|
const encodedEmail = new TextEncoder().encode('Dear Bob, hello!');
|
|
411
|
-
const emailRecordsWrite =
|
|
398
|
+
const emailRecordsWrite = await TestDataGenerator.generateRecordsWrite({
|
|
412
399
|
author: alice,
|
|
413
400
|
protocol: protocolDefinition.protocol,
|
|
414
401
|
protocolPath: 'email', // this comes from `types` in protocol definition
|
|
@@ -417,47 +404,47 @@ export function testRecordsReadHandler() {
|
|
|
417
404
|
data: encodedEmail,
|
|
418
405
|
recipient: bob.did
|
|
419
406
|
});
|
|
420
|
-
const imageReply =
|
|
407
|
+
const imageReply = await dwn.processMessage(alice.did, emailRecordsWrite.message, { dataStream: emailRecordsWrite.dataStream });
|
|
421
408
|
expect(imageReply.status.code).toBe(202);
|
|
422
409
|
// Bob reads Alice's email
|
|
423
|
-
const bobRecordsRead =
|
|
410
|
+
const bobRecordsRead = await RecordsRead.create({
|
|
424
411
|
filter: {
|
|
425
412
|
recordId: emailRecordsWrite.message.recordId,
|
|
426
413
|
},
|
|
427
414
|
signer: Jws.createSigner(bob)
|
|
428
415
|
});
|
|
429
|
-
const bobReadReply =
|
|
416
|
+
const bobReadReply = await dwn.processMessage(alice.did, bobRecordsRead.message);
|
|
430
417
|
expect(bobReadReply.status.code).toBe(200);
|
|
431
418
|
// ImposterBob is not able to read Alice's email
|
|
432
|
-
const imposterRecordsRead =
|
|
419
|
+
const imposterRecordsRead = await RecordsRead.create({
|
|
433
420
|
filter: {
|
|
434
421
|
recordId: emailRecordsWrite.message.recordId,
|
|
435
422
|
},
|
|
436
423
|
signer: Jws.createSigner(imposterBob)
|
|
437
424
|
});
|
|
438
|
-
const imposterReadReply =
|
|
425
|
+
const imposterReadReply = await dwn.processMessage(alice.did, imposterRecordsRead.message);
|
|
439
426
|
expect(imposterReadReply.status.code).toBe(401);
|
|
440
427
|
expect(imposterReadReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
|
|
441
|
-
})
|
|
428
|
+
});
|
|
442
429
|
});
|
|
443
430
|
describe('author action rules', () => {
|
|
444
|
-
it('should allow read with ancestor author rule', () =>
|
|
431
|
+
it('should allow read with ancestor author rule', async () => {
|
|
445
432
|
// scenario: Bob sends an email to Alice, then Bob reads the email.
|
|
446
433
|
// ImposterBob tries and fails to read the email.
|
|
447
|
-
const alice =
|
|
448
|
-
const bob =
|
|
449
|
-
const imposterBob =
|
|
434
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
435
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
436
|
+
const imposterBob = await TestDataGenerator.generateDidKeyPersona();
|
|
450
437
|
const protocolDefinition = emailProtocolDefinition;
|
|
451
438
|
// Install email protocol on Alice's DWN
|
|
452
|
-
const protocolsConfig =
|
|
439
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
453
440
|
author: alice,
|
|
454
441
|
protocolDefinition
|
|
455
442
|
});
|
|
456
|
-
const protocolsConfigureReply =
|
|
443
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
457
444
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
458
445
|
// Alice writes an email with Bob as recipient
|
|
459
446
|
const encodedEmail = new TextEncoder().encode('Dear Alice, hello!');
|
|
460
|
-
const emailRecordsWrite =
|
|
447
|
+
const emailRecordsWrite = await TestDataGenerator.generateRecordsWrite({
|
|
461
448
|
author: bob,
|
|
462
449
|
protocol: protocolDefinition.protocol,
|
|
463
450
|
protocolPath: 'email', // this comes from `types` in protocol definition
|
|
@@ -466,40 +453,40 @@ export function testRecordsReadHandler() {
|
|
|
466
453
|
data: encodedEmail,
|
|
467
454
|
recipient: alice.did
|
|
468
455
|
});
|
|
469
|
-
const imageReply =
|
|
456
|
+
const imageReply = await dwn.processMessage(alice.did, emailRecordsWrite.message, { dataStream: emailRecordsWrite.dataStream });
|
|
470
457
|
expect(imageReply.status.code).toBe(202);
|
|
471
458
|
// Bob reads the email he just sent
|
|
472
|
-
const bobRecordsRead =
|
|
459
|
+
const bobRecordsRead = await RecordsRead.create({
|
|
473
460
|
filter: {
|
|
474
461
|
recordId: emailRecordsWrite.message.recordId,
|
|
475
462
|
},
|
|
476
463
|
signer: Jws.createSigner(bob)
|
|
477
464
|
});
|
|
478
|
-
const bobReadReply =
|
|
465
|
+
const bobReadReply = await dwn.processMessage(alice.did, bobRecordsRead.message);
|
|
479
466
|
expect(bobReadReply.status.code).toBe(200);
|
|
480
467
|
// ImposterBob is not able to read the email
|
|
481
|
-
const imposterRecordsRead =
|
|
468
|
+
const imposterRecordsRead = await RecordsRead.create({
|
|
482
469
|
filter: {
|
|
483
470
|
recordId: emailRecordsWrite.message.recordId,
|
|
484
471
|
},
|
|
485
472
|
signer: Jws.createSigner(imposterBob)
|
|
486
473
|
});
|
|
487
|
-
const imposterReadReply =
|
|
474
|
+
const imposterReadReply = await dwn.processMessage(alice.did, imposterRecordsRead.message);
|
|
488
475
|
expect(imposterReadReply.status.code).toBe(401);
|
|
489
476
|
expect(imposterReadReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
|
|
490
|
-
})
|
|
477
|
+
});
|
|
491
478
|
});
|
|
492
479
|
describe('filter based reads', () => {
|
|
493
|
-
it('should return a filter based read if there is only a single result', () =>
|
|
494
|
-
const alice =
|
|
495
|
-
const protocolDefinition =
|
|
496
|
-
const protocolsConfig =
|
|
480
|
+
it('should return a filter based read if there is only a single result', async () => {
|
|
481
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
482
|
+
const protocolDefinition = { ...nestedProtocol };
|
|
483
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
497
484
|
author: alice,
|
|
498
485
|
protocolDefinition
|
|
499
486
|
});
|
|
500
|
-
const protocolConfigReply =
|
|
487
|
+
const protocolConfigReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
501
488
|
expect(protocolConfigReply.status.code).toBe(202);
|
|
502
|
-
const foo1Write =
|
|
489
|
+
const foo1Write = await TestDataGenerator.generateRecordsWrite({
|
|
503
490
|
author: alice,
|
|
504
491
|
protocol: protocolDefinition.protocol,
|
|
505
492
|
protocolPath: 'foo',
|
|
@@ -508,29 +495,29 @@ export function testRecordsReadHandler() {
|
|
|
508
495
|
data: new TextEncoder().encode('foo'),
|
|
509
496
|
recipient: alice.did
|
|
510
497
|
});
|
|
511
|
-
const foo1WriteReply =
|
|
498
|
+
const foo1WriteReply = await dwn.processMessage(alice.did, foo1Write.message, { dataStream: foo1Write.dataStream });
|
|
512
499
|
expect(foo1WriteReply.status.code).toBe(202);
|
|
513
|
-
const fooPathRead =
|
|
500
|
+
const fooPathRead = await RecordsRead.create({
|
|
514
501
|
filter: {
|
|
515
502
|
protocol: protocolDefinition.protocol,
|
|
516
503
|
protocolPath: 'foo',
|
|
517
504
|
},
|
|
518
505
|
signer: Jws.createSigner(alice),
|
|
519
506
|
});
|
|
520
|
-
const fooPathReply =
|
|
507
|
+
const fooPathReply = await dwn.processMessage(alice.did, fooPathRead.message);
|
|
521
508
|
expect(fooPathReply.status.code).toBe(200);
|
|
522
509
|
expect(fooPathReply.entry.recordsWrite.recordId).toBe(foo1Write.message.recordId);
|
|
523
|
-
})
|
|
524
|
-
it('should return the most recently updated record when filter matches multiple results', () =>
|
|
525
|
-
const alice =
|
|
526
|
-
const protocolDefinition =
|
|
527
|
-
const protocolsConfig =
|
|
510
|
+
});
|
|
511
|
+
it('should return the most recently updated record when filter matches multiple results', async () => {
|
|
512
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
513
|
+
const protocolDefinition = { ...nestedProtocol };
|
|
514
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
528
515
|
author: alice,
|
|
529
516
|
protocolDefinition
|
|
530
517
|
});
|
|
531
|
-
const protocolConfigReply =
|
|
518
|
+
const protocolConfigReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
532
519
|
expect(protocolConfigReply.status.code).toBe(202);
|
|
533
|
-
const foo1Write =
|
|
520
|
+
const foo1Write = await TestDataGenerator.generateRecordsWrite({
|
|
534
521
|
author: alice,
|
|
535
522
|
protocol: protocolDefinition.protocol,
|
|
536
523
|
protocolPath: 'foo',
|
|
@@ -539,10 +526,10 @@ export function testRecordsReadHandler() {
|
|
|
539
526
|
data: new TextEncoder().encode('foo1'),
|
|
540
527
|
recipient: alice.did
|
|
541
528
|
});
|
|
542
|
-
const foo1WriteReply =
|
|
529
|
+
const foo1WriteReply = await dwn.processMessage(alice.did, foo1Write.message, { dataStream: foo1Write.dataStream });
|
|
543
530
|
expect(foo1WriteReply.status.code).toBe(202);
|
|
544
|
-
|
|
545
|
-
const foo2Write =
|
|
531
|
+
await Time.minimalSleep();
|
|
532
|
+
const foo2Write = await TestDataGenerator.generateRecordsWrite({
|
|
546
533
|
author: alice,
|
|
547
534
|
protocol: protocolDefinition.protocol,
|
|
548
535
|
protocolPath: 'foo',
|
|
@@ -551,30 +538,30 @@ export function testRecordsReadHandler() {
|
|
|
551
538
|
data: new TextEncoder().encode('foo2'),
|
|
552
539
|
recipient: alice.did
|
|
553
540
|
});
|
|
554
|
-
const foo2WriteReply =
|
|
541
|
+
const foo2WriteReply = await dwn.processMessage(alice.did, foo2Write.message, { dataStream: foo2Write.dataStream });
|
|
555
542
|
expect(foo2WriteReply.status.code).toBe(202);
|
|
556
543
|
// default sort is updatedDescending, so the most recently updated record should be returned
|
|
557
|
-
const fooPathRead =
|
|
544
|
+
const fooPathRead = await RecordsRead.create({
|
|
558
545
|
filter: {
|
|
559
546
|
protocol: protocolDefinition.protocol,
|
|
560
547
|
protocolPath: 'foo',
|
|
561
548
|
},
|
|
562
549
|
signer: Jws.createSigner(alice),
|
|
563
550
|
});
|
|
564
|
-
const fooPathReply =
|
|
551
|
+
const fooPathReply = await dwn.processMessage(alice.did, fooPathRead.message);
|
|
565
552
|
expect(fooPathReply.status.code).toBe(200);
|
|
566
553
|
expect(fooPathReply.entry.recordsWrite.recordId).toBe(foo2Write.message.recordId);
|
|
567
|
-
})
|
|
568
|
-
it('should return the oldest record when `dateSort` is `CreatedAscending` and filter matches multiple results', () =>
|
|
569
|
-
const alice =
|
|
570
|
-
const protocolDefinition =
|
|
571
|
-
const protocolsConfig =
|
|
554
|
+
});
|
|
555
|
+
it('should return the oldest record when `dateSort` is `CreatedAscending` and filter matches multiple results', async () => {
|
|
556
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
557
|
+
const protocolDefinition = { ...nestedProtocol };
|
|
558
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
572
559
|
author: alice,
|
|
573
560
|
protocolDefinition
|
|
574
561
|
});
|
|
575
|
-
const protocolConfigReply =
|
|
562
|
+
const protocolConfigReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
576
563
|
expect(protocolConfigReply.status.code).toBe(202);
|
|
577
|
-
const foo1Write =
|
|
564
|
+
const foo1Write = await TestDataGenerator.generateRecordsWrite({
|
|
578
565
|
author: alice,
|
|
579
566
|
protocol: protocolDefinition.protocol,
|
|
580
567
|
protocolPath: 'foo',
|
|
@@ -583,10 +570,10 @@ export function testRecordsReadHandler() {
|
|
|
583
570
|
data: new TextEncoder().encode('foo1'),
|
|
584
571
|
recipient: alice.did
|
|
585
572
|
});
|
|
586
|
-
const foo1WriteReply =
|
|
573
|
+
const foo1WriteReply = await dwn.processMessage(alice.did, foo1Write.message, { dataStream: foo1Write.dataStream });
|
|
587
574
|
expect(foo1WriteReply.status.code).toBe(202);
|
|
588
|
-
|
|
589
|
-
const foo2Write =
|
|
575
|
+
await Time.minimalSleep();
|
|
576
|
+
const foo2Write = await TestDataGenerator.generateRecordsWrite({
|
|
590
577
|
author: alice,
|
|
591
578
|
protocol: protocolDefinition.protocol,
|
|
592
579
|
protocolPath: 'foo',
|
|
@@ -595,10 +582,10 @@ export function testRecordsReadHandler() {
|
|
|
595
582
|
data: new TextEncoder().encode('foo2'),
|
|
596
583
|
recipient: alice.did
|
|
597
584
|
});
|
|
598
|
-
const foo2WriteReply =
|
|
585
|
+
const foo2WriteReply = await dwn.processMessage(alice.did, foo2Write.message, { dataStream: foo2Write.dataStream });
|
|
599
586
|
expect(foo2WriteReply.status.code).toBe(202);
|
|
600
587
|
// with createdAscending sort, the oldest record should be returned
|
|
601
|
-
const fooPathRead =
|
|
588
|
+
const fooPathRead = await RecordsRead.create({
|
|
602
589
|
filter: {
|
|
603
590
|
protocol: protocolDefinition.protocol,
|
|
604
591
|
protocolPath: 'foo',
|
|
@@ -606,20 +593,20 @@ export function testRecordsReadHandler() {
|
|
|
606
593
|
dateSort: DateSort.CreatedAscending,
|
|
607
594
|
signer: Jws.createSigner(alice),
|
|
608
595
|
});
|
|
609
|
-
const fooPathReply =
|
|
596
|
+
const fooPathReply = await dwn.processMessage(alice.did, fooPathRead.message);
|
|
610
597
|
expect(fooPathReply.status.code).toBe(200);
|
|
611
598
|
expect(fooPathReply.entry.recordsWrite.recordId).toBe(foo1Write.message.recordId);
|
|
612
|
-
})
|
|
613
|
-
it('should return the newest record when `dateSort` is `CreatedDescending` and filter matches multiple results', () =>
|
|
614
|
-
const alice =
|
|
615
|
-
const protocolDefinition =
|
|
616
|
-
const protocolsConfig =
|
|
599
|
+
});
|
|
600
|
+
it('should return the newest record when `dateSort` is `CreatedDescending` and filter matches multiple results', async () => {
|
|
601
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
602
|
+
const protocolDefinition = { ...nestedProtocol };
|
|
603
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
617
604
|
author: alice,
|
|
618
605
|
protocolDefinition
|
|
619
606
|
});
|
|
620
|
-
const protocolConfigReply =
|
|
607
|
+
const protocolConfigReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
621
608
|
expect(protocolConfigReply.status.code).toBe(202);
|
|
622
|
-
const foo1Write =
|
|
609
|
+
const foo1Write = await TestDataGenerator.generateRecordsWrite({
|
|
623
610
|
author: alice,
|
|
624
611
|
protocol: protocolDefinition.protocol,
|
|
625
612
|
protocolPath: 'foo',
|
|
@@ -628,10 +615,10 @@ export function testRecordsReadHandler() {
|
|
|
628
615
|
data: new TextEncoder().encode('foo1'),
|
|
629
616
|
recipient: alice.did
|
|
630
617
|
});
|
|
631
|
-
const foo1WriteReply =
|
|
618
|
+
const foo1WriteReply = await dwn.processMessage(alice.did, foo1Write.message, { dataStream: foo1Write.dataStream });
|
|
632
619
|
expect(foo1WriteReply.status.code).toBe(202);
|
|
633
|
-
|
|
634
|
-
const foo2Write =
|
|
620
|
+
await Time.minimalSleep();
|
|
621
|
+
const foo2Write = await TestDataGenerator.generateRecordsWrite({
|
|
635
622
|
author: alice,
|
|
636
623
|
protocol: protocolDefinition.protocol,
|
|
637
624
|
protocolPath: 'foo',
|
|
@@ -640,9 +627,9 @@ export function testRecordsReadHandler() {
|
|
|
640
627
|
data: new TextEncoder().encode('foo2'),
|
|
641
628
|
recipient: alice.did
|
|
642
629
|
});
|
|
643
|
-
const foo2WriteReply =
|
|
630
|
+
const foo2WriteReply = await dwn.processMessage(alice.did, foo2Write.message, { dataStream: foo2Write.dataStream });
|
|
644
631
|
expect(foo2WriteReply.status.code).toBe(202);
|
|
645
|
-
const fooPathRead =
|
|
632
|
+
const fooPathRead = await RecordsRead.create({
|
|
646
633
|
filter: {
|
|
647
634
|
protocol: protocolDefinition.protocol,
|
|
648
635
|
protocolPath: 'foo',
|
|
@@ -650,20 +637,20 @@ export function testRecordsReadHandler() {
|
|
|
650
637
|
dateSort: DateSort.CreatedDescending,
|
|
651
638
|
signer: Jws.createSigner(alice),
|
|
652
639
|
});
|
|
653
|
-
const fooPathReply =
|
|
640
|
+
const fooPathReply = await dwn.processMessage(alice.did, fooPathRead.message);
|
|
654
641
|
expect(fooPathReply.status.code).toBe(200);
|
|
655
642
|
expect(fooPathReply.entry.recordsWrite.recordId).toBe(foo2Write.message.recordId);
|
|
656
|
-
})
|
|
657
|
-
it('should return the oldest updated record when `dateSort` is `UpdatedAscending`', () =>
|
|
658
|
-
const alice =
|
|
659
|
-
const protocolDefinition =
|
|
660
|
-
const protocolsConfig =
|
|
643
|
+
});
|
|
644
|
+
it('should return the oldest updated record when `dateSort` is `UpdatedAscending`', async () => {
|
|
645
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
646
|
+
const protocolDefinition = { ...nestedProtocol };
|
|
647
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
661
648
|
author: alice,
|
|
662
649
|
protocolDefinition
|
|
663
650
|
});
|
|
664
|
-
const protocolConfigReply =
|
|
651
|
+
const protocolConfigReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
665
652
|
expect(protocolConfigReply.status.code).toBe(202);
|
|
666
|
-
const foo1Write =
|
|
653
|
+
const foo1Write = await TestDataGenerator.generateRecordsWrite({
|
|
667
654
|
author: alice,
|
|
668
655
|
protocol: protocolDefinition.protocol,
|
|
669
656
|
protocolPath: 'foo',
|
|
@@ -672,10 +659,10 @@ export function testRecordsReadHandler() {
|
|
|
672
659
|
data: new TextEncoder().encode('foo1'),
|
|
673
660
|
recipient: alice.did
|
|
674
661
|
});
|
|
675
|
-
const foo1WriteReply =
|
|
662
|
+
const foo1WriteReply = await dwn.processMessage(alice.did, foo1Write.message, { dataStream: foo1Write.dataStream });
|
|
676
663
|
expect(foo1WriteReply.status.code).toBe(202);
|
|
677
|
-
|
|
678
|
-
const foo2Write =
|
|
664
|
+
await Time.minimalSleep();
|
|
665
|
+
const foo2Write = await TestDataGenerator.generateRecordsWrite({
|
|
679
666
|
author: alice,
|
|
680
667
|
protocol: protocolDefinition.protocol,
|
|
681
668
|
protocolPath: 'foo',
|
|
@@ -684,9 +671,9 @@ export function testRecordsReadHandler() {
|
|
|
684
671
|
data: new TextEncoder().encode('foo2'),
|
|
685
672
|
recipient: alice.did
|
|
686
673
|
});
|
|
687
|
-
const foo2WriteReply =
|
|
674
|
+
const foo2WriteReply = await dwn.processMessage(alice.did, foo2Write.message, { dataStream: foo2Write.dataStream });
|
|
688
675
|
expect(foo2WriteReply.status.code).toBe(202);
|
|
689
|
-
const fooPathRead =
|
|
676
|
+
const fooPathRead = await RecordsRead.create({
|
|
690
677
|
filter: {
|
|
691
678
|
protocol: protocolDefinition.protocol,
|
|
692
679
|
protocolPath: 'foo',
|
|
@@ -694,20 +681,20 @@ export function testRecordsReadHandler() {
|
|
|
694
681
|
dateSort: DateSort.UpdatedAscending,
|
|
695
682
|
signer: Jws.createSigner(alice),
|
|
696
683
|
});
|
|
697
|
-
const fooPathReply =
|
|
684
|
+
const fooPathReply = await dwn.processMessage(alice.did, fooPathRead.message);
|
|
698
685
|
expect(fooPathReply.status.code).toBe(200);
|
|
699
686
|
expect(fooPathReply.entry.recordsWrite.recordId).toBe(foo1Write.message.recordId);
|
|
700
|
-
})
|
|
701
|
-
it('should return the most recently updated record when `dateSort` is `UpdatedDescending`', () =>
|
|
702
|
-
const alice =
|
|
703
|
-
const protocolDefinition =
|
|
704
|
-
const protocolsConfig =
|
|
687
|
+
});
|
|
688
|
+
it('should return the most recently updated record when `dateSort` is `UpdatedDescending`', async () => {
|
|
689
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
690
|
+
const protocolDefinition = { ...nestedProtocol };
|
|
691
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
705
692
|
author: alice,
|
|
706
693
|
protocolDefinition
|
|
707
694
|
});
|
|
708
|
-
const protocolConfigReply =
|
|
695
|
+
const protocolConfigReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
709
696
|
expect(protocolConfigReply.status.code).toBe(202);
|
|
710
|
-
const foo1Write =
|
|
697
|
+
const foo1Write = await TestDataGenerator.generateRecordsWrite({
|
|
711
698
|
author: alice,
|
|
712
699
|
protocol: protocolDefinition.protocol,
|
|
713
700
|
protocolPath: 'foo',
|
|
@@ -716,10 +703,10 @@ export function testRecordsReadHandler() {
|
|
|
716
703
|
data: new TextEncoder().encode('foo1'),
|
|
717
704
|
recipient: alice.did
|
|
718
705
|
});
|
|
719
|
-
const foo1WriteReply =
|
|
706
|
+
const foo1WriteReply = await dwn.processMessage(alice.did, foo1Write.message, { dataStream: foo1Write.dataStream });
|
|
720
707
|
expect(foo1WriteReply.status.code).toBe(202);
|
|
721
|
-
|
|
722
|
-
const foo2Write =
|
|
708
|
+
await Time.minimalSleep();
|
|
709
|
+
const foo2Write = await TestDataGenerator.generateRecordsWrite({
|
|
723
710
|
author: alice,
|
|
724
711
|
protocol: protocolDefinition.protocol,
|
|
725
712
|
protocolPath: 'foo',
|
|
@@ -728,9 +715,9 @@ export function testRecordsReadHandler() {
|
|
|
728
715
|
data: new TextEncoder().encode('foo2'),
|
|
729
716
|
recipient: alice.did
|
|
730
717
|
});
|
|
731
|
-
const foo2WriteReply =
|
|
718
|
+
const foo2WriteReply = await dwn.processMessage(alice.did, foo2Write.message, { dataStream: foo2Write.dataStream });
|
|
732
719
|
expect(foo2WriteReply.status.code).toBe(202);
|
|
733
|
-
const fooPathRead =
|
|
720
|
+
const fooPathRead = await RecordsRead.create({
|
|
734
721
|
filter: {
|
|
735
722
|
protocol: protocolDefinition.protocol,
|
|
736
723
|
protocolPath: 'foo',
|
|
@@ -738,219 +725,219 @@ export function testRecordsReadHandler() {
|
|
|
738
725
|
dateSort: DateSort.UpdatedDescending,
|
|
739
726
|
signer: Jws.createSigner(alice),
|
|
740
727
|
});
|
|
741
|
-
const fooPathReply =
|
|
728
|
+
const fooPathReply = await dwn.processMessage(alice.did, fooPathRead.message);
|
|
742
729
|
expect(fooPathReply.status.code).toBe(200);
|
|
743
730
|
expect(fooPathReply.entry.recordsWrite.recordId).toBe(foo2Write.message.recordId);
|
|
744
|
-
})
|
|
745
|
-
it('should return the earliest published record when `dateSort` is `PublishedAscending`', () =>
|
|
746
|
-
const alice =
|
|
731
|
+
});
|
|
732
|
+
it('should return the earliest published record when `dateSort` is `PublishedAscending`', async () => {
|
|
733
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
747
734
|
const schema = 'aSchema';
|
|
748
|
-
const write1 =
|
|
735
|
+
const write1 = await TestDataGenerator.generateRecordsWrite({
|
|
749
736
|
author: alice,
|
|
750
737
|
schema,
|
|
751
738
|
published: true,
|
|
752
739
|
});
|
|
753
|
-
const write1Reply =
|
|
740
|
+
const write1Reply = await dwn.processMessage(alice.did, write1.message, { dataStream: write1.dataStream });
|
|
754
741
|
expect(write1Reply.status.code).toBe(202);
|
|
755
|
-
|
|
756
|
-
const write2 =
|
|
742
|
+
await Time.minimalSleep();
|
|
743
|
+
const write2 = await TestDataGenerator.generateRecordsWrite({
|
|
757
744
|
author: alice,
|
|
758
745
|
schema,
|
|
759
746
|
published: true,
|
|
760
747
|
});
|
|
761
|
-
const write2Reply =
|
|
748
|
+
const write2Reply = await dwn.processMessage(alice.did, write2.message, { dataStream: write2.dataStream });
|
|
762
749
|
expect(write2Reply.status.code).toBe(202);
|
|
763
|
-
const read =
|
|
750
|
+
const read = await RecordsRead.create({
|
|
764
751
|
filter: { schema },
|
|
765
752
|
dateSort: DateSort.PublishedAscending,
|
|
766
753
|
signer: Jws.createSigner(alice),
|
|
767
754
|
});
|
|
768
|
-
const readReply =
|
|
755
|
+
const readReply = await dwn.processMessage(alice.did, read.message);
|
|
769
756
|
expect(readReply.status.code).toBe(200);
|
|
770
757
|
expect(readReply.entry.recordsWrite.recordId).toBe(write1.message.recordId);
|
|
771
|
-
})
|
|
772
|
-
it('should return the latest published record when `dateSort` is `PublishedDescending`', () =>
|
|
773
|
-
const alice =
|
|
758
|
+
});
|
|
759
|
+
it('should return the latest published record when `dateSort` is `PublishedDescending`', async () => {
|
|
760
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
774
761
|
const schema = 'aSchema';
|
|
775
|
-
const write1 =
|
|
762
|
+
const write1 = await TestDataGenerator.generateRecordsWrite({
|
|
776
763
|
author: alice,
|
|
777
764
|
schema,
|
|
778
765
|
published: true,
|
|
779
766
|
});
|
|
780
|
-
const write1Reply =
|
|
767
|
+
const write1Reply = await dwn.processMessage(alice.did, write1.message, { dataStream: write1.dataStream });
|
|
781
768
|
expect(write1Reply.status.code).toBe(202);
|
|
782
|
-
|
|
783
|
-
const write2 =
|
|
769
|
+
await Time.minimalSleep();
|
|
770
|
+
const write2 = await TestDataGenerator.generateRecordsWrite({
|
|
784
771
|
author: alice,
|
|
785
772
|
schema,
|
|
786
773
|
published: true,
|
|
787
774
|
});
|
|
788
|
-
const write2Reply =
|
|
775
|
+
const write2Reply = await dwn.processMessage(alice.did, write2.message, { dataStream: write2.dataStream });
|
|
789
776
|
expect(write2Reply.status.code).toBe(202);
|
|
790
|
-
const read =
|
|
777
|
+
const read = await RecordsRead.create({
|
|
791
778
|
filter: { schema },
|
|
792
779
|
dateSort: DateSort.PublishedDescending,
|
|
793
780
|
signer: Jws.createSigner(alice),
|
|
794
781
|
});
|
|
795
|
-
const readReply =
|
|
782
|
+
const readReply = await dwn.processMessage(alice.did, read.message);
|
|
796
783
|
expect(readReply.status.code).toBe(200);
|
|
797
784
|
expect(readReply.entry.recordsWrite.recordId).toBe(write2.message.recordId);
|
|
798
|
-
})
|
|
785
|
+
});
|
|
799
786
|
});
|
|
800
787
|
describe('protocolRole based reads', () => {
|
|
801
|
-
it('uses a root-level role to authorize a read', () =>
|
|
788
|
+
it('uses a root-level role to authorize a read', async () => {
|
|
802
789
|
// scenario: Alice writes a chat message writes a chat message. Bob invokes his
|
|
803
790
|
// friend role in order to read the chat message.
|
|
804
|
-
const alice =
|
|
805
|
-
const bob =
|
|
791
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
792
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
806
793
|
const protocolDefinition = friendRoleProtocolDefinition;
|
|
807
|
-
const protocolsConfig =
|
|
794
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
808
795
|
author: alice,
|
|
809
796
|
protocolDefinition
|
|
810
797
|
});
|
|
811
|
-
const protocolsConfigureReply =
|
|
798
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
812
799
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
813
800
|
// Alice writes a 'friend' root-level role record with Bob as recipient
|
|
814
|
-
const friendRoleRecord =
|
|
801
|
+
const friendRoleRecord = await TestDataGenerator.generateRecordsWrite({
|
|
815
802
|
author: alice,
|
|
816
803
|
recipient: bob.did,
|
|
817
804
|
protocol: protocolDefinition.protocol,
|
|
818
805
|
protocolPath: 'friend',
|
|
819
806
|
data: new TextEncoder().encode('Bob is my friend'),
|
|
820
807
|
});
|
|
821
|
-
const friendRoleReply =
|
|
808
|
+
const friendRoleReply = await dwn.processMessage(alice.did, friendRoleRecord.message, { dataStream: friendRoleRecord.dataStream });
|
|
822
809
|
expect(friendRoleReply.status.code).toBe(202);
|
|
823
810
|
// Alice writes a 'chat' record
|
|
824
|
-
const chatRecord =
|
|
811
|
+
const chatRecord = await TestDataGenerator.generateRecordsWrite({
|
|
825
812
|
author: alice,
|
|
826
813
|
recipient: alice.did,
|
|
827
814
|
protocol: protocolDefinition.protocol,
|
|
828
815
|
protocolPath: 'chat',
|
|
829
816
|
data: new TextEncoder().encode('Bob can read this cuz he is my friend'),
|
|
830
817
|
});
|
|
831
|
-
const chatReply =
|
|
818
|
+
const chatReply = await dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
832
819
|
expect(chatReply.status.code).toBe(202);
|
|
833
820
|
// Bob reads Alice's chat record
|
|
834
|
-
const readChatRecord =
|
|
821
|
+
const readChatRecord = await RecordsRead.create({
|
|
835
822
|
signer: Jws.createSigner(bob),
|
|
836
823
|
filter: {
|
|
837
824
|
recordId: chatRecord.message.recordId,
|
|
838
825
|
},
|
|
839
826
|
protocolRole: 'friend'
|
|
840
827
|
});
|
|
841
|
-
const chatReadReply =
|
|
828
|
+
const chatReadReply = await dwn.processMessage(alice.did, readChatRecord.message);
|
|
842
829
|
expect(chatReadReply.status.code).toBe(200);
|
|
843
|
-
})
|
|
844
|
-
it('rejects root-level role authorized reads if the protocolRole is not a valid protocol path to an active role record', () =>
|
|
830
|
+
});
|
|
831
|
+
it('rejects root-level role authorized reads if the protocolRole is not a valid protocol path to an active role record', async () => {
|
|
845
832
|
// scenario: Alice writes a chat message writes a chat message. Bob tries to invoke the 'chat' role,
|
|
846
833
|
// but 'chat' is not a role.
|
|
847
|
-
const alice =
|
|
848
|
-
const bob =
|
|
834
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
835
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
849
836
|
const protocolDefinition = friendRoleProtocolDefinition;
|
|
850
|
-
const protocolsConfig =
|
|
837
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
851
838
|
author: alice,
|
|
852
839
|
protocolDefinition
|
|
853
840
|
});
|
|
854
|
-
const protocolsConfigureReply =
|
|
841
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
855
842
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
856
843
|
// Alice writes a 'chat' record
|
|
857
|
-
const chatRecord =
|
|
844
|
+
const chatRecord = await TestDataGenerator.generateRecordsWrite({
|
|
858
845
|
author: alice,
|
|
859
846
|
recipient: alice.did,
|
|
860
847
|
protocol: protocolDefinition.protocol,
|
|
861
848
|
protocolPath: 'chat',
|
|
862
849
|
data: new TextEncoder().encode('Blah blah blah'),
|
|
863
850
|
});
|
|
864
|
-
const chatReply =
|
|
851
|
+
const chatReply = await dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
865
852
|
expect(chatReply.status.code).toBe(202);
|
|
866
853
|
// Bob tries to invoke a 'chat' role but 'chat' is not a role
|
|
867
|
-
const readChatRecord =
|
|
854
|
+
const readChatRecord = await RecordsRead.create({
|
|
868
855
|
signer: Jws.createSigner(bob),
|
|
869
856
|
filter: {
|
|
870
857
|
recordId: chatRecord.message.recordId,
|
|
871
858
|
},
|
|
872
859
|
protocolRole: 'chat'
|
|
873
860
|
});
|
|
874
|
-
const chatReadReply =
|
|
861
|
+
const chatReadReply = await dwn.processMessage(alice.did, readChatRecord.message);
|
|
875
862
|
expect(chatReadReply.status.code).toBe(401);
|
|
876
863
|
expect(chatReadReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationNotARole);
|
|
877
|
-
})
|
|
878
|
-
it('rejects root-level role authorized reads if there is no active role for the recipient', () =>
|
|
864
|
+
});
|
|
865
|
+
it('rejects root-level role authorized reads if there is no active role for the recipient', async () => {
|
|
879
866
|
// scenario: Alice writes a chat message writes a chat message. Bob tries to invoke a role,
|
|
880
867
|
// but he has not been given one.
|
|
881
|
-
const alice =
|
|
882
|
-
const bob =
|
|
868
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
869
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
883
870
|
const protocolDefinition = friendRoleProtocolDefinition;
|
|
884
|
-
const protocolsConfig =
|
|
871
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
885
872
|
author: alice,
|
|
886
873
|
protocolDefinition
|
|
887
874
|
});
|
|
888
|
-
const protocolsConfigureReply =
|
|
875
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
889
876
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
890
877
|
// Alice writes a 'chat' record
|
|
891
|
-
const chatRecord =
|
|
878
|
+
const chatRecord = await TestDataGenerator.generateRecordsWrite({
|
|
892
879
|
author: alice,
|
|
893
880
|
recipient: alice.did,
|
|
894
881
|
protocol: protocolDefinition.protocol,
|
|
895
882
|
protocolPath: 'chat',
|
|
896
883
|
data: new TextEncoder().encode('Blah blah blah'),
|
|
897
884
|
});
|
|
898
|
-
const chatReply =
|
|
885
|
+
const chatReply = await dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
899
886
|
expect(chatReply.status.code).toBe(202);
|
|
900
887
|
// Bob tries to invoke a 'friend' role but he is not a 'friend'
|
|
901
|
-
const readChatRecord =
|
|
888
|
+
const readChatRecord = await RecordsRead.create({
|
|
902
889
|
signer: Jws.createSigner(bob),
|
|
903
890
|
filter: {
|
|
904
891
|
recordId: chatRecord.message.recordId,
|
|
905
892
|
},
|
|
906
893
|
protocolRole: 'friend',
|
|
907
894
|
});
|
|
908
|
-
const chatReadReply =
|
|
895
|
+
const chatReadReply = await dwn.processMessage(alice.did, readChatRecord.message);
|
|
909
896
|
expect(chatReadReply.status.code).toBe(401);
|
|
910
897
|
expect(chatReadReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound);
|
|
911
|
-
})
|
|
912
|
-
it('can authorize a read using a context role', () =>
|
|
898
|
+
});
|
|
899
|
+
it('can authorize a read using a context role', async () => {
|
|
913
900
|
// scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Alice writes a chat message.
|
|
914
901
|
// Bob invokes the record to read in the chat message.
|
|
915
|
-
const alice =
|
|
916
|
-
const bob =
|
|
902
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
903
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
917
904
|
const protocolDefinition = threadRoleProtocolDefinition;
|
|
918
|
-
const protocolsConfig =
|
|
905
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
919
906
|
author: alice,
|
|
920
907
|
protocolDefinition
|
|
921
908
|
});
|
|
922
|
-
const protocolsConfigureReply =
|
|
909
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
923
910
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
924
911
|
// Alice creates a thread
|
|
925
|
-
const threadRecord =
|
|
912
|
+
const threadRecord = await TestDataGenerator.generateRecordsWrite({
|
|
926
913
|
author: alice,
|
|
927
914
|
protocol: protocolDefinition.protocol,
|
|
928
915
|
protocolPath: 'thread'
|
|
929
916
|
});
|
|
930
|
-
const threadRecordReply =
|
|
917
|
+
const threadRecordReply = await dwn.processMessage(alice.did, threadRecord.message, { dataStream: threadRecord.dataStream });
|
|
931
918
|
expect(threadRecordReply.status.code).toBe(202);
|
|
932
919
|
// Alice adds Bob as a 'thread/participant' in that thread
|
|
933
|
-
const participantRecord =
|
|
920
|
+
const participantRecord = await TestDataGenerator.generateRecordsWrite({
|
|
934
921
|
author: alice,
|
|
935
922
|
recipient: bob.did,
|
|
936
923
|
protocol: protocolDefinition.protocol,
|
|
937
924
|
protocolPath: 'thread/participant',
|
|
938
925
|
parentContextId: threadRecord.message.contextId,
|
|
939
926
|
});
|
|
940
|
-
const participantRecordReply =
|
|
927
|
+
const participantRecordReply = await dwn.processMessage(alice.did, participantRecord.message, { dataStream: participantRecord.dataStream });
|
|
941
928
|
expect(participantRecordReply.status.code).toBe(202);
|
|
942
929
|
// Alice writes a chat message in the thread
|
|
943
|
-
const chatRecord =
|
|
930
|
+
const chatRecord = await TestDataGenerator.generateRecordsWrite({
|
|
944
931
|
author: alice,
|
|
945
932
|
protocol: protocolDefinition.protocol,
|
|
946
933
|
protocolPath: 'thread/chat',
|
|
947
934
|
parentContextId: threadRecord.message.contextId,
|
|
948
935
|
});
|
|
949
|
-
const chatRecordReply =
|
|
936
|
+
const chatRecordReply = await dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
950
937
|
expect(chatRecordReply.status.code).toBe(202);
|
|
951
938
|
// Bob is able to read his own 'participant' role
|
|
952
939
|
// He doesn't need to invoke the role because recipients of a record are always authorized to read it
|
|
953
|
-
const participantRead =
|
|
940
|
+
const participantRead = await RecordsRead.create({
|
|
954
941
|
signer: Jws.createSigner(bob),
|
|
955
942
|
filter: {
|
|
956
943
|
protocolPath: 'thread/participant',
|
|
@@ -958,105 +945,105 @@ export function testRecordsReadHandler() {
|
|
|
958
945
|
contextId: threadRecord.message.contextId
|
|
959
946
|
},
|
|
960
947
|
});
|
|
961
|
-
const participantReadReply =
|
|
948
|
+
const participantReadReply = await dwn.processMessage(alice.did, participantRead.message);
|
|
962
949
|
expect(participantReadReply.status.code).toBe(200);
|
|
963
950
|
// Bob is able to read the thread root record
|
|
964
|
-
const threadRead =
|
|
951
|
+
const threadRead = await RecordsRead.create({
|
|
965
952
|
signer: Jws.createSigner(bob),
|
|
966
953
|
filter: {
|
|
967
954
|
recordId: participantReadReply.entry.recordsWrite.descriptor.parentId,
|
|
968
955
|
},
|
|
969
956
|
protocolRole: 'thread/participant'
|
|
970
957
|
});
|
|
971
|
-
const threadReadReply =
|
|
958
|
+
const threadReadReply = await dwn.processMessage(alice.did, threadRead.message);
|
|
972
959
|
expect(threadReadReply.status.code).toBe(200);
|
|
973
960
|
// Bob invokes his 'participant' role to read the chat message
|
|
974
|
-
const chatRead =
|
|
961
|
+
const chatRead = await RecordsRead.create({
|
|
975
962
|
signer: Jws.createSigner(bob),
|
|
976
963
|
filter: {
|
|
977
964
|
recordId: chatRecord.message.recordId,
|
|
978
965
|
},
|
|
979
966
|
protocolRole: 'thread/participant'
|
|
980
967
|
});
|
|
981
|
-
const chatReadReply =
|
|
968
|
+
const chatReadReply = await dwn.processMessage(alice.did, chatRead.message);
|
|
982
969
|
expect(chatReadReply.status.code).toBe(200);
|
|
983
|
-
})
|
|
984
|
-
it('should not allow context role to be invoked against a wrong context', () =>
|
|
970
|
+
});
|
|
971
|
+
it('should not allow context role to be invoked against a wrong context', async () => {
|
|
985
972
|
// scenario: Alice creates a thread and adds Bob as a participant. Alice creates another thread. Bob tries and fails to invoke his
|
|
986
973
|
// context role to write a chat in the second thread
|
|
987
|
-
const alice =
|
|
988
|
-
const bob =
|
|
974
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
975
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
989
976
|
const protocolDefinition = threadRoleProtocolDefinition;
|
|
990
|
-
const protocolsConfig =
|
|
977
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
991
978
|
author: alice,
|
|
992
979
|
protocolDefinition
|
|
993
980
|
});
|
|
994
|
-
const protocolsConfigureReply =
|
|
981
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
995
982
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
996
983
|
// Alice creates a thread
|
|
997
|
-
const threadRecord1 =
|
|
984
|
+
const threadRecord1 = await TestDataGenerator.generateRecordsWrite({
|
|
998
985
|
author: alice,
|
|
999
986
|
recipient: bob.did,
|
|
1000
987
|
protocol: protocolDefinition.protocol,
|
|
1001
988
|
protocolPath: 'thread'
|
|
1002
989
|
});
|
|
1003
|
-
const threadRecordReply1 =
|
|
990
|
+
const threadRecordReply1 = await dwn.processMessage(alice.did, threadRecord1.message, { dataStream: threadRecord1.dataStream });
|
|
1004
991
|
expect(threadRecordReply1.status.code).toBe(202);
|
|
1005
992
|
// Alice adds Bob as a 'thread/participant' in that thread
|
|
1006
|
-
const participantRecord =
|
|
993
|
+
const participantRecord = await TestDataGenerator.generateRecordsWrite({
|
|
1007
994
|
author: alice,
|
|
1008
995
|
recipient: bob.did,
|
|
1009
996
|
protocol: protocolDefinition.protocol,
|
|
1010
997
|
protocolPath: 'thread/participant',
|
|
1011
998
|
parentContextId: threadRecord1.message.contextId,
|
|
1012
999
|
});
|
|
1013
|
-
const participantRecordReply =
|
|
1000
|
+
const participantRecordReply = await dwn.processMessage(alice.did, participantRecord.message, { dataStream: participantRecord.dataStream });
|
|
1014
1001
|
expect(participantRecordReply.status.code).toBe(202);
|
|
1015
1002
|
// Alice creates a second thread
|
|
1016
|
-
const threadRecord2 =
|
|
1003
|
+
const threadRecord2 = await TestDataGenerator.generateRecordsWrite({
|
|
1017
1004
|
author: alice,
|
|
1018
1005
|
recipient: bob.did,
|
|
1019
1006
|
protocol: protocolDefinition.protocol,
|
|
1020
1007
|
protocolPath: 'thread'
|
|
1021
1008
|
});
|
|
1022
|
-
const threadRecordReply2 =
|
|
1009
|
+
const threadRecordReply2 = await dwn.processMessage(alice.did, threadRecord2.message, { dataStream: threadRecord2.dataStream });
|
|
1023
1010
|
expect(threadRecordReply2.status.code).toBe(202);
|
|
1024
1011
|
// Alice writes a chat message in the thread
|
|
1025
|
-
const chatRecord =
|
|
1012
|
+
const chatRecord = await TestDataGenerator.generateRecordsWrite({
|
|
1026
1013
|
author: alice,
|
|
1027
1014
|
protocol: protocolDefinition.protocol,
|
|
1028
1015
|
protocolPath: 'thread/chat',
|
|
1029
1016
|
parentContextId: threadRecord2.message.contextId,
|
|
1030
1017
|
});
|
|
1031
|
-
const chatRecordReply =
|
|
1018
|
+
const chatRecordReply = await dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
1032
1019
|
expect(chatRecordReply.status.code).toBe(202);
|
|
1033
1020
|
// Bob invokes his 'participant' role to read the chat message
|
|
1034
|
-
const chatRead =
|
|
1021
|
+
const chatRead = await RecordsRead.create({
|
|
1035
1022
|
signer: Jws.createSigner(bob),
|
|
1036
1023
|
filter: {
|
|
1037
1024
|
recordId: chatRecord.message.recordId,
|
|
1038
1025
|
},
|
|
1039
1026
|
protocolRole: 'thread/participant'
|
|
1040
1027
|
});
|
|
1041
|
-
const chatReadReply =
|
|
1028
|
+
const chatReadReply = await dwn.processMessage(alice.did, chatRead.message);
|
|
1042
1029
|
expect(chatReadReply.status.code).toBe(401);
|
|
1043
1030
|
expect(chatReadReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound);
|
|
1044
|
-
})
|
|
1031
|
+
});
|
|
1045
1032
|
});
|
|
1046
1033
|
});
|
|
1047
1034
|
describe('grant based reads', () => {
|
|
1048
|
-
it('rejects with 401 an external party attempts to RecordReads if grant has different DWN method scope', () =>
|
|
1035
|
+
it('rejects with 401 an external party attempts to RecordReads if grant has different DWN method scope', async () => {
|
|
1049
1036
|
// scenario: Alice grants Bob access to RecordsWrite, then Bob tries to invoke the grant with RecordsRead
|
|
1050
|
-
const alice =
|
|
1051
|
-
const bob =
|
|
1037
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1038
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1052
1039
|
// Alice writes a record which Bob will later try to read
|
|
1053
|
-
const { recordsWrite, dataStream } =
|
|
1040
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1054
1041
|
author: alice,
|
|
1055
1042
|
});
|
|
1056
|
-
const recordsWriteReply =
|
|
1043
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1057
1044
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1058
1045
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1059
|
-
const permissionGrant =
|
|
1046
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1060
1047
|
signer: Jws.createSigner(alice),
|
|
1061
1048
|
grantedTo: bob.did,
|
|
1062
1049
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1067,44 +1054,44 @@ export function testRecordsReadHandler() {
|
|
|
1067
1054
|
}
|
|
1068
1055
|
});
|
|
1069
1056
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1070
|
-
const permissionGrantWriteReply =
|
|
1057
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1071
1058
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1072
1059
|
// Bob tries to RecordsRead
|
|
1073
|
-
const recordsRead =
|
|
1060
|
+
const recordsRead = await RecordsRead.create({
|
|
1074
1061
|
filter: {
|
|
1075
1062
|
recordId: recordsWrite.message.recordId,
|
|
1076
1063
|
},
|
|
1077
1064
|
signer: Jws.createSigner(bob),
|
|
1078
1065
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1079
1066
|
});
|
|
1080
|
-
const recordsReadReply =
|
|
1067
|
+
const recordsReadReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1081
1068
|
expect(recordsReadReply.status.code).toBe(401);
|
|
1082
1069
|
expect(recordsReadReply.status.detail).toContain(DwnErrorCode.GrantAuthorizationMethodMismatch);
|
|
1083
|
-
})
|
|
1070
|
+
});
|
|
1084
1071
|
describe('protocol records', () => {
|
|
1085
|
-
it('allows reads of protocol records with unrestricted grant scopes', () =>
|
|
1072
|
+
it('allows reads of protocol records with unrestricted grant scopes', async () => {
|
|
1086
1073
|
// scenario: Alice writes a protocol record. Alice gives Bob a grant to read all records in her DWN
|
|
1087
1074
|
// Bob invokes that grant to read the protocol record.
|
|
1088
|
-
const alice =
|
|
1089
|
-
const bob =
|
|
1075
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1076
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1090
1077
|
const protocolDefinition = minimalProtocolDefinition;
|
|
1091
1078
|
// Alice installs the protocol
|
|
1092
|
-
const protocolsConfig =
|
|
1079
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
1093
1080
|
author: alice,
|
|
1094
1081
|
protocolDefinition
|
|
1095
1082
|
});
|
|
1096
|
-
const protocolsConfigureReply =
|
|
1083
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
1097
1084
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1098
1085
|
// Alice writes a record which Bob will later try to read
|
|
1099
|
-
const { recordsWrite, dataStream } =
|
|
1086
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1100
1087
|
author: alice,
|
|
1101
1088
|
protocol: protocolDefinition.protocol,
|
|
1102
1089
|
protocolPath: 'foo',
|
|
1103
1090
|
});
|
|
1104
|
-
const recordsWriteReply =
|
|
1091
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1105
1092
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1106
1093
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1107
|
-
const permissionGrant =
|
|
1094
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1108
1095
|
signer: Jws.createSigner(alice),
|
|
1109
1096
|
grantedTo: bob.did,
|
|
1110
1097
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1115,52 +1102,52 @@ export function testRecordsReadHandler() {
|
|
|
1115
1102
|
}
|
|
1116
1103
|
});
|
|
1117
1104
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1118
|
-
const permissionGrantWriteReply =
|
|
1105
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1119
1106
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1120
1107
|
// Bob is unable to read the record without using the permission grant
|
|
1121
|
-
const recordsReadWithoutGrant =
|
|
1108
|
+
const recordsReadWithoutGrant = await RecordsRead.create({
|
|
1122
1109
|
filter: {
|
|
1123
1110
|
recordId: recordsWrite.message.recordId,
|
|
1124
1111
|
},
|
|
1125
1112
|
signer: Jws.createSigner(bob),
|
|
1126
1113
|
});
|
|
1127
|
-
const recordsReadWithoutGrantReply =
|
|
1114
|
+
const recordsReadWithoutGrantReply = await dwn.processMessage(alice.did, recordsReadWithoutGrant.message);
|
|
1128
1115
|
expect(recordsReadWithoutGrantReply.status.code).toBe(401);
|
|
1129
1116
|
expect(recordsReadWithoutGrantReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionRulesNotFound);
|
|
1130
1117
|
// Bob is able to read the record when he uses the permission grant
|
|
1131
|
-
const recordsReadWithGrant =
|
|
1118
|
+
const recordsReadWithGrant = await RecordsRead.create({
|
|
1132
1119
|
filter: {
|
|
1133
1120
|
recordId: recordsWrite.message.recordId,
|
|
1134
1121
|
},
|
|
1135
1122
|
signer: Jws.createSigner(bob),
|
|
1136
1123
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1137
1124
|
});
|
|
1138
|
-
const recordsReadWithGrantReply =
|
|
1125
|
+
const recordsReadWithGrantReply = await dwn.processMessage(alice.did, recordsReadWithGrant.message);
|
|
1139
1126
|
expect(recordsReadWithGrantReply.status.code).toBe(200);
|
|
1140
|
-
})
|
|
1141
|
-
it('allows reads of protocol records with matching protocol grant scopes', () =>
|
|
1127
|
+
});
|
|
1128
|
+
it('allows reads of protocol records with matching protocol grant scopes', async () => {
|
|
1142
1129
|
// scenario: Alice writes a protocol record. Alice gives Bob a grant to read all records in the protocol
|
|
1143
1130
|
// Bob invokes that grant to read the protocol record.
|
|
1144
|
-
const alice =
|
|
1145
|
-
const bob =
|
|
1131
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1132
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1146
1133
|
const protocolDefinition = minimalProtocolDefinition;
|
|
1147
1134
|
// Alice installs the protocol
|
|
1148
|
-
const protocolsConfig =
|
|
1135
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
1149
1136
|
author: alice,
|
|
1150
1137
|
protocolDefinition
|
|
1151
1138
|
});
|
|
1152
|
-
const protocolsConfigureReply =
|
|
1139
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
1153
1140
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1154
1141
|
// Alice writes a record which Bob will later try to read
|
|
1155
|
-
const { recordsWrite, dataStream } =
|
|
1142
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1156
1143
|
author: alice,
|
|
1157
1144
|
protocol: protocolDefinition.protocol,
|
|
1158
1145
|
protocolPath: 'foo',
|
|
1159
1146
|
});
|
|
1160
|
-
const recordsWriteReply =
|
|
1147
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1161
1148
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1162
1149
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1163
|
-
const permissionGrant =
|
|
1150
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1164
1151
|
signer: Jws.createSigner(alice),
|
|
1165
1152
|
grantedTo: bob.did,
|
|
1166
1153
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1171,52 +1158,52 @@ export function testRecordsReadHandler() {
|
|
|
1171
1158
|
}
|
|
1172
1159
|
});
|
|
1173
1160
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1174
|
-
const permissionGrantWriteReply =
|
|
1161
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1175
1162
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1176
1163
|
// Bob is unable to read the record without using the permission grant
|
|
1177
|
-
const recordsReadWithoutGrant =
|
|
1164
|
+
const recordsReadWithoutGrant = await RecordsRead.create({
|
|
1178
1165
|
filter: {
|
|
1179
1166
|
recordId: recordsWrite.message.recordId,
|
|
1180
1167
|
},
|
|
1181
1168
|
signer: Jws.createSigner(bob),
|
|
1182
1169
|
});
|
|
1183
|
-
const recordsReadWithoutGrantReply =
|
|
1170
|
+
const recordsReadWithoutGrantReply = await dwn.processMessage(alice.did, recordsReadWithoutGrant.message);
|
|
1184
1171
|
expect(recordsReadWithoutGrantReply.status.code).toBe(401);
|
|
1185
1172
|
expect(recordsReadWithoutGrantReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionRulesNotFound);
|
|
1186
1173
|
// Bob is able to read the record when he uses the permission grant
|
|
1187
|
-
const recordsReadWithGrant =
|
|
1174
|
+
const recordsReadWithGrant = await RecordsRead.create({
|
|
1188
1175
|
filter: {
|
|
1189
1176
|
recordId: recordsWrite.message.recordId,
|
|
1190
1177
|
},
|
|
1191
1178
|
signer: Jws.createSigner(bob),
|
|
1192
1179
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1193
1180
|
});
|
|
1194
|
-
const recordsReadWithGrantReply =
|
|
1181
|
+
const recordsReadWithGrantReply = await dwn.processMessage(alice.did, recordsReadWithGrant.message);
|
|
1195
1182
|
expect(recordsReadWithGrantReply.status.code).toBe(200);
|
|
1196
|
-
})
|
|
1197
|
-
it('rejects reads of protocol records with mismatching protocol grant scopes', () =>
|
|
1183
|
+
});
|
|
1184
|
+
it('rejects reads of protocol records with mismatching protocol grant scopes', async () => {
|
|
1198
1185
|
// scenario: Alice writes a protocol record. Alice gives Bob a grant to read a different protocol
|
|
1199
1186
|
// Bob invokes that grant to read the protocol record, but fails.
|
|
1200
|
-
const alice =
|
|
1201
|
-
const bob =
|
|
1187
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1188
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1202
1189
|
const protocolDefinition = minimalProtocolDefinition;
|
|
1203
1190
|
// Alice installs the protocol
|
|
1204
|
-
const protocolsConfig =
|
|
1191
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
1205
1192
|
author: alice,
|
|
1206
1193
|
protocolDefinition
|
|
1207
1194
|
});
|
|
1208
|
-
const protocolsConfigureReply =
|
|
1195
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
1209
1196
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1210
1197
|
// Alice writes a record which Bob will later try to read
|
|
1211
|
-
const { recordsWrite, dataStream } =
|
|
1198
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1212
1199
|
author: alice,
|
|
1213
1200
|
protocol: protocolDefinition.protocol,
|
|
1214
1201
|
protocolPath: 'foo',
|
|
1215
1202
|
});
|
|
1216
|
-
const recordsWriteReply =
|
|
1203
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1217
1204
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1218
1205
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1219
|
-
const permissionGrant =
|
|
1206
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1220
1207
|
signer: Jws.createSigner(alice),
|
|
1221
1208
|
grantedTo: bob.did,
|
|
1222
1209
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1227,43 +1214,43 @@ export function testRecordsReadHandler() {
|
|
|
1227
1214
|
}
|
|
1228
1215
|
});
|
|
1229
1216
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1230
|
-
const permissionGrantWriteReply =
|
|
1217
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1231
1218
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1232
1219
|
// Bob is unable to read the record using the mismatched permission grant
|
|
1233
|
-
const recordsReadWithoutGrant =
|
|
1220
|
+
const recordsReadWithoutGrant = await RecordsRead.create({
|
|
1234
1221
|
filter: {
|
|
1235
1222
|
recordId: recordsWrite.message.recordId,
|
|
1236
1223
|
},
|
|
1237
1224
|
signer: Jws.createSigner(bob),
|
|
1238
1225
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1239
1226
|
});
|
|
1240
|
-
const recordsReadWithoutGrantReply =
|
|
1227
|
+
const recordsReadWithoutGrantReply = await dwn.processMessage(alice.did, recordsReadWithoutGrant.message);
|
|
1241
1228
|
expect(recordsReadWithoutGrantReply.status.code).toBe(401);
|
|
1242
1229
|
expect(recordsReadWithoutGrantReply.status.detail).toContain(DwnErrorCode.RecordsGrantAuthorizationScopeProtocolMismatch);
|
|
1243
|
-
})
|
|
1244
|
-
it('allows reads of records in the contextId specified in the grant', () =>
|
|
1230
|
+
});
|
|
1231
|
+
it('allows reads of records in the contextId specified in the grant', async () => {
|
|
1245
1232
|
// scenario: Alice grants Bob access to RecordsRead records with a specific contextId.
|
|
1246
1233
|
// Bob uses it to read a record in that context.
|
|
1247
|
-
const alice =
|
|
1248
|
-
const bob =
|
|
1234
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1235
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1249
1236
|
const protocolDefinition = minimalProtocolDefinition;
|
|
1250
1237
|
// Alice installs the protocol
|
|
1251
|
-
const protocolsConfig =
|
|
1238
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
1252
1239
|
author: alice,
|
|
1253
1240
|
protocolDefinition
|
|
1254
1241
|
});
|
|
1255
|
-
const protocolsConfigureReply =
|
|
1242
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
1256
1243
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1257
1244
|
// Alice writes a record which Bob will later try to read
|
|
1258
|
-
const { recordsWrite, dataStream } =
|
|
1245
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1259
1246
|
author: alice,
|
|
1260
1247
|
protocol: protocolDefinition.protocol,
|
|
1261
1248
|
protocolPath: 'foo',
|
|
1262
1249
|
});
|
|
1263
|
-
const recordsWriteReply =
|
|
1250
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1264
1251
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1265
1252
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1266
|
-
const permissionGrant =
|
|
1253
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1267
1254
|
signer: Jws.createSigner(alice),
|
|
1268
1255
|
grantedTo: bob.did,
|
|
1269
1256
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1275,42 +1262,42 @@ export function testRecordsReadHandler() {
|
|
|
1275
1262
|
}
|
|
1276
1263
|
});
|
|
1277
1264
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1278
|
-
const permissionGrantWriteReply =
|
|
1265
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1279
1266
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1280
1267
|
// Bob is unable to read the record using the mismatched permission grant
|
|
1281
|
-
const recordsReadWithoutGrant =
|
|
1268
|
+
const recordsReadWithoutGrant = await RecordsRead.create({
|
|
1282
1269
|
filter: {
|
|
1283
1270
|
recordId: recordsWrite.message.recordId,
|
|
1284
1271
|
},
|
|
1285
1272
|
signer: Jws.createSigner(bob),
|
|
1286
1273
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1287
1274
|
});
|
|
1288
|
-
const recordsReadWithoutGrantReply =
|
|
1275
|
+
const recordsReadWithoutGrantReply = await dwn.processMessage(alice.did, recordsReadWithoutGrant.message);
|
|
1289
1276
|
expect(recordsReadWithoutGrantReply.status.code).toBe(200);
|
|
1290
|
-
})
|
|
1291
|
-
it('rejects reads of records in a different contextId than is specified in the grant', () =>
|
|
1277
|
+
});
|
|
1278
|
+
it('rejects reads of records in a different contextId than is specified in the grant', async () => {
|
|
1292
1279
|
// scenario: Alice grants Bob access to RecordsRead records with a specific contextId.
|
|
1293
1280
|
// Bob tries and fails to invoke the grant in order to read a record outside of the context.
|
|
1294
|
-
const alice =
|
|
1295
|
-
const bob =
|
|
1281
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1282
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1296
1283
|
const protocolDefinition = minimalProtocolDefinition;
|
|
1297
1284
|
// Alice installs the protocol
|
|
1298
|
-
const protocolsConfig =
|
|
1285
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
1299
1286
|
author: alice,
|
|
1300
1287
|
protocolDefinition
|
|
1301
1288
|
});
|
|
1302
|
-
const protocolsConfigureReply =
|
|
1289
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
1303
1290
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1304
1291
|
// Alice writes a record which Bob will later try to read
|
|
1305
|
-
const { recordsWrite, dataStream } =
|
|
1292
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1306
1293
|
author: alice,
|
|
1307
1294
|
protocol: protocolDefinition.protocol,
|
|
1308
1295
|
protocolPath: 'foo',
|
|
1309
1296
|
});
|
|
1310
|
-
const recordsWriteReply =
|
|
1297
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1311
1298
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1312
1299
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1313
|
-
const permissionGrant =
|
|
1300
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1314
1301
|
signer: Jws.createSigner(alice),
|
|
1315
1302
|
grantedTo: bob.did,
|
|
1316
1303
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1318,47 +1305,47 @@ export function testRecordsReadHandler() {
|
|
|
1318
1305
|
interface: DwnInterfaceName.Records,
|
|
1319
1306
|
method: DwnMethodName.Read,
|
|
1320
1307
|
protocol: protocolDefinition.protocol,
|
|
1321
|
-
contextId:
|
|
1308
|
+
contextId: await TestDataGenerator.randomCborSha256Cid(), // different contextId than what Bob will try to read
|
|
1322
1309
|
}
|
|
1323
1310
|
});
|
|
1324
1311
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1325
|
-
const permissionGrantWriteReply =
|
|
1312
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1326
1313
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1327
1314
|
// Bob is unable to read the record using the mismatched permission grant
|
|
1328
|
-
const recordsReadWithoutGrant =
|
|
1315
|
+
const recordsReadWithoutGrant = await RecordsRead.create({
|
|
1329
1316
|
filter: {
|
|
1330
1317
|
recordId: recordsWrite.message.recordId,
|
|
1331
1318
|
},
|
|
1332
1319
|
signer: Jws.createSigner(bob),
|
|
1333
1320
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1334
1321
|
});
|
|
1335
|
-
const recordsReadWithoutGrantReply =
|
|
1322
|
+
const recordsReadWithoutGrantReply = await dwn.processMessage(alice.did, recordsReadWithoutGrant.message);
|
|
1336
1323
|
expect(recordsReadWithoutGrantReply.status.code).toBe(401);
|
|
1337
1324
|
expect(recordsReadWithoutGrantReply.status.detail).toContain(DwnErrorCode.RecordsGrantAuthorizationScopeContextIdMismatch);
|
|
1338
|
-
})
|
|
1339
|
-
it('allows reads of records in the protocolPath specified in the grant', () =>
|
|
1325
|
+
});
|
|
1326
|
+
it('allows reads of records in the protocolPath specified in the grant', async () => {
|
|
1340
1327
|
// scenario: Alice grants Bob access to RecordsRead records with a specific protocolPath.
|
|
1341
1328
|
// Bob uses it to read a record in that protocolPath.
|
|
1342
|
-
const alice =
|
|
1343
|
-
const bob =
|
|
1329
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1330
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1344
1331
|
const protocolDefinition = minimalProtocolDefinition;
|
|
1345
1332
|
// Alice installs the protocol
|
|
1346
|
-
const protocolsConfig =
|
|
1333
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
1347
1334
|
author: alice,
|
|
1348
1335
|
protocolDefinition
|
|
1349
1336
|
});
|
|
1350
|
-
const protocolsConfigureReply =
|
|
1337
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
1351
1338
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1352
1339
|
// Alice writes a record which Bob will later try to read
|
|
1353
|
-
const { recordsWrite, dataStream } =
|
|
1340
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1354
1341
|
author: alice,
|
|
1355
1342
|
protocol: protocolDefinition.protocol,
|
|
1356
1343
|
protocolPath: 'foo',
|
|
1357
1344
|
});
|
|
1358
|
-
const recordsWriteReply =
|
|
1345
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1359
1346
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1360
1347
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1361
|
-
const permissionGrant =
|
|
1348
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1362
1349
|
signer: Jws.createSigner(alice),
|
|
1363
1350
|
grantedTo: bob.did,
|
|
1364
1351
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1370,42 +1357,42 @@ export function testRecordsReadHandler() {
|
|
|
1370
1357
|
}
|
|
1371
1358
|
});
|
|
1372
1359
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1373
|
-
const permissionGrantWriteReply =
|
|
1360
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1374
1361
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1375
1362
|
// Bob is unable to read the record using the mismatched permission grant
|
|
1376
|
-
const recordsReadWithoutGrant =
|
|
1363
|
+
const recordsReadWithoutGrant = await RecordsRead.create({
|
|
1377
1364
|
filter: {
|
|
1378
1365
|
recordId: recordsWrite.message.recordId,
|
|
1379
1366
|
},
|
|
1380
1367
|
signer: Jws.createSigner(bob),
|
|
1381
1368
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1382
1369
|
});
|
|
1383
|
-
const recordsReadWithoutGrantReply =
|
|
1370
|
+
const recordsReadWithoutGrantReply = await dwn.processMessage(alice.did, recordsReadWithoutGrant.message);
|
|
1384
1371
|
expect(recordsReadWithoutGrantReply.status.code).toBe(200);
|
|
1385
|
-
})
|
|
1386
|
-
it('rejects reads of records in a different protocolPath than is specified in the grant', () =>
|
|
1372
|
+
});
|
|
1373
|
+
it('rejects reads of records in a different protocolPath than is specified in the grant', async () => {
|
|
1387
1374
|
// scenario: Alice grants Bob access to RecordsRead records with a specific protocolPath.
|
|
1388
1375
|
// Bob tries and fails to invoke the grant in order to read a record outside of the protocolPath.
|
|
1389
|
-
const alice =
|
|
1390
|
-
const bob =
|
|
1376
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1377
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1391
1378
|
const protocolDefinition = minimalProtocolDefinition;
|
|
1392
1379
|
// Alice installs the protocol
|
|
1393
|
-
const protocolsConfig =
|
|
1380
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
1394
1381
|
author: alice,
|
|
1395
1382
|
protocolDefinition
|
|
1396
1383
|
});
|
|
1397
|
-
const protocolsConfigureReply =
|
|
1384
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
|
|
1398
1385
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1399
1386
|
// Alice writes a record which Bob will later try to read
|
|
1400
|
-
const { recordsWrite, dataStream } =
|
|
1387
|
+
const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1401
1388
|
author: alice,
|
|
1402
1389
|
protocol: protocolDefinition.protocol,
|
|
1403
1390
|
protocolPath: 'foo',
|
|
1404
1391
|
});
|
|
1405
|
-
const recordsWriteReply =
|
|
1392
|
+
const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1406
1393
|
expect(recordsWriteReply.status.code).toBe(202);
|
|
1407
1394
|
// Alice gives Bob a permission grant with scope RecordsRead
|
|
1408
|
-
const permissionGrant =
|
|
1395
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
1409
1396
|
signer: Jws.createSigner(alice),
|
|
1410
1397
|
grantedTo: bob.did,
|
|
1411
1398
|
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
|
|
@@ -1417,145 +1404,144 @@ export function testRecordsReadHandler() {
|
|
|
1417
1404
|
}
|
|
1418
1405
|
});
|
|
1419
1406
|
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
1420
|
-
const permissionGrantWriteReply =
|
|
1407
|
+
const permissionGrantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
1421
1408
|
expect(permissionGrantWriteReply.status.code).toBe(202);
|
|
1422
1409
|
// Bob is unable to read the record using the mismatched permission grant
|
|
1423
|
-
const recordsReadWithoutGrant =
|
|
1410
|
+
const recordsReadWithoutGrant = await RecordsRead.create({
|
|
1424
1411
|
filter: {
|
|
1425
1412
|
recordId: recordsWrite.message.recordId,
|
|
1426
1413
|
},
|
|
1427
1414
|
signer: Jws.createSigner(bob),
|
|
1428
1415
|
permissionGrantId: permissionGrant.recordsWrite.message.recordId,
|
|
1429
1416
|
});
|
|
1430
|
-
const recordsReadWithoutGrantReply =
|
|
1417
|
+
const recordsReadWithoutGrantReply = await dwn.processMessage(alice.did, recordsReadWithoutGrant.message);
|
|
1431
1418
|
expect(recordsReadWithoutGrantReply.status.code).toBe(401);
|
|
1432
1419
|
expect(recordsReadWithoutGrantReply.status.detail).toContain(DwnErrorCode.RecordsGrantAuthorizationScopeProtocolPathMismatch);
|
|
1433
|
-
})
|
|
1420
|
+
});
|
|
1434
1421
|
});
|
|
1435
1422
|
});
|
|
1436
|
-
it('should return 404 RecordRead if data does not exist', () =>
|
|
1437
|
-
const alice =
|
|
1438
|
-
const recordsRead =
|
|
1423
|
+
it('should return 404 RecordRead if data does not exist', async () => {
|
|
1424
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1425
|
+
const recordsRead = await RecordsRead.create({
|
|
1439
1426
|
filter: {
|
|
1440
1427
|
recordId: `non-existent-record-id`,
|
|
1441
1428
|
},
|
|
1442
1429
|
signer: Jws.createSigner(alice)
|
|
1443
1430
|
});
|
|
1444
|
-
const readReply =
|
|
1431
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1445
1432
|
expect(readReply.status.code).toBe(404);
|
|
1446
|
-
})
|
|
1447
|
-
it('should return 404 RecordRead if data has been deleted', () =>
|
|
1448
|
-
|
|
1449
|
-
const alice = yield TestDataGenerator.generateDidKeyPersona();
|
|
1433
|
+
});
|
|
1434
|
+
it('should return 404 RecordRead if data has been deleted', async () => {
|
|
1435
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1450
1436
|
// insert public data
|
|
1451
|
-
const { message, dataStream } =
|
|
1452
|
-
const writeReply =
|
|
1437
|
+
const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({ author: alice, published: true });
|
|
1438
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
1453
1439
|
expect(writeReply.status.code).toBe(202);
|
|
1454
1440
|
// ensure data is inserted
|
|
1455
|
-
const queryData =
|
|
1441
|
+
const queryData = await TestDataGenerator.generateRecordsQuery({
|
|
1456
1442
|
author: alice,
|
|
1457
1443
|
filter: { recordId: message.recordId }
|
|
1458
1444
|
});
|
|
1459
|
-
const reply =
|
|
1445
|
+
const reply = await dwn.processMessage(alice.did, queryData.message);
|
|
1460
1446
|
expect(reply.status.code).toBe(200);
|
|
1461
|
-
expect(
|
|
1447
|
+
expect(reply.entries?.length).toBe(1);
|
|
1462
1448
|
// RecordsDelete
|
|
1463
|
-
const recordsDelete =
|
|
1449
|
+
const recordsDelete = await RecordsDelete.create({
|
|
1464
1450
|
recordId: message.recordId,
|
|
1465
1451
|
signer: Jws.createSigner(alice)
|
|
1466
1452
|
});
|
|
1467
|
-
const deleteReply =
|
|
1453
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
1468
1454
|
expect(deleteReply.status.code).toBe(202);
|
|
1469
1455
|
// RecordsRead
|
|
1470
|
-
const recordsRead =
|
|
1456
|
+
const recordsRead = await RecordsRead.create({
|
|
1471
1457
|
filter: {
|
|
1472
1458
|
recordId: message.recordId,
|
|
1473
1459
|
},
|
|
1474
1460
|
signer: Jws.createSigner(alice)
|
|
1475
1461
|
});
|
|
1476
|
-
const readReply =
|
|
1462
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1477
1463
|
expect(readReply.status.code).toBe(404);
|
|
1478
|
-
})
|
|
1479
|
-
it('should return 404 underlying data store cannot locate the data when data is above threshold', () =>
|
|
1480
|
-
const alice =
|
|
1464
|
+
});
|
|
1465
|
+
it('should return 404 underlying data store cannot locate the data when data is above threshold', async () => {
|
|
1466
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1481
1467
|
sinon.stub(dataStore, 'get').resolves(undefined);
|
|
1482
1468
|
// insert data larger than the allowed amount in encodedData
|
|
1483
|
-
const { message, dataStream } =
|
|
1469
|
+
const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1484
1470
|
author: alice,
|
|
1485
1471
|
data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)
|
|
1486
1472
|
});
|
|
1487
|
-
const writeReply =
|
|
1473
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
1488
1474
|
expect(writeReply.status.code).toBe(202);
|
|
1489
1475
|
// testing RecordsRead
|
|
1490
|
-
const recordsRead =
|
|
1476
|
+
const recordsRead = await RecordsRead.create({
|
|
1491
1477
|
filter: {
|
|
1492
1478
|
recordId: message.recordId,
|
|
1493
1479
|
},
|
|
1494
1480
|
signer: Jws.createSigner(alice)
|
|
1495
1481
|
});
|
|
1496
|
-
const readReply =
|
|
1482
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1497
1483
|
expect(readReply.status.code).toBe(404);
|
|
1498
|
-
})
|
|
1484
|
+
});
|
|
1499
1485
|
describe('data from encodedData', () => {
|
|
1500
|
-
it('should not get data from DataStore if encodedData exists', () =>
|
|
1501
|
-
const alice =
|
|
1486
|
+
it('should not get data from DataStore if encodedData exists', async () => {
|
|
1487
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1502
1488
|
//since the data is at the threshold it will be returned from the messageStore in the `encodedData` field.
|
|
1503
|
-
const { message, dataStream, dataBytes } =
|
|
1489
|
+
const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({
|
|
1504
1490
|
author: alice,
|
|
1505
1491
|
data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded)
|
|
1506
1492
|
});
|
|
1507
|
-
const writeReply =
|
|
1493
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
1508
1494
|
expect(writeReply.status.code).toBe(202);
|
|
1509
|
-
const recordRead =
|
|
1495
|
+
const recordRead = await RecordsRead.create({
|
|
1510
1496
|
filter: {
|
|
1511
1497
|
recordId: message.recordId,
|
|
1512
1498
|
},
|
|
1513
1499
|
signer: Jws.createSigner(alice)
|
|
1514
1500
|
});
|
|
1515
1501
|
const dataStoreGet = sinon.spy(dataStore, 'get');
|
|
1516
|
-
const recordsReadResponse =
|
|
1502
|
+
const recordsReadResponse = await dwn.processMessage(alice.did, recordRead.message);
|
|
1517
1503
|
expect(recordsReadResponse.status.code).toBe(200);
|
|
1518
1504
|
expect(recordsReadResponse.entry.recordsWrite).toBeDefined();
|
|
1519
1505
|
expect(recordsReadResponse.entry.data).toBeDefined();
|
|
1520
1506
|
sinon.assert.notCalled(dataStoreGet);
|
|
1521
|
-
const readData =
|
|
1507
|
+
const readData = await DataStream.toBytes(recordsReadResponse.entry.data);
|
|
1522
1508
|
expect(readData).toEqual(dataBytes);
|
|
1523
|
-
})
|
|
1524
|
-
it('should get data from DataStore if encodedData does not exist', () =>
|
|
1525
|
-
const alice =
|
|
1509
|
+
});
|
|
1510
|
+
it('should get data from DataStore if encodedData does not exist', async () => {
|
|
1511
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1526
1512
|
//since the data is over the threshold it will not be returned from the messageStore in the `encodedData` field.
|
|
1527
|
-
const { message, dataStream, dataBytes } =
|
|
1513
|
+
const { message, dataStream, dataBytes } = await TestDataGenerator.generateRecordsWrite({
|
|
1528
1514
|
author: alice,
|
|
1529
1515
|
data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)
|
|
1530
1516
|
});
|
|
1531
|
-
const writeReply =
|
|
1517
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
1532
1518
|
expect(writeReply.status.code).toBe(202);
|
|
1533
|
-
const recordRead =
|
|
1519
|
+
const recordRead = await RecordsRead.create({
|
|
1534
1520
|
filter: {
|
|
1535
1521
|
recordId: message.recordId,
|
|
1536
1522
|
},
|
|
1537
1523
|
signer: Jws.createSigner(alice)
|
|
1538
1524
|
});
|
|
1539
1525
|
const dataStoreGet = sinon.spy(dataStore, 'get');
|
|
1540
|
-
const recordsReadResponse =
|
|
1526
|
+
const recordsReadResponse = await dwn.processMessage(alice.did, recordRead.message);
|
|
1541
1527
|
expect(recordsReadResponse.status.code).toBe(200);
|
|
1542
1528
|
expect(recordsReadResponse.entry.recordsWrite).toBeDefined();
|
|
1543
1529
|
expect(recordsReadResponse.entry.data).toBeDefined();
|
|
1544
1530
|
sinon.assert.calledOnce(dataStoreGet);
|
|
1545
|
-
const readData =
|
|
1531
|
+
const readData = await DataStream.toBytes(recordsReadResponse.entry.data);
|
|
1546
1532
|
expect(readData).toEqual(dataBytes);
|
|
1547
|
-
})
|
|
1533
|
+
});
|
|
1548
1534
|
});
|
|
1549
1535
|
describe('encryption scenarios', () => {
|
|
1550
|
-
it('should be able to decrypt flat-space schema-contained record with a correct derived key', () =>
|
|
1536
|
+
it('should be able to decrypt flat-space schema-contained record with a correct derived key', async () => {
|
|
1551
1537
|
// scenario: Alice writes into her own DWN an encrypted record and she is able to decrypt it
|
|
1552
|
-
const alice =
|
|
1538
|
+
const alice = await TestDataGenerator.generatePersona();
|
|
1553
1539
|
TestStubGenerator.stubDidResolver(didResolver, [alice]);
|
|
1554
1540
|
// encrypt Alice's record
|
|
1555
1541
|
const originalData = TestDataGenerator.randomBytes(1000);
|
|
1556
1542
|
const dataEncryptionInitializationVector = TestDataGenerator.randomBytes(12);
|
|
1557
1543
|
const dataEncryptionKey = TestDataGenerator.randomBytes(32);
|
|
1558
|
-
const { ciphertext: encryptedDataBytes, tag: authenticationTag } =
|
|
1544
|
+
const { ciphertext: encryptedDataBytes, tag: authenticationTag } = await Encryption.aeadEncrypt(ContentEncryptionAlgorithm.A256GCM, dataEncryptionKey, dataEncryptionInitializationVector, originalData);
|
|
1559
1545
|
// TODO: #450 - Should not require a root key to specify the derivation scheme (https://github.com/enboxorg/enbox/issues/450)
|
|
1560
1546
|
const rootPrivateKeyWithSchemasScheme = {
|
|
1561
1547
|
rootKeyId: alice.keyId,
|
|
@@ -1564,16 +1550,16 @@ export function testRecordsReadHandler() {
|
|
|
1564
1550
|
};
|
|
1565
1551
|
const schema = 'https://some-schema.com';
|
|
1566
1552
|
const schemaDerivationPath = Records.constructKeyDerivationPathUsingSchemasScheme(schema);
|
|
1567
|
-
const schemaDerivedPrivateKey =
|
|
1568
|
-
const schemaDerivedPublicKey =
|
|
1553
|
+
const schemaDerivedPrivateKey = await HdKey.derivePrivateKey(rootPrivateKeyWithSchemasScheme, schemaDerivationPath);
|
|
1554
|
+
const schemaDerivedPublicKey = await HdKey.derivePublicKey(rootPrivateKeyWithSchemasScheme, schemaDerivationPath);
|
|
1569
1555
|
const rootPrivateKeyWithDataFormatsScheme = {
|
|
1570
1556
|
rootKeyId: alice.keyId,
|
|
1571
1557
|
derivationScheme: KeyDerivationScheme.DataFormats,
|
|
1572
1558
|
derivedPrivateKey: alice.encryptionKeyPair.privateJwk
|
|
1573
1559
|
};
|
|
1574
1560
|
const dataFormat = 'some/format';
|
|
1575
|
-
const dataFormatDerivationPath = Records.constructKeyDerivationPathUsingDataFormatsScheme(
|
|
1576
|
-
const dataFormatDerivedPublicKey =
|
|
1561
|
+
const dataFormatDerivationPath = Records.constructKeyDerivationPathUsingDataFormatsScheme(dataFormat);
|
|
1562
|
+
const dataFormatDerivedPublicKey = await HdKey.derivePublicKey(rootPrivateKeyWithDataFormatsScheme, dataFormatDerivationPath);
|
|
1577
1563
|
const encryptionInput = {
|
|
1578
1564
|
initializationVector: dataEncryptionInitializationVector,
|
|
1579
1565
|
key: dataEncryptionKey,
|
|
@@ -1589,53 +1575,53 @@ export function testRecordsReadHandler() {
|
|
|
1589
1575
|
derivationScheme: KeyDerivationScheme.DataFormats
|
|
1590
1576
|
}]
|
|
1591
1577
|
};
|
|
1592
|
-
const { message, dataStream } =
|
|
1578
|
+
const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1593
1579
|
author: alice,
|
|
1594
1580
|
schema,
|
|
1595
1581
|
dataFormat,
|
|
1596
1582
|
data: encryptedDataBytes,
|
|
1597
1583
|
encryptionInput
|
|
1598
1584
|
});
|
|
1599
|
-
const writeReply =
|
|
1585
|
+
const writeReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
1600
1586
|
expect(writeReply.status.code).toBe(202);
|
|
1601
|
-
const recordsRead =
|
|
1587
|
+
const recordsRead = await RecordsRead.create({
|
|
1602
1588
|
filter: {
|
|
1603
1589
|
recordId: message.recordId,
|
|
1604
1590
|
},
|
|
1605
1591
|
signer: Jws.createSigner(alice)
|
|
1606
1592
|
});
|
|
1607
1593
|
// test able to derive correct key using `schemas` scheme from root key to decrypt the message
|
|
1608
|
-
const readReply =
|
|
1594
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1609
1595
|
expect(readReply.status.code).toBe(200);
|
|
1610
1596
|
const recordsWriteMessage = readReply.entry.recordsWrite;
|
|
1611
1597
|
const cipherStream = readReply.entry.data;
|
|
1612
|
-
const plaintextDataStream =
|
|
1613
|
-
const plaintextBytes =
|
|
1598
|
+
const plaintextDataStream = await Records.decrypt(recordsWriteMessage, schemaDerivedPrivateKey, cipherStream);
|
|
1599
|
+
const plaintextBytes = await DataStream.toBytes(plaintextDataStream);
|
|
1614
1600
|
expect(ArrayUtility.byteArraysEqual(plaintextBytes, originalData)).toBe(true);
|
|
1615
1601
|
// test able to derive correct key using `dataFormat` scheme from root key to decrypt the message
|
|
1616
|
-
const readReply2 =
|
|
1602
|
+
const readReply2 = await dwn.processMessage(alice.did, recordsRead.message); // send the same read message to get a new cipher stream
|
|
1617
1603
|
expect(readReply2.status.code).toBe(200);
|
|
1618
1604
|
const cipherStream2 = readReply2.entry.data;
|
|
1619
|
-
const plaintextDataStream2 =
|
|
1620
|
-
const plaintextBytes2 =
|
|
1605
|
+
const plaintextDataStream2 = await Records.decrypt(recordsWriteMessage, rootPrivateKeyWithDataFormatsScheme, cipherStream2);
|
|
1606
|
+
const plaintextBytes2 = await DataStream.toBytes(plaintextDataStream2);
|
|
1621
1607
|
expect(ArrayUtility.byteArraysEqual(plaintextBytes2, originalData)).toBe(true);
|
|
1622
|
-
// test unable to decrypt the message if dataFormat-derived key
|
|
1623
|
-
const readReply3 =
|
|
1608
|
+
// test unable to decrypt the message if dataFormat-derived key uses an incorrect data format in derivation path
|
|
1609
|
+
const readReply3 = await dwn.processMessage(alice.did, recordsRead.message); // process the same read message to get a new cipher stream
|
|
1624
1610
|
expect(readReply3.status.code).toBe(200);
|
|
1625
1611
|
const cipherStream3 = readReply3.entry.data;
|
|
1626
|
-
const invalidDerivationPath = [KeyDerivationScheme.DataFormats,
|
|
1627
|
-
const inValidDescendantPrivateKey =
|
|
1628
|
-
|
|
1629
|
-
})
|
|
1630
|
-
it('should be able to decrypt flat-space schema-less record with the correct derived key', () =>
|
|
1612
|
+
const invalidDerivationPath = [KeyDerivationScheme.DataFormats, 'wrong/format'];
|
|
1613
|
+
const inValidDescendantPrivateKey = await HdKey.derivePrivateKey(rootPrivateKeyWithDataFormatsScheme, invalidDerivationPath);
|
|
1614
|
+
await expect(Records.decrypt(recordsWriteMessage, inValidDescendantPrivateKey, cipherStream3)).rejects.toThrow(DwnErrorCode.RecordsInvalidAncestorKeyDerivationSegment);
|
|
1615
|
+
});
|
|
1616
|
+
it('should be able to decrypt flat-space schema-less record with the correct derived key', async () => {
|
|
1631
1617
|
// scenario: Alice writes into her own DWN an encrypted record and she is able to decrypt it
|
|
1632
|
-
const alice =
|
|
1618
|
+
const alice = await TestDataGenerator.generatePersona();
|
|
1633
1619
|
TestStubGenerator.stubDidResolver(didResolver, [alice]);
|
|
1634
1620
|
// encrypt Alice's record
|
|
1635
1621
|
const originalData = TestDataGenerator.randomBytes(1000);
|
|
1636
1622
|
const dataEncryptionInitializationVector = TestDataGenerator.randomBytes(12);
|
|
1637
1623
|
const dataEncryptionKey = TestDataGenerator.randomBytes(32);
|
|
1638
|
-
const { ciphertext: encryptedDataBytes, tag: authenticationTag } =
|
|
1624
|
+
const { ciphertext: encryptedDataBytes, tag: authenticationTag } = await Encryption.aeadEncrypt(ContentEncryptionAlgorithm.A256GCM, dataEncryptionKey, dataEncryptionInitializationVector, originalData);
|
|
1639
1625
|
// TODO: #450 - Should not require a root key to specify the derivation scheme (https://github.com/enboxorg/enbox/issues/450)
|
|
1640
1626
|
const rootPrivateKeyWithDataFormatsScheme = {
|
|
1641
1627
|
rootKeyId: alice.keyId,
|
|
@@ -1643,8 +1629,8 @@ export function testRecordsReadHandler() {
|
|
|
1643
1629
|
derivedPrivateKey: alice.encryptionKeyPair.privateJwk
|
|
1644
1630
|
};
|
|
1645
1631
|
const dataFormat = `image/jpg`;
|
|
1646
|
-
const dataFormatDerivationPath = Records.constructKeyDerivationPathUsingDataFormatsScheme(
|
|
1647
|
-
const dataFormatDerivedPublicKey =
|
|
1632
|
+
const dataFormatDerivationPath = Records.constructKeyDerivationPathUsingDataFormatsScheme(dataFormat);
|
|
1633
|
+
const dataFormatDerivedPublicKey = await HdKey.derivePublicKey(rootPrivateKeyWithDataFormatsScheme, dataFormatDerivationPath);
|
|
1648
1634
|
const encryptionInput = {
|
|
1649
1635
|
initializationVector: dataEncryptionInitializationVector,
|
|
1650
1636
|
key: dataEncryptionKey,
|
|
@@ -1655,67 +1641,67 @@ export function testRecordsReadHandler() {
|
|
|
1655
1641
|
derivationScheme: KeyDerivationScheme.DataFormats
|
|
1656
1642
|
}]
|
|
1657
1643
|
};
|
|
1658
|
-
const recordsWrite =
|
|
1644
|
+
const recordsWrite = await RecordsWrite.create({
|
|
1659
1645
|
signer: Jws.createSigner(alice),
|
|
1660
1646
|
dataFormat,
|
|
1661
1647
|
data: encryptedDataBytes,
|
|
1662
1648
|
encryptionInput
|
|
1663
1649
|
});
|
|
1664
1650
|
const dataStream = DataStream.fromBytes(encryptedDataBytes);
|
|
1665
|
-
const writeReply =
|
|
1651
|
+
const writeReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
|
|
1666
1652
|
expect(writeReply.status.code).toBe(202);
|
|
1667
|
-
const recordsRead =
|
|
1653
|
+
const recordsRead = await RecordsRead.create({
|
|
1668
1654
|
filter: {
|
|
1669
1655
|
recordId: recordsWrite.message.recordId,
|
|
1670
1656
|
},
|
|
1671
1657
|
signer: Jws.createSigner(alice)
|
|
1672
1658
|
});
|
|
1673
1659
|
// test able to derive correct key using `dataFormat` scheme from root key to decrypt the message
|
|
1674
|
-
const readReply =
|
|
1660
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message); // send the same read message to get a new cipher stream
|
|
1675
1661
|
expect(readReply.status.code).toBe(200);
|
|
1676
1662
|
const cipherStream = readReply.entry.data;
|
|
1677
1663
|
const recordsWriteMessage = readReply.entry.recordsWrite;
|
|
1678
|
-
const plaintextDataStream =
|
|
1679
|
-
const plaintextBytes =
|
|
1664
|
+
const plaintextDataStream = await Records.decrypt(recordsWriteMessage, rootPrivateKeyWithDataFormatsScheme, cipherStream);
|
|
1665
|
+
const plaintextBytes = await DataStream.toBytes(plaintextDataStream);
|
|
1680
1666
|
expect(ArrayUtility.byteArraysEqual(plaintextBytes, originalData)).toBe(true);
|
|
1681
|
-
})
|
|
1682
|
-
it('should only be able to decrypt record with a correct derived private key - `protocol-context` derivation scheme', () =>
|
|
1667
|
+
});
|
|
1668
|
+
it('should only be able to decrypt record with a correct derived private key - `protocol-context` derivation scheme', async () => {
|
|
1683
1669
|
// scenario: Bob initiated an encrypted chat thread with Alice,
|
|
1684
1670
|
// bob is able to decrypt subsequent messages from Alice using the `protocol-context` derived private key
|
|
1685
1671
|
// creating Alice and Bob persona and setting up a stub DID resolver
|
|
1686
|
-
const alice =
|
|
1687
|
-
const bob =
|
|
1672
|
+
const alice = await TestDataGenerator.generatePersona();
|
|
1673
|
+
const bob = await TestDataGenerator.generatePersona();
|
|
1688
1674
|
TestStubGenerator.stubDidResolver(didResolver, [alice, bob]);
|
|
1689
1675
|
// Alice configures chat protocol with encryption
|
|
1690
1676
|
const protocolDefinition = chatProtocolDefinition;
|
|
1691
|
-
const protocolDefinitionForAlice =
|
|
1692
|
-
const protocolsConfigureForAlice =
|
|
1677
|
+
const protocolDefinitionForAlice = await Protocols.deriveAndInjectPublicEncryptionKeys(protocolDefinition, alice.keyId, alice.encryptionKeyPair.privateJwk);
|
|
1678
|
+
const protocolsConfigureForAlice = await TestDataGenerator.generateProtocolsConfigure({
|
|
1693
1679
|
author: alice,
|
|
1694
1680
|
protocolDefinition: protocolDefinitionForAlice
|
|
1695
1681
|
});
|
|
1696
|
-
const protocolsConfigureForAliceReply =
|
|
1682
|
+
const protocolsConfigureForAliceReply = await dwn.processMessage(alice.did, protocolsConfigureForAlice.message);
|
|
1697
1683
|
expect(protocolsConfigureForAliceReply.status.code).toBe(202);
|
|
1698
1684
|
// Bob configures chat protocol with encryption
|
|
1699
|
-
const protocolDefinitionForBob =
|
|
1700
|
-
const protocolsConfigureForBob =
|
|
1685
|
+
const protocolDefinitionForBob = await Protocols.deriveAndInjectPublicEncryptionKeys(protocolDefinition, bob.keyId, bob.encryptionKeyPair.privateJwk);
|
|
1686
|
+
const protocolsConfigureForBob = await TestDataGenerator.generateProtocolsConfigure({
|
|
1701
1687
|
author: bob,
|
|
1702
1688
|
protocolDefinition: protocolDefinitionForBob
|
|
1703
1689
|
});
|
|
1704
|
-
const protocolsConfigureReply =
|
|
1690
|
+
const protocolsConfigureReply = await dwn.processMessage(bob.did, protocolsConfigureForBob.message);
|
|
1705
1691
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1706
1692
|
// Bob queries for Alice's chat protocol definition
|
|
1707
|
-
const protocolsQuery =
|
|
1693
|
+
const protocolsQuery = await ProtocolsQuery.create({
|
|
1708
1694
|
filter: { protocol: chatProtocolDefinition.protocol }
|
|
1709
1695
|
});
|
|
1710
|
-
const protocolsQueryReply =
|
|
1696
|
+
const protocolsQueryReply = await dwn.processMessage(alice.did, protocolsQuery.message);
|
|
1711
1697
|
const protocolsConfigureMessageReceived = protocolsQueryReply.entries[0];
|
|
1712
1698
|
// Bob verifies that the chat protocol definition is authored by Alice
|
|
1713
|
-
|
|
1714
|
-
const protocolsConfigureFetched =
|
|
1699
|
+
await authenticate(protocolsConfigureMessageReceived.authorization, didResolver);
|
|
1700
|
+
const protocolsConfigureFetched = await ProtocolsConfigure.parse(protocolsConfigureMessageReceived);
|
|
1715
1701
|
expect(protocolsConfigureFetched.author).toBe(alice.did);
|
|
1716
1702
|
// Bob creates an initiating a chat thread RecordsWrite
|
|
1717
1703
|
const plaintextMessageToAlice = TestDataGenerator.randomBytes(100);
|
|
1718
|
-
const { message: threadMessage, dataStream, recordsWrite, encryptedDataBytes, encryptionInput } =
|
|
1704
|
+
const { message: threadMessage, dataStream, recordsWrite, encryptedDataBytes, encryptionInput } = await TestDataGenerator.generateProtocolEncryptedRecordsWrite({
|
|
1719
1705
|
plaintextBytes: plaintextMessageToAlice,
|
|
1720
1706
|
author: bob,
|
|
1721
1707
|
protocolDefinition: protocolsConfigureForAlice.message.descriptor.definition,
|
|
@@ -1724,11 +1710,11 @@ export function testRecordsReadHandler() {
|
|
|
1724
1710
|
encryptSymmetricKeyWithProtocolContextDerivedKey: true
|
|
1725
1711
|
});
|
|
1726
1712
|
// Bob writes the encrypted chat thread to Alice's DWN
|
|
1727
|
-
const bobToAliceWriteReply =
|
|
1713
|
+
const bobToAliceWriteReply = await dwn.processMessage(alice.did, threadMessage, { dataStream });
|
|
1728
1714
|
expect(bobToAliceWriteReply.status.code).toBe(202);
|
|
1729
1715
|
// Bob also needs to write the same encrypted chat thread to his own DWN
|
|
1730
1716
|
// Opportunity here to create a much nicer utility method for this entire block
|
|
1731
|
-
const bobToBobRecordsWrite =
|
|
1717
|
+
const bobToBobRecordsWrite = await RecordsWrite.createFrom({
|
|
1732
1718
|
recordsWriteMessage: recordsWrite.message,
|
|
1733
1719
|
messageTimestamp: recordsWrite.message.descriptor.messageTimestamp
|
|
1734
1720
|
});
|
|
@@ -1738,7 +1724,7 @@ export function testRecordsReadHandler() {
|
|
|
1738
1724
|
derivedPrivateKey: bob.encryptionKeyPair.privateJwk
|
|
1739
1725
|
};
|
|
1740
1726
|
const protocolPathDerivationPath = Records.constructKeyDerivationPathUsingProtocolPathScheme(recordsWrite.message.descriptor);
|
|
1741
|
-
const protocolPathDerivedPublicJwkForBobsDwn =
|
|
1727
|
+
const protocolPathDerivedPublicJwkForBobsDwn = await HdKey.derivePublicKey(bobRootPrivateKey, protocolPathDerivationPath);
|
|
1742
1728
|
const protocolPathDerivedKeyEncryptionInputForBobsDwn = {
|
|
1743
1729
|
publicKeyId: bob.keyId, // reusing signing key for encryption purely as a convenience
|
|
1744
1730
|
publicKey: protocolPathDerivedPublicJwkForBobsDwn,
|
|
@@ -1747,27 +1733,27 @@ export function testRecordsReadHandler() {
|
|
|
1747
1733
|
const encryptionInputForBobsDwn = encryptionInput;
|
|
1748
1734
|
const indexOfKeyEncryptionInputToReplace = encryptionInputForBobsDwn.keyEncryptionInputs.findIndex(input => input.derivationScheme === KeyDerivationScheme.ProtocolPath);
|
|
1749
1735
|
encryptionInputForBobsDwn.keyEncryptionInputs[indexOfKeyEncryptionInputToReplace] = protocolPathDerivedKeyEncryptionInputForBobsDwn;
|
|
1750
|
-
|
|
1751
|
-
|
|
1736
|
+
await bobToBobRecordsWrite.encryptSymmetricEncryptionKey(encryptionInputForBobsDwn);
|
|
1737
|
+
await bobToBobRecordsWrite.sign({ signer: Jws.createSigner(bob) });
|
|
1752
1738
|
const dataStreamForBobsDwn = DataStream.fromBytes(encryptedDataBytes);
|
|
1753
|
-
const bobToBobWriteReply =
|
|
1739
|
+
const bobToBobWriteReply = await dwn.processMessage(bob.did, bobToBobRecordsWrite.message, { dataStream: dataStreamForBobsDwn });
|
|
1754
1740
|
expect(bobToBobWriteReply.status.code).toBe(202);
|
|
1755
1741
|
// NOTE: we know Alice is able to decrypt the message using protocol-path derived key through other tests, so we won't verify it again
|
|
1756
1742
|
// test that anyone with the protocol-context derived private key is able to decrypt the message
|
|
1757
|
-
const recordsRead =
|
|
1743
|
+
const recordsRead = await RecordsRead.create({
|
|
1758
1744
|
filter: {
|
|
1759
1745
|
recordId: threadMessage.recordId,
|
|
1760
1746
|
},
|
|
1761
1747
|
signer: Jws.createSigner(alice)
|
|
1762
1748
|
});
|
|
1763
|
-
const readReply =
|
|
1749
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1764
1750
|
expect(readReply.status.code).toBe(200);
|
|
1765
1751
|
const fetchedRecordsWrite = readReply.entry.recordsWrite;
|
|
1766
1752
|
const cipherStream = readReply.entry.data;
|
|
1767
1753
|
const derivationPathFromReadContext = Records.constructKeyDerivationPathUsingProtocolContextScheme(fetchedRecordsWrite.contextId);
|
|
1768
|
-
const protocolContextDerivedPrivateJwk =
|
|
1769
|
-
const plaintextDataStream =
|
|
1770
|
-
const plaintextBytes =
|
|
1754
|
+
const protocolContextDerivedPrivateJwk = await HdKey.derivePrivateKey(bobRootPrivateKey, derivationPathFromReadContext);
|
|
1755
|
+
const plaintextDataStream = await Records.decrypt(fetchedRecordsWrite, protocolContextDerivedPrivateJwk, cipherStream);
|
|
1756
|
+
const plaintextBytes = await DataStream.toBytes(plaintextDataStream);
|
|
1771
1757
|
expect(ArrayUtility.byteArraysEqual(plaintextBytes, plaintextMessageToAlice)).toBe(true);
|
|
1772
1758
|
// verify that Alice is able to send an encrypted message using the protocol-context derived public key and Bob is able to decrypt it
|
|
1773
1759
|
// NOTE: we will skip verification of Bob's protocol configuration because we have test the such scenario above as well as in other tests
|
|
@@ -1775,7 +1761,7 @@ export function testRecordsReadHandler() {
|
|
|
1775
1761
|
const protocolContextDerivedPublicJwkReturned = matchingRecipient.header.derivedPublicKey;
|
|
1776
1762
|
const protocolContextDerivingRootKeyIdReturned = matchingRecipient.header.kid;
|
|
1777
1763
|
const plaintextMessageToBob = TestDataGenerator.randomBytes(100);
|
|
1778
|
-
const recordsWriteToBob =
|
|
1764
|
+
const recordsWriteToBob = await TestDataGenerator.generateProtocolEncryptedRecordsWrite({
|
|
1779
1765
|
plaintextBytes: plaintextMessageToBob,
|
|
1780
1766
|
author: alice,
|
|
1781
1767
|
protocolDefinition: protocolsConfigureForBob.message.descriptor.definition,
|
|
@@ -1787,57 +1773,56 @@ export function testRecordsReadHandler() {
|
|
|
1787
1773
|
encryptSymmetricKeyWithProtocolContextDerivedKey: true
|
|
1788
1774
|
});
|
|
1789
1775
|
// Alice sends the message to Bob
|
|
1790
|
-
const aliceWriteReply =
|
|
1776
|
+
const aliceWriteReply = await dwn.processMessage(bob.did, recordsWriteToBob.message, { dataStream: recordsWriteToBob.dataStream });
|
|
1791
1777
|
expect(aliceWriteReply.status.code).toBe(202);
|
|
1792
1778
|
// test that Bob is able to read and decrypt Alice's message
|
|
1793
|
-
const recordsReadByBob =
|
|
1779
|
+
const recordsReadByBob = await RecordsRead.create({
|
|
1794
1780
|
filter: {
|
|
1795
1781
|
recordId: recordsWriteToBob.message.recordId,
|
|
1796
1782
|
},
|
|
1797
1783
|
signer: Jws.createSigner(bob)
|
|
1798
1784
|
});
|
|
1799
|
-
const readByBobReply =
|
|
1785
|
+
const readByBobReply = await dwn.processMessage(bob.did, recordsReadByBob.message);
|
|
1800
1786
|
expect(readByBobReply.status.code).toBe(200);
|
|
1801
1787
|
const fetchedRecordsWrite2 = readByBobReply.entry.recordsWrite;
|
|
1802
1788
|
const cipherStream2 = readByBobReply.entry.data;
|
|
1803
|
-
const plaintextDataStream2 =
|
|
1804
|
-
const plaintextBytes2 =
|
|
1789
|
+
const plaintextDataStream2 = await Records.decrypt(fetchedRecordsWrite2, protocolContextDerivedPrivateJwk, cipherStream2);
|
|
1790
|
+
const plaintextBytes2 = await DataStream.toBytes(plaintextDataStream2);
|
|
1805
1791
|
expect(ArrayUtility.byteArraysEqual(plaintextBytes2, plaintextMessageToBob)).toBe(true);
|
|
1806
|
-
})
|
|
1807
|
-
it('should only be able to decrypt record with a correct derived private key - `protocols` derivation scheme', () =>
|
|
1792
|
+
});
|
|
1793
|
+
it('should only be able to decrypt record with a correct derived private key - `protocols` derivation scheme', async () => {
|
|
1808
1794
|
// scenario: Bob writes into Alice's DWN an encrypted "email", alice is able to decrypt it
|
|
1809
|
-
var _a;
|
|
1810
1795
|
// creating Alice and Bob persona and setting up a stub DID resolver
|
|
1811
|
-
const alice =
|
|
1812
|
-
const bob =
|
|
1796
|
+
const alice = await TestDataGenerator.generatePersona();
|
|
1797
|
+
const bob = await TestDataGenerator.generatePersona();
|
|
1813
1798
|
TestStubGenerator.stubDidResolver(didResolver, [alice, bob]);
|
|
1814
1799
|
// Alice configures email protocol with encryption
|
|
1815
1800
|
const protocolDefinition = emailProtocolDefinition;
|
|
1816
|
-
const encryptedProtocolDefinition =
|
|
1817
|
-
const protocolsConfigure =
|
|
1801
|
+
const encryptedProtocolDefinition = await Protocols.deriveAndInjectPublicEncryptionKeys(protocolDefinition, alice.keyId, alice.encryptionKeyPair.privateJwk);
|
|
1802
|
+
const protocolsConfigure = await TestDataGenerator.generateProtocolsConfigure({
|
|
1818
1803
|
author: alice,
|
|
1819
1804
|
protocolDefinition: encryptedProtocolDefinition
|
|
1820
1805
|
});
|
|
1821
|
-
const protocolsConfigureReply =
|
|
1806
|
+
const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfigure.message);
|
|
1822
1807
|
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
1823
1808
|
// Bob queries for Alice's email protocol definition
|
|
1824
|
-
const protocolsQuery =
|
|
1809
|
+
const protocolsQuery = await ProtocolsQuery.create({
|
|
1825
1810
|
filter: { protocol: emailProtocolDefinition.protocol }
|
|
1826
1811
|
});
|
|
1827
|
-
const protocolsQueryReply =
|
|
1812
|
+
const protocolsQueryReply = await dwn.processMessage(alice.did, protocolsQuery.message);
|
|
1828
1813
|
const protocolsConfigureMessageReceived = protocolsQueryReply.entries[0];
|
|
1829
1814
|
// Bob verifies that the email protocol definition is authored by Alice
|
|
1830
|
-
|
|
1831
|
-
const protocolsConfigureFetched =
|
|
1815
|
+
await authenticate(protocolsConfigureMessageReceived.authorization, didResolver);
|
|
1816
|
+
const protocolsConfigureFetched = await ProtocolsConfigure.parse(protocolsConfigureMessageReceived);
|
|
1832
1817
|
expect(protocolsConfigureFetched.author).toBe(alice.did);
|
|
1833
1818
|
// Bob encrypts his email to Alice with a randomly generated symmetric key
|
|
1834
1819
|
const bobMessageBytes = TestDataGenerator.randomBytes(100);
|
|
1835
1820
|
const dataEncryptionInitializationVector = TestDataGenerator.randomBytes(12);
|
|
1836
1821
|
const dataEncryptionKey = TestDataGenerator.randomBytes(32);
|
|
1837
|
-
const { ciphertext: bobMessageEncryptedBytes, tag: authenticationTag } =
|
|
1822
|
+
const { ciphertext: bobMessageEncryptedBytes, tag: authenticationTag } = await Encryption.aeadEncrypt(ContentEncryptionAlgorithm.A256GCM, dataEncryptionKey, dataEncryptionInitializationVector, bobMessageBytes);
|
|
1838
1823
|
// Bob generates an encrypted RecordsWrite,
|
|
1839
1824
|
// the public encryption key designated by Alice is used to encrypt the symmetric key Bob generated above
|
|
1840
|
-
const publicJwk =
|
|
1825
|
+
const publicJwk = protocolsConfigureFetched.message.descriptor.definition.structure.email.$encryption?.publicKeyJwk;
|
|
1841
1826
|
expect(publicJwk).toBeDefined();
|
|
1842
1827
|
const encryptionInput = {
|
|
1843
1828
|
initializationVector: dataEncryptionInitializationVector,
|
|
@@ -1849,7 +1834,7 @@ export function testRecordsReadHandler() {
|
|
|
1849
1834
|
derivationScheme: KeyDerivationScheme.ProtocolPath
|
|
1850
1835
|
}]
|
|
1851
1836
|
};
|
|
1852
|
-
const { message, dataStream } =
|
|
1837
|
+
const { message, dataStream } = await TestDataGenerator.generateRecordsWrite({
|
|
1853
1838
|
author: bob,
|
|
1854
1839
|
protocol: protocolDefinition.protocol,
|
|
1855
1840
|
protocolPath: 'email', // this comes from `types` in protocol definition
|
|
@@ -1859,17 +1844,17 @@ export function testRecordsReadHandler() {
|
|
|
1859
1844
|
encryptionInput
|
|
1860
1845
|
});
|
|
1861
1846
|
// Bob writes the encrypted email to Alice's DWN
|
|
1862
|
-
const bobWriteReply =
|
|
1847
|
+
const bobWriteReply = await dwn.processMessage(alice.did, message, { dataStream });
|
|
1863
1848
|
expect(bobWriteReply.status.code).toBe(202);
|
|
1864
1849
|
// Alice reads the encrypted email
|
|
1865
1850
|
// assume Alice already made query to get the `recordId` of the email
|
|
1866
|
-
const recordsRead =
|
|
1851
|
+
const recordsRead = await RecordsRead.create({
|
|
1867
1852
|
filter: {
|
|
1868
1853
|
recordId: message.recordId,
|
|
1869
1854
|
},
|
|
1870
1855
|
signer: Jws.createSigner(alice)
|
|
1871
1856
|
});
|
|
1872
|
-
const readReply =
|
|
1857
|
+
const readReply = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1873
1858
|
expect(readReply.status.code).toBe(200);
|
|
1874
1859
|
// test that Alice is able decrypt the encrypted email from Bob using the root key
|
|
1875
1860
|
const rootPrivateKey = {
|
|
@@ -1879,43 +1864,43 @@ export function testRecordsReadHandler() {
|
|
|
1879
1864
|
};
|
|
1880
1865
|
const fetchedRecordsWrite = readReply.entry.recordsWrite;
|
|
1881
1866
|
const cipherStream = readReply.entry.data;
|
|
1882
|
-
const plaintextDataStream =
|
|
1883
|
-
const plaintextBytes =
|
|
1867
|
+
const plaintextDataStream = await Records.decrypt(fetchedRecordsWrite, rootPrivateKey, cipherStream);
|
|
1868
|
+
const plaintextBytes = await DataStream.toBytes(plaintextDataStream);
|
|
1884
1869
|
expect(ArrayUtility.byteArraysEqual(plaintextBytes, bobMessageBytes)).toBe(true);
|
|
1885
1870
|
// test that a correct derived key is able decrypt the encrypted email from Bob
|
|
1886
|
-
const readReply2 =
|
|
1871
|
+
const readReply2 = await dwn.processMessage(alice.did, recordsRead.message);
|
|
1887
1872
|
expect(readReply2.status.code).toBe(200);
|
|
1888
1873
|
const relativeDescendantDerivationPath = Records.constructKeyDerivationPath(KeyDerivationScheme.ProtocolPath, fetchedRecordsWrite);
|
|
1889
|
-
const derivedPrivateKey =
|
|
1874
|
+
const derivedPrivateKey = await HdKey.derivePrivateKey(rootPrivateKey, relativeDescendantDerivationPath);
|
|
1890
1875
|
const fetchedRecordsWrite2 = readReply2.entry.recordsWrite;
|
|
1891
1876
|
const cipherStream2 = readReply2.entry.data;
|
|
1892
|
-
const plaintextDataStream2 =
|
|
1893
|
-
const plaintextBytes2 =
|
|
1877
|
+
const plaintextDataStream2 = await Records.decrypt(fetchedRecordsWrite2, derivedPrivateKey, cipherStream2);
|
|
1878
|
+
const plaintextBytes2 = await DataStream.toBytes(plaintextDataStream2);
|
|
1894
1879
|
expect(ArrayUtility.byteArraysEqual(plaintextBytes2, bobMessageBytes)).toBe(true);
|
|
1895
1880
|
// test unable to decrypt the message if derived key has an unexpected path
|
|
1896
1881
|
const invalidDerivationPath = [KeyDerivationScheme.ProtocolPath, protocolDefinition.protocol, 'invalidContextId'];
|
|
1897
|
-
const inValidDescendantPrivateKey =
|
|
1898
|
-
|
|
1882
|
+
const inValidDescendantPrivateKey = await HdKey.derivePrivateKey(rootPrivateKey, invalidDerivationPath);
|
|
1883
|
+
await expect(Records.decrypt(fetchedRecordsWrite, inValidDescendantPrivateKey, cipherStream)).rejects.toThrow(DwnErrorCode.RecordsInvalidAncestorKeyDerivationSegment);
|
|
1899
1884
|
// test unable to decrypt the message if no derivation scheme used by the message matches the scheme used by the given private key
|
|
1900
1885
|
const privateKeyWithMismatchingDerivationScheme = {
|
|
1901
1886
|
rootKeyId: alice.keyId,
|
|
1902
1887
|
derivationScheme: 'scheme-that-is-not-protocol-context',
|
|
1903
1888
|
derivedPrivateKey: alice.encryptionKeyPair.privateJwk
|
|
1904
1889
|
};
|
|
1905
|
-
|
|
1890
|
+
await expect(Records.decrypt(fetchedRecordsWrite, privateKeyWithMismatchingDerivationScheme, cipherStream)).rejects.toThrow(DwnErrorCode.RecordsDecryptNoMatchingKeyEncryptedFound);
|
|
1906
1891
|
// test unable to decrypt the message if public key ID does not match the derived private key
|
|
1907
1892
|
const privateKeyWithMismatchingKeyId = {
|
|
1908
1893
|
rootKeyId: 'mismatchingKeyId',
|
|
1909
1894
|
derivationScheme: KeyDerivationScheme.ProtocolPath,
|
|
1910
1895
|
derivedPrivateKey: alice.encryptionKeyPair.privateJwk
|
|
1911
1896
|
};
|
|
1912
|
-
|
|
1913
|
-
})
|
|
1897
|
+
await expect(Records.decrypt(fetchedRecordsWrite, privateKeyWithMismatchingKeyId, cipherStream)).rejects.toThrow(DwnErrorCode.RecordsDecryptNoMatchingKeyEncryptedFound);
|
|
1898
|
+
});
|
|
1914
1899
|
});
|
|
1915
1900
|
});
|
|
1916
|
-
it('should return 401 if signature check fails', () =>
|
|
1917
|
-
const alice =
|
|
1918
|
-
const recordsRead =
|
|
1901
|
+
it('should return 401 if signature check fails', async () => {
|
|
1902
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1903
|
+
const recordsRead = await RecordsRead.create({
|
|
1919
1904
|
filter: {
|
|
1920
1905
|
recordId: 'any-id',
|
|
1921
1906
|
},
|
|
@@ -1923,17 +1908,17 @@ export function testRecordsReadHandler() {
|
|
|
1923
1908
|
});
|
|
1924
1909
|
// setting up a stub did resolver & message store
|
|
1925
1910
|
// intentionally not supplying the public key so a different public key is generated to simulate invalid signature
|
|
1926
|
-
const mismatchingPersona =
|
|
1911
|
+
const mismatchingPersona = await TestDataGenerator.generatePersona({ did: alice.did, keyId: alice.keyId });
|
|
1927
1912
|
const didResolver = TestStubGenerator.createDidResolverStub(mismatchingPersona);
|
|
1928
1913
|
const messageStoreStub = sinon.createStubInstance(MessageStoreLevel);
|
|
1929
1914
|
const dataStoreStub = sinon.createStubInstance(DataStoreLevel);
|
|
1930
1915
|
const recordsReadHandler = new RecordsReadHandler(didResolver, messageStoreStub, dataStoreStub);
|
|
1931
|
-
const reply =
|
|
1916
|
+
const reply = await recordsReadHandler.handle({ tenant: alice.did, message: recordsRead.message });
|
|
1932
1917
|
expect(reply.status.code).toBe(401);
|
|
1933
|
-
})
|
|
1934
|
-
it('should return 400 if fail parsing the message', () =>
|
|
1935
|
-
const alice =
|
|
1936
|
-
const recordsRead =
|
|
1918
|
+
});
|
|
1919
|
+
it('should return 400 if fail parsing the message', async () => {
|
|
1920
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1921
|
+
const recordsRead = await RecordsRead.create({
|
|
1937
1922
|
filter: {
|
|
1938
1923
|
recordId: 'any-id',
|
|
1939
1924
|
},
|
|
@@ -1945,9 +1930,9 @@ export function testRecordsReadHandler() {
|
|
|
1945
1930
|
const recordsReadHandler = new RecordsReadHandler(didResolver, messageStoreStub, dataStoreStub);
|
|
1946
1931
|
// stub the `parse()` function to throw an error
|
|
1947
1932
|
sinon.stub(RecordsRead, 'parse').throws('anyError');
|
|
1948
|
-
const reply =
|
|
1933
|
+
const reply = await recordsReadHandler.handle({ tenant: alice.did, message: recordsRead.message });
|
|
1949
1934
|
expect(reply.status.code).toBe(400);
|
|
1950
|
-
})
|
|
1935
|
+
});
|
|
1951
1936
|
});
|
|
1952
1937
|
}
|
|
1953
1938
|
//# sourceMappingURL=records-read.spec.js.map
|