@toa.io/extensions.exposition 1.0.0-alpha.6 → 1.0.0-alpha.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/context.toa.yaml +2 -2
- package/components/identity.bans/manifest.toa.yaml +15 -7
- package/components/identity.bans/operations/transit.d.ts +14 -0
- package/components/identity.bans/operations/transit.js +11 -0
- package/components/identity.bans/operations/transit.js.map +1 -0
- package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.bans/source/transit.ts +21 -0
- package/components/identity.bans/tsconfig.json +9 -0
- package/components/identity.basic/manifest.toa.yaml +21 -10
- package/components/identity.basic/operations/authenticate.d.ts +5 -1
- package/components/identity.basic/operations/authenticate.js +5 -2
- package/components/identity.basic/operations/authenticate.js.map +1 -1
- package/components/identity.basic/operations/incept.d.ts +12 -0
- package/components/identity.basic/operations/incept.js +26 -0
- package/components/identity.basic/operations/incept.js.map +1 -0
- package/components/identity.basic/operations/transit.d.ts +4 -4
- package/components/identity.basic/operations/transit.js +5 -3
- package/components/identity.basic/operations/transit.js.map +1 -1
- package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/operations/types.d.ts +8 -4
- package/components/identity.basic/source/authenticate.ts +16 -5
- package/components/identity.basic/source/incept.ts +38 -0
- package/components/identity.basic/source/transit.ts +8 -6
- package/components/identity.basic/source/types.ts +8 -4
- package/components/identity.federation/manifest.toa.yaml +32 -16
- package/components/identity.federation/operations/authenticate.d.ts +2 -2
- package/components/identity.federation/operations/authenticate.js +4 -11
- package/components/identity.federation/operations/authenticate.js.map +1 -1
- package/components/identity.federation/operations/incept.d.ts +11 -0
- package/components/identity.federation/operations/{create.js → incept.js} +6 -7
- package/components/identity.federation/operations/incept.js.map +1 -0
- package/components/identity.federation/operations/lib/jwt.d.ts +5 -5
- package/components/identity.federation/operations/lib/jwt.js +25 -12
- package/components/identity.federation/operations/lib/jwt.js.map +1 -1
- package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/operations/types/configuration.d.ts +14 -0
- package/components/identity.federation/operations/types/configuration.js +3 -0
- package/components/identity.federation/operations/types/configuration.js.map +1 -0
- package/components/identity.federation/operations/{types.d.ts → types/context.d.ts} +15 -7
- package/components/identity.federation/operations/types/context.js +3 -0
- package/components/identity.federation/operations/types/context.js.map +1 -0
- package/components/identity.federation/operations/types/entity.d.ts +6 -0
- package/components/identity.federation/operations/types/entity.js +3 -0
- package/components/identity.federation/operations/types/entity.js.map +1 -0
- package/components/identity.federation/operations/types/index.d.ts +3 -0
- package/components/identity.federation/operations/types/index.js +20 -0
- package/components/identity.federation/operations/types/index.js.map +1 -0
- package/components/identity.federation/source/authenticate.ts +6 -19
- package/components/identity.federation/source/{create.ts → incept.ts} +10 -9
- package/components/identity.federation/source/lib/jwt.test.ts +123 -4
- package/components/identity.federation/source/lib/jwt.ts +36 -16
- package/components/identity.federation/source/types/configuration.ts +15 -0
- package/components/identity.federation/source/{types.ts → types/context.ts} +17 -6
- package/components/identity.federation/source/types/entity.ts +6 -0
- package/components/identity.federation/source/types/index.ts +3 -0
- package/components/identity.federation/tsconfig.json +5 -4
- package/components/identity.roles/manifest.toa.yaml +18 -7
- package/components/identity.roles/operations/grant.d.ts +10 -0
- package/components/identity.roles/operations/grant.js +21 -0
- package/components/identity.roles/operations/grant.js.map +1 -0
- package/components/identity.roles/operations/lib/Entity.d.ts +5 -0
- package/components/identity.roles/operations/lib/Entity.js +3 -0
- package/components/identity.roles/operations/lib/Entity.js.map +1 -0
- package/components/identity.roles/operations/list.d.ts +1 -4
- package/components/identity.roles/operations/list.js.map +1 -1
- package/components/identity.roles/operations/principal.d.ts +4 -6
- package/components/identity.roles/operations/principal.js +6 -1
- package/components/identity.roles/operations/principal.js.map +1 -1
- package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/source/grant.ts +32 -0
- package/components/identity.roles/source/lib/Entity.ts +5 -0
- package/components/identity.roles/source/list.ts +2 -4
- package/components/identity.roles/source/principal.ts +10 -8
- package/components/identity.tokens/manifest.toa.yaml +19 -5
- package/components/identity.tokens/operations/authenticate.d.ts +2 -2
- package/components/identity.tokens/operations/authenticate.js +12 -5
- package/components/identity.tokens/operations/authenticate.js.map +1 -1
- package/components/identity.tokens/operations/decrypt.js +1 -0
- package/components/identity.tokens/operations/decrypt.js.map +1 -1
- package/components/identity.tokens/operations/encrypt.js +5 -1
- package/components/identity.tokens/operations/encrypt.js.map +1 -1
- package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/operations/types.d.ts +8 -2
- package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
- package/components/identity.tokens/source/authenticate.test.ts +11 -4
- package/components/identity.tokens/source/authenticate.ts +14 -6
- package/components/identity.tokens/source/decrypt.test.ts +5 -3
- package/components/identity.tokens/source/decrypt.ts +9 -8
- package/components/identity.tokens/source/encrypt.test.ts +26 -2
- package/components/identity.tokens/source/encrypt.ts +5 -1
- package/components/identity.tokens/source/types.ts +9 -2
- package/components/octets.storage/manifest.toa.yaml +6 -7
- package/components/octets.storage/operations/get.js +2 -2
- package/components/octets.storage/operations/store.js +113 -3
- package/documentation/access.md +75 -38
- package/documentation/authorities.md +49 -0
- package/documentation/cache.md +8 -1
- package/documentation/components.md +47 -22
- package/documentation/flow.md +31 -0
- package/documentation/identity.md +17 -22
- package/documentation/introspection.md +82 -0
- package/documentation/octets.md +81 -23
- package/documentation/protocol.md +3 -0
- package/documentation/query.md +29 -4
- package/documentation/require.md +15 -0
- package/documentation/tree.md +13 -0
- package/documentation/vary.md +14 -14
- package/features/access.feature +78 -46
- package/features/annotation.feature +1 -0
- package/features/auth.claim.feature +170 -0
- package/features/authorities.basic.feature +141 -0
- package/features/authorities.feature +32 -0
- package/features/authorities.federation.feature +100 -0
- package/features/authorities.tokens.feature +117 -0
- package/features/body.feature +3 -0
- package/features/cache.feature +109 -5
- package/features/cors.feature +6 -1
- package/features/debug.feature +34 -0
- package/features/directives.feature +3 -0
- package/features/dynamic.feature +4 -0
- package/features/errors.feature +20 -7
- package/features/etag.feature +31 -0
- package/features/flow.feature +45 -0
- package/features/identity.bans.feature +137 -0
- package/features/identity.basic.feature +125 -23
- package/features/identity.feature +7 -2
- package/features/identity.federation.feature +66 -11
- package/features/identity.roles.feature +250 -7
- package/features/identity.tokens.feature +54 -4
- package/features/introspection.feature +153 -0
- package/features/io.feature +38 -1
- package/features/methods.feature +47 -0
- package/features/octets.download.feature +189 -0
- package/features/octets.entries.feature +8 -1
- package/features/octets.feature +82 -54
- package/features/octets.meta.feature +3 -0
- package/features/octets.workflows.feature +239 -19
- package/features/probes.feature +14 -0
- package/features/{queries.feature → query.feature} +65 -2
- package/features/require.feature +67 -0
- package/features/response.feature +38 -3
- package/features/routes.feature +93 -2
- package/features/steps/Database.ts +17 -10
- package/features/steps/Gateway.ts +23 -6
- package/features/steps/IdP.ts +30 -25
- package/features/steps/Parameters.ts +1 -1
- package/features/steps/components/echo/manifest.toa.yaml +14 -1
- package/features/steps/components/echo/operations/identity.js +7 -0
- package/features/steps/components/echo/operations/parameters.js +7 -0
- package/features/steps/components/echo.beacon/manifest.toa.yaml +2 -0
- package/features/steps/components/echo.beacon/operations/hello.js +5 -0
- package/features/steps/components/octets.tester/manifest.toa.yaml +22 -1
- package/features/steps/components/octets.tester/operations/authority.js +7 -0
- package/features/steps/components/octets.tester/operations/baz.js +1 -2
- package/features/steps/components/octets.tester/operations/diversify.js +3 -1
- package/features/steps/components/octets.tester/operations/foo.js +2 -2
- package/features/steps/components/octets.tester/operations/redirect.js +12 -0
- package/features/steps/components/octets.tester/operations/yex.js +16 -0
- package/features/steps/components/octets.tester/operations/yield.js +13 -0
- package/features/steps/components/pots/manifest.toa.yaml +14 -3
- package/features/steps/components/users/manifest.toa.yaml +0 -1
- package/features/steps/components/users.properties/manifest.toa.yaml +1 -1
- package/features/streams.feature +1 -0
- package/features/timing.feature +27 -1
- package/features/vary.feature +71 -0
- package/package.json +22 -14
- package/readme.md +19 -14
- package/schemas/annotation.cos.yaml +1 -1
- package/schemas/method.cos.yaml +1 -1
- package/schemas/node.cos.yaml +1 -0
- package/schemas/octets/store.cos.yaml +25 -3
- package/schemas/query.cos.yaml +4 -10
- package/source/Annotation.ts +3 -3
- package/source/Composition.ts +2 -2
- package/source/Directive.ts +4 -5
- package/source/Endpoint.ts +48 -12
- package/source/Factory.ts +10 -11
- package/source/Gateway.ts +49 -20
- package/source/HTTP/Context.ts +24 -2
- package/source/HTTP/Server.ts +51 -44
- package/source/HTTP/exceptions.ts +13 -1
- package/source/HTTP/formats/index.ts +3 -3
- package/source/HTTP/messages.test.ts +39 -2
- package/source/HTTP/messages.ts +7 -3
- package/source/Introspection.ts +11 -0
- package/source/Mapping.ts +63 -21
- package/source/Query.test.ts +3 -3
- package/source/Query.ts +117 -33
- package/source/RTD/Endpoint.ts +3 -0
- package/source/RTD/Method.ts +16 -0
- package/source/RTD/Node.ts +29 -13
- package/source/RTD/Route.ts +5 -4
- package/source/RTD/factory.ts +5 -2
- package/source/RTD/syntax/parse.ts +37 -24
- package/source/RTD/syntax/types.ts +6 -4
- package/source/Remotes.ts +2 -9
- package/source/Tenant.ts +0 -8
- package/source/deployment.ts +32 -22
- package/source/directives/auth/Authorization.ts +37 -14
- package/source/directives/auth/Delegate.ts +42 -0
- package/source/directives/auth/Federation.ts +84 -0
- package/source/directives/auth/Incept.ts +4 -3
- package/source/directives/auth/Role.test.ts +53 -6
- package/source/directives/auth/Role.ts +22 -14
- package/source/directives/auth/split.ts +1 -1
- package/source/directives/auth/types.ts +1 -1
- package/source/directives/cache/Cache.ts +13 -6
- package/source/directives/cache/Control.ts +42 -16
- package/source/directives/cors/CORS.ts +1 -1
- package/source/directives/dev/Development.ts +1 -1
- package/source/directives/flow/Fetch.ts +88 -0
- package/source/directives/flow/Flow.ts +34 -0
- package/source/directives/flow/index.ts +3 -0
- package/source/directives/flow/types.ts +6 -0
- package/source/directives/index.ts +3 -1
- package/source/directives/io/Input.ts +4 -4
- package/source/directives/io/Output.ts +1 -1
- package/source/directives/octets/Context.ts +7 -5
- package/source/directives/octets/Delete.ts +4 -2
- package/source/directives/octets/Directive.ts +10 -0
- package/source/directives/octets/Fetch.ts +15 -13
- package/source/directives/octets/List.ts +9 -7
- package/source/directives/octets/Octets.ts +4 -5
- package/source/directives/octets/Store.ts +34 -12
- package/source/directives/octets/Workflow.ts +10 -3
- package/source/directives/octets/bytes.test.ts +30 -0
- package/source/directives/octets/bytes.ts +18 -0
- package/source/directives/octets/schemas.ts +4 -6
- package/source/directives/octets/types.ts +0 -7
- package/source/directives/octets/workflows/Execution.ts +59 -8
- package/source/directives/octets/workflows/Workflow.ts +2 -1
- package/source/directives/require/Directive.ts +5 -0
- package/source/directives/require/Headers.ts +20 -0
- package/source/directives/require/Require.ts +28 -0
- package/source/directives/require/index.ts +3 -0
- package/source/directives/vary/Directive.ts +2 -1
- package/source/directives/vary/Embed.ts +14 -8
- package/source/directives/vary/Vary.ts +6 -4
- package/source/directives/vary/embeddings/Authority.ts +8 -0
- package/source/directives/vary/embeddings/Embedding.ts +2 -1
- package/source/directives/vary/embeddings/Parameter.ts +14 -0
- package/source/directives/vary/embeddings/index.ts +6 -4
- package/source/exceptions.ts +22 -11
- package/source/manifest.ts +10 -11
- package/source/schemas.ts +1 -1
- package/transpiled/Annotation.d.ts +3 -3
- package/transpiled/Composition.js +2 -2
- package/transpiled/Composition.js.map +1 -1
- package/transpiled/Directive.js +4 -4
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Endpoint.d.ts +6 -4
- package/transpiled/Endpoint.js +28 -4
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.d.ts +1 -1
- package/transpiled/Factory.js +9 -8
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.d.ts +2 -0
- package/transpiled/Gateway.js +36 -12
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +8 -1
- package/transpiled/HTTP/Context.js +15 -2
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +13 -2
- package/transpiled/HTTP/Server.js +38 -36
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/exceptions.d.ts +7 -1
- package/transpiled/HTTP/exceptions.js +13 -1
- package/transpiled/HTTP/exceptions.js.map +1 -1
- package/transpiled/HTTP/formats/index.js +3 -3
- package/transpiled/HTTP/formats/index.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +1 -0
- package/transpiled/HTTP/messages.js +9 -3
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Introspection.d.ts +9 -0
- package/transpiled/Introspection.js +3 -0
- package/transpiled/Introspection.js.map +1 -0
- package/transpiled/Mapping.d.ts +10 -2
- package/transpiled/Mapping.js +48 -19
- package/transpiled/Mapping.js.map +1 -1
- package/transpiled/Query.d.ts +10 -1
- package/transpiled/Query.js +83 -30
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RTD/Endpoint.d.ts +1 -0
- package/transpiled/RTD/Method.d.ts +4 -0
- package/transpiled/RTD/Method.js +11 -0
- package/transpiled/RTD/Method.js.map +1 -1
- package/transpiled/RTD/Node.d.ts +4 -1
- package/transpiled/RTD/Node.js +23 -12
- package/transpiled/RTD/Node.js.map +1 -1
- package/transpiled/RTD/Route.d.ts +1 -1
- package/transpiled/RTD/Route.js +0 -1
- package/transpiled/RTD/Route.js.map +1 -1
- package/transpiled/RTD/factory.js +5 -2
- package/transpiled/RTD/factory.js.map +1 -1
- package/transpiled/RTD/syntax/parse.js +34 -22
- package/transpiled/RTD/syntax/parse.js.map +1 -1
- package/transpiled/RTD/syntax/types.d.ts +5 -3
- package/transpiled/RTD/syntax/types.js +1 -1
- package/transpiled/RTD/syntax/types.js.map +1 -1
- package/transpiled/Remotes.d.ts +2 -4
- package/transpiled/Remotes.js +0 -5
- package/transpiled/Remotes.js.map +1 -1
- package/transpiled/Tenant.d.ts +0 -1
- package/transpiled/Tenant.js +0 -6
- package/transpiled/Tenant.js.map +1 -1
- package/transpiled/deployment.d.ts +1 -1
- package/transpiled/deployment.js +28 -20
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Authorization.js +26 -10
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Delegate.d.ts +10 -0
- package/transpiled/directives/auth/Delegate.js +34 -0
- package/transpiled/directives/auth/Delegate.js.map +1 -0
- package/transpiled/directives/auth/Federation.d.ts +16 -0
- package/transpiled/directives/auth/Federation.js +57 -0
- package/transpiled/directives/auth/Federation.js.map +1 -0
- package/transpiled/directives/auth/Incept.js +4 -3
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/Role.d.ts +4 -1
- package/transpiled/directives/auth/Role.js +20 -14
- package/transpiled/directives/auth/Role.js.map +1 -1
- package/transpiled/directives/auth/split.js +1 -1
- package/transpiled/directives/auth/split.js.map +1 -1
- package/transpiled/directives/cache/Cache.d.ts +3 -3
- package/transpiled/directives/cache/Cache.js +10 -4
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/Control.d.ts +2 -1
- package/transpiled/directives/cache/Control.js +29 -12
- package/transpiled/directives/cache/Control.js.map +1 -1
- package/transpiled/directives/cors/CORS.js +1 -1
- package/transpiled/directives/cors/CORS.js.map +1 -1
- package/transpiled/directives/dev/Development.js +1 -1
- package/transpiled/directives/dev/Development.js.map +1 -1
- package/transpiled/directives/flow/Fetch.d.ts +13 -0
- package/transpiled/directives/flow/Fetch.js +59 -0
- package/transpiled/directives/flow/Fetch.js.map +1 -0
- package/transpiled/directives/flow/Flow.d.ts +10 -0
- package/transpiled/directives/flow/Flow.js +27 -0
- package/transpiled/directives/flow/Flow.js.map +1 -0
- package/transpiled/directives/flow/index.d.ts +2 -0
- package/transpiled/directives/flow/index.js +6 -0
- package/transpiled/directives/flow/index.js.map +1 -0
- package/transpiled/directives/flow/types.d.ts +5 -0
- package/transpiled/directives/flow/types.js.map +1 -0
- package/transpiled/directives/index.js +3 -1
- package/transpiled/directives/index.js.map +1 -1
- package/transpiled/directives/io/Input.js +2 -2
- package/transpiled/directives/io/Input.js.map +1 -1
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/octets/Context.d.ts +3 -3
- package/transpiled/directives/octets/Context.js +8 -26
- package/transpiled/directives/octets/Context.js.map +1 -1
- package/transpiled/directives/octets/Delete.d.ts +3 -2
- package/transpiled/directives/octets/Delete.js +3 -1
- package/transpiled/directives/octets/Delete.js.map +1 -1
- package/transpiled/directives/octets/Directive.d.ts +8 -0
- package/transpiled/directives/octets/Directive.js +8 -0
- package/transpiled/directives/octets/Directive.js.map +1 -0
- package/transpiled/directives/octets/Fetch.d.ts +6 -5
- package/transpiled/directives/octets/Fetch.js +11 -9
- package/transpiled/directives/octets/Fetch.js.map +1 -1
- package/transpiled/directives/octets/List.d.ts +6 -5
- package/transpiled/directives/octets/List.js +6 -4
- package/transpiled/directives/octets/List.js.map +1 -1
- package/transpiled/directives/octets/Octets.d.ts +2 -1
- package/transpiled/directives/octets/Octets.js +2 -4
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/octets/Store.d.ts +9 -3
- package/transpiled/directives/octets/Store.js +20 -8
- package/transpiled/directives/octets/Store.js.map +1 -1
- package/transpiled/directives/octets/Workflow.d.ts +3 -2
- package/transpiled/directives/octets/Workflow.js +9 -2
- package/transpiled/directives/octets/Workflow.js.map +1 -1
- package/transpiled/directives/octets/bytes.d.ts +1 -0
- package/transpiled/directives/octets/bytes.js +21 -0
- package/transpiled/directives/octets/bytes.js.map +1 -0
- package/transpiled/directives/octets/schemas.d.ts +4 -6
- package/transpiled/directives/octets/schemas.js +1 -3
- package/transpiled/directives/octets/schemas.js.map +1 -1
- package/transpiled/directives/octets/types.d.ts +0 -5
- package/transpiled/directives/octets/workflows/Execution.d.ts +5 -1
- package/transpiled/directives/octets/workflows/Execution.js +43 -9
- package/transpiled/directives/octets/workflows/Execution.js.map +1 -1
- package/transpiled/directives/octets/workflows/Workflow.js +2 -1
- package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
- package/transpiled/directives/require/Directive.d.ts +4 -0
- package/transpiled/directives/require/Directive.js +3 -0
- package/transpiled/directives/require/Directive.js.map +1 -0
- package/transpiled/directives/require/Headers.d.ts +7 -0
- package/transpiled/directives/require/Headers.js +19 -0
- package/transpiled/directives/require/Headers.js.map +1 -0
- package/transpiled/directives/require/Require.d.ts +9 -0
- package/transpiled/directives/require/Require.js +27 -0
- package/transpiled/directives/require/Require.js.map +1 -0
- package/transpiled/directives/require/index.d.ts +2 -0
- package/transpiled/directives/require/index.js +6 -0
- package/transpiled/directives/require/index.js.map +1 -0
- package/transpiled/directives/vary/Directive.d.ts +2 -1
- package/transpiled/directives/vary/Embed.d.ts +2 -1
- package/transpiled/directives/vary/Embed.js +8 -6
- package/transpiled/directives/vary/Embed.js.map +1 -1
- package/transpiled/directives/vary/Vary.d.ts +2 -2
- package/transpiled/directives/vary/Vary.js +3 -3
- package/transpiled/directives/vary/Vary.js.map +1 -1
- package/transpiled/directives/vary/embeddings/Authority.d.ts +5 -0
- package/transpiled/directives/vary/embeddings/Authority.js +10 -0
- package/transpiled/directives/vary/embeddings/Authority.js.map +1 -0
- package/transpiled/directives/vary/embeddings/Embedding.d.ts +2 -1
- package/transpiled/directives/vary/embeddings/Parameter.d.ts +7 -0
- package/transpiled/directives/vary/embeddings/Parameter.js +14 -0
- package/transpiled/directives/vary/embeddings/Parameter.js.map +1 -0
- package/transpiled/directives/vary/embeddings/index.d.ts +2 -2
- package/transpiled/directives/vary/embeddings/index.js +8 -4
- package/transpiled/directives/vary/embeddings/index.js.map +1 -1
- package/transpiled/exceptions.d.ts +3 -2
- package/transpiled/exceptions.js +13 -7
- package/transpiled/exceptions.js.map +1 -1
- package/transpiled/manifest.js +10 -11
- package/transpiled/manifest.js.map +1 -1
- package/transpiled/schemas.d.ts +1 -1
- package/transpiled/schemas.js +2 -2
- package/transpiled/schemas.js.map +1 -1
- package/transpiled/tsconfig.tsbuildinfo +1 -1
- package/tsconfig.json +9 -7
- package/components/identity.basic/operations/create.d.ts +0 -10
- package/components/identity.basic/operations/create.js +0 -10
- package/components/identity.basic/operations/create.js.map +0 -1
- package/components/identity.basic/source/create.ts +0 -18
- package/components/identity.federation/operations/create.d.ts +0 -10
- package/components/identity.federation/operations/create.js.map +0 -1
- package/components/identity.federation/operations/schemas.d.ts +0 -59
- package/components/identity.federation/operations/schemas.js +0 -9
- package/components/identity.federation/operations/schemas.js.map +0 -1
- package/components/identity.federation/operations/types.js.map +0 -1
- package/components/identity.federation/source/schemas.ts +0 -61
- package/components/octets.storage/operations/permute.js +0 -7
- package/schemas/octets/context.cos.yaml +0 -1
- package/source/HTTP/Server.test.ts +0 -126
- package/source/directives/octets/Permute.ts +0 -43
- package/transpiled/directives/octets/Permute.d.ts +0 -10
- package/transpiled/directives/octets/Permute.js +0 -56
- package/transpiled/directives/octets/Permute.js.map +0 -1
- /package/{components/identity.federation/operations → transpiled/directives/flow}/types.js +0 -0
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> {
|
package/source/deployment.ts
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
39
|
-
service.variables.push({
|
|
40
|
-
name: 'TOA_EXPOSITION_DEBUG',
|
|
41
|
-
value: '1'
|
|
42
|
-
})
|
|
42
|
+
const { debug, trace, authorities } = annotation
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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 (
|
|
51
|
-
|
|
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,8 +7,10 @@ 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 { Federation } from './Federation'
|
|
13
|
+
import { split } from './split'
|
|
12
14
|
import { PRIMARY, PROVIDERS } from './schemes'
|
|
13
15
|
import type { Output } from '../../io'
|
|
14
16
|
import type { Component } from '@toa.io/core'
|
|
@@ -38,7 +40,7 @@ export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
|
38
40
|
|
|
39
41
|
public create (name: string, value: any, remotes: Remotes): Directive {
|
|
40
42
|
assert.ok(name in constructors,
|
|
41
|
-
`Directive '
|
|
43
|
+
`Directive 'auth:${name}' is not implemented.`)
|
|
42
44
|
|
|
43
45
|
const Class = constructors[name]
|
|
44
46
|
|
|
@@ -49,13 +51,22 @@ export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
|
49
51
|
Role, () => new Role(value as string | string[], this.discovery.roles),
|
|
50
52
|
Rule, () => new Rule(value as Record<string, string>, this.create.bind(this)),
|
|
51
53
|
Incept, () => new Incept(value as string, this.discovery),
|
|
54
|
+
Delegate, () => new Delegate(value as string, this.discovery.roles),
|
|
52
55
|
() => new Class(value))
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
public async preflight (directives: Directive[],
|
|
56
59
|
input: Input,
|
|
57
60
|
parameters: Parameter[]): Promise<Output> {
|
|
58
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Some authentication scheme providers may create identity during authentication;
|
|
63
|
+
* therefore, we need to skip the authentication process if the Incept directive is present.
|
|
64
|
+
*
|
|
65
|
+
* If the provided credentials already exist,
|
|
66
|
+
* the inception will cause a unique constraint violation on the settle stage.
|
|
67
|
+
*/
|
|
68
|
+
const inception = directives.reduce((yes, directive) => yes || directive instanceof Incept, false)
|
|
69
|
+
const identity = inception ? null : await this.resolve(input.authority, input.request.headers.authorization)
|
|
59
70
|
|
|
60
71
|
input.identity = identity
|
|
61
72
|
|
|
@@ -79,25 +90,31 @@ export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
|
79
90
|
|
|
80
91
|
const identity = request.identity
|
|
81
92
|
|
|
82
|
-
if (identity === null)
|
|
93
|
+
if (identity === null)
|
|
94
|
+
return
|
|
83
95
|
|
|
84
|
-
if (identity.scheme === PRIMARY && !identity.refresh)
|
|
96
|
+
if (identity.scheme === PRIMARY && !identity.refresh)
|
|
97
|
+
return
|
|
85
98
|
|
|
86
99
|
// Role directive may have already set the value
|
|
87
|
-
if (identity.roles === undefined)
|
|
100
|
+
if (identity.roles === undefined)
|
|
101
|
+
await Role.set(identity, this.discovery.roles)
|
|
88
102
|
|
|
89
103
|
this.tokens ??= await this.discovery.tokens
|
|
90
104
|
|
|
91
|
-
const token = await this.tokens.invoke<string>('encrypt', {
|
|
92
|
-
|
|
105
|
+
const token = await this.tokens.invoke<string>('encrypt', {
|
|
106
|
+
input: { authority: request.authority, identity }
|
|
107
|
+
})
|
|
93
108
|
|
|
94
|
-
|
|
109
|
+
const authorization = `Token ${token}`
|
|
95
110
|
|
|
111
|
+
response.headers ??= new Headers()
|
|
96
112
|
response.headers.set('authorization', authorization)
|
|
97
113
|
}
|
|
98
114
|
|
|
99
|
-
private async resolve (authorization: string | undefined): Promise<Identity | null> {
|
|
100
|
-
if (authorization === undefined)
|
|
115
|
+
private async resolve (authority: string, authorization: string | undefined): Promise<Identity | null> {
|
|
116
|
+
if (authorization === undefined)
|
|
117
|
+
return null
|
|
101
118
|
|
|
102
119
|
const [scheme, credentials] = split(authorization)
|
|
103
120
|
const provider = PROVIDERS[scheme]
|
|
@@ -108,10 +125,14 @@ export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
|
108
125
|
this.schemes[scheme] ??= await this.discovery[provider]
|
|
109
126
|
|
|
110
127
|
const result = await this.schemes[scheme].invoke<AuthenticationResult>('authenticate', {
|
|
111
|
-
input:
|
|
128
|
+
input: {
|
|
129
|
+
authority,
|
|
130
|
+
credentials
|
|
131
|
+
}
|
|
112
132
|
})
|
|
113
133
|
|
|
114
|
-
if (result instanceof Error)
|
|
134
|
+
if (result instanceof Error)
|
|
135
|
+
return null
|
|
115
136
|
|
|
116
137
|
const identity = result.identity
|
|
117
138
|
|
|
@@ -139,7 +160,9 @@ const constructors: Record<string, new (value: any, argument?: any) => Directive
|
|
|
139
160
|
rule: Rule,
|
|
140
161
|
incept: Incept,
|
|
141
162
|
scheme: Scheme,
|
|
142
|
-
echo: Echo
|
|
163
|
+
echo: Echo,
|
|
164
|
+
delegate: Delegate,
|
|
165
|
+
claim: Federation
|
|
143
166
|
}
|
|
144
167
|
|
|
145
168
|
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
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import type { Directive, Identity, Input } from './types'
|
|
3
|
+
import type { Parameter } from '../../RTD'
|
|
4
|
+
|
|
5
|
+
export class Federation implements Directive {
|
|
6
|
+
private readonly matchers: Array<[keyof Claim, Matcher]>
|
|
7
|
+
|
|
8
|
+
public constructor (options: Options) {
|
|
9
|
+
this.matchers = (Object.entries(options) as Array<[keyof Claim, string]>)
|
|
10
|
+
.map(([key, value]) => [key, toMatcher(value)])
|
|
11
|
+
|
|
12
|
+
assert.ok(this.matchers.length > 0, 'auth:claim requires at least one property defined')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public authorize (identity: Identity | null, context: Input, parameters: Parameter[]): boolean {
|
|
16
|
+
if (identity === null || !('claim' in identity))
|
|
17
|
+
return false
|
|
18
|
+
|
|
19
|
+
const claim = (identity as FederatedIdentity).claim
|
|
20
|
+
|
|
21
|
+
for (const [key, match] of this.matchers)
|
|
22
|
+
if (!match(claim[key], context, parameters))
|
|
23
|
+
return false
|
|
24
|
+
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function toMatcher (expression: string): Matcher {
|
|
30
|
+
if (expression.startsWith(':')) {
|
|
31
|
+
const key = expression.slice(1) as 'authority'
|
|
32
|
+
|
|
33
|
+
if (key === 'authority')
|
|
34
|
+
return (value, context) => matches(value, context[key])
|
|
35
|
+
|
|
36
|
+
if (key === 'domain')
|
|
37
|
+
return (value, context) => {
|
|
38
|
+
return Array.isArray(value)
|
|
39
|
+
? value.some((iss) => codomain(iss, context))
|
|
40
|
+
: codomain(value, context)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw new Error(`Unknown 'auth:claim' syntax: ${expression}`)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (expression.startsWith('/:')) {
|
|
47
|
+
const name = expression.slice(2)
|
|
48
|
+
|
|
49
|
+
return (value, _, parameters) => parameters
|
|
50
|
+
.some((parameter) => parameter.name === name && matches(value, parameter.value))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (value) => matches(value, expression)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function matches (value: string | string[], reference: string): boolean {
|
|
57
|
+
return Array.isArray(value)
|
|
58
|
+
? value.includes(reference)
|
|
59
|
+
: value === reference
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function codomain (iss: string, context: Input): boolean {
|
|
63
|
+
const hostname = new URL(iss).hostname
|
|
64
|
+
const dot = hostname.indexOf('.')
|
|
65
|
+
const basename = dot === -1 ? hostname : hostname.slice(dot)
|
|
66
|
+
|
|
67
|
+
return context.authority.slice(-basename.length) === basename
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type Matcher = (value: string | string[], context: Input, parameters: Parameter[]) => boolean
|
|
71
|
+
|
|
72
|
+
interface Claim {
|
|
73
|
+
iss: string
|
|
74
|
+
sub: string
|
|
75
|
+
aud: string | string[]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface Options extends Partial<Claim> {
|
|
79
|
+
iss: string
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface FederatedIdentity extends Identity {
|
|
83
|
+
claim: Claim
|
|
84
|
+
}
|
|
@@ -23,7 +23,7 @@ export class Incept implements Directive {
|
|
|
23
23
|
|
|
24
24
|
if (id === undefined)
|
|
25
25
|
throw new http.Conflict('Identity inception has failed as the response body ' +
|
|
26
|
-
`
|
|
26
|
+
`does not contain the '${this.property}' property.`)
|
|
27
27
|
|
|
28
28
|
const [scheme, credentials] = split(input.request.headers.authorization!)
|
|
29
29
|
const provider = PROVIDERS[scheme]
|
|
@@ -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>>('
|
|
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.
|
|
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
|
-
|
|
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', {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 ===
|
|
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
|
|
47
|
+
const ok = required.some((expected) => expected === role || expected.startsWith(role + ':'))
|
|
40
48
|
|
|
41
|
-
if (
|
|
49
|
+
if (ok)
|
|
42
50
|
return true
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
return false
|
|
46
54
|
}
|
|
47
|
-
}
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
return false
|
|
60
|
+
assert.ok(value !== undefined,
|
|
61
|
+
`Role '${role}' requires '${key}' route parameter.`)
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
return value
|
|
64
|
+
}))
|
|
65
|
+
}
|
|
58
66
|
}
|
|
@@ -5,7 +5,7 @@ export function split (authorization: string): [Scheme, string] {
|
|
|
5
5
|
const space = authorization.indexOf(' ')
|
|
6
6
|
|
|
7
7
|
if (space === -1)
|
|
8
|
-
throw new http.Unauthorized('Malformed authorization header
|
|
8
|
+
throw new http.Unauthorized('Malformed authorization header')
|
|
9
9
|
|
|
10
10
|
const Scheme = authorization.slice(0, space)
|
|
11
11
|
const scheme = Scheme.toLowerCase() as Scheme
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { Control } from './Control'
|
|
2
2
|
import { Exact } from './Exact'
|
|
3
|
-
import type {
|
|
4
|
-
import type { Directive } from './types'
|
|
3
|
+
import type { Output } from '../../io'
|
|
4
|
+
import type { AuthenticatedContext, Directive } from './types'
|
|
5
5
|
import type { DirectiveFamily } from '../../RTD'
|
|
6
6
|
import type * as http from '../../HTTP'
|
|
7
7
|
|
|
8
8
|
export class Cache implements DirectiveFamily<Directive> {
|
|
9
9
|
public readonly name: string = 'cache'
|
|
10
|
-
public readonly mandatory: boolean =
|
|
10
|
+
public readonly mandatory: boolean = true
|
|
11
11
|
|
|
12
12
|
public create (name: string, value: any): Directive {
|
|
13
13
|
const Class = constructors[name]
|
|
14
14
|
|
|
15
15
|
if (Class === undefined)
|
|
16
|
-
throw new Error(`Directive '
|
|
16
|
+
throw new Error(`Directive 'cache:${name}' is not implemented.`)
|
|
17
17
|
|
|
18
18
|
return new Class(value)
|
|
19
19
|
}
|
|
@@ -23,9 +23,16 @@ export class Cache implements DirectiveFamily<Directive> {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public async settle
|
|
26
|
-
(directives: Directive[],
|
|
26
|
+
(directives: Directive[], context: AuthenticatedContext, response: http.OutgoingMessage): Promise<void> {
|
|
27
|
+
const directive = directives[0]
|
|
28
|
+
|
|
27
29
|
response.headers ??= new Headers()
|
|
28
|
-
|
|
30
|
+
|
|
31
|
+
if (directive === undefined) {
|
|
32
|
+
if (context.identity !== null && !Control.disabled(response.headers))
|
|
33
|
+
response.headers.set('cache-control', 'private')
|
|
34
|
+
} else
|
|
35
|
+
directive.set(context, response.headers)
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
|