@owlmeans/server-iam 0.1.18-rc.55 → 0.1.18-rc.57

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 (50) hide show
  1. package/README.md +4 -4
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/server-iam/SKILL.md +12 -12
  4. package/build/append.d.ts +1 -5
  5. package/build/append.d.ts.map +1 -1
  6. package/build/append.js.map +1 -1
  7. package/build/consts.local.d.ts +3 -0
  8. package/build/consts.local.d.ts.map +1 -0
  9. package/build/consts.local.js +3 -0
  10. package/build/consts.local.js.map +1 -0
  11. package/build/gate.d.ts +3 -14
  12. package/build/gate.d.ts.map +1 -1
  13. package/build/gate.js +69 -70
  14. package/build/gate.js.map +1 -1
  15. package/build/index.d.ts +5 -3
  16. package/build/index.d.ts.map +1 -1
  17. package/build/index.js +2 -2
  18. package/build/index.js.map +1 -1
  19. package/build/organization/types.d.ts +21 -0
  20. package/build/organization/types.d.ts.map +1 -0
  21. package/build/organization/types.js +2 -0
  22. package/build/organization/types.js.map +1 -0
  23. package/build/organization.d.ts +5 -14
  24. package/build/organization.d.ts.map +1 -1
  25. package/build/organization.js +20 -25
  26. package/build/organization.js.map +1 -1
  27. package/build/runtime.d.ts +4 -30
  28. package/build/runtime.d.ts.map +1 -1
  29. package/build/runtime.js +33 -31
  30. package/build/runtime.js.map +1 -1
  31. package/build/types.d.ts +42 -0
  32. package/build/types.d.ts.map +1 -0
  33. package/build/types.js +2 -0
  34. package/build/types.js.map +1 -0
  35. package/build/types.local.d.ts +16 -0
  36. package/build/types.local.d.ts.map +1 -0
  37. package/build/types.local.js +2 -0
  38. package/build/types.local.js.map +1 -0
  39. package/package.json +11 -11
  40. package/src/append.ts +1 -4
  41. package/src/consts.local.ts +2 -0
  42. package/src/gate.ts +77 -95
  43. package/src/index.ts +5 -3
  44. package/src/organization/types.ts +21 -0
  45. package/src/organization.ts +30 -31
  46. package/src/runtime.ts +45 -86
  47. package/src/types.local.ts +18 -0
  48. package/src/types.ts +43 -0
  49. package/tests/organization.spec.ts +8 -8
  50. package/tests/runtime.spec.ts +5 -4
package/README.md CHANGED
@@ -7,14 +7,14 @@ One-call OIDC RP wiring and IAM gate for OwlMeans servers — `appendIam()` and
7
7
  - `appendIam(context)` — registers the OIDC client, wrapping service, and IAM gate in a single call, replacing verbose manual wiring
8
8
  - `makeIamGate()` — produces a guard that asserts unscoped or resource-scoped permissions against the IAM backend (claims-first, UMA2 fallback)
9
9
  - Re-exports `hasPermission` from `@owlmeans/iam` for inline permission checks
10
- - `organizationOf` / `organizationsOf` — the organizations of a tenanted session, from its session record
11
- - `iamRuntime(context, request)` — a typed client of the provider's runtime IAM API, acting as the request's subject
10
+ - `makeOrganizationScope(context, request)` — `.organizationOf(slug)` / `.organizationsOf()`: the organizations of a tenanted session, from its session record
11
+ - `makeIamRuntimeClient(context, request)` — a typed client of the provider's runtime IAM API, acting as the request's subject
12
12
  - Designed for IAM consumers such as the viable target template backend
13
13
 
14
14
  ## Installation
15
15
 
16
16
  ```bash
17
- bun add @owlmeans/server-iam@^0.1.18-rc.55
17
+ bun add @owlmeans/server-iam@^0.1.18-rc.57
18
18
  ```
19
19
 
20
20
  ## Usage
@@ -47,7 +47,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
47
47
  your project's skill store (`.agents/skills/`):
48
48
 
49
49
  ```sh
50
- npx @owlmeans/agent-skills@^0.1.18-rc.47
50
+ npx @owlmeans/agent-skills@^0.1.18-rc.49
51
51
  ```
52
52
 
53
53
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/server-iam",
4
- "version": "0.1.18-rc.55",
5
- "generatedAt": "2026-10-03T20:05:07.589Z",
4
+ "version": "0.1.18-rc.57",
5
+ "generatedAt": "2026-10-05T21:03:06.380Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: server-iam
3
- description: "How to use @owlmeans/server-iam — one-call OIDC RP wiring (appendIam), the IAM gate that asserts unbound, organization-bound and resource-scoped permissions (claims-first, UMA2 fallback), the session's organizations (organizationOf/organizationsOf), the request-bound runtime IAM client (iamRuntime), plus the gate-param grammar it re-exports. Use when gating server endpoints, declaring gate params, acting in a tenanted client's organizations, managing members or grants from a target's server, or diagnosing a permission refusal. Applies to files matching **/owlmeans.ts, **/gate*.ts, **/auth-guard*.ts."
3
+ description: "How to use @owlmeans/server-iam — one-call OIDC RP wiring (appendIam), the IAM gate that asserts unbound, organization-bound and resource-scoped permissions (claims-first, UMA2 fallback), the session's organizations (makeOrganizationScope: organizationOf/organizationsOf), the request-bound runtime IAM client (makeIamRuntimeClient), plus the gate-param grammar it re-exports. Use when gating server endpoints, declaring gate params, acting in a tenanted client's organizations, managing members or grants from a target's server, or diagnosing a permission refusal. Applies to files matching **/owlmeans.ts, **/gate*.ts, **/auth-guard*.ts."
4
4
  metadata:
5
5
  applyTo: "**/owlmeans.ts, **/gate*.ts, **/auth-guard*.ts"
6
6
  ---
@@ -8,7 +8,7 @@ metadata:
8
8
 
9
9
  # Using `@owlmeans/server-iam`
10
10
 
11
- **Install:** `"@owlmeans/server-iam": "^0.1.18-rc.55"` in `dependencies`
11
+ **Install:** `"@owlmeans/server-iam": "^0.1.18-rc.57"` in `dependencies`
12
12
 
13
13
  Boilerplate-less server-side consumer of the OwlMeans IAM. One call wires the OIDC RP stack and the
14
14
  IAM gate; the consumer never knows which IAM backend (Keycloak or integrated) is active. For a
@@ -22,13 +22,13 @@ as the signed-in subject.
22
22
  | `appendIam(context)` | fn | Registers `makeOidcClientService()`, `makeOidcWrappingService()`, `makeIamGate()` (under `OIDC_GATE`), and the OIDC guard |
23
23
  | `makeIamGate(alias?, opts?)` | fn | The IAM `GateService` — claims-first assertion with UMA2 fallback |
24
24
  | `IamGateOptions` | type | `{ strictResourceScope?: boolean }` — refuse a scoped param on the fallback path instead of widening it |
25
- | `parseGateParam` / `parseGateSelector` / `formatGateParam` / `resolveGateResource` / `validateGateParams` | fn | Re-exports from `@owlmeans/iam`, which owns the grammar |
25
+ | `gateParamHelper` (`.parseGateParam` / `.parseGateSelector` / `.formatGateParam`) / `gateValidationHelper.validateGateParams` / `resolveGateResource` | helper / fn | Re-exports from `@owlmeans/iam`, which owns the grammar |
26
26
  | `RESOURCE_PARAM_SEPARATOR` / `RESOURCE_SOURCE_SEPARATOR` / `RESOURCE_PATH_SEPARATOR` | const | `'@'`, `':'` and `'.'`, re-exported |
27
27
  | `GateParamSource` / `GateParamErrorCode` / `GateResolutionFailure` | enum | Re-exported; the sources a selector may name, and why one failed |
28
28
  | `hasPermission` | fn | Re-export from `@owlmeans/iam` |
29
- | `organizationOf(context, request, entitySlug)` | fn | One organization of the request's subject as a `ResolvedEntity` (`{ id: entityKey, slug, iamKey: entityKey }`); one the subject is not in is `AuthForbidden(ORGANIZATION_REFUSAL)` |
30
- | `organizationsOf(context, request)` | fn | Every organization of the request's subject, as `ResolvedEntity[]` |
31
- | `iamRuntime(context, request)` | fn | The request-bound `IamRuntimeClient` of the provider's runtime IAM API — see "The runtime IAM client" |
29
+ | `makeOrganizationScope(context, request).organizationOf(entitySlug)` | scope | One organization of the request's subject as a `ResolvedEntity` (`{ id: entityKey, slug, iamKey: entityKey }`); one the subject is not in is `AuthForbidden(ORGANIZATION_REFUSAL)` |
30
+ | `makeOrganizationScope(context, request).organizationsOf()` | scope | Every organization of the request's subject, as `ResolvedEntity[]` |
31
+ | `makeIamRuntimeClient(context, request)` | fn | The request-bound `IamRuntimeClient` of the provider's runtime IAM API — see "The runtime IAM client" |
32
32
  | `IamRuntimeClient` | type | `organizations.{list,create,update}`, `members.{list,add,update,remove}`, `permissions.list`, `grants.{list,assign,revoke}` |
33
33
  | `ORGANIZATION_REFUSAL` / `ORGANIZATION_OWNER_REFUSAL` | const | Re-exported from `@owlmeans/oidc`: the `AuthForbidden` reasons of a non-member and of a non-owner |
34
34
  | `SERVER_IAM_SERVICE` | const | `'server-iam-service'` — exported and referenced nowhere; the gate registers under `OIDC_GATE`, not under this |
@@ -74,10 +74,10 @@ Sources: `params`, `query`, `body`, `headers`, `auth`.
74
74
  **The `@` belongs to the gate and nowhere else.** It is never part of a permission's stored NAME. A
75
75
  definition or grant written as `enquiry--view@enquiryId` is a key nothing looks up, so the permission
76
76
  reads as granted in every screen and every request is still refused, with nothing logged.
77
- `ensurePermission` refuses such a name; `validateGateParams` catches the mirror-image mistake at
77
+ `ensurePermission` refuses such a name; `gateValidationHelper.validateGateParams` catches the mirror-image mistake at
78
78
  generation time.
79
79
 
80
- ### `validateGateParams(params, audit?)`
80
+ ### `gateValidationHelper.validateGateParams(params, audit?)`
81
81
 
82
82
  Reports what is provable from an entrypoint's own declaration: a selector naming a route param the
83
83
  path does not carry, or a `body`/`query`/`headers` key the `Filter` does not declare **while that
@@ -103,7 +103,7 @@ await ctx.service<GateService>(OIDC_GATE).assert(req, res, ['article--modify'])
103
103
  1. `req.auth == null` → `AuthForbidden('auth')`.
104
104
  2. **Claims mode** — when `req.auth.permissions` is a valid `PermissionSet[]` (minted into the id_token
105
105
  by the integrated IAM provider and mapped into `Auth` by `@owlmeans/server-oidc-rp`), params are
106
- asserted locally via `hasPermission`, with `entitySlug: req.entity?.slug ?? entitySlugOf(auth)` —
106
+ asserted locally via `hasPermission`, with `entitySlug: req.entity?.slug ?? authHelper.entitySlugOf(auth)` —
107
107
  the organization the request acts in.
108
108
  3. **Fallback** — otherwise `@…` suffixes are stripped and the check delegates to the UMA2 gate model
109
109
  from `@owlmeans/server-oidc-rp` (`createGateModel().loadPermissions`) — exactly the check
@@ -144,7 +144,7 @@ store must not grant against slugs, because a rename would then orphan every gra
144
144
 
145
145
  A relying party of a tenanted client has no organization registry of its own: the provider's
146
146
  `organizations` claim, kept in the session record (`@owlmeans/server-oidc-rp`), is the only source,
147
- re-read on every validation. `organizationsOf` answers all of it and `organizationOf` one entry by
147
+ re-read on every validation. `makeOrganizationScope(context, request).organizationsOf()` answers all of it and `.organizationOf(slug)` one entry by
148
148
  slug, as `ResolvedEntity` values keyed by the frozen `entityKey` — use them for a handler that acts in
149
149
  an organization its URL names rather than the session's acting one (which the guard already attaches
150
150
  as `req.entity`). A session of a client without the scope acts in none and has none to offer; an
@@ -152,7 +152,7 @@ unauthenticated request or a session that is gone is `AuthorizationError` (401).
152
152
 
153
153
  ## The runtime IAM client
154
154
 
155
- `iamRuntime(context, request)` calls the provider's runtime IAM API (`makeIamRuntimeProtocols` in
155
+ `makeIamRuntimeClient(context, request)` calls the provider's runtime IAM API (`makeIamRuntimeProtocols` in
156
156
  `@owlmeans/iam`) as that request's subject:
157
157
 
158
158
  - **Base** — the provider's discovery field `IAM_API_METADATA` (`owlmeans_iam_api`), read through
@@ -182,7 +182,7 @@ the token; nothing sent here can widen them.
182
182
  - The OIDC provider entry must request the `permissions` scope (`extraScopes`) for claims mode to
183
183
  engage; without it the gate transparently uses the fallback. A tenanted client also requests
184
184
  `organizations`.
185
- - Reach the runtime IAM API only through `iamRuntime`; never forward the browser's wrapped token or
185
+ - Reach the runtime IAM API only through `makeIamRuntimeClient`; never forward the browser's wrapped token or
186
186
  build a bearer from anything but the session record.
187
187
 
188
188
  ## Related instructions
package/build/append.d.ts CHANGED
@@ -1,7 +1,4 @@
1
- import type { ServerConfig, ServerContext } from '@owlmeans/server-context';
2
- import type { WithSharedConfig } from '@owlmeans/oidc';
3
- type IamServerConfig = ServerConfig & WithSharedConfig;
4
- type IamServerContext<C extends IamServerConfig = IamServerConfig> = ServerContext<C>;
1
+ import type { IamServerConfig, IamServerContext } from './types.local.js';
5
2
  /**
6
3
  * One-call OIDC RP setup for a server context.
7
4
  *
@@ -15,5 +12,4 @@ type IamServerContext<C extends IamServerConfig = IamServerConfig> = ServerConte
15
12
  * context.cfg.oidc.providers[] — populate it before calling appendIam().
16
13
  */
17
14
  export declare const appendIam: <C extends IamServerConfig, T extends IamServerContext<C>>(context: T) => T;
18
- export {};
19
15
  //# sourceMappingURL=append.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAItD,KAAK,eAAe,GAAG,YAAY,GAAG,gBAAgB,CAAA;AACtD,KAAK,gBAAgB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,IAAI,aAAa,CAAC,CAAC,CAAC,CAAA;AAErF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,eAAe,EAAE,CAAC,SAAS,gBAAgB,CAAC,CAAC,CAAC,WACvE,CAAC,KACT,CAQF,CAAA"}
1
+ {"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGzE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,eAAe,EAAE,CAAC,SAAS,gBAAgB,CAAC,CAAC,CAAC,WACvE,CAAC,KACT,CAQF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"append.js","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAC1G,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAKvC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,OAAU,EACP,EAAE;IACL,OAAO,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAA;IAChD,OAAO,CAAC,eAAe,CAAC,uBAAuB,EAAE,CAAC,CAAA;IAClD,sEAAsE;IACtE,gEAAgE;IAChE,OAAO,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC,CAAA;IACtC,eAAe,CAAO,OAAO,CAAC,CAAA;IAC9B,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
1
+ {"version":3,"file":"append.js","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAC1G,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAIvC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,OAAU,EACP,EAAE;IACL,OAAO,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC,CAAA;IAChD,OAAO,CAAC,eAAe,CAAC,uBAAuB,EAAE,CAAC,CAAA;IAClD,sEAAsE;IACtE,gEAAgE;IAChE,OAAO,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC,CAAA;IACtC,eAAe,CAAO,OAAO,CAAC,CAAA;IAC9B,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ /** `@owlmeans/server-api`'s incident header; a production error body is nothing but this id. */
2
+ export declare const INCIDENT_ID_HEADER = "x-incident-id";
3
+ //# sourceMappingURL=consts.local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.local.d.ts","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,kBAAkB,CAAA"}
@@ -0,0 +1,3 @@
1
+ /** `@owlmeans/server-api`'s incident header; a production error body is nothing but this id. */
2
+ export const INCIDENT_ID_HEADER = 'x-incident-id';
3
+ //# sourceMappingURL=consts.local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.local.js","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAA"}
package/build/gate.d.ts CHANGED
@@ -1,23 +1,12 @@
1
1
  import type { GateService } from '@owlmeans/entrypoint';
2
+ import type { IamGateOptions } from './types.js';
2
3
  /**
3
4
  * The gate-param grammar lives in `@owlmeans/iam` so the browser, the adapters and code-generation
4
5
  * tooling can all read it. Re-exported here because this module was its home and is the documented
5
6
  * import path.
6
7
  */
7
- export { RESOURCE_PARAM_SEPARATOR, RESOURCE_SOURCE_SEPARATOR, RESOURCE_PATH_SEPARATOR, GateParamSource, GateParamErrorCode, GateResolutionFailure, parseGateParam, parseGateSelector, formatGateParam, resolveGateResource, validateGateParams } from '@owlmeans/iam';
8
- export type { ParsedGateParam, GateResourceSelector, GateParamAudit } from '@owlmeans/iam';
9
- export interface IamGateOptions {
10
- /**
11
- * Refuse a resource-scoped param on the UMA2 fallback path instead of widening it to a
12
- * project-wide check.
13
- *
14
- * Off by default, and deliberately so. A Keycloak-backed deployment cannot hold a resource-scoped
15
- * grant at all — the adapter throws `IamUnsupported('resource-scoped-grant')` — so denying would
16
- * lock every user out of every scoped endpoint rather than tightening anything. Turn it on only
17
- * where the resulting refusals are the intended outcome.
18
- */
19
- strictResourceScope?: boolean;
20
- }
8
+ export { RESOURCE_PARAM_SEPARATOR, RESOURCE_SOURCE_SEPARATOR, RESOURCE_PATH_SEPARATOR, GateParamSource, GateParamErrorCode, GateResolutionFailure, gateParamHelper, gateValidationHelper, resolveGateResource } from '@owlmeans/iam';
9
+ export type { ParsedGateParam, GateResourceSelector, GateParamAudit, GateParamHelper, GateValidationHelper } from '@owlmeans/iam';
21
10
  /**
22
11
  * IAM gate: claims-first with UMA2 fallback. Registered under the OIDC_GATE alias by
23
12
  * appendIam() so target code never knows which IAM backend is active.
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAqC,MAAM,sBAAsB,CAAA;AAa1F;;;;GAIG;AACH,OAAO,EACL,wBAAwB,EAAE,yBAAyB,EAAE,uBAAuB,EAC5E,eAAe,EAAE,kBAAkB,EAAE,qBAAqB,EAC1D,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,kBAAkB,EAC5F,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE1F,MAAM,WAAW,cAAc;IAC7B;;;;;;;;OAQG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B;AAgFD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,WAAW,MAAM,SAAqB,cAAc,KAAG,WAiG9E,CAAA"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAqC,MAAM,sBAAsB,CAAA;AAM1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;GAIG;AACH,OAAO,EACL,wBAAwB,EAAE,yBAAyB,EAAE,uBAAuB,EAC5E,eAAe,EAAE,kBAAkB,EAAE,qBAAqB,EAC1D,eAAe,EAAE,oBAAoB,EAAE,mBAAmB,EAC3D,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAejI;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,WAAW,MAAM,SAAqB,cAAc,KAAG,WAkK9E,CAAA"}
package/build/gate.js CHANGED
@@ -1,16 +1,15 @@
1
1
  import { createLazyService } from '@owlmeans/context';
2
- import { entitySlugOf } from '@owlmeans/auth';
2
+ import { authHelper, AuthForbidden } from '@owlmeans/auth';
3
3
  import { OIDC_GATE } from '@owlmeans/oidc';
4
- import { AuthForbidden } from '@owlmeans/auth';
5
4
  import { createGateModel, extractPermissionSets } from '@owlmeans/server-oidc-rp';
6
- import { hasPermission, parseGateParam, resolveGateResource, validateGateParams, GateResolutionFailure } from '@owlmeans/iam';
5
+ import { hasPermission, gateParamHelper, gateValidationHelper, resolveGateResource, GateResolutionFailure } from '@owlmeans/iam';
7
6
  import { logger, logThrottle } from '@owlmeans/log';
8
7
  /**
9
8
  * The gate-param grammar lives in `@owlmeans/iam` so the browser, the adapters and code-generation
10
9
  * tooling can all read it. Re-exported here because this module was its home and is the documented
11
10
  * import path.
12
11
  */
13
- export { RESOURCE_PARAM_SEPARATOR, RESOURCE_SOURCE_SEPARATOR, RESOURCE_PATH_SEPARATOR, GateParamSource, GateParamErrorCode, GateResolutionFailure, parseGateParam, parseGateSelector, formatGateParam, resolveGateResource, validateGateParams } from '@owlmeans/iam';
12
+ export { RESOURCE_PARAM_SEPARATOR, RESOURCE_SOURCE_SEPARATOR, RESOURCE_PATH_SEPARATOR, GateParamSource, GateParamErrorCode, GateResolutionFailure, gateParamHelper, gateValidationHelper, resolveGateResource } from '@owlmeans/iam';
14
13
  /**
15
14
  * Structural faults are logged once per alias+param+reason.
16
15
  *
@@ -19,68 +18,8 @@ export { RESOURCE_PARAM_SEPARATOR, RESOURCE_SOURCE_SEPARATOR, RESOURCE_PATH_SEPA
19
18
  */
20
19
  const reported = new Set();
21
20
  const log = logger('server-iam:gate');
22
- const reportOnce = (key, message, data) => {
23
- if (reported.has(key)) {
24
- return;
25
- }
26
- reported.add(key);
27
- log.error(message, data);
28
- };
29
- /**
30
- * A refusal of the gate. Logged once a minute per route, reason and subject — a hot endpoint
31
- * refuses on every request, and one line per window says the same thing.
32
- */
33
- const forbidden = (req, reason, params) => {
34
- const auth = req.auth;
35
- if (logThrottle(`access.forbidden\0${req.alias ?? ''}\0${reason}\0${auth?.userId ?? ''}`, 60_000)) {
36
- log.warn('Access forbidden', {
37
- alias: req.alias, reason, params, userId: auth?.userId, entitySlug: req.entity?.slug ?? (auth != null ? entitySlugOf(auth) : undefined),
38
- }, { event: 'access.forbidden' });
39
- }
40
- return new AuthForbidden(reason);
41
- };
42
21
  /** Aliases whose declarations have already been checked. */
43
22
  const audited = new Set();
44
- /**
45
- * Check an entrypoint's gate params against what it declares, once, the first time it is reached.
46
- *
47
- * Structurally unable to affect the outcome: it only ever logs. A selector naming a key the
48
- * entrypoint's filter does not declare is stripped by validation before the gate runs, so the
49
- * endpoint denies every request with a clean build and nothing else to go on — this is the line that
50
- * says why.
51
- */
52
- const auditEntrypoint = (ctx, req, params) => {
53
- if (req.alias == null || audited.has(req.alias)) {
54
- return;
55
- }
56
- audited.add(req.alias);
57
- try {
58
- const entrypoint = ctx.entrypoint(req.alias);
59
- if (entrypoint == null) {
60
- return;
61
- }
62
- let routePath;
63
- try {
64
- routePath = entrypoint.mount();
65
- }
66
- catch {
67
- // The mount needs a service with an address; an entrypoint that has none still has a filter
68
- // worth auditing.
69
- }
70
- const audit = {
71
- ...(routePath != null ? { routePath } : {}),
72
- ...(entrypoint.filter != null ? { filter: entrypoint.filter } : {})
73
- };
74
- for (const issue of validateGateParams(params, audit)) {
75
- log.error('Gate param is misconfigured', {
76
- param: issue.param, alias: req.alias, code: issue.code, detail: issue.detail,
77
- });
78
- }
79
- }
80
- catch {
81
- // An entrypoint that cannot be looked up is not this gate's problem to report.
82
- }
83
- };
84
23
  /**
85
24
  * IAM gate: claims-first with UMA2 fallback. Registered under the OIDC_GATE alias by
86
25
  * appendIam() so target code never knows which IAM backend is active.
@@ -97,6 +36,66 @@ const auditEntrypoint = (ctx, req, params) => {
97
36
  * have passed must not be refused because of it.
98
37
  */
99
38
  export const makeIamGate = (alias = OIDC_GATE, opts) => {
39
+ const reportOnce = (key, message, data) => {
40
+ if (reported.has(key)) {
41
+ return;
42
+ }
43
+ reported.add(key);
44
+ log.error(message, data);
45
+ };
46
+ /**
47
+ * A refusal of the gate. Logged once a minute per route, reason and subject — a hot endpoint
48
+ * refuses on every request, and one line per window says the same thing.
49
+ */
50
+ const forbidden = (req, reason, params) => {
51
+ const auth = req.auth;
52
+ if (logThrottle(`access.forbidden\0${req.alias ?? ''}\0${reason}\0${auth?.userId ?? ''}`, 60_000)) {
53
+ log.warn('Access forbidden', {
54
+ alias: req.alias, reason, params, userId: auth?.userId, entitySlug: req.entity?.slug ?? (auth != null ? authHelper.entitySlugOf(auth) : undefined),
55
+ }, { event: 'access.forbidden' });
56
+ }
57
+ return new AuthForbidden(reason);
58
+ };
59
+ /**
60
+ * Check an entrypoint's gate params against what it declares, once, the first time it is reached.
61
+ *
62
+ * Structurally unable to affect the outcome: it only ever logs. A selector naming a key the
63
+ * entrypoint's filter does not declare is stripped by validation before the gate runs, so the
64
+ * endpoint denies every request with a clean build and nothing else to go on — this is the line that
65
+ * says why.
66
+ */
67
+ const auditEntrypoint = (ctx, req, params) => {
68
+ if (req.alias == null || audited.has(req.alias)) {
69
+ return;
70
+ }
71
+ audited.add(req.alias);
72
+ try {
73
+ const entrypoint = ctx.entrypoint(req.alias);
74
+ if (entrypoint == null) {
75
+ return;
76
+ }
77
+ let routePath;
78
+ try {
79
+ routePath = entrypoint.mount();
80
+ }
81
+ catch {
82
+ // The mount needs a service with an address; an entrypoint that has none still has a filter
83
+ // worth auditing.
84
+ }
85
+ const audit = {
86
+ ...(routePath != null ? { routePath } : {}),
87
+ ...(entrypoint.filter != null ? { filter: entrypoint.filter } : {})
88
+ };
89
+ for (const issue of gateValidationHelper.validateGateParams(params, audit)) {
90
+ log.error('Gate param is misconfigured', {
91
+ param: issue.param, alias: req.alias, code: issue.code, detail: issue.detail,
92
+ });
93
+ }
94
+ }
95
+ catch {
96
+ // An entrypoint that cannot be looked up is not this gate's problem to report.
97
+ }
98
+ };
100
99
  const service = createLazyService(alias, {
101
100
  assert: async (req, _, params) => {
102
101
  await service.ready();
@@ -115,13 +114,13 @@ export const makeIamGate = (alias = OIDC_GATE, opts) => {
115
114
  // The organization the request acts in. A relying party of a tenanted client attaches it
116
115
  // through the guard; otherwise it is the token's. A set bound to any other organization
117
116
  // never satisfies the check.
118
- const entitySlug = req.entity?.slug ?? entitySlugOf(auth);
117
+ const entitySlug = req.entity?.slug ?? authHelper.entitySlugOf(auth);
119
118
  const granted = params.some(param => {
120
- const { permission, resource, error } = parseGateParam(param);
119
+ const { permission, resource, error } = gateParamHelper.parseGateParam(param);
121
120
  // Grants are stored against the entity's stable id wherever one is resolvable; the
122
121
  // slug is only a fallback for deployments with no organization store of their own,
123
122
  // where the slug IS the identifier.
124
- const fixed = permission.replaceAll('{entity}', req.entity?.id ?? entitySlugOf(auth) ?? '-');
123
+ const fixed = permission.replaceAll('{entity}', req.entity?.id ?? authHelper.entitySlugOf(auth) ?? '-');
125
124
  if (error != null) {
126
125
  structural.push(`"${param}" does not parse [${error.code}]: ${error.detail}`);
127
126
  return false;
@@ -148,16 +147,16 @@ export const makeIamGate = (alias = OIDC_GATE, opts) => {
148
147
  // UMA2 fallback. Resource scoping is NOT enforced here: a Keycloak-backed deployment cannot
149
148
  // store a resource-scoped grant, so a scoped param widens to a project-wide check and the same
150
149
  // declaration means two different things depending on which backend is active.
151
- const scoped = params.filter(param => parseGateParam(param).resource != null);
150
+ const scoped = params.filter(param => gateParamHelper.parseGateParam(param).resource != null);
152
151
  scoped.forEach(param => reportOnce(`uma2\0${req.alias}\0${param}`, 'Gate param is resource-scoped, but resource scoping is not enforced in UMA2 mode — it is checked as a '
153
152
  + 'project-wide permission', { param, alias: req.alias }));
154
153
  const usable = opts?.strictResourceScope === true
155
- ? params.filter(param => parseGateParam(param).resource == null)
154
+ ? params.filter(param => gateParamHelper.parseGateParam(param).resource == null)
156
155
  : params;
157
156
  if (usable.length < 1) {
158
157
  throw forbidden(req, 'permission', params);
159
158
  }
160
- const stripped = usable.map(param => parseGateParam(param).permission);
159
+ const stripped = usable.map(param => gateParamHelper.parseGateParam(param).permission);
161
160
  const model = createGateModel(ctx);
162
161
  const permissions = await model.loadPermissions(auth, stripped);
163
162
  if (permissions.length < 1) {
package/build/gate.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
package/build/index.d.ts CHANGED
@@ -4,7 +4,9 @@ export { ORGANIZATION_REFUSAL, ORGANIZATION_OWNER_REFUSAL } from '@owlmeans/oidc
4
4
  export * from './consts.js';
5
5
  export * from './append.js';
6
6
  export * from './gate.js';
7
- export { organizationOf, organizationsOf } from './organization.js';
8
- export { iamRuntime } from './runtime.js';
9
- export type { IamRuntimeClient } from './runtime.js';
7
+ export type * from './types.js';
8
+ export { makeOrganizationScope, organizationOf, organizationsOf } from './organization.js';
9
+ export type * from './organization/types.js';
10
+ export { makeIamRuntimeClient, iamRuntime } from './runtime.js';
11
+ export type { IamRuntimeClient } from './types.js';
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,eAAe,CAAA;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AACjF,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,eAAe,CAAA;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AACjF,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAC1F,mBAAmB,yBAAyB,CAAA;AAC5C,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA"}
package/build/index.js CHANGED
@@ -3,6 +3,6 @@ export { ORGANIZATION_REFUSAL, ORGANIZATION_OWNER_REFUSAL } from '@owlmeans/oidc
3
3
  export * from './consts.js';
4
4
  export * from './append.js';
5
5
  export * from './gate.js';
6
- export { organizationOf, organizationsOf } from './organization.js';
7
- export { iamRuntime } from './runtime.js';
6
+ export { makeOrganizationScope, organizationOf, organizationsOf } from './organization.js';
7
+ export { makeIamRuntimeClient, iamRuntime } from './runtime.js';
8
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AACjF,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AACjF,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AAEzB,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAE1F,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,21 @@
1
+ import type { ResolvedEntity } from '@owlmeans/entrypoint';
2
+ import type { OIDCAuthCache } from '@owlmeans/server-oidc-rp';
3
+ /** The organizations of one request's subject, read from its session — built once per handler. */
4
+ export interface OrganizationScope {
5
+ /** The session record behind the request's wrapped token — the guard has already refreshed it. */
6
+ sessionOf: () => Promise<OIDCAuthCache>;
7
+ /**
8
+ * Every organization of the request's subject, as request entities keyed by their frozen IAM key.
9
+ *
10
+ * The session record is the authority — the provider's last claim, re-read on every validation —
11
+ * never the browser: a relying party of a tenanted client has no organization registry of its own.
12
+ */
13
+ organizationsOf: () => Promise<ResolvedEntity[]>;
14
+ /**
15
+ * One organization of the request's subject by its slug — for a handler that acts in an
16
+ * organization the URL names rather than in the session's acting one. One the subject is not in is
17
+ * refused as `AuthForbidden(ORGANIZATION_REFUSAL)`, exactly as the switch refuses it.
18
+ */
19
+ organizationOf: (entitySlug: string) => Promise<ResolvedEntity>;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/organization/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE7D,kGAAkG;AAClG,MAAM,WAAW,iBAAiB;IAChC,kGAAkG;IAClG,SAAS,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IACvC;;;;;OAKG;IACH,eAAe,EAAE,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;IAChD;;;;OAIG;IACH,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;CAChE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/organization/types.ts"],"names":[],"mappings":""}
@@ -1,18 +1,9 @@
1
1
  import type { AbstractRequest, ResolvedEntity } from '@owlmeans/entrypoint';
2
- import type { Config, Context, OIDCAuthCache } from '@owlmeans/server-oidc-rp';
3
- /** The session record behind the request's wrapped token — the guard has already refreshed it. */
4
- export declare const sessionOf: <C extends Config, T extends Context<C>>(context: T, request: AbstractRequest) => Promise<OIDCAuthCache>;
5
- /**
6
- * Every organization of the request's subject, as request entities keyed by their frozen IAM key.
7
- *
8
- * The session record is the authority — the provider's last claim, re-read on every validation —
9
- * never the browser: a relying party of a tenanted client has no organization registry of its own.
10
- */
2
+ import type { Config, Context } from '@owlmeans/server-oidc-rp';
3
+ import type { OrganizationScope } from './organization/types.js';
4
+ export declare const makeOrganizationScope: <C extends Config, T extends Context<C>>(context: T, request: AbstractRequest) => OrganizationScope;
5
+ /** @deprecated compat:factory-refactor — use `makeOrganizationScope(context, request).organizationsOf()` */
11
6
  export declare const organizationsOf: <C extends Config, T extends Context<C>>(context: T, request: AbstractRequest) => Promise<ResolvedEntity[]>;
12
- /**
13
- * One organization of the request's subject by its slug — for a handler that acts in an
14
- * organization the URL names rather than in the session's acting one. One the subject is not in is
15
- * refused as `AuthForbidden(ORGANIZATION_REFUSAL)`, exactly as the switch refuses it.
16
- */
7
+ /** @deprecated compat:factory-refactor — use `makeOrganizationScope(context, request).organizationOf(…)` */
17
8
  export declare const organizationOf: <C extends Config, T extends Context<C>>(context: T, request: AbstractRequest, entitySlug: string) => Promise<ResolvedEntity>;
18
9
  //# sourceMappingURL=organization.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../src/organization.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAI3E,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE9E,kGAAkG;AAClG,eAAO,MAAM,SAAS,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WAC3D,CAAC,WAAW,eAAe,KACnC,OAAO,CAAC,aAAa,CAMvB,CAAA;AASD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WACjE,CAAC,WAAW,eAAe,KACnC,OAAO,CAAC,cAAc,EAAE,CAA6E,CAAA;AAExG;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WAChE,CAAC,WAAW,eAAe,cAAc,MAAM,KACvD,OAAO,CAAC,cAAc,CAOxB,CAAA"}
1
+ {"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../src/organization.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAI3E,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAiB,MAAM,0BAA0B,CAAA;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAShE,eAAO,MAAM,qBAAqB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WACjE,CAAC,WAAW,eAAe,KACnC,iBAqBF,CAAA;AAED,4GAA4G;AAC5G,eAAO,MAAM,eAAe,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WACjE,CAAC,WAAW,eAAe,KACnC,OAAO,CAAC,cAAc,EAAE,CAA0E,CAAA;AAErG,4GAA4G;AAC5G,eAAO,MAAM,cAAc,GAAU,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,WAChE,CAAC,WAAW,eAAe,cAAc,MAAM,KACvD,OAAO,CAAC,cAAc,CAAmF,CAAA"}
@@ -1,35 +1,30 @@
1
1
  import { AuthForbidden, AuthorizationError } from '@owlmeans/auth';
2
2
  import { ORGANIZATION_REFUSAL } from '@owlmeans/oidc';
3
3
  import { resolvedEntityOf, sessionRecord } from '@owlmeans/server-oidc-rp';
4
- /** The session record behind the request's wrapped token — the guard has already refreshed it. */
5
- export const sessionOf = async (context, request) => {
6
- if (request.auth == null) {
7
- throw new AuthorizationError('auth');
8
- }
9
- return sessionRecord(context, request.auth.token);
10
- };
11
4
  /**
12
5
  * The organizations the provider last claimed for the session's subject. A session that acts in
13
6
  * none — a client without the organizations scope — has none to offer, whatever its record holds.
14
7
  */
15
8
  const claimedOf = (record) => record.acting == null ? [] : record.organizations ?? [];
16
- /**
17
- * Every organization of the request's subject, as request entities keyed by their frozen IAM key.
18
- *
19
- * The session record is the authority — the provider's last claim, re-read on every validation —
20
- * never the browser: a relying party of a tenanted client has no organization registry of its own.
21
- */
22
- export const organizationsOf = async (context, request) => claimedOf(await sessionOf(context, request)).map(resolvedEntityOf);
23
- /**
24
- * One organization of the request's subject by its slug — for a handler that acts in an
25
- * organization the URL names rather than in the session's acting one. One the subject is not in is
26
- * refused as `AuthForbidden(ORGANIZATION_REFUSAL)`, exactly as the switch refuses it.
27
- */
28
- export const organizationOf = async (context, request, entitySlug) => {
29
- const org = claimedOf(await sessionOf(context, request)).find(org => org.entitySlug === entitySlug);
30
- if (org == null) {
31
- throw new AuthForbidden(ORGANIZATION_REFUSAL);
32
- }
33
- return resolvedEntityOf(org);
9
+ export const makeOrganizationScope = (context, request) => {
10
+ const sessionOf = async () => {
11
+ if (request.auth == null) {
12
+ throw new AuthorizationError('auth');
13
+ }
14
+ return sessionRecord(context, request.auth.token);
15
+ };
16
+ const organizationsOf = async () => claimedOf(await sessionOf()).map(resolvedEntityOf);
17
+ const organizationOf = async (entitySlug) => {
18
+ const org = claimedOf(await sessionOf()).find(org => org.entitySlug === entitySlug);
19
+ if (org == null) {
20
+ throw new AuthForbidden(ORGANIZATION_REFUSAL);
21
+ }
22
+ return resolvedEntityOf(org);
23
+ };
24
+ return { sessionOf, organizationsOf, organizationOf };
34
25
  };
26
+ /** @deprecated compat:factory-refactor — use `makeOrganizationScope(context, request).organizationsOf()` */
27
+ export const organizationsOf = async (context, request) => await makeOrganizationScope(context, request).organizationsOf();
28
+ /** @deprecated compat:factory-refactor — use `makeOrganizationScope(context, request).organizationOf(…)` */
29
+ export const organizationOf = async (context, request, entitySlug) => await makeOrganizationScope(context, request).organizationOf(entitySlug);
35
30
  //# sourceMappingURL=organization.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"organization.js","sourceRoot":"","sources":["../src/organization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAG1E,kGAAkG;AAClG,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC5B,OAAU,EAAE,OAAwB,EACZ,EAAE;IAC1B,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAA;IACtC,CAAC;IAED,OAAO,aAAa,CAAO,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACzD,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,MAAqB,EAA2B,EAAE,CACnE,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,OAAU,EAAE,OAAwB,EACT,EAAE,CAAC,SAAS,CAAC,MAAM,SAAS,CAAO,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;AAExG;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,OAAU,EAAE,OAAwB,EAAE,UAAkB,EAC/B,EAAE;IAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,SAAS,CAAO,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,UAAU,CAAC,CAAA;IACzG,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC/C,CAAC;IAED,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAA;AAC9B,CAAC,CAAA"}
1
+ {"version":3,"file":"organization.js","sourceRoot":"","sources":["../src/organization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAI1E;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,MAAqB,EAA2B,EAAE,CACnE,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAA;AAEzD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,OAAU,EAAE,OAAwB,EACjB,EAAE;IACrB,MAAM,SAAS,GAAG,KAAK,IAA4B,EAAE;QACnD,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAA;QACtC,CAAC;QAED,OAAO,aAAa,CAAO,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzD,CAAC,CAAA;IAED,MAAM,eAAe,GAAG,KAAK,IAA+B,EAAE,CAAC,SAAS,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAEjH,MAAM,cAAc,GAAG,KAAK,EAAE,UAAkB,EAA2B,EAAE;QAC3E,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,UAAU,CAAC,CAAA;QACnF,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,aAAa,CAAC,oBAAoB,CAAC,CAAA;QAC/C,CAAC;QAED,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAA;IAC9B,CAAC,CAAA;IAED,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,CAAA;AACvD,CAAC,CAAA;AAED,4GAA4G;AAC5G,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,OAAU,EAAE,OAAwB,EACT,EAAE,CAAC,MAAM,qBAAqB,CAAO,OAAO,EAAE,OAAO,CAAC,CAAC,eAAe,EAAE,CAAA;AAErG,4GAA4G;AAC5G,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,OAAU,EAAE,OAAwB,EAAE,UAAkB,EAC/B,EAAE,CAAC,MAAM,qBAAqB,CAAO,OAAO,EAAE,OAAO,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA"}