@toa.io/extensions.exposition 1.0.0-alpha.4 → 1.0.0-alpha.41

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 (398) hide show
  1. package/components/context.toa.yaml +2 -2
  2. package/components/identity.bans/manifest.toa.yaml +15 -7
  3. package/components/identity.bans/operations/transit.d.ts +14 -0
  4. package/components/identity.bans/operations/transit.js +11 -0
  5. package/components/identity.bans/operations/transit.js.map +1 -0
  6. package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -0
  7. package/components/identity.bans/source/transit.ts +21 -0
  8. package/components/identity.bans/tsconfig.json +9 -0
  9. package/components/identity.basic/manifest.toa.yaml +22 -9
  10. package/components/identity.basic/operations/authenticate.d.ts +5 -1
  11. package/components/identity.basic/operations/authenticate.js +5 -2
  12. package/components/identity.basic/operations/authenticate.js.map +1 -1
  13. package/components/identity.basic/operations/incept.d.ts +12 -0
  14. package/components/identity.basic/operations/incept.js +26 -0
  15. package/components/identity.basic/operations/incept.js.map +1 -0
  16. package/components/identity.basic/operations/transit.d.ts +4 -4
  17. package/components/identity.basic/operations/transit.js +5 -3
  18. package/components/identity.basic/operations/transit.js.map +1 -1
  19. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  20. package/components/identity.basic/operations/types.d.ts +8 -4
  21. package/components/identity.basic/source/authenticate.ts +16 -5
  22. package/components/identity.basic/source/incept.ts +38 -0
  23. package/components/identity.basic/source/transit.ts +8 -6
  24. package/components/identity.basic/source/types.ts +8 -4
  25. package/components/identity.federation/manifest.toa.yaml +28 -22
  26. package/components/identity.federation/operations/authenticate.d.ts +2 -2
  27. package/components/identity.federation/operations/authenticate.js +3 -10
  28. package/components/identity.federation/operations/authenticate.js.map +1 -1
  29. package/components/identity.federation/operations/incept.d.ts +11 -0
  30. package/components/identity.federation/operations/{create.js → incept.js} +6 -7
  31. package/components/identity.federation/operations/incept.js.map +1 -0
  32. package/components/identity.federation/operations/lib/jwt.d.ts +4 -5
  33. package/components/identity.federation/operations/lib/jwt.js +3 -3
  34. package/components/identity.federation/operations/lib/jwt.js.map +1 -1
  35. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  36. package/components/identity.federation/operations/types/configuration.d.ts +14 -0
  37. package/components/identity.federation/operations/types/configuration.js +3 -0
  38. package/components/identity.federation/operations/types/configuration.js.map +1 -0
  39. package/components/identity.federation/operations/{types.d.ts → types/context.d.ts} +13 -6
  40. package/components/identity.federation/operations/types/context.js +3 -0
  41. package/components/identity.federation/operations/types/context.js.map +1 -0
  42. package/components/identity.federation/operations/types/entity.d.ts +6 -0
  43. package/components/identity.federation/operations/{types.js → types/entity.js} +1 -1
  44. package/components/identity.federation/operations/types/entity.js.map +1 -0
  45. package/components/identity.federation/operations/types/index.d.ts +3 -0
  46. package/components/identity.federation/operations/types/index.js +20 -0
  47. package/components/identity.federation/operations/types/index.js.map +1 -0
  48. package/components/identity.federation/source/authenticate.ts +5 -18
  49. package/components/identity.federation/source/{create.ts → incept.ts} +10 -9
  50. package/components/identity.federation/source/lib/jwt.test.ts +2 -2
  51. package/components/identity.federation/source/lib/jwt.ts +7 -8
  52. package/components/identity.federation/source/types/configuration.ts +15 -0
  53. package/components/identity.federation/source/{types.ts → types/context.ts} +15 -5
  54. package/components/identity.federation/source/types/entity.ts +6 -0
  55. package/components/identity.federation/source/types/index.ts +3 -0
  56. package/components/identity.federation/tsconfig.json +2 -2
  57. package/components/identity.roles/manifest.toa.yaml +18 -6
  58. package/components/identity.roles/operations/grant.d.ts +10 -0
  59. package/components/identity.roles/operations/grant.js +21 -0
  60. package/components/identity.roles/operations/grant.js.map +1 -0
  61. package/components/identity.roles/operations/lib/Entity.d.ts +5 -0
  62. package/components/identity.roles/operations/lib/Entity.js +3 -0
  63. package/components/identity.roles/operations/lib/Entity.js.map +1 -0
  64. package/components/identity.roles/operations/list.d.ts +1 -4
  65. package/components/identity.roles/operations/list.js.map +1 -1
  66. package/components/identity.roles/operations/principal.d.ts +4 -6
  67. package/components/identity.roles/operations/principal.js +6 -1
  68. package/components/identity.roles/operations/principal.js.map +1 -1
  69. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  70. package/components/identity.roles/source/grant.ts +32 -0
  71. package/components/identity.roles/source/lib/Entity.ts +5 -0
  72. package/components/identity.roles/source/list.ts +2 -4
  73. package/components/identity.roles/source/principal.ts +10 -8
  74. package/components/identity.tokens/manifest.toa.yaml +19 -5
  75. package/components/identity.tokens/operations/authenticate.d.ts +2 -2
  76. package/components/identity.tokens/operations/authenticate.js +10 -4
  77. package/components/identity.tokens/operations/authenticate.js.map +1 -1
  78. package/components/identity.tokens/operations/decrypt.js +1 -0
  79. package/components/identity.tokens/operations/decrypt.js.map +1 -1
  80. package/components/identity.tokens/operations/encrypt.js +5 -1
  81. package/components/identity.tokens/operations/encrypt.js.map +1 -1
  82. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  83. package/components/identity.tokens/operations/types.d.ts +8 -2
  84. package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
  85. package/components/identity.tokens/source/authenticate.test.ts +11 -4
  86. package/components/identity.tokens/source/authenticate.ts +12 -5
  87. package/components/identity.tokens/source/decrypt.test.ts +5 -3
  88. package/components/identity.tokens/source/decrypt.ts +9 -8
  89. package/components/identity.tokens/source/encrypt.test.ts +26 -2
  90. package/components/identity.tokens/source/encrypt.ts +5 -1
  91. package/components/identity.tokens/source/types.ts +9 -2
  92. package/components/octets.storage/manifest.toa.yaml +0 -7
  93. package/documentation/access.md +27 -16
  94. package/documentation/authorities.md +53 -0
  95. package/documentation/cache.md +8 -1
  96. package/documentation/components.md +47 -22
  97. package/documentation/identity.md +17 -22
  98. package/documentation/io.md +56 -0
  99. package/documentation/protocol.md +3 -0
  100. package/documentation/query.md +17 -11
  101. package/documentation/require.md +15 -0
  102. package/documentation/tree.md +22 -4
  103. package/documentation/vary.md +14 -14
  104. package/features/access.feature +89 -47
  105. package/features/annotation.feature +2 -0
  106. package/features/authorities.basic.feature +141 -0
  107. package/features/authorities.feature +32 -0
  108. package/features/authorities.federation.feature +99 -0
  109. package/features/authorities.tokens.feature +118 -0
  110. package/features/body.feature +4 -0
  111. package/features/cache.feature +112 -5
  112. package/features/cors.feature +7 -2
  113. package/features/debug.feature +34 -0
  114. package/features/directives.feature +5 -0
  115. package/features/dynamic.feature +18 -7
  116. package/features/errors.feature +18 -4
  117. package/features/etag.feature +18 -1
  118. package/features/identity.bans.feature +137 -0
  119. package/features/identity.basic.feature +142 -19
  120. package/features/identity.feature +7 -2
  121. package/features/identity.federation.feature +67 -14
  122. package/features/identity.roles.feature +220 -4
  123. package/features/identity.tokens.feature +57 -4
  124. package/features/io.feature +205 -0
  125. package/features/octets.entries.feature +10 -0
  126. package/features/octets.feature +60 -64
  127. package/features/octets.meta.feature +7 -3
  128. package/features/octets.workflows.feature +14 -0
  129. package/features/probes.feature +14 -0
  130. package/features/{queries.feature → query.feature} +50 -3
  131. package/features/require.feature +67 -0
  132. package/features/response.feature +12 -3
  133. package/features/routes.feature +25 -12
  134. package/features/steps/Database.ts +17 -10
  135. package/features/steps/Gateway.ts +23 -6
  136. package/features/steps/IdP.ts +28 -23
  137. package/features/steps/components/echo/manifest.toa.yaml +5 -1
  138. package/features/steps/components/echo/operations/identity.js +7 -0
  139. package/features/steps/components/pots/manifest.toa.yaml +2 -0
  140. package/features/steps/components/users.properties/manifest.toa.yaml +2 -1
  141. package/features/streams.feature +1 -0
  142. package/features/timing.feature +27 -1
  143. package/features/vary.feature +105 -3
  144. package/package.json +12 -11
  145. package/readme.md +19 -14
  146. package/schemas/annotation.cos.yaml +1 -1
  147. package/schemas/io/input.cos.yaml +3 -0
  148. package/schemas/io/message.cos.yaml +5 -0
  149. package/schemas/io/output.cos.yaml +5 -0
  150. package/source/Annotation.ts +3 -3
  151. package/source/Context.ts +6 -4
  152. package/source/Directive.test.ts +4 -4
  153. package/source/Directive.ts +11 -38
  154. package/source/Endpoint.ts +43 -8
  155. package/source/Factory.ts +11 -7
  156. package/source/Gateway.ts +16 -44
  157. package/source/HTTP/Context.ts +24 -2
  158. package/source/HTTP/Server.ts +56 -43
  159. package/source/HTTP/exceptions.ts +7 -1
  160. package/source/HTTP/messages.test.ts +38 -2
  161. package/source/HTTP/messages.ts +7 -3
  162. package/source/Mapping.ts +6 -1
  163. package/source/Query.test.ts +1 -1
  164. package/source/Query.ts +35 -24
  165. package/source/RTD/Context.ts +7 -10
  166. package/source/RTD/Directives.ts +28 -4
  167. package/source/RTD/Endpoint.ts +6 -4
  168. package/source/RTD/Match.ts +2 -7
  169. package/source/RTD/Method.ts +7 -13
  170. package/source/RTD/Node.ts +13 -14
  171. package/source/RTD/Tree.ts +17 -16
  172. package/source/RTD/factory.ts +3 -6
  173. package/source/Tenant.ts +0 -8
  174. package/source/deployment.ts +32 -22
  175. package/source/directives/auth/Authorization.ts +38 -19
  176. package/source/directives/auth/Delegate.ts +42 -0
  177. package/source/directives/auth/Incept.ts +3 -2
  178. package/source/directives/auth/Role.test.ts +53 -6
  179. package/source/directives/auth/Role.ts +22 -14
  180. package/source/directives/auth/types.ts +1 -1
  181. package/source/directives/cache/Cache.ts +15 -8
  182. package/source/directives/cache/Control.ts +42 -16
  183. package/source/directives/cors/CORS.ts +13 -7
  184. package/source/directives/dev/Development.ts +4 -4
  185. package/source/directives/index.ts +6 -4
  186. package/source/directives/io/Directive.ts +11 -0
  187. package/source/directives/io/IO.ts +43 -0
  188. package/source/directives/io/Input.ts +50 -0
  189. package/source/directives/io/Message.ts +1 -0
  190. package/source/directives/io/Output.ts +69 -0
  191. package/source/directives/io/index.ts +3 -0
  192. package/source/directives/io/schemas.ts +12 -0
  193. package/source/directives/octets/Context.ts +4 -3
  194. package/source/directives/octets/Delete.ts +4 -2
  195. package/source/directives/octets/Directive.ts +10 -0
  196. package/source/directives/octets/Fetch.ts +4 -3
  197. package/source/directives/octets/List.ts +4 -2
  198. package/source/directives/octets/Octets.ts +6 -8
  199. package/source/directives/octets/Store.ts +12 -4
  200. package/source/directives/octets/Workflow.ts +10 -3
  201. package/source/directives/octets/types.ts +0 -7
  202. package/source/directives/require/Directive.ts +5 -0
  203. package/source/directives/require/Headers.ts +20 -0
  204. package/source/directives/require/Require.ts +28 -0
  205. package/source/directives/require/index.ts +3 -0
  206. package/source/directives/vary/Directive.ts +2 -1
  207. package/source/directives/vary/Embed.ts +14 -8
  208. package/source/directives/vary/Vary.ts +7 -5
  209. package/source/directives/vary/embeddings/Authority.ts +8 -0
  210. package/source/directives/vary/embeddings/Embedding.ts +2 -1
  211. package/source/directives/vary/embeddings/Header.ts +8 -6
  212. package/source/directives/vary/embeddings/Language.ts +1 -1
  213. package/source/directives/vary/embeddings/Parameter.ts +14 -0
  214. package/source/directives/vary/embeddings/index.ts +6 -4
  215. package/source/exceptions.ts +22 -11
  216. package/source/root.ts +5 -0
  217. package/source/schemas.ts +1 -1
  218. package/transpiled/Annotation.d.ts +3 -3
  219. package/transpiled/Context.d.ts +6 -4
  220. package/transpiled/Directive.d.ts +4 -17
  221. package/transpiled/Directive.js +4 -7
  222. package/transpiled/Directive.js.map +1 -1
  223. package/transpiled/Endpoint.d.ts +5 -3
  224. package/transpiled/Endpoint.js +30 -5
  225. package/transpiled/Endpoint.js.map +1 -1
  226. package/transpiled/Factory.js +9 -4
  227. package/transpiled/Factory.js.map +1 -1
  228. package/transpiled/Gateway.d.ts +1 -4
  229. package/transpiled/Gateway.js +10 -26
  230. package/transpiled/Gateway.js.map +1 -1
  231. package/transpiled/HTTP/Context.d.ts +8 -1
  232. package/transpiled/HTTP/Context.js +15 -2
  233. package/transpiled/HTTP/Context.js.map +1 -1
  234. package/transpiled/HTTP/Server.d.ts +13 -2
  235. package/transpiled/HTTP/Server.js +41 -35
  236. package/transpiled/HTTP/Server.js.map +1 -1
  237. package/transpiled/HTTP/exceptions.d.ts +4 -1
  238. package/transpiled/HTTP/exceptions.js +7 -1
  239. package/transpiled/HTTP/exceptions.js.map +1 -1
  240. package/transpiled/HTTP/messages.d.ts +1 -0
  241. package/transpiled/HTTP/messages.js +9 -3
  242. package/transpiled/HTTP/messages.js.map +1 -1
  243. package/transpiled/Mapping.js +4 -1
  244. package/transpiled/Mapping.js.map +1 -1
  245. package/transpiled/Query.d.ts +1 -0
  246. package/transpiled/Query.js +21 -20
  247. package/transpiled/Query.js.map +1 -1
  248. package/transpiled/RTD/Context.d.ts +7 -6
  249. package/transpiled/RTD/Directives.d.ts +19 -4
  250. package/transpiled/RTD/Endpoint.d.ts +6 -4
  251. package/transpiled/RTD/Match.d.ts +2 -4
  252. package/transpiled/RTD/Method.d.ts +7 -7
  253. package/transpiled/RTD/Method.js.map +1 -1
  254. package/transpiled/RTD/Node.d.ts +4 -6
  255. package/transpiled/RTD/Node.js +2 -1
  256. package/transpiled/RTD/Node.js.map +1 -1
  257. package/transpiled/RTD/Tree.d.ts +6 -6
  258. package/transpiled/RTD/Tree.js +4 -1
  259. package/transpiled/RTD/Tree.js.map +1 -1
  260. package/transpiled/RTD/factory.d.ts +2 -4
  261. package/transpiled/RTD/factory.js +1 -1
  262. package/transpiled/RTD/factory.js.map +1 -1
  263. package/transpiled/Tenant.d.ts +0 -1
  264. package/transpiled/Tenant.js +0 -6
  265. package/transpiled/Tenant.js.map +1 -1
  266. package/transpiled/deployment.d.ts +1 -1
  267. package/transpiled/deployment.js +28 -20
  268. package/transpiled/deployment.js.map +1 -1
  269. package/transpiled/directives/auth/Authorization.d.ts +2 -3
  270. package/transpiled/directives/auth/Authorization.js +26 -12
  271. package/transpiled/directives/auth/Authorization.js.map +1 -1
  272. package/transpiled/directives/auth/Delegate.d.ts +10 -0
  273. package/transpiled/directives/auth/Delegate.js +34 -0
  274. package/transpiled/directives/auth/Delegate.js.map +1 -0
  275. package/transpiled/directives/auth/Incept.js +3 -2
  276. package/transpiled/directives/auth/Incept.js.map +1 -1
  277. package/transpiled/directives/auth/Role.d.ts +4 -1
  278. package/transpiled/directives/auth/Role.js +20 -14
  279. package/transpiled/directives/auth/Role.js.map +1 -1
  280. package/transpiled/directives/cache/Cache.d.ts +5 -5
  281. package/transpiled/directives/cache/Cache.js +10 -4
  282. package/transpiled/directives/cache/Cache.js.map +1 -1
  283. package/transpiled/directives/cache/Control.d.ts +2 -1
  284. package/transpiled/directives/cache/Control.js +29 -12
  285. package/transpiled/directives/cache/Control.js.map +1 -1
  286. package/transpiled/directives/cors/CORS.d.ts +2 -3
  287. package/transpiled/directives/cors/CORS.js +13 -7
  288. package/transpiled/directives/cors/CORS.js.map +1 -1
  289. package/transpiled/directives/dev/Development.d.ts +3 -3
  290. package/transpiled/directives/dev/Development.js +1 -1
  291. package/transpiled/directives/dev/Development.js.map +1 -1
  292. package/transpiled/directives/index.d.ts +2 -2
  293. package/transpiled/directives/index.js +5 -3
  294. package/transpiled/directives/index.js.map +1 -1
  295. package/transpiled/directives/io/Directive.d.ts +8 -0
  296. package/transpiled/directives/io/Directive.js +3 -0
  297. package/transpiled/directives/io/Directive.js.map +1 -0
  298. package/transpiled/directives/io/IO.d.ts +9 -0
  299. package/transpiled/directives/io/IO.js +33 -0
  300. package/transpiled/directives/io/IO.js.map +1 -0
  301. package/transpiled/directives/io/Input.d.ts +11 -0
  302. package/transpiled/directives/{octets/Permute.js → io/Input.js} +33 -26
  303. package/transpiled/directives/io/Input.js.map +1 -0
  304. package/transpiled/directives/io/Message.d.ts +1 -0
  305. package/transpiled/directives/io/Message.js +3 -0
  306. package/transpiled/directives/io/Message.js.map +1 -0
  307. package/transpiled/directives/io/Output.d.ts +13 -0
  308. package/transpiled/directives/io/Output.js +76 -0
  309. package/transpiled/directives/io/Output.js.map +1 -0
  310. package/transpiled/directives/io/index.d.ts +2 -0
  311. package/transpiled/directives/io/index.js +6 -0
  312. package/transpiled/directives/io/index.js.map +1 -0
  313. package/transpiled/directives/io/schemas.d.ts +7 -0
  314. package/transpiled/directives/io/schemas.js +14 -0
  315. package/transpiled/directives/io/schemas.js.map +1 -0
  316. package/transpiled/directives/octets/Context.d.ts +3 -3
  317. package/transpiled/directives/octets/Context.js +4 -2
  318. package/transpiled/directives/octets/Context.js.map +1 -1
  319. package/transpiled/directives/octets/Delete.d.ts +3 -2
  320. package/transpiled/directives/octets/Delete.js +3 -1
  321. package/transpiled/directives/octets/Delete.js.map +1 -1
  322. package/transpiled/directives/octets/Directive.d.ts +8 -0
  323. package/transpiled/directives/octets/Directive.js +8 -0
  324. package/transpiled/directives/octets/Directive.js.map +1 -0
  325. package/transpiled/directives/octets/Fetch.d.ts +3 -2
  326. package/transpiled/directives/octets/Fetch.js +3 -1
  327. package/transpiled/directives/octets/Fetch.js.map +1 -1
  328. package/transpiled/directives/octets/List.d.ts +3 -2
  329. package/transpiled/directives/octets/List.js +3 -1
  330. package/transpiled/directives/octets/List.js.map +1 -1
  331. package/transpiled/directives/octets/Octets.d.ts +4 -4
  332. package/transpiled/directives/octets/Octets.js +2 -4
  333. package/transpiled/directives/octets/Octets.js.map +1 -1
  334. package/transpiled/directives/octets/Store.d.ts +3 -2
  335. package/transpiled/directives/octets/Store.js +10 -3
  336. package/transpiled/directives/octets/Store.js.map +1 -1
  337. package/transpiled/directives/octets/Workflow.d.ts +3 -2
  338. package/transpiled/directives/octets/Workflow.js +9 -2
  339. package/transpiled/directives/octets/Workflow.js.map +1 -1
  340. package/transpiled/directives/octets/types.d.ts +0 -5
  341. package/transpiled/directives/require/Directive.d.ts +4 -0
  342. package/transpiled/directives/require/Directive.js +3 -0
  343. package/transpiled/directives/require/Directive.js.map +1 -0
  344. package/transpiled/directives/require/Headers.d.ts +7 -0
  345. package/transpiled/directives/require/Headers.js +19 -0
  346. package/transpiled/directives/require/Headers.js.map +1 -0
  347. package/transpiled/directives/require/Require.d.ts +9 -0
  348. package/transpiled/directives/require/Require.js +27 -0
  349. package/transpiled/directives/require/Require.js.map +1 -0
  350. package/transpiled/directives/require/index.d.ts +2 -0
  351. package/transpiled/directives/require/index.js +6 -0
  352. package/transpiled/directives/require/index.js.map +1 -0
  353. package/transpiled/directives/vary/Directive.d.ts +2 -1
  354. package/transpiled/directives/vary/Embed.d.ts +2 -1
  355. package/transpiled/directives/vary/Embed.js +8 -6
  356. package/transpiled/directives/vary/Embed.js.map +1 -1
  357. package/transpiled/directives/vary/Vary.d.ts +3 -3
  358. package/transpiled/directives/vary/Vary.js +3 -3
  359. package/transpiled/directives/vary/Vary.js.map +1 -1
  360. package/transpiled/directives/vary/embeddings/Authority.d.ts +5 -0
  361. package/transpiled/directives/vary/embeddings/Authority.js +10 -0
  362. package/transpiled/directives/vary/embeddings/Authority.js.map +1 -0
  363. package/transpiled/directives/vary/embeddings/Embedding.d.ts +2 -1
  364. package/transpiled/directives/vary/embeddings/Header.js +8 -6
  365. package/transpiled/directives/vary/embeddings/Header.js.map +1 -1
  366. package/transpiled/directives/vary/embeddings/Language.js +1 -1
  367. package/transpiled/directives/vary/embeddings/Language.js.map +1 -1
  368. package/transpiled/directives/vary/embeddings/Parameter.d.ts +7 -0
  369. package/transpiled/directives/vary/embeddings/Parameter.js +14 -0
  370. package/transpiled/directives/vary/embeddings/Parameter.js.map +1 -0
  371. package/transpiled/directives/vary/embeddings/index.d.ts +2 -2
  372. package/transpiled/directives/vary/embeddings/index.js +8 -4
  373. package/transpiled/directives/vary/embeddings/index.js.map +1 -1
  374. package/transpiled/exceptions.d.ts +3 -2
  375. package/transpiled/exceptions.js +13 -7
  376. package/transpiled/exceptions.js.map +1 -1
  377. package/transpiled/root.js +5 -0
  378. package/transpiled/root.js.map +1 -1
  379. package/transpiled/schemas.d.ts +1 -1
  380. package/transpiled/schemas.js +2 -2
  381. package/transpiled/schemas.js.map +1 -1
  382. package/transpiled/tsconfig.tsbuildinfo +1 -1
  383. package/components/identity.basic/operations/create.d.ts +0 -10
  384. package/components/identity.basic/operations/create.js +0 -10
  385. package/components/identity.basic/operations/create.js.map +0 -1
  386. package/components/identity.basic/source/create.ts +0 -18
  387. package/components/identity.federation/operations/create.d.ts +0 -10
  388. package/components/identity.federation/operations/create.js.map +0 -1
  389. package/components/identity.federation/operations/schemas.d.ts +0 -59
  390. package/components/identity.federation/operations/schemas.js +0 -9
  391. package/components/identity.federation/operations/schemas.js.map +0 -1
  392. package/components/identity.federation/operations/types.js.map +0 -1
  393. package/components/identity.federation/source/schemas.ts +0 -61
  394. package/components/octets.storage/operations/permute.js +0 -7
  395. package/source/HTTP/Server.test.ts +0 -126
  396. package/source/directives/octets/Permute.ts +0 -43
  397. package/transpiled/directives/octets/Permute.d.ts +0 -10
  398. package/transpiled/directives/octets/Permute.js.map +0 -1
@@ -1,11 +1,13 @@
1
1
  import { type Context } from './Context'
2
+ import type * as http from '../HTTP'
2
3
  import type * as syntax from './syntax'
4
+ import type * as RTD from './index'
3
5
 
4
- export interface Endpoint<T extends Endpoint = any> {
5
- call: T['call']
6
+ export interface Endpoint {
7
+ call: (context: http.Context, parameters: RTD.Parameter[]) => Promise<http.OutgoingMessage>
6
8
  close: () => Promise<void>
7
9
  }
8
10
 
9
- export interface EndpointsFactory<T extends Endpoint<T> = any> {
10
- create: (method: syntax.Method, context: Context) => T
11
+ export interface EndpointsFactory {
12
+ create: (method: syntax.Method, context: Context) => Endpoint
11
13
  }
@@ -1,12 +1,7 @@
1
1
  import { type Node } from './Node'
2
- import { type Directives } from './Directives'
3
- import { type Endpoint } from './Endpoint'
4
2
 
5
- export interface Match<
6
- TEndpoint extends Endpoint<TEndpoint> = any,
7
- TDirectives extends Directives<TDirectives> = any
8
- > {
9
- node: Node<TEndpoint, TDirectives>
3
+ export interface Match {
4
+ node: Node
10
5
  parameters: Parameter[]
11
6
  }
12
7
 
@@ -1,14 +1,11 @@
1
- import { type Directives } from './Directives'
2
- import { type Endpoint } from './Endpoint'
1
+ import type { Endpoint } from './Endpoint'
2
+ import type { Directives } from './Directives'
3
3
 
4
- export class Method<
5
- TEndpoint extends Endpoint<TEndpoint> = any,
6
- TDirectives extends Directives<TDirectives> = any
7
- > {
8
- public readonly endpoint: TEndpoint | null
9
- public readonly directives: TDirectives
4
+ export class Method {
5
+ public readonly endpoint: Endpoint | null
6
+ public readonly directives: Directives
10
7
 
11
- public constructor (endpoint: TEndpoint | null, directives: TDirectives) {
8
+ public constructor (endpoint: Endpoint | null, directives: Directives) {
12
9
  this.endpoint = endpoint
13
10
  this.directives = directives
14
11
  }
@@ -18,7 +15,4 @@ export class Method<
18
15
  }
19
16
  }
20
17
 
21
- export type Methods<
22
- TEndpoint extends Endpoint<TEndpoint> = any,
23
- TDirectives extends Directives<TDirectives> = any
24
- > = Record<string, Method<TEndpoint, TDirectives>>
18
+ export type Methods = Record<string, Method>
@@ -1,20 +1,15 @@
1
1
  import { type Route } from './Route'
2
2
  import { type Methods } from './Method'
3
3
  import { type Match, type Parameter } from './Match'
4
- import { type Directives } from './Directives'
5
- import { type Endpoint } from './Endpoint'
6
4
 
7
- export class Node<
8
- TEndpoint extends Endpoint<TEndpoint> = any,
9
- TDirectives extends Directives<TDirectives> = any
10
- > {
5
+ export class Node {
11
6
  public intermediate: boolean
12
- public methods: Methods<TEndpoint, TDirectives>
7
+ public methods: Methods
13
8
  private readonly protected: boolean
14
9
  private routes: Route[]
15
10
 
16
11
  public constructor
17
- (routes: Route[], methods: Methods<TEndpoint, TDirectives>, properties: Properties) {
12
+ (routes: Route[], methods: Methods, properties: Properties) {
18
13
  this.routes = routes
19
14
  this.methods = methods
20
15
  this.protected = properties.protected
@@ -34,26 +29,30 @@ export class Node<
34
29
  return null
35
30
  }
36
31
 
37
- public merge (node: Node<TEndpoint, TDirectives>): void {
32
+ public merge (node: Node): void {
38
33
  this.intermediate = node.intermediate
39
34
 
40
- if (!this.protected) this.replace(node)
41
- else this.append(node)
35
+ if (!this.protected)
36
+ this.replace(node)
37
+ else
38
+ this.append(node)
42
39
 
43
40
  this.sort()
44
41
  }
45
42
 
46
- private replace (node: Node<TEndpoint, TDirectives>): void {
43
+ private replace (node: Node): void {
47
44
  const methods = Object.values(this.methods)
48
45
 
49
46
  this.routes = node.routes
50
47
  this.methods = node.methods
51
48
 
52
49
  for (const method of methods)
53
- void method.close() // race condition is really unlikely
50
+ void method.close()
51
+
52
+ // race condition is really unlikely
54
53
  }
55
54
 
56
- private append (node: Node<TEndpoint, TDirectives>): void {
55
+ private append (node: Node): void {
57
56
  for (const route of node.routes)
58
57
  this.mergeRoute(route)
59
58
 
@@ -1,32 +1,32 @@
1
- import { type Node } from './Node'
2
1
  import { createNode } from './factory'
3
2
  import { fragment } from './segment'
4
- import { type Match } from './Match'
5
- import { type Context } from './Context'
6
- import { type Directives, type DirectivesFactory } from './Directives'
7
- import { type Endpoint, type EndpointsFactory } from './Endpoint'
3
+ import type { Node } from './Node'
4
+ import type { Match } from './Match'
5
+ import type { Context } from './Context'
6
+ import type { DirectiveFactory } from './Directives'
7
+ import type { EndpointsFactory } from './Endpoint'
8
8
  import type * as syntax from './syntax'
9
9
 
10
- export class Tree<
11
- TEndpoint extends Endpoint<TEndpoint> = any,
12
- TDirectives extends Directives<TDirectives> = any
13
- > {
10
+ export class Tree {
14
11
  private readonly root: syntax.Node
15
- private readonly trunk: Node<TEndpoint, TDirectives>
16
- private readonly endpoints: EndpointsFactory<TEndpoint>
17
- private readonly directives: DirectivesFactory
12
+ private readonly trunk: Node
13
+ private readonly endpoints: EndpointsFactory
14
+ private readonly directives: DirectiveFactory
18
15
 
19
16
  public constructor
20
- (node: syntax.Node, endpoints: EndpointsFactory, directives: DirectivesFactory) {
17
+ (node: syntax.Node, endpoints: EndpointsFactory, directives: DirectiveFactory) {
21
18
  this.endpoints = endpoints
22
19
  this.directives = directives
23
20
  this.trunk = this.createNode(node, PROTECTED)
24
21
  this.root = node
25
22
  }
26
23
 
27
- public match (path: string): Match<TEndpoint, TDirectives> | null {
24
+ public match (path: string): Match | null {
28
25
  if (path === '/')
29
- return { node: this.trunk, parameters: [] }
26
+ return {
27
+ node: this.trunk,
28
+ parameters: []
29
+ }
30
30
 
31
31
  const fragments = fragment(path)
32
32
 
@@ -39,7 +39,8 @@ export class Tree<
39
39
  this.trunk.merge(branch)
40
40
  }
41
41
 
42
- private createNode (node: syntax.Node, protect: boolean, extension?: any): Node {
42
+ private createNode
43
+ (node: syntax.Node, protect: boolean, extension?: any): Node {
43
44
  const context: Context = {
44
45
  protected: protect,
45
46
  endpoints: this.endpoints,
@@ -1,14 +1,11 @@
1
1
  import { Node, type Properties } from './Node'
2
2
  import { Route } from './Route'
3
- import { type Context } from './Context'
4
3
  import { segment } from './segment'
5
4
  import { Method, type Methods } from './Method'
6
- import { type Endpoint } from './Endpoint'
7
- import { type Directives } from './Directives'
5
+ import type { Context } from './Context'
8
6
  import type * as syntax from './syntax'
9
7
 
10
- export function createNode<TEndpoint extends Endpoint, TDirectives extends Directives>
11
- (node: syntax.Node, context: Context): Node<TEndpoint, TDirectives> {
8
+ export function createNode (node: syntax.Node, context: Context): Node {
12
9
  if (node.isolated === true)
13
10
  context.directives.stack = node.directives
14
11
  else
@@ -36,7 +33,7 @@ function createRoute (route: syntax.Route, context: Context): Route {
36
33
  }
37
34
 
38
35
  function createMethod (method: syntax.Method, context: Context): Method {
39
- const stack = context.directives.stack.concat(method.directives.reverse())
36
+ const stack = method.directives.concat(context.directives.stack)
40
37
  const directives = context.directives.factory.create(stack)
41
38
 
42
39
  const endpoint = method.mapping?.endpoint === undefined
package/source/Tenant.ts CHANGED
@@ -25,14 +25,6 @@ export class Tenant extends Connector {
25
25
  public override async open (): Promise<void> {
26
26
  await this.expose()
27
27
  await this.broadcast.receive('ping', this.expose.bind(this))
28
-
29
- console.info('Exposition Tenant for ' +
30
- `'${this.branch.namespace}.${this.branch.component}' has started.`)
31
- }
32
-
33
- public override async dispose (): Promise<void> {
34
- console.info('Exposition Tenant for ' +
35
- `'${this.branch.namespace}.${this.branch.component}' has been stopped.`)
36
28
  }
37
29
 
38
30
  private async expose (): Promise<void> {
@@ -1,3 +1,4 @@
1
+ import assert from 'node:assert'
1
2
  import { type Dependency, type Service } from '@toa.io/operations'
2
3
  import { encode } from '@toa.io/generic'
3
4
  import { type Annotation } from './Annotation'
@@ -5,26 +6,29 @@ import * as schemas from './schemas'
5
6
  import { shortcuts } from './Directive'
6
7
  import { components } from './Composition'
7
8
  import { parse } from './RTD/syntax'
9
+ import { DELAY, PORT } from './HTTP/Server'
10
+
11
+ export function deployment (_: unknown, annotation?: Annotation): Dependency {
12
+ assert.ok(annotation !== undefined, 'Exposition context annotation is required')
13
+ schemas.annotation.validate(annotation)
8
14
 
9
- export function deployment (_: unknown, annotation: Annotation | undefined): Dependency {
10
15
  const labels = components().labels
11
16
 
12
17
  const service: Service = {
13
18
  group: 'exposition',
14
19
  name: 'gateway',
15
- port: 8000,
20
+ port: PORT,
16
21
  // eslint-disable-next-line @typescript-eslint/no-var-requires
17
22
  version: require('../package.json').version,
18
23
  variables: [],
19
- components: labels
20
- }
21
-
22
- if (annotation?.host !== undefined)
23
- service.ingress = {
24
- host: annotation.host,
25
- class: annotation.class,
26
- annotations: annotation.annotations
24
+ components: labels,
25
+ ingress: { hosts: [] },
26
+ probe: {
27
+ path: '/.ready',
28
+ port: PORT,
29
+ delay: DELAY
27
30
  }
31
+ }
28
32
 
29
33
  if (annotation?.['/'] !== undefined) {
30
34
  const tree = parse(annotation['/'], shortcuts)
@@ -35,20 +39,26 @@ export function deployment (_: unknown, annotation: Annotation | undefined): Dep
35
39
  })
36
40
  }
37
41
 
38
- if (annotation?.debug === true)
39
- service.variables.push({
40
- name: 'TOA_EXPOSITION_DEBUG',
41
- value: '1'
42
- })
42
+ const { debug, trace, authorities } = annotation
43
43
 
44
- if (annotation?.trace === true)
45
- service.variables.push({
46
- name: 'TOA_EXPOSITION_TRACE',
47
- value: '1'
48
- })
44
+ service.ingress.hosts = Object.values(authorities)
45
+ service.ingress.class = annotation.class
46
+ service.ingress.annotations = annotation.annotations
47
+
48
+ const properties: Properties = { authorities }
49
49
 
50
- if (annotation !== undefined)
51
- schemas.annotaion.validate(annotation)
50
+ if (debug === true)
51
+ properties.debug = true
52
+
53
+ if (trace === true)
54
+ properties.trace = true
55
+
56
+ service.variables.push({
57
+ name: 'TOA_EXPOSITION_PROPERTIES',
58
+ value: encode(properties)
59
+ })
52
60
 
53
61
  return { services: [service] }
54
62
  }
63
+
64
+ type Properties = Pick<Annotation, 'authorities' | 'debug' | 'trace'>
@@ -7,14 +7,14 @@ import { Role } from './Role'
7
7
  import { Rule } from './Rule'
8
8
  import { Incept } from './Incept'
9
9
  import { Echo } from './Echo'
10
- import { split } from './split'
11
10
  import { Scheme } from './Scheme'
11
+ import { Delegate } from './Delegate'
12
+ import { split } from './split'
12
13
  import { PRIMARY, PROVIDERS } from './schemes'
13
14
  import type { Output } from '../../io'
14
15
  import type { Component } from '@toa.io/core'
15
16
  import type { Remotes } from '../../Remotes'
16
- import type { Family } from '../../Directive'
17
- import type { Parameter } from '../../RTD'
17
+ import type { Parameter, DirectiveFamily } from '../../RTD'
18
18
  import type {
19
19
  AuthenticationResult,
20
20
  Ban,
@@ -27,7 +27,7 @@ import type {
27
27
  Schemes
28
28
  } from './types'
29
29
 
30
- export class Authorization implements Family<Directive, Extension> {
30
+ export class Authorization implements DirectiveFamily<Directive, Extension> {
31
31
  public readonly depends: string[] = ['Vary']
32
32
  public readonly name: string = 'auth'
33
33
  public readonly mandatory: boolean = true
@@ -38,10 +38,10 @@ export class Authorization implements Family<Directive, Extension> {
38
38
  private bans: Component | null = null
39
39
 
40
40
  public create (name: string, value: any, remotes: Remotes): Directive {
41
- assert.ok(name in CLASSES,
42
- `Directive '${name}' is not provided by the '${this.name}' family.`)
41
+ assert.ok(name in constructors,
42
+ `Directive 'auth:${name}' is not implemented.`)
43
43
 
44
- const Class = CLASSES[name]
44
+ const Class = constructors[name]
45
45
 
46
46
  for (const name of REMOTES)
47
47
  this.discovery[name] ??= remotes.discover('identity', name)
@@ -50,13 +50,22 @@ export class Authorization implements Family<Directive, Extension> {
50
50
  Role, () => new Role(value as string | string[], this.discovery.roles),
51
51
  Rule, () => new Rule(value as Record<string, string>, this.create.bind(this)),
52
52
  Incept, () => new Incept(value as string, this.discovery),
53
+ Delegate, () => new Delegate(value as string, this.discovery.roles),
53
54
  () => new Class(value))
54
55
  }
55
56
 
56
57
  public async preflight (directives: Directive[],
57
58
  input: Input,
58
59
  parameters: Parameter[]): Promise<Output> {
59
- const identity = await this.resolve(input.request.headers.authorization)
60
+ /**
61
+ * Some authentication scheme providers may create identity during authentication;
62
+ * therefore, we need to skip the authentication process if the Incept directive is present.
63
+ *
64
+ * If the provided credentials already exist,
65
+ * the inception will cause a unique constraint violation on the settle stage.
66
+ */
67
+ const inception = directives.reduce((yes, directive) => yes || directive instanceof Incept, false)
68
+ const identity = inception ? null : await this.resolve(input.authority, input.request.headers.authorization)
60
69
 
61
70
  input.identity = identity
62
71
 
@@ -80,25 +89,31 @@ export class Authorization implements Family<Directive, Extension> {
80
89
 
81
90
  const identity = request.identity
82
91
 
83
- if (identity === null) return
92
+ if (identity === null)
93
+ return
84
94
 
85
- if (identity.scheme === PRIMARY && !identity.refresh) return
95
+ if (identity.scheme === PRIMARY && !identity.refresh)
96
+ return
86
97
 
87
98
  // Role directive may have already set the value
88
- if (identity.roles === undefined) await Role.set(identity, this.discovery.roles)
99
+ if (identity.roles === undefined)
100
+ await Role.set(identity, this.discovery.roles)
89
101
 
90
102
  this.tokens ??= await this.discovery.tokens
91
103
 
92
- const token = await this.tokens.invoke<string>('encrypt', { input: { identity } })
93
- const authorization = `Token ${token}`
104
+ const token = await this.tokens.invoke<string>('encrypt', {
105
+ input: { authority: request.authority, identity }
106
+ })
94
107
 
95
- if (response.headers === undefined) response.headers = new Headers()
108
+ const authorization = `Token ${token}`
96
109
 
110
+ response.headers ??= new Headers()
97
111
  response.headers.set('authorization', authorization)
98
112
  }
99
113
 
100
- private async resolve (authorization: string | undefined): Promise<Identity | null> {
101
- if (authorization === undefined) return null
114
+ private async resolve (authority: string, authorization: string | undefined): Promise<Identity | null> {
115
+ if (authorization === undefined)
116
+ return null
102
117
 
103
118
  const [scheme, credentials] = split(authorization)
104
119
  const provider = PROVIDERS[scheme]
@@ -109,7 +124,10 @@ export class Authorization implements Family<Directive, Extension> {
109
124
  this.schemes[scheme] ??= await this.discovery[provider]
110
125
 
111
126
  const result = await this.schemes[scheme].invoke<AuthenticationResult>('authenticate', {
112
- input: credentials
127
+ input: {
128
+ authority,
129
+ credentials
130
+ }
113
131
  })
114
132
 
115
133
  if (result instanceof Error) return null
@@ -133,14 +151,15 @@ export class Authorization implements Family<Directive, Extension> {
133
151
  }
134
152
  }
135
153
 
136
- const CLASSES: Record<string, new (value: any, argument?: any) => Directive> = {
154
+ const constructors: Record<string, new (value: any, argument?: any) => Directive> = {
137
155
  anonymous: Anonymous,
138
156
  id: Id,
139
157
  role: Role,
140
158
  rule: Rule,
141
159
  incept: Incept,
142
160
  scheme: Scheme,
143
- echo: Echo
161
+ echo: Echo,
162
+ delegate: Delegate
144
163
  }
145
164
 
146
165
  const REMOTES: Remote[] = ['basic', 'federation', 'tokens', 'roles', 'bans']
@@ -0,0 +1,42 @@
1
+ import { BadRequest } from '../../HTTP'
2
+ import { type Directive, type Identity } from './types'
3
+ import { Role } from './Role'
4
+ import type { Component } from '@toa.io/core'
5
+ import type { Input } from '../../io'
6
+
7
+ export class Delegate implements Directive {
8
+ private readonly property: string
9
+ private readonly discovery: Promise<Component>
10
+
11
+ public constructor (property: string, discovery: Promise<Component>) {
12
+ this.property = property
13
+ this.discovery = discovery
14
+ }
15
+
16
+ public async authorize (identity: Identity | null, context: Input): Promise<boolean> {
17
+ if (identity === null)
18
+ return false
19
+
20
+ if (identity.roles === undefined)
21
+ await Role.set(identity, this.discovery)
22
+
23
+ context.pipelines.body.push((body) => this.embed(body, identity))
24
+
25
+ return true
26
+ }
27
+
28
+ private embed (body: unknown, identity: Identity): Record<string, unknown> {
29
+ if (body === undefined)
30
+ body = {}
31
+
32
+ check(body)
33
+ body[this.property] = structuredClone(identity)
34
+
35
+ return body
36
+ }
37
+ }
38
+
39
+ function check (body: unknown): asserts body is Record<string, unknown> {
40
+ if (typeof body !== 'object' || body === null)
41
+ throw new BadRequest('Invalid request body')
42
+ }
@@ -31,15 +31,16 @@ export class Incept implements Directive {
31
31
  this.schemes[scheme] ??= await this.discovery[provider]
32
32
 
33
33
  const identity = await this.schemes[scheme]
34
- .invoke<Maybe<Identity>>('create', {
34
+ .invoke<Maybe<Identity>>('incept', {
35
35
  input: {
36
+ authority: input.authority,
36
37
  id,
37
38
  credentials
38
39
  }
39
40
  })
40
41
 
41
42
  if (identity instanceof Error)
42
- throw new http.Conflict(identity)
43
+ throw new http.UnprocessableEntity(identity)
43
44
 
44
45
  input.identity = identity
45
46
  input.identity.scheme = scheme
@@ -2,6 +2,7 @@ import { type Component } from '@toa.io/core'
2
2
  import { generate } from 'randomstring'
3
3
  import { Role } from './Role'
4
4
  import { type Identity } from './types'
5
+ import type { Parameter } from '../../RTD'
5
6
 
6
7
  const remote = {
7
8
  invoke: jest.fn()
@@ -16,16 +17,26 @@ beforeEach(() => {
16
17
  it('should return false if not matched', async () => {
17
18
  const roles = ['admin', 'user']
18
19
  const directive = new Role(roles, discovery)
19
- const identity: Identity = { id: generate(), scheme: '', refresh: false }
20
+
21
+ const identity: Identity = {
22
+ id: generate(),
23
+ scheme: '',
24
+ refresh: false
25
+ }
20
26
 
21
27
  remote.invoke.mockResolvedValueOnce(['guest'])
22
28
 
23
- const result = await directive.authorize(identity)
29
+ const result = await directive.authorize(identity, undefined, [])
24
30
 
25
31
  expect(result).toBe(false)
26
32
 
27
33
  expect(remote.invoke)
28
- .toBeCalledWith('list', { query: { criteria: `identity==${identity.id}`, limit: 1024 } })
34
+ .toBeCalledWith('list', {
35
+ query: {
36
+ criteria: `identity==${identity.id}`,
37
+ limit: 1024
38
+ }
39
+ })
29
40
  })
30
41
 
31
42
  it('should return true on exact match', async () => {
@@ -52,11 +63,47 @@ it('should return false on non-scope substring match', async () => {
52
63
  expect(result).toBe(false)
53
64
  })
54
65
 
55
- async function match (expected: string[], actual: string[]): Promise<boolean> {
66
+ it('should return true on match with parameters', async () => {
67
+ const result = await match(['app:{org}:reviews'],
68
+ ['app:29e54ae1:reviews'], [{
69
+ name: 'org',
70
+ value: '29e54ae1'
71
+ }])
72
+
73
+ expect(result).toBe(true)
74
+ })
75
+
76
+ it('should return true on match with parameters', async () => {
77
+ const result = await match(['app:{org}:reviews'],
78
+ ['app:29e54ae1:reviews'], [{
79
+ name: 'org',
80
+ value: '29e54ae1'
81
+ }])
82
+
83
+ expect(result).toBe(true)
84
+ })
85
+
86
+ it('should return false on mismatch with parameters', async () => {
87
+ const result = await match(['app:{org}:reviews'],
88
+ ['app:29e54ae1:reviews'], [{
89
+ name: 'org',
90
+ value: '88584c9b'
91
+ }])
92
+
93
+ expect(result).toBe(false)
94
+ })
95
+
96
+ async function match
97
+ (expected: string[], actual: string[], parameters: Parameter[] = []): Promise<boolean> {
56
98
  const directive = new Role(expected, discovery)
57
- const identity: Identity = { id: generate(), scheme: '', refresh: false }
99
+
100
+ const identity: Identity = {
101
+ id: generate(),
102
+ scheme: '',
103
+ refresh: false
104
+ }
58
105
 
59
106
  remote.invoke.mockResolvedValueOnce(actual)
60
107
 
61
- return await directive.authorize(identity)
108
+ return await directive.authorize(identity, undefined, parameters)
62
109
  }
@@ -1,14 +1,18 @@
1
+ import assert from 'node:assert'
1
2
  import { type Component, type Query } from '@toa.io/core'
2
3
  import { type Directive, type Identity } from './types'
4
+ import type { Parameter } from '../../RTD'
3
5
 
4
6
  export class Role implements Directive {
5
7
  public static remote: Component | null = null
6
8
  private readonly roles: string[]
7
9
  private readonly discovery: Promise<Component>
10
+ private readonly dynamic: boolean
8
11
 
9
12
  public constructor (roles: string | string[], discovery: Promise<Component>) {
10
13
  this.roles = typeof roles === 'string' ? [roles] : roles
11
14
  this.discovery = discovery
15
+ this.dynamic = this.roles.some((role) => role.includes('{'))
12
16
  }
13
17
 
14
18
  public static async set (identity: Identity, discovery: Promise<Component>): Promise<void> {
@@ -22,37 +26,41 @@ export class Role implements Directive {
22
26
  identity.roles = await this.remote.invoke('list', { query })
23
27
  }
24
28
 
25
- public async authorize (identity: Identity | null): Promise<boolean> {
29
+ public async authorize
30
+ (identity: Identity | null, _: unknown, parameters: Parameter[]): Promise<boolean> {
26
31
  if (identity === null)
27
32
  return false
28
33
 
29
34
  await Role.set(identity, this.discovery)
30
35
 
31
- if (identity.roles === undefined)
36
+ if (identity.roles!.length === 0) // Role.set()
37
+
32
38
  return false
33
39
 
34
- return this.match(identity.roles)
40
+ return this.match(identity.roles!, parameters)
35
41
  }
36
42
 
37
- private match (roles: string[]): boolean {
43
+ private match (roles: string[], parameters: Parameter[]): boolean {
44
+ const required = this.dynamic ? this.substitute(parameters) : this.roles
45
+
38
46
  for (const role of roles) {
39
- const index = this.roles.findIndex((expected) => compare(expected, role))
47
+ const ok = required.some((expected) => expected === role || expected.startsWith(role + ':'))
40
48
 
41
- if (index !== -1)
49
+ if (ok)
42
50
  return true
43
51
  }
44
52
 
45
53
  return false
46
54
  }
47
- }
48
55
 
49
- function compare (expected: string, actual: string): boolean {
50
- const exp = expected.split(':')
51
- const act = actual.split(':')
56
+ private substitute (parameters: Parameter[]): string[] {
57
+ return this.roles.map((role) => role.replaceAll(/{(\w+)}/g, (_, key) => {
58
+ const value = parameters.find((parameter) => parameter.name === key)?.value
52
59
 
53
- for (let i = 0; i < act.length; i++)
54
- if (exp[i] !== act[i])
55
- return false
60
+ assert.ok(value !== undefined,
61
+ `Role '${role}' requires '${key}' route parameter.`)
56
62
 
57
- return true
63
+ return value
64
+ }))
65
+ }
58
66
  }