@enbox/dwn-server 0.0.3 → 0.0.5

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