@enbox/dwn-server 0.0.2 → 0.0.4
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/LICENSE +3 -2
- package/README.md +115 -215
- package/dist/esm/src/admin/activity-log.d.ts +44 -0
- package/dist/esm/src/admin/activity-log.d.ts.map +1 -0
- package/dist/esm/src/admin/activity-log.js +85 -0
- package/dist/esm/src/admin/activity-log.js.map +1 -0
- package/dist/esm/src/admin/admin-api.d.ts +61 -0
- package/dist/esm/src/admin/admin-api.d.ts.map +1 -0
- package/dist/esm/src/admin/admin-api.js +1047 -0
- package/dist/esm/src/admin/admin-api.js.map +1 -0
- package/dist/esm/src/admin/admin-auth.d.ts +9 -0
- package/dist/esm/src/admin/admin-auth.d.ts.map +1 -0
- package/dist/esm/src/admin/admin-auth.js +45 -0
- package/dist/esm/src/admin/admin-auth.js.map +1 -0
- package/dist/esm/src/admin/admin-store.d.ts +111 -0
- package/dist/esm/src/admin/admin-store.d.ts.map +1 -0
- package/dist/esm/src/admin/admin-store.js +376 -0
- package/dist/esm/src/admin/admin-store.js.map +1 -0
- package/dist/esm/src/admin/audit-log.d.ts +94 -0
- package/dist/esm/src/admin/audit-log.d.ts.map +1 -0
- package/dist/esm/src/admin/audit-log.js +220 -0
- package/dist/esm/src/admin/audit-log.js.map +1 -0
- package/dist/esm/src/admin/index.d.ts +10 -0
- package/dist/esm/src/admin/index.d.ts.map +1 -0
- package/dist/esm/src/admin/index.js +7 -0
- package/dist/esm/src/admin/index.js.map +1 -0
- package/dist/esm/src/admin/types.d.ts +306 -0
- package/dist/esm/src/admin/types.d.ts.map +1 -0
- package/dist/esm/src/admin/types.js +2 -0
- package/dist/esm/src/admin/types.js.map +1 -0
- package/dist/esm/src/admin/webhook-manager.d.ts +55 -0
- package/dist/esm/src/admin/webhook-manager.d.ts.map +1 -0
- package/dist/esm/src/admin/webhook-manager.js +184 -0
- package/dist/esm/src/admin/webhook-manager.js.map +1 -0
- package/dist/esm/src/config.d.ts +124 -9
- package/dist/esm/src/config.d.ts.map +1 -1
- package/dist/esm/src/config.js +155 -13
- package/dist/esm/src/config.js.map +1 -1
- package/dist/esm/src/connection/connection-manager.d.ts +32 -9
- package/dist/esm/src/connection/connection-manager.d.ts.map +1 -1
- package/dist/esm/src/connection/connection-manager.js +38 -5
- package/dist/esm/src/connection/connection-manager.js.map +1 -1
- package/dist/esm/src/connection/flow-controller.d.ts +53 -0
- package/dist/esm/src/connection/flow-controller.d.ts.map +1 -0
- package/dist/esm/src/connection/flow-controller.js +101 -0
- package/dist/esm/src/connection/flow-controller.js.map +1 -0
- package/dist/esm/src/connection/socket-connection.d.ts +54 -18
- package/dist/esm/src/connection/socket-connection.d.ts.map +1 -1
- package/dist/esm/src/connection/socket-connection.js +102 -40
- package/dist/esm/src/connection/socket-connection.js.map +1 -1
- package/dist/esm/src/delivery-service.d.ts +43 -0
- package/dist/esm/src/delivery-service.d.ts.map +1 -0
- package/dist/esm/src/delivery-service.js +574 -0
- package/dist/esm/src/delivery-service.js.map +1 -0
- package/dist/esm/src/dwn-error.d.ts +10 -1
- package/dist/esm/src/dwn-error.d.ts.map +1 -1
- package/dist/esm/src/dwn-error.js +9 -0
- package/dist/esm/src/dwn-error.js.map +1 -1
- package/dist/esm/src/dwn-server.d.ts +13 -6
- package/dist/esm/src/dwn-server.d.ts.map +1 -1
- package/dist/esm/src/dwn-server.js +199 -24
- package/dist/esm/src/dwn-server.js.map +1 -1
- package/dist/esm/src/http-api.d.ts +28 -13
- package/dist/esm/src/http-api.d.ts.map +1 -1
- package/dist/esm/src/http-api.js +649 -374
- package/dist/esm/src/http-api.js.map +1 -1
- package/dist/esm/src/index.d.ts +6 -2
- package/dist/esm/src/index.d.ts.map +1 -1
- package/dist/esm/src/index.js +4 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/json-rpc-api.js +2 -1
- package/dist/esm/src/json-rpc-api.js.map +1 -1
- package/dist/esm/src/json-rpc-handlers/dwn/process-message.d.ts.map +1 -1
- package/dist/esm/src/json-rpc-handlers/dwn/process-message.js +109 -7
- package/dist/esm/src/json-rpc-handlers/dwn/process-message.js.map +1 -1
- package/dist/esm/src/json-rpc-handlers/subscription/ack.d.ts +20 -0
- package/dist/esm/src/json-rpc-handlers/subscription/ack.d.ts.map +1 -0
- package/dist/esm/src/json-rpc-handlers/subscription/ack.js +41 -0
- package/dist/esm/src/json-rpc-handlers/subscription/ack.js.map +1 -0
- package/dist/esm/src/json-rpc-handlers/subscription/close.d.ts.map +1 -1
- package/dist/esm/src/json-rpc-handlers/subscription/close.js +1 -1
- package/dist/esm/src/json-rpc-handlers/subscription/close.js.map +1 -1
- package/dist/esm/src/json-rpc-handlers/subscription/index.d.ts +1 -0
- package/dist/esm/src/json-rpc-handlers/subscription/index.d.ts.map +1 -1
- package/dist/esm/src/json-rpc-handlers/subscription/index.js +1 -0
- package/dist/esm/src/json-rpc-handlers/subscription/index.js.map +1 -1
- package/dist/esm/src/lib/json-rpc-router.d.ts +25 -8
- package/dist/esm/src/lib/json-rpc-router.d.ts.map +1 -1
- package/dist/esm/src/lib/json-rpc-router.js.map +1 -1
- package/dist/esm/src/lib/sql-utils.d.ts +6 -0
- package/dist/esm/src/lib/sql-utils.d.ts.map +1 -0
- package/dist/esm/src/lib/sql-utils.js +8 -0
- package/dist/esm/src/lib/sql-utils.js.map +1 -0
- package/dist/esm/src/main.js +0 -6
- package/dist/esm/src/main.js.map +1 -1
- package/dist/esm/src/message-processed-hook.d.ts +35 -0
- package/dist/esm/src/message-processed-hook.d.ts.map +1 -0
- package/dist/esm/src/message-processed-hook.js +2 -0
- package/dist/esm/src/message-processed-hook.js.map +1 -0
- package/dist/esm/src/metrics.d.ts +14 -2
- package/dist/esm/src/metrics.d.ts.map +1 -1
- package/dist/esm/src/metrics.js +41 -1
- package/dist/esm/src/metrics.js.map +1 -1
- package/dist/esm/src/plugins/event-log-nats.d.ts +25 -0
- package/dist/esm/src/plugins/event-log-nats.d.ts.map +1 -0
- package/dist/esm/src/plugins/event-log-nats.js +379 -0
- package/dist/esm/src/plugins/event-log-nats.js.map +1 -0
- package/dist/esm/src/rate-limiter.d.ts +60 -0
- package/dist/esm/src/rate-limiter.d.ts.map +1 -0
- package/dist/esm/src/rate-limiter.js +116 -0
- package/dist/esm/src/rate-limiter.js.map +1 -0
- package/dist/esm/src/registration/jwt-provider-auth-plugin.d.ts +53 -0
- package/dist/esm/src/registration/jwt-provider-auth-plugin.d.ts.map +1 -0
- package/dist/esm/src/registration/jwt-provider-auth-plugin.js +90 -0
- package/dist/esm/src/registration/jwt-provider-auth-plugin.js.map +1 -0
- package/dist/esm/src/registration/open-auth-handler.d.ts +37 -0
- package/dist/esm/src/registration/open-auth-handler.d.ts.map +1 -0
- package/dist/esm/src/registration/open-auth-handler.js +214 -0
- package/dist/esm/src/registration/open-auth-handler.js.map +1 -0
- package/dist/esm/src/registration/proof-of-work-manager.d.ts +1 -1
- package/dist/esm/src/registration/proof-of-work-manager.d.ts.map +1 -1
- package/dist/esm/src/registration/proof-of-work-manager.js +3 -3
- package/dist/esm/src/registration/proof-of-work-manager.js.map +1 -1
- package/dist/esm/src/registration/provider-auth-plugin.d.ts +46 -0
- package/dist/esm/src/registration/provider-auth-plugin.d.ts.map +1 -0
- package/dist/esm/src/registration/provider-auth-plugin.js +29 -0
- package/dist/esm/src/registration/provider-auth-plugin.js.map +1 -0
- package/dist/esm/src/registration/registration-manager.d.ts +28 -5
- package/dist/esm/src/registration/registration-manager.d.ts.map +1 -1
- package/dist/esm/src/registration/registration-manager.js +83 -12
- package/dist/esm/src/registration/registration-manager.js.map +1 -1
- package/dist/esm/src/registration/registration-store.d.ts +83 -3
- package/dist/esm/src/registration/registration-store.d.ts.map +1 -1
- package/dist/esm/src/registration/registration-store.js +248 -11
- package/dist/esm/src/registration/registration-store.js.map +1 -1
- package/dist/esm/src/storage.d.ts +5 -5
- package/dist/esm/src/storage.d.ts.map +1 -1
- package/dist/esm/src/storage.js +105 -24
- package/dist/esm/src/storage.js.map +1 -1
- package/dist/esm/src/web5-connect/sql-ttl-cache.d.ts.map +1 -1
- package/dist/esm/src/web5-connect/sql-ttl-cache.js +11 -3
- package/dist/esm/src/web5-connect/sql-ttl-cache.js.map +1 -1
- package/dist/esm/src/web5-connect/web5-connect-server.d.ts.map +1 -1
- package/dist/esm/src/web5-connect/web5-connect-server.js +2 -2
- package/dist/esm/src/web5-connect/web5-connect-server.js.map +1 -1
- package/dist/esm/src/ws-api.d.ts +18 -4
- package/dist/esm/src/ws-api.d.ts.map +1 -1
- package/dist/esm/src/ws-api.js +12 -16
- package/dist/esm/src/ws-api.js.map +1 -1
- package/package.json +34 -53
- package/src/admin/activity-log.ts +100 -0
- package/src/admin/admin-api.ts +1308 -0
- package/src/admin/admin-auth.ts +56 -0
- package/src/admin/admin-store.ts +515 -0
- package/src/admin/audit-log.ts +327 -0
- package/src/admin/index.ts +34 -0
- package/src/admin/types.ts +352 -0
- package/src/admin/webhook-manager.ts +245 -0
- package/src/config.ts +190 -22
- package/src/connection/connection-manager.ts +67 -17
- package/src/connection/flow-controller.ts +117 -0
- package/src/connection/socket-connection.ts +144 -67
- package/src/delivery-service.ts +740 -0
- package/src/dwn-error.ts +11 -2
- package/src/dwn-server.ts +254 -39
- package/src/http-api.ts +736 -392
- package/src/index.ts +13 -2
- package/src/json-rpc-api.ts +2 -1
- package/src/json-rpc-handlers/dwn/process-message.ts +149 -15
- package/src/json-rpc-handlers/subscription/ack.ts +63 -0
- package/src/json-rpc-handlers/subscription/close.ts +5 -9
- package/src/json-rpc-handlers/subscription/index.ts +1 -0
- package/src/lib/json-rpc-router.ts +26 -11
- package/src/lib/sql-utils.ts +7 -0
- package/src/main.ts +0 -8
- package/src/message-processed-hook.ts +33 -0
- package/src/metrics.ts +57 -8
- package/src/plugins/event-log-nats.ts +466 -0
- package/src/process-handlers.ts +5 -5
- package/src/rate-limiter.ts +143 -0
- package/src/registration/jwt-provider-auth-plugin.ts +119 -0
- package/src/registration/open-auth-handler.ts +263 -0
- package/src/registration/proof-of-work-manager.ts +11 -10
- package/src/registration/provider-auth-plugin.ts +84 -0
- package/src/registration/registration-manager.ts +129 -31
- package/src/registration/registration-store.ts +332 -22
- package/src/storage.ts +136 -40
- package/src/web5-connect/sql-ttl-cache.ts +12 -5
- package/src/web5-connect/web5-connect-server.ts +9 -8
- package/src/ws-api.ts +39 -26
- package/dist/cjs/index.js +0 -6811
- package/dist/cjs/package.json +0 -1
- package/dist/esm/src/json-rpc-socket.d.ts +0 -39
- package/dist/esm/src/json-rpc-socket.d.ts.map +0 -1
- package/dist/esm/src/json-rpc-socket.js +0 -125
- package/dist/esm/src/json-rpc-socket.js.map +0 -1
- package/dist/esm/src/lib/http-server-shutdown-handler.d.ts +0 -10
- package/dist/esm/src/lib/http-server-shutdown-handler.d.ts.map +0 -1
- package/dist/esm/src/lib/http-server-shutdown-handler.js +0 -65
- package/dist/esm/src/lib/http-server-shutdown-handler.js.map +0 -1
- package/dist/esm/src/lib/json-rpc.d.ts +0 -54
- package/dist/esm/src/lib/json-rpc.d.ts.map +0 -1
- package/dist/esm/src/lib/json-rpc.js +0 -60
- package/dist/esm/src/lib/json-rpc.js.map +0 -1
- package/dist/esm/src/registration/proof-of-work-types.d.ts +0 -8
- package/dist/esm/src/registration/proof-of-work-types.d.ts.map +0 -1
- package/dist/esm/src/registration/proof-of-work-types.js +0 -2
- package/dist/esm/src/registration/proof-of-work-types.js.map +0 -1
- package/dist/esm/src/registration/registration-types.d.ts +0 -18
- package/dist/esm/src/registration/registration-types.d.ts.map +0 -1
- package/dist/esm/src/registration/registration-types.js +0 -2
- package/dist/esm/src/registration/registration-types.js.map +0 -1
- package/dist/esm/tests/common-scenario-validator.d.ts +0 -11
- package/dist/esm/tests/common-scenario-validator.d.ts.map +0 -1
- package/dist/esm/tests/common-scenario-validator.js +0 -114
- package/dist/esm/tests/common-scenario-validator.js.map +0 -1
- package/dist/esm/tests/connection/connection-manager.spec.d.ts +0 -2
- package/dist/esm/tests/connection/connection-manager.spec.d.ts.map +0 -1
- package/dist/esm/tests/connection/connection-manager.spec.js +0 -47
- package/dist/esm/tests/connection/connection-manager.spec.js.map +0 -1
- package/dist/esm/tests/connection/socket-connection.spec.d.ts +0 -2
- package/dist/esm/tests/connection/socket-connection.spec.d.ts.map +0 -1
- package/dist/esm/tests/connection/socket-connection.spec.js +0 -125
- package/dist/esm/tests/connection/socket-connection.spec.js.map +0 -1
- package/dist/esm/tests/cors/http-api.browser.d.ts +0 -2
- package/dist/esm/tests/cors/http-api.browser.d.ts.map +0 -1
- package/dist/esm/tests/cors/http-api.browser.js +0 -60
- package/dist/esm/tests/cors/http-api.browser.js.map +0 -1
- package/dist/esm/tests/cors/ping.browser.d.ts +0 -2
- package/dist/esm/tests/cors/ping.browser.d.ts.map +0 -1
- package/dist/esm/tests/cors/ping.browser.js +0 -7
- package/dist/esm/tests/cors/ping.browser.js.map +0 -1
- package/dist/esm/tests/dwn-process-message.spec.d.ts +0 -2
- package/dist/esm/tests/dwn-process-message.spec.d.ts.map +0 -1
- package/dist/esm/tests/dwn-process-message.spec.js +0 -172
- package/dist/esm/tests/dwn-process-message.spec.js.map +0 -1
- package/dist/esm/tests/dwn-server.spec.d.ts +0 -2
- package/dist/esm/tests/dwn-server.spec.d.ts.map +0 -1
- package/dist/esm/tests/dwn-server.spec.js +0 -49
- package/dist/esm/tests/dwn-server.spec.js.map +0 -1
- package/dist/esm/tests/http-api.spec.d.ts +0 -2
- package/dist/esm/tests/http-api.spec.d.ts.map +0 -1
- package/dist/esm/tests/http-api.spec.js +0 -775
- package/dist/esm/tests/http-api.spec.js.map +0 -1
- package/dist/esm/tests/json-rpc-socket.spec.d.ts +0 -2
- package/dist/esm/tests/json-rpc-socket.spec.d.ts.map +0 -1
- package/dist/esm/tests/json-rpc-socket.spec.js +0 -225
- package/dist/esm/tests/json-rpc-socket.spec.js.map +0 -1
- package/dist/esm/tests/plugins/data-store-sqlite.d.ts +0 -17
- package/dist/esm/tests/plugins/data-store-sqlite.d.ts.map +0 -1
- package/dist/esm/tests/plugins/data-store-sqlite.js +0 -23
- package/dist/esm/tests/plugins/data-store-sqlite.js.map +0 -1
- package/dist/esm/tests/plugins/event-log-sqlite.d.ts +0 -17
- package/dist/esm/tests/plugins/event-log-sqlite.d.ts.map +0 -1
- package/dist/esm/tests/plugins/event-log-sqlite.js +0 -23
- package/dist/esm/tests/plugins/event-log-sqlite.js.map +0 -1
- package/dist/esm/tests/plugins/event-stream-in-memory.d.ts +0 -17
- package/dist/esm/tests/plugins/event-stream-in-memory.d.ts.map +0 -1
- package/dist/esm/tests/plugins/event-stream-in-memory.js +0 -21
- package/dist/esm/tests/plugins/event-stream-in-memory.js.map +0 -1
- package/dist/esm/tests/plugins/message-store-sqlite.d.ts +0 -17
- package/dist/esm/tests/plugins/message-store-sqlite.d.ts.map +0 -1
- package/dist/esm/tests/plugins/message-store-sqlite.js +0 -23
- package/dist/esm/tests/plugins/message-store-sqlite.js.map +0 -1
- package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts +0 -17
- package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts.map +0 -1
- package/dist/esm/tests/plugins/resumable-task-store-sqlite.js +0 -23
- package/dist/esm/tests/plugins/resumable-task-store-sqlite.js.map +0 -1
- package/dist/esm/tests/process-handler.spec.d.ts +0 -2
- package/dist/esm/tests/process-handler.spec.d.ts.map +0 -1
- package/dist/esm/tests/process-handler.spec.js +0 -60
- package/dist/esm/tests/process-handler.spec.js.map +0 -1
- package/dist/esm/tests/registration/proof-of-work-manager.spec.d.ts +0 -2
- package/dist/esm/tests/registration/proof-of-work-manager.spec.d.ts.map +0 -1
- package/dist/esm/tests/registration/proof-of-work-manager.spec.js +0 -157
- package/dist/esm/tests/registration/proof-of-work-manager.spec.js.map +0 -1
- package/dist/esm/tests/rpc-subscribe-close.spec.d.ts +0 -2
- package/dist/esm/tests/rpc-subscribe-close.spec.d.ts.map +0 -1
- package/dist/esm/tests/rpc-subscribe-close.spec.js +0 -81
- package/dist/esm/tests/rpc-subscribe-close.spec.js.map +0 -1
- package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.d.ts +0 -2
- package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.d.ts.map +0 -1
- package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js +0 -73
- package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js.map +0 -1
- package/dist/esm/tests/scenarios/registration.spec.d.ts +0 -2
- package/dist/esm/tests/scenarios/registration.spec.d.ts.map +0 -1
- package/dist/esm/tests/scenarios/registration.spec.js +0 -507
- package/dist/esm/tests/scenarios/registration.spec.js.map +0 -1
- package/dist/esm/tests/scenarios/web5-connect.spec.d.ts +0 -2
- package/dist/esm/tests/scenarios/web5-connect.spec.d.ts.map +0 -1
- package/dist/esm/tests/scenarios/web5-connect.spec.js +0 -137
- package/dist/esm/tests/scenarios/web5-connect.spec.js.map +0 -1
- package/dist/esm/tests/test-dwn.d.ts +0 -7
- package/dist/esm/tests/test-dwn.d.ts.map +0 -1
- package/dist/esm/tests/test-dwn.js +0 -34
- package/dist/esm/tests/test-dwn.js.map +0 -1
- package/dist/esm/tests/utils.d.ts +0 -46
- package/dist/esm/tests/utils.d.ts.map +0 -1
- package/dist/esm/tests/utils.js +0 -116
- package/dist/esm/tests/utils.js.map +0 -1
- package/dist/esm/tests/ws-api.spec.d.ts +0 -2
- package/dist/esm/tests/ws-api.spec.d.ts.map +0 -1
- package/dist/esm/tests/ws-api.spec.js +0 -327
- package/dist/esm/tests/ws-api.spec.js.map +0 -1
- package/src/json-rpc-socket.ts +0 -155
- package/src/lib/http-server-shutdown-handler.ts +0 -79
- package/src/lib/json-rpc.ts +0 -126
- package/src/registration/proof-of-work-types.ts +0 -7
- package/src/registration/registration-types.ts +0 -18
|
@@ -1,775 +0,0 @@
|
|
|
1
|
-
// node.js 18 and earlier, needs globalThis.crypto polyfill
|
|
2
|
-
import sinon from 'sinon';
|
|
3
|
-
import { DataStream, DwnErrorCode, ProtocolsConfigure, RecordsQuery, TestDataGenerator, Time, } from '@enbox/dwn-sdk-js';
|
|
4
|
-
import { expect } from 'chai';
|
|
5
|
-
import fetch from 'node-fetch';
|
|
6
|
-
import { webcrypto } from 'node:crypto';
|
|
7
|
-
import { useFakeTimers } from 'sinon';
|
|
8
|
-
import request from 'supertest';
|
|
9
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
-
import { config } from '../src/config.js';
|
|
11
|
-
import log from 'loglevel';
|
|
12
|
-
import { HttpApi } from '../src/http-api.js';
|
|
13
|
-
import { createJsonRpcRequest, JsonRpcErrorCodes, } from '../src/lib/json-rpc.js';
|
|
14
|
-
import { getTestDwn } from './test-dwn.js';
|
|
15
|
-
import { createRecordsWriteMessage, getDwnResponse, getFileAsReadStream, } from './utils.js';
|
|
16
|
-
import { RegistrationManager } from '../src/registration/registration-manager.js';
|
|
17
|
-
import CommonScenarioValidator from './common-scenario-validator.js';
|
|
18
|
-
import { Convert } from '@enbox/common';
|
|
19
|
-
if (!globalThis.crypto) {
|
|
20
|
-
// @ts-ignore
|
|
21
|
-
globalThis.crypto = webcrypto;
|
|
22
|
-
}
|
|
23
|
-
describe('http api', function () {
|
|
24
|
-
let httpApi;
|
|
25
|
-
let alice;
|
|
26
|
-
let registrationManager;
|
|
27
|
-
let dwn;
|
|
28
|
-
let clock;
|
|
29
|
-
before(async function () {
|
|
30
|
-
clock = useFakeTimers({ shouldAdvanceTime: true });
|
|
31
|
-
// TODO: Remove direct use of default config to avoid changes bleed/pollute between tests - https://github.com/TBD54566975/dwn-server/issues/144
|
|
32
|
-
config.registrationStoreUrl = 'sqlite://';
|
|
33
|
-
config.registrationProofOfWorkEnabled = true;
|
|
34
|
-
config.termsOfServiceFilePath = './tests/fixtures/terms-of-service.txt';
|
|
35
|
-
config.registrationProofOfWorkInitialMaxHash = '0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'; // 1 in 16 chance of solving
|
|
36
|
-
// RegistrationManager creation
|
|
37
|
-
const registrationStoreUrl = config.registrationStoreUrl;
|
|
38
|
-
const termsOfServiceFilePath = config.termsOfServiceFilePath;
|
|
39
|
-
const proofOfWorkInitialMaximumAllowedHash = config.registrationProofOfWorkInitialMaxHash;
|
|
40
|
-
registrationManager = await RegistrationManager.create({ registrationStoreUrl, termsOfServiceFilePath, proofOfWorkInitialMaximumAllowedHash });
|
|
41
|
-
dwn = await getTestDwn({ tenantGate: registrationManager });
|
|
42
|
-
httpApi = await HttpApi.create(config, dwn, registrationManager);
|
|
43
|
-
});
|
|
44
|
-
beforeEach(async function () {
|
|
45
|
-
sinon.restore();
|
|
46
|
-
await httpApi.start(3000);
|
|
47
|
-
// generate a new persona for each test to avoid state pollution
|
|
48
|
-
alice = await TestDataGenerator.generateDidKeyPersona();
|
|
49
|
-
await registrationManager.recordTenantRegistration({ did: alice.did, termsOfServiceHash: registrationManager.getTermsOfServiceHash() });
|
|
50
|
-
});
|
|
51
|
-
afterEach(async function () {
|
|
52
|
-
await httpApi.close();
|
|
53
|
-
});
|
|
54
|
-
after(function () {
|
|
55
|
-
sinon.restore();
|
|
56
|
-
clock.restore();
|
|
57
|
-
});
|
|
58
|
-
describe('/ (rpc)', function () {
|
|
59
|
-
it('responds with a 400 if no dwn-request header is provided', async function () {
|
|
60
|
-
const response = await request(httpApi.api).post('/').send();
|
|
61
|
-
expect(response.statusCode).to.equal(400);
|
|
62
|
-
const body = response.body;
|
|
63
|
-
expect(body.error.code).to.equal(JsonRpcErrorCodes.BadRequest);
|
|
64
|
-
expect(body.error.message).to.equal('request payload required.');
|
|
65
|
-
});
|
|
66
|
-
it('responds with a 400 if parsing dwn request fails', async function () {
|
|
67
|
-
const response = await request(httpApi.api)
|
|
68
|
-
.post('/')
|
|
69
|
-
.set('dwn-request', ';;;;@!#@!$$#!@%')
|
|
70
|
-
.send();
|
|
71
|
-
expect(response.statusCode).to.equal(400);
|
|
72
|
-
const body = response.body;
|
|
73
|
-
expect(body.error.code).to.equal(JsonRpcErrorCodes.BadRequest);
|
|
74
|
-
expect(body.error.message).to.include('JSON');
|
|
75
|
-
});
|
|
76
|
-
it('responds with a 2XX HTTP status if JSON RPC handler returns 4XX/5XX DWN status code', async function () {
|
|
77
|
-
const { recordsWrite, dataStream } = await createRecordsWriteMessage(alice);
|
|
78
|
-
// Intentionally delete a required property to produce an invalid RecordsWrite message.
|
|
79
|
-
const message = recordsWrite.toJSON();
|
|
80
|
-
delete message['descriptor']['interface'];
|
|
81
|
-
const requestId = uuidv4();
|
|
82
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
83
|
-
message: message,
|
|
84
|
-
target: alice.did,
|
|
85
|
-
});
|
|
86
|
-
const dataBytes = await DataStream.toBytes(dataStream);
|
|
87
|
-
// Attempt an initial RecordsWrite with the invalid message to ensure the DWN returns an error.
|
|
88
|
-
const responseInitialWrite = await fetch('http://localhost:3000', {
|
|
89
|
-
method: 'POST',
|
|
90
|
-
headers: {
|
|
91
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
92
|
-
},
|
|
93
|
-
body: new Blob([dataBytes]),
|
|
94
|
-
});
|
|
95
|
-
expect(responseInitialWrite.status).to.equal(200);
|
|
96
|
-
const body = (await responseInitialWrite.json());
|
|
97
|
-
expect(body.id).to.equal(requestId);
|
|
98
|
-
expect(body.error).to.not.exist;
|
|
99
|
-
const { reply } = body.result;
|
|
100
|
-
expect(reply.status.code).to.equal(400);
|
|
101
|
-
expect(reply.status.detail).to.include('Both interface and method must be present');
|
|
102
|
-
});
|
|
103
|
-
it('exposes dwn-response header', async function () {
|
|
104
|
-
// This test verifies that the Express web server includes `dwn-response` in the list of
|
|
105
|
-
// `access-control-expose-headers` returned in each HTTP response. This is necessary to enable applications
|
|
106
|
-
// that have CORS enabled to read and parse DWeb Messages that are returned as Response headers, particularly
|
|
107
|
-
// in the case of RecordsRead messages.
|
|
108
|
-
// TODO: github.com/TBD54566975/dwn-server/issues/50
|
|
109
|
-
// Consider replacing this test with a more robust method of testing, such as writing Playwright tests
|
|
110
|
-
// that run in a browser to verify that the `dwn-response` header can be read from the `fetch()` response
|
|
111
|
-
// when CORS mode is enabled.
|
|
112
|
-
const response = await request(httpApi.api).post('/').send();
|
|
113
|
-
// Check if the 'access-control-expose-headers' header is present
|
|
114
|
-
expect(response.headers).to.have.property('access-control-expose-headers');
|
|
115
|
-
// Check if the 'dwn-response' header is listed in 'access-control-expose-headers'
|
|
116
|
-
const exposedHeaders = response.headers['access-control-expose-headers'];
|
|
117
|
-
expect(exposedHeaders).to.include('dwn-response');
|
|
118
|
-
});
|
|
119
|
-
it('works fine when no request body is provided', async function () {
|
|
120
|
-
const recordsQuery = await RecordsQuery.create({
|
|
121
|
-
filter: {
|
|
122
|
-
schema: 'woosa',
|
|
123
|
-
},
|
|
124
|
-
signer: alice.signer,
|
|
125
|
-
});
|
|
126
|
-
const requestId = uuidv4();
|
|
127
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
128
|
-
message: recordsQuery.toJSON(),
|
|
129
|
-
target: alice.did,
|
|
130
|
-
});
|
|
131
|
-
const response = await request(httpApi.api)
|
|
132
|
-
.post('/')
|
|
133
|
-
.set('dwn-request', JSON.stringify(dwnRequest))
|
|
134
|
-
.send();
|
|
135
|
-
expect(response.statusCode).to.equal(200);
|
|
136
|
-
expect(response.body.id).to.equal(requestId);
|
|
137
|
-
expect(response.body.error).to.not.exist;
|
|
138
|
-
expect(response.body.result.reply.status.code).to.equal(200);
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
describe('P0 Scenarios', function () {
|
|
142
|
-
it('should be able to read and write a protocol record', async function () {
|
|
143
|
-
await CommonScenarioValidator.sanityTestDwnReadWrite(config.baseUrl, alice);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
describe('RecordsWrite', function () {
|
|
147
|
-
it('handles RecordsWrite overwrite that does not mutate data', async function () {
|
|
148
|
-
// First RecordsWrite that creates the record.
|
|
149
|
-
const { recordsWrite: initialWrite, dataStream } = await createRecordsWriteMessage(alice);
|
|
150
|
-
const dataBytes = await DataStream.toBytes(dataStream);
|
|
151
|
-
let requestId = uuidv4();
|
|
152
|
-
let dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
153
|
-
message: initialWrite.toJSON(),
|
|
154
|
-
target: alice.did,
|
|
155
|
-
});
|
|
156
|
-
const responseInitialWrite = await fetch('http://localhost:3000', {
|
|
157
|
-
method: 'POST',
|
|
158
|
-
headers: {
|
|
159
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
160
|
-
},
|
|
161
|
-
body: new Blob([dataBytes]),
|
|
162
|
-
});
|
|
163
|
-
expect(responseInitialWrite.status).to.equal(200);
|
|
164
|
-
// Waiting for minimal time to make sure subsequent RecordsWrite has a later timestamp.
|
|
165
|
-
await Time.minimalSleep();
|
|
166
|
-
// Subsequent RecordsWrite that mutates the published property of the record.
|
|
167
|
-
const { recordsWrite: overWrite } = await createRecordsWriteMessage(alice, {
|
|
168
|
-
recordId: initialWrite.message.recordId,
|
|
169
|
-
dataCid: initialWrite.message.descriptor.dataCid,
|
|
170
|
-
dataSize: initialWrite.message.descriptor.dataSize,
|
|
171
|
-
dateCreated: initialWrite.message.descriptor.dateCreated,
|
|
172
|
-
published: true,
|
|
173
|
-
});
|
|
174
|
-
requestId = uuidv4();
|
|
175
|
-
dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
176
|
-
message: overWrite.toJSON(),
|
|
177
|
-
target: alice.did,
|
|
178
|
-
});
|
|
179
|
-
const responseOverwrite = await fetch('http://localhost:3000', {
|
|
180
|
-
method: 'POST',
|
|
181
|
-
headers: {
|
|
182
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
183
|
-
},
|
|
184
|
-
});
|
|
185
|
-
expect(responseOverwrite.status).to.equal(200);
|
|
186
|
-
const body = (await responseOverwrite.json());
|
|
187
|
-
expect(body.error).to.not.exist;
|
|
188
|
-
expect(body.id).to.equal(requestId);
|
|
189
|
-
expect(body.error).to.not.exist;
|
|
190
|
-
const { reply } = body.result;
|
|
191
|
-
expect(reply.status.code).to.equal(202);
|
|
192
|
-
});
|
|
193
|
-
it('handles a RecordsWrite tombstone', async function () {
|
|
194
|
-
const { recordsWrite: tombstone } = await createRecordsWriteMessage(alice);
|
|
195
|
-
const requestId = uuidv4();
|
|
196
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
197
|
-
message: tombstone.toJSON(),
|
|
198
|
-
target: alice.did,
|
|
199
|
-
});
|
|
200
|
-
const responeTombstone = await fetch('http://localhost:3000', {
|
|
201
|
-
method: 'POST',
|
|
202
|
-
headers: {
|
|
203
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
204
|
-
},
|
|
205
|
-
});
|
|
206
|
-
expect(responeTombstone.status).to.equal(200);
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
describe('health check', function () {
|
|
210
|
-
it('returns a health check', async function () {
|
|
211
|
-
const response = await fetch('http://localhost:3000/health', {
|
|
212
|
-
method: 'GET',
|
|
213
|
-
});
|
|
214
|
-
expect(response.status).to.equal(200);
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
describe('default http get response', function () {
|
|
218
|
-
it('returns returns a default message', async function () {
|
|
219
|
-
const response = await fetch('http://localhost:3000/', {
|
|
220
|
-
method: 'GET',
|
|
221
|
-
});
|
|
222
|
-
expect(response.status).to.equal(200);
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
describe('/:did/records/:id', function () {
|
|
226
|
-
it('returns record data if record is published', async function () {
|
|
227
|
-
const filePath = './fixtures/test.jpeg';
|
|
228
|
-
const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
|
|
229
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice, {
|
|
230
|
-
dataCid: expectedCid,
|
|
231
|
-
dataSize: size,
|
|
232
|
-
published: true,
|
|
233
|
-
});
|
|
234
|
-
const requestId = uuidv4();
|
|
235
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
236
|
-
message: recordsWrite.toJSON(),
|
|
237
|
-
target: alice.did,
|
|
238
|
-
});
|
|
239
|
-
let response = await fetch('http://localhost:3000', {
|
|
240
|
-
method: 'POST',
|
|
241
|
-
headers: {
|
|
242
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
243
|
-
},
|
|
244
|
-
body: stream,
|
|
245
|
-
});
|
|
246
|
-
expect(response.status).to.equal(200);
|
|
247
|
-
const body = (await response.json());
|
|
248
|
-
expect(body.id).to.equal(requestId);
|
|
249
|
-
expect(body.error).to.not.exist;
|
|
250
|
-
const { reply } = body.result;
|
|
251
|
-
expect(reply.status.code).to.equal(202);
|
|
252
|
-
response = await fetch(`http://localhost:3000/${alice.did}/records/${recordsWrite.message.recordId}`);
|
|
253
|
-
const blob = await response.blob();
|
|
254
|
-
expect(blob.size).to.equal(size);
|
|
255
|
-
});
|
|
256
|
-
it('returns a 404 if an unpublished record is requested', async function () {
|
|
257
|
-
const filePath = './fixtures/test.jpeg';
|
|
258
|
-
const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
|
|
259
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice, {
|
|
260
|
-
dataCid: expectedCid,
|
|
261
|
-
dataSize: size,
|
|
262
|
-
});
|
|
263
|
-
const requestId = uuidv4();
|
|
264
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
265
|
-
message: recordsWrite.toJSON(),
|
|
266
|
-
target: alice.did,
|
|
267
|
-
});
|
|
268
|
-
let response = await fetch('http://localhost:3000', {
|
|
269
|
-
method: 'POST',
|
|
270
|
-
headers: {
|
|
271
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
272
|
-
},
|
|
273
|
-
body: stream,
|
|
274
|
-
});
|
|
275
|
-
expect(response.status).to.equal(200);
|
|
276
|
-
const body = (await response.json());
|
|
277
|
-
expect(body.id).to.equal(requestId);
|
|
278
|
-
expect(body.error).to.not.exist;
|
|
279
|
-
const { reply } = body.result;
|
|
280
|
-
expect(reply.status.code).to.equal(202);
|
|
281
|
-
response = await fetch(`http://localhost:3000/${alice.did}/records/${recordsWrite.message.recordId}`);
|
|
282
|
-
expect(response.status).to.equal(404);
|
|
283
|
-
});
|
|
284
|
-
it('returns a 404 if record does not exist', async function () {
|
|
285
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice);
|
|
286
|
-
const response = await fetch(`http://localhost:3000/${alice.did}/records/${recordsWrite.message.recordId}`);
|
|
287
|
-
expect(response.status).to.equal(404);
|
|
288
|
-
});
|
|
289
|
-
it('returns a 404 for invalid or unauthorized did', async function () {
|
|
290
|
-
const unauthorized = await TestDataGenerator.generateDidKeyPersona();
|
|
291
|
-
const { recordsWrite } = await createRecordsWriteMessage(unauthorized);
|
|
292
|
-
const response = await fetch(`http://localhost:3000/${unauthorized.did}/records/${recordsWrite.message.recordId}`);
|
|
293
|
-
expect(response.status).to.equal(404);
|
|
294
|
-
});
|
|
295
|
-
it('returns a 404 for invalid record id', async function () {
|
|
296
|
-
const response = await fetch(`http://localhost:3000/${alice.did}/records/kaka`);
|
|
297
|
-
expect(response.status).to.equal(404);
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
describe('/:did/read/records/:id', function () {
|
|
301
|
-
it('returns record data if record is published', async function () {
|
|
302
|
-
const filePath = './fixtures/test.jpeg';
|
|
303
|
-
const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
|
|
304
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice, {
|
|
305
|
-
dataCid: expectedCid,
|
|
306
|
-
dataSize: size,
|
|
307
|
-
published: true,
|
|
308
|
-
});
|
|
309
|
-
const requestId = uuidv4();
|
|
310
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
311
|
-
message: recordsWrite.toJSON(),
|
|
312
|
-
target: alice.did,
|
|
313
|
-
});
|
|
314
|
-
let response = await fetch('http://localhost:3000', {
|
|
315
|
-
method: 'POST',
|
|
316
|
-
headers: {
|
|
317
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
318
|
-
},
|
|
319
|
-
body: stream,
|
|
320
|
-
});
|
|
321
|
-
expect(response.status).to.equal(200);
|
|
322
|
-
const body = (await response.json());
|
|
323
|
-
expect(body.id).to.equal(requestId);
|
|
324
|
-
expect(body.error).to.not.exist;
|
|
325
|
-
const { reply } = body.result;
|
|
326
|
-
expect(reply.status.code).to.equal(202);
|
|
327
|
-
response = await fetch(`http://localhost:3000/${alice.did}/read/records/${recordsWrite.message.recordId}`);
|
|
328
|
-
const blob = await response.blob();
|
|
329
|
-
expect(blob.size).to.equal(size);
|
|
330
|
-
});
|
|
331
|
-
it('returns a 404 if an unpublished record is requested', async function () {
|
|
332
|
-
const filePath = './fixtures/test.jpeg';
|
|
333
|
-
const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
|
|
334
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice, {
|
|
335
|
-
dataCid: expectedCid,
|
|
336
|
-
dataSize: size,
|
|
337
|
-
});
|
|
338
|
-
const requestId = uuidv4();
|
|
339
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
340
|
-
message: recordsWrite.toJSON(),
|
|
341
|
-
target: alice.did,
|
|
342
|
-
});
|
|
343
|
-
let response = await fetch('http://localhost:3000', {
|
|
344
|
-
method: 'POST',
|
|
345
|
-
headers: {
|
|
346
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
347
|
-
},
|
|
348
|
-
body: stream,
|
|
349
|
-
});
|
|
350
|
-
expect(response.status).to.equal(200);
|
|
351
|
-
const body = (await response.json());
|
|
352
|
-
expect(body.id).to.equal(requestId);
|
|
353
|
-
expect(body.error).to.not.exist;
|
|
354
|
-
const { reply } = body.result;
|
|
355
|
-
expect(reply.status.code).to.equal(202);
|
|
356
|
-
response = await fetch(`http://localhost:3000/${alice.did}/read/records/${recordsWrite.message.recordId}`);
|
|
357
|
-
expect(response.status).to.equal(404);
|
|
358
|
-
});
|
|
359
|
-
it('returns a 404 if record does not exist', async function () {
|
|
360
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice);
|
|
361
|
-
const response = await fetch(`http://localhost:3000/${alice.did}/read/records/${recordsWrite.message.recordId}`);
|
|
362
|
-
expect(response.status).to.equal(404);
|
|
363
|
-
});
|
|
364
|
-
it('returns a 404 for invalid or unauthorized did', async function () {
|
|
365
|
-
const unauthorized = await TestDataGenerator.generateDidKeyPersona();
|
|
366
|
-
const { recordsWrite } = await createRecordsWriteMessage(unauthorized);
|
|
367
|
-
const response = await fetch(`http://localhost:3000/${unauthorized.did}/read/records/${recordsWrite.message.recordId}`);
|
|
368
|
-
expect(response.status).to.equal(404);
|
|
369
|
-
});
|
|
370
|
-
it('returns a 404 for invalid record id', async function () {
|
|
371
|
-
const response = await fetch(`http://localhost:3000/${alice.did}/read/records/kaka`);
|
|
372
|
-
expect(response.status).to.equal(404);
|
|
373
|
-
});
|
|
374
|
-
});
|
|
375
|
-
describe('/:did/read/protocols/:protocol', function () {
|
|
376
|
-
it('returns protocol definition if protocol is published', async function () {
|
|
377
|
-
// Create and publish a protocol
|
|
378
|
-
const protocolConfigure = await ProtocolsConfigure.create({
|
|
379
|
-
definition: {
|
|
380
|
-
protocol: 'http://example.com/protocol',
|
|
381
|
-
published: true,
|
|
382
|
-
types: {
|
|
383
|
-
foo: {},
|
|
384
|
-
},
|
|
385
|
-
structure: {
|
|
386
|
-
foo: {}
|
|
387
|
-
}
|
|
388
|
-
},
|
|
389
|
-
signer: alice.signer,
|
|
390
|
-
});
|
|
391
|
-
const requestId = uuidv4();
|
|
392
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
393
|
-
message: protocolConfigure.toJSON(),
|
|
394
|
-
target: alice.did,
|
|
395
|
-
});
|
|
396
|
-
const response = await fetch('http://localhost:3000', {
|
|
397
|
-
method: 'POST',
|
|
398
|
-
headers: {
|
|
399
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
400
|
-
},
|
|
401
|
-
});
|
|
402
|
-
expect(response.status).to.equal(200);
|
|
403
|
-
// Fetch the protocol definition using the HTTP API
|
|
404
|
-
const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
|
|
405
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}`;
|
|
406
|
-
const protocolQueryResponse = await fetch(protocolUrl);
|
|
407
|
-
expect(protocolQueryResponse.status).to.equal(200);
|
|
408
|
-
// get the JSON response
|
|
409
|
-
const protocolConfigureReply = await protocolQueryResponse.json();
|
|
410
|
-
expect(protocolConfigureReply.descriptor).to.deep.equal(protocolConfigure.message.descriptor);
|
|
411
|
-
});
|
|
412
|
-
it('returns a 404 if protocol is not published', async function () {
|
|
413
|
-
// Create a not-published protocol
|
|
414
|
-
const protocolConfigure = await ProtocolsConfigure.create({
|
|
415
|
-
definition: {
|
|
416
|
-
protocol: 'http://example.com/protocol',
|
|
417
|
-
published: false,
|
|
418
|
-
types: {
|
|
419
|
-
foo: {},
|
|
420
|
-
},
|
|
421
|
-
structure: {
|
|
422
|
-
foo: {}
|
|
423
|
-
}
|
|
424
|
-
},
|
|
425
|
-
signer: alice.signer,
|
|
426
|
-
});
|
|
427
|
-
const requestId = uuidv4();
|
|
428
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
429
|
-
message: protocolConfigure.toJSON(),
|
|
430
|
-
target: alice.did,
|
|
431
|
-
});
|
|
432
|
-
const response = await fetch('http://localhost:3000', {
|
|
433
|
-
method: 'POST',
|
|
434
|
-
headers: {
|
|
435
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
436
|
-
},
|
|
437
|
-
});
|
|
438
|
-
expect(response.status).to.equal(200);
|
|
439
|
-
// Fetch the protocol definition using the HTTP API
|
|
440
|
-
const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
|
|
441
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}`;
|
|
442
|
-
const protocolQueryResponse = await fetch(protocolUrl);
|
|
443
|
-
expect(protocolQueryResponse.status).to.equal(404);
|
|
444
|
-
});
|
|
445
|
-
it('returns a 400 if protocol is not base64url encoded', async function () {
|
|
446
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/invalid-protocol`;
|
|
447
|
-
const protocolQueryResponse = await fetch(protocolUrl);
|
|
448
|
-
expect(protocolQueryResponse.status).to.equal(400);
|
|
449
|
-
expect(await protocolQueryResponse.text()).to.equal('Bad Request');
|
|
450
|
-
});
|
|
451
|
-
});
|
|
452
|
-
describe('/:did/query/protocols', function () {
|
|
453
|
-
it('returns protocol definition if protocol is published', async function () {
|
|
454
|
-
// create two protocol definitions, one published and one not
|
|
455
|
-
const protocolConfigurePublished = await ProtocolsConfigure.create({
|
|
456
|
-
definition: {
|
|
457
|
-
protocol: 'http://example.com/protocol',
|
|
458
|
-
published: true,
|
|
459
|
-
types: {
|
|
460
|
-
foo: {},
|
|
461
|
-
},
|
|
462
|
-
structure: {
|
|
463
|
-
foo: {}
|
|
464
|
-
}
|
|
465
|
-
},
|
|
466
|
-
signer: alice.signer,
|
|
467
|
-
});
|
|
468
|
-
const requestId = uuidv4();
|
|
469
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
470
|
-
message: protocolConfigurePublished.toJSON(),
|
|
471
|
-
target: alice.did,
|
|
472
|
-
});
|
|
473
|
-
const response = await fetch('http://localhost:3000', {
|
|
474
|
-
method: 'POST',
|
|
475
|
-
headers: {
|
|
476
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
477
|
-
},
|
|
478
|
-
});
|
|
479
|
-
expect(response.status).to.equal(200);
|
|
480
|
-
const protocolConfigureNotPublished = await ProtocolsConfigure.create({
|
|
481
|
-
definition: {
|
|
482
|
-
protocol: 'http://example.com/protocol2',
|
|
483
|
-
published: false,
|
|
484
|
-
types: {
|
|
485
|
-
foo: {},
|
|
486
|
-
},
|
|
487
|
-
structure: {
|
|
488
|
-
foo: {}
|
|
489
|
-
}
|
|
490
|
-
},
|
|
491
|
-
signer: alice.signer,
|
|
492
|
-
});
|
|
493
|
-
const requestId2 = uuidv4();
|
|
494
|
-
const dwnRequest2 = createJsonRpcRequest(requestId2, 'dwn.processMessage', {
|
|
495
|
-
message: protocolConfigureNotPublished.toJSON(),
|
|
496
|
-
target: alice.did,
|
|
497
|
-
});
|
|
498
|
-
const response2 = await fetch('http://localhost:3000', {
|
|
499
|
-
method: 'POST',
|
|
500
|
-
headers: {
|
|
501
|
-
'dwn-request': JSON.stringify(dwnRequest2),
|
|
502
|
-
},
|
|
503
|
-
});
|
|
504
|
-
expect(response2.status).to.equal(200);
|
|
505
|
-
// now query for a list of protocols
|
|
506
|
-
const protocolQueryUrl = `http://localhost:3000/${alice.did}/query/protocols`;
|
|
507
|
-
const protocolQueryResponse = await fetch(protocolQueryUrl);
|
|
508
|
-
expect(protocolQueryResponse.status).to.equal(200);
|
|
509
|
-
// get the JSON response
|
|
510
|
-
const protocolQueryReply = await protocolQueryResponse.json();
|
|
511
|
-
expect(protocolQueryReply).to.have.lengthOf(1);
|
|
512
|
-
// check that the published protocol is returned
|
|
513
|
-
expect(protocolQueryReply[0].descriptor).to.deep.equal(protocolConfigurePublished.message.descriptor);
|
|
514
|
-
});
|
|
515
|
-
});
|
|
516
|
-
describe('/:did/read/protocols/:protocol/*', function () {
|
|
517
|
-
it('returns record for a given protocol and protocolPath that is published', async function () {
|
|
518
|
-
// Create and publish a protocol
|
|
519
|
-
const protocolConfigure = await ProtocolsConfigure.create({
|
|
520
|
-
definition: {
|
|
521
|
-
protocol: 'http://example.com/protocol',
|
|
522
|
-
published: true,
|
|
523
|
-
types: {
|
|
524
|
-
foo: {},
|
|
525
|
-
},
|
|
526
|
-
structure: {
|
|
527
|
-
foo: {}
|
|
528
|
-
}
|
|
529
|
-
},
|
|
530
|
-
signer: alice.signer,
|
|
531
|
-
});
|
|
532
|
-
const requestId = uuidv4();
|
|
533
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
534
|
-
message: protocolConfigure.toJSON(),
|
|
535
|
-
target: alice.did,
|
|
536
|
-
});
|
|
537
|
-
const response = await fetch('http://localhost:3000', {
|
|
538
|
-
method: 'POST',
|
|
539
|
-
headers: {
|
|
540
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
541
|
-
},
|
|
542
|
-
});
|
|
543
|
-
expect(response.status).to.equal(200);
|
|
544
|
-
// Create a foo record
|
|
545
|
-
const filePath = './fixtures/test.jpeg';
|
|
546
|
-
const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
|
|
547
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice, {
|
|
548
|
-
dataCid: expectedCid,
|
|
549
|
-
dataSize: size,
|
|
550
|
-
published: true,
|
|
551
|
-
protocol: protocolConfigure.message.descriptor.definition.protocol,
|
|
552
|
-
protocolPath: 'foo',
|
|
553
|
-
});
|
|
554
|
-
const recordsWriteRequestId = uuidv4();
|
|
555
|
-
const recordsWriteDwnRequest = createJsonRpcRequest(recordsWriteRequestId, 'dwn.processMessage', {
|
|
556
|
-
message: recordsWrite.toJSON(),
|
|
557
|
-
target: alice.did,
|
|
558
|
-
});
|
|
559
|
-
const recordsWriteResponse = await fetch('http://localhost:3000', {
|
|
560
|
-
method: 'POST',
|
|
561
|
-
headers: {
|
|
562
|
-
'dwn-request': JSON.stringify(recordsWriteDwnRequest),
|
|
563
|
-
},
|
|
564
|
-
body: stream,
|
|
565
|
-
});
|
|
566
|
-
expect(recordsWriteResponse.status).to.equal(200);
|
|
567
|
-
const responseJson = await recordsWriteResponse.json();
|
|
568
|
-
expect(responseJson.result.reply.status.code).to.equal(202);
|
|
569
|
-
// Fetch the record using the HTTP API
|
|
570
|
-
const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
|
|
571
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/foo`;
|
|
572
|
-
const recordReadResponse = await fetch(protocolUrl);
|
|
573
|
-
expect(recordReadResponse.status).to.equal(200);
|
|
574
|
-
// get the data response
|
|
575
|
-
const blob = await recordReadResponse.blob();
|
|
576
|
-
expect(blob.size).to.equal(size);
|
|
577
|
-
// get dwn message response
|
|
578
|
-
const { status, entry } = getDwnResponse(recordReadResponse);
|
|
579
|
-
expect(status.code).to.equal(200);
|
|
580
|
-
expect(entry).to.exist;
|
|
581
|
-
expect(entry.recordsWrite.recordId).to.equal(recordsWrite.message.recordId);
|
|
582
|
-
});
|
|
583
|
-
it('removes the trailing slash from the protocol path', async function () {
|
|
584
|
-
const recordsQueryCreateSpy = sinon.spy(RecordsQuery, 'create');
|
|
585
|
-
const base64urlEncodedProtocol = Convert.string('http://example.com/protocol').toBase64Url();
|
|
586
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/foo/`; // trailing slash
|
|
587
|
-
const recordReadResponse = await fetch(protocolUrl);
|
|
588
|
-
expect(recordReadResponse.status).to.equal(404);
|
|
589
|
-
expect(recordsQueryCreateSpy.calledOnce).to.be.true;
|
|
590
|
-
const recordsQueryFilter = recordsQueryCreateSpy.getCall(0).args[0].filter;
|
|
591
|
-
expect(recordsQueryFilter.protocolPath).to.equal('foo');
|
|
592
|
-
});
|
|
593
|
-
it('returns a 404 if record for a given protocol and protocolPath is not published', async function () {
|
|
594
|
-
// Create and publish a protocol
|
|
595
|
-
const protocolConfigure = await ProtocolsConfigure.create({
|
|
596
|
-
definition: {
|
|
597
|
-
protocol: 'http://example.com/protocol',
|
|
598
|
-
published: true,
|
|
599
|
-
types: {
|
|
600
|
-
foo: {},
|
|
601
|
-
},
|
|
602
|
-
structure: {
|
|
603
|
-
foo: {}
|
|
604
|
-
}
|
|
605
|
-
},
|
|
606
|
-
signer: alice.signer,
|
|
607
|
-
});
|
|
608
|
-
const requestId = uuidv4();
|
|
609
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
610
|
-
message: protocolConfigure.toJSON(),
|
|
611
|
-
target: alice.did,
|
|
612
|
-
});
|
|
613
|
-
const response = await fetch('http://localhost:3000', {
|
|
614
|
-
method: 'POST',
|
|
615
|
-
headers: {
|
|
616
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
617
|
-
},
|
|
618
|
-
});
|
|
619
|
-
expect(response.status).to.equal(200);
|
|
620
|
-
// Create a foo record
|
|
621
|
-
const filePath = './fixtures/test.jpeg';
|
|
622
|
-
const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
|
|
623
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice, {
|
|
624
|
-
dataCid: expectedCid,
|
|
625
|
-
dataSize: size,
|
|
626
|
-
published: false, // not published
|
|
627
|
-
protocol: protocolConfigure.message.descriptor.definition.protocol,
|
|
628
|
-
protocolPath: 'foo',
|
|
629
|
-
});
|
|
630
|
-
const recordsWriteRequestId = uuidv4();
|
|
631
|
-
const recordsWriteDwnRequest = createJsonRpcRequest(recordsWriteRequestId, 'dwn.processMessage', {
|
|
632
|
-
message: recordsWrite.toJSON(),
|
|
633
|
-
target: alice.did,
|
|
634
|
-
});
|
|
635
|
-
const recordsWriteResponse = await fetch('http://localhost:3000', {
|
|
636
|
-
method: 'POST',
|
|
637
|
-
headers: {
|
|
638
|
-
'dwn-request': JSON.stringify(recordsWriteDwnRequest),
|
|
639
|
-
},
|
|
640
|
-
body: stream,
|
|
641
|
-
});
|
|
642
|
-
expect(recordsWriteResponse.status).to.equal(200);
|
|
643
|
-
const responseJson = await recordsWriteResponse.json();
|
|
644
|
-
expect(responseJson.result.reply.status.code).to.equal(202);
|
|
645
|
-
// Fetch the record using the HTTP API
|
|
646
|
-
const base64urlEncodedProtocol = Convert.string(protocolConfigure.message.descriptor.definition.protocol).toBase64Url();
|
|
647
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/foo`;
|
|
648
|
-
const recordReadResponse = await fetch(protocolUrl);
|
|
649
|
-
expect(recordReadResponse.status).to.equal(404);
|
|
650
|
-
});
|
|
651
|
-
it('returns a 400 if protocol path is not provided', async function () {
|
|
652
|
-
// Fetch a protocol record without providing a protocol path
|
|
653
|
-
const base64urlEncodedProtocol = Convert.string('http://example.com/protocol').toBase64Url();
|
|
654
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/${base64urlEncodedProtocol}/`; // missing protocol path
|
|
655
|
-
const recordReadResponse = await fetch(protocolUrl);
|
|
656
|
-
expect(recordReadResponse.status).to.equal(400);
|
|
657
|
-
expect(await recordReadResponse.text()).to.equal('protocol path is required');
|
|
658
|
-
});
|
|
659
|
-
it('returns a 400 error if protocol cannot be base64url encoded', async function () {
|
|
660
|
-
const protocolUrl = `http://localhost:3000/${alice.did}/read/protocols/invalid-protocol/foo`;
|
|
661
|
-
const recordReadResponse = await fetch(protocolUrl);
|
|
662
|
-
expect(recordReadResponse.status).to.equal(400);
|
|
663
|
-
expect(await recordReadResponse.text()).to.equal('Bad Request');
|
|
664
|
-
});
|
|
665
|
-
});
|
|
666
|
-
describe('/:did/query', function () {
|
|
667
|
-
it('returns record data if record is published', async function () {
|
|
668
|
-
const filePath = './fixtures/test.jpeg';
|
|
669
|
-
const { cid: expectedCid, size, stream, } = await getFileAsReadStream(filePath);
|
|
670
|
-
const { recordsWrite } = await createRecordsWriteMessage(alice, {
|
|
671
|
-
dataCid: expectedCid,
|
|
672
|
-
dataSize: size,
|
|
673
|
-
published: true,
|
|
674
|
-
});
|
|
675
|
-
const requestId = uuidv4();
|
|
676
|
-
const dwnRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
677
|
-
message: recordsWrite.toJSON(),
|
|
678
|
-
target: alice.did,
|
|
679
|
-
});
|
|
680
|
-
const response = await fetch('http://localhost:3000', {
|
|
681
|
-
method: 'POST',
|
|
682
|
-
headers: {
|
|
683
|
-
'dwn-request': JSON.stringify(dwnRequest),
|
|
684
|
-
},
|
|
685
|
-
body: stream,
|
|
686
|
-
});
|
|
687
|
-
expect(response.status).to.equal(200);
|
|
688
|
-
const body = (await response.json());
|
|
689
|
-
expect(body.id).to.equal(requestId);
|
|
690
|
-
expect(body.error).to.not.exist;
|
|
691
|
-
const { reply } = body.result;
|
|
692
|
-
expect(reply.status.code).to.equal(202);
|
|
693
|
-
const { entries } = await fetch(`http://localhost:3000/${alice.did}/query?filter.recordId=${recordsWrite.message.recordId}&other.random.param=unused-value`).then(response => response.json());
|
|
694
|
-
expect(entries?.length).to.equal(1);
|
|
695
|
-
});
|
|
696
|
-
it('should return 400 if user provide invalid query', async function () {
|
|
697
|
-
const response = await fetch(`http://localhost:3000/${alice.did}/query?filter=invalid-filter`);
|
|
698
|
-
expect(response.status).to.equal(400);
|
|
699
|
-
const responseBody = await response.json();
|
|
700
|
-
expect(responseBody.code).to.equal(DwnErrorCode.SchemaValidatorAdditionalPropertyNotAllowed);
|
|
701
|
-
});
|
|
702
|
-
});
|
|
703
|
-
describe('/info', function () {
|
|
704
|
-
it('verify /info has some of the fields it is supposed to have', async function () {
|
|
705
|
-
const resp = await fetch(`http://localhost:3000/info`);
|
|
706
|
-
expect(resp.status).to.equal(200);
|
|
707
|
-
const info = await resp.json();
|
|
708
|
-
expect(info['url']).to.equal('http://localhost:3000');
|
|
709
|
-
expect(info['server']).to.equal('@enbox/dwn-server');
|
|
710
|
-
expect(info['registrationRequirements']).to.include('terms-of-service');
|
|
711
|
-
expect(info['registrationRequirements']).to.include('proof-of-work-sha256-v0');
|
|
712
|
-
});
|
|
713
|
-
it('verify /info signals websocket support', async function () {
|
|
714
|
-
let resp = await fetch(`http://localhost:3000/info`);
|
|
715
|
-
expect(resp.status).to.equal(200);
|
|
716
|
-
let info = await resp.json();
|
|
717
|
-
expect(info['server']).to.equal('@enbox/dwn-server');
|
|
718
|
-
expect(info['webSocketSupport']).to.equal(true);
|
|
719
|
-
// start server without websocket support enabled
|
|
720
|
-
await httpApi.close();
|
|
721
|
-
config.webSocketSupport = false;
|
|
722
|
-
httpApi = await HttpApi.create(config, dwn, registrationManager);
|
|
723
|
-
await httpApi.start(3000);
|
|
724
|
-
resp = await fetch(`http://localhost:3000/info`);
|
|
725
|
-
expect(resp.status).to.equal(200);
|
|
726
|
-
info = await resp.json();
|
|
727
|
-
expect(info['server']).to.equal('@enbox/dwn-server');
|
|
728
|
-
expect(info['webSocketSupport']).to.equal(false);
|
|
729
|
-
// restore old config value
|
|
730
|
-
config.webSocketSupport = true;
|
|
731
|
-
});
|
|
732
|
-
it('verify /info still returns when package.json file does not exist', async function () {
|
|
733
|
-
await httpApi.close();
|
|
734
|
-
// set up spy to check for an info log by the server
|
|
735
|
-
const logSpy = sinon.spy(log, 'info');
|
|
736
|
-
// set the config to an invalid file path
|
|
737
|
-
const packageJsonConfig = config.packageJsonPath;
|
|
738
|
-
config.packageJsonPath = '/some/invalid/file.json';
|
|
739
|
-
httpApi = await HttpApi.create(config, dwn, registrationManager);
|
|
740
|
-
await httpApi.start(3000);
|
|
741
|
-
const resp = await fetch(`http://localhost:3000/info`);
|
|
742
|
-
const info = await resp.json();
|
|
743
|
-
expect(resp.status).to.equal(200);
|
|
744
|
-
// check that server name exists in the info object
|
|
745
|
-
expect(info['server']).to.equal('@enbox/dwn-server');
|
|
746
|
-
// check that `sdkVersion` and `version` are undefined as they were not abel to be retrieved from the invalid file.
|
|
747
|
-
expect(info['sdkVersion']).to.be.undefined;
|
|
748
|
-
expect(info['version']).to.be.undefined;
|
|
749
|
-
// check the logSpy was called
|
|
750
|
-
expect(logSpy.callCount).to.be.gt(0);
|
|
751
|
-
expect(logSpy.calledWith(sinon.match('could not read `package.json` for version info'))).to.be.true;
|
|
752
|
-
// restore old config path
|
|
753
|
-
config.packageJsonPath = packageJsonConfig;
|
|
754
|
-
});
|
|
755
|
-
it('verify /info returns server name from config', async function () {
|
|
756
|
-
await httpApi.close();
|
|
757
|
-
// set a custom name for the `serverName`
|
|
758
|
-
const serverName = config.serverName;
|
|
759
|
-
config.serverName = '@enbox/dwn-server-2';
|
|
760
|
-
httpApi = await HttpApi.create(config, dwn, registrationManager);
|
|
761
|
-
await httpApi.start(3000);
|
|
762
|
-
const resp = await fetch(`http://localhost:3000/info`);
|
|
763
|
-
const info = await resp.json();
|
|
764
|
-
expect(resp.status).to.equal(200);
|
|
765
|
-
// verify that the custom server name was passed to the info endpoint
|
|
766
|
-
expect(info['server']).to.equal('@enbox/dwn-server-2');
|
|
767
|
-
// verify that `sdkVersion` and `version` exist.
|
|
768
|
-
expect(info['sdkVersion']).to.not.be.undefined;
|
|
769
|
-
expect(info['version']).to.not.be.undefined;
|
|
770
|
-
// restore server name config
|
|
771
|
-
config.serverName = serverName;
|
|
772
|
-
});
|
|
773
|
-
});
|
|
774
|
-
});
|
|
775
|
-
//# sourceMappingURL=http-api.spec.js.map
|