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