@dudousxd/nestjs-authz 0.8.1 → 0.9.0

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 (122) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +279 -0
  3. package/dist/authz.guard.d.ts +48 -0
  4. package/dist/authz.guard.d.ts.map +1 -0
  5. package/dist/authz.guard.js +144 -0
  6. package/dist/authz.guard.js.map +1 -0
  7. package/dist/can-endpoint.controller.d.ts +0 -19
  8. package/dist/can-endpoint.controller.d.ts.map +1 -1
  9. package/dist/can-endpoint.controller.js +18 -9
  10. package/dist/can-endpoint.controller.js.map +1 -1
  11. package/dist/decision-provider.d.ts +25 -16
  12. package/dist/decision-provider.d.ts.map +1 -1
  13. package/dist/decision-provider.js +11 -1
  14. package/dist/decision-provider.js.map +1 -1
  15. package/dist/decisions.d.ts +24 -0
  16. package/dist/decisions.d.ts.map +1 -0
  17. package/dist/decisions.js +87 -0
  18. package/dist/decisions.js.map +1 -0
  19. package/dist/decorator/roles.decorator.d.ts +6 -12
  20. package/dist/decorator/roles.decorator.d.ts.map +1 -1
  21. package/dist/decorator/roles.decorator.js +13 -15
  22. package/dist/decorator/roles.decorator.js.map +1 -1
  23. package/dist/diagnostics.d.ts +15 -5
  24. package/dist/diagnostics.d.ts.map +1 -1
  25. package/dist/diagnostics.js +3 -1
  26. package/dist/diagnostics.js.map +1 -1
  27. package/dist/errors/exceptions.d.ts +0 -8
  28. package/dist/errors/exceptions.d.ts.map +1 -1
  29. package/dist/errors/exceptions.js +0 -14
  30. package/dist/errors/exceptions.js.map +1 -1
  31. package/dist/gate.d.ts +83 -218
  32. package/dist/gate.d.ts.map +1 -1
  33. package/dist/gate.js +209 -611
  34. package/dist/gate.js.map +1 -1
  35. package/dist/helpers.d.ts +46 -0
  36. package/dist/helpers.d.ts.map +1 -0
  37. package/dist/helpers.js +89 -0
  38. package/dist/helpers.js.map +1 -0
  39. package/dist/index.d.ts +28 -21
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +30 -13
  42. package/dist/index.js.map +1 -1
  43. package/dist/links.d.ts +39 -0
  44. package/dist/links.d.ts.map +1 -0
  45. package/dist/links.js +57 -0
  46. package/dist/links.js.map +1 -0
  47. package/dist/module.d.ts +23 -22
  48. package/dist/module.d.ts.map +1 -1
  49. package/dist/module.js +129 -158
  50. package/dist/module.js.map +1 -1
  51. package/dist/official.d.ts +39 -0
  52. package/dist/official.d.ts.map +1 -0
  53. package/dist/official.js +44 -0
  54. package/dist/official.js.map +1 -0
  55. package/dist/policies/authz-policy.d.ts +42 -0
  56. package/dist/policies/authz-policy.d.ts.map +1 -0
  57. package/dist/policies/authz-policy.js +80 -0
  58. package/dist/policies/authz-policy.js.map +1 -0
  59. package/dist/policies/gate.policy.d.ts +18 -0
  60. package/dist/policies/gate.policy.d.ts.map +1 -0
  61. package/dist/policies/gate.policy.js +37 -0
  62. package/dist/policies/gate.policy.js.map +1 -0
  63. package/dist/policies/index.d.ts +5 -0
  64. package/dist/policies/index.d.ts.map +1 -0
  65. package/dist/policies/index.js +5 -0
  66. package/dist/policies/index.js.map +1 -0
  67. package/dist/policies/permission.policy.d.ts +27 -0
  68. package/dist/policies/permission.policy.d.ts.map +1 -0
  69. package/dist/policies/permission.policy.js +61 -0
  70. package/dist/policies/permission.policy.js.map +1 -0
  71. package/dist/policies/role.policy.d.ts +27 -0
  72. package/dist/policies/role.policy.d.ts.map +1 -0
  73. package/dist/policies/role.policy.js +51 -0
  74. package/dist/policies/role.policy.js.map +1 -0
  75. package/dist/policy-index.d.ts +51 -0
  76. package/dist/policy-index.d.ts.map +1 -0
  77. package/dist/policy-index.js +135 -0
  78. package/dist/policy-index.js.map +1 -0
  79. package/dist/rbac.d.ts +92 -0
  80. package/dist/rbac.d.ts.map +1 -0
  81. package/dist/rbac.js +293 -0
  82. package/dist/rbac.js.map +1 -0
  83. package/dist/resource-resolver.d.ts +15 -17
  84. package/dist/resource-resolver.d.ts.map +1 -1
  85. package/dist/resource-resolver.js +8 -8
  86. package/dist/resource-resolver.js.map +1 -1
  87. package/dist/runtime.d.ts +31 -0
  88. package/dist/runtime.d.ts.map +1 -0
  89. package/dist/runtime.js +40 -0
  90. package/dist/runtime.js.map +1 -0
  91. package/dist/tokens.d.ts +4 -8
  92. package/dist/tokens.d.ts.map +1 -1
  93. package/dist/tokens.js +4 -8
  94. package/dist/tokens.js.map +1 -1
  95. package/dist/types.d.ts +52 -171
  96. package/dist/types.d.ts.map +1 -1
  97. package/package.json +19 -10
  98. package/skills/authz-enforcement/SKILL.md +67 -135
  99. package/skills/authz-policies/SKILL.md +43 -117
  100. package/skills/authz-query-scopes/SKILL.md +16 -9
  101. package/skills/authz-rbac-seams/SKILL.md +29 -12
  102. package/skills/authz-setup/SKILL.md +45 -106
  103. package/dist/decorator/can.decorator.d.ts +0 -29
  104. package/dist/decorator/can.decorator.d.ts.map +0 -1
  105. package/dist/decorator/can.decorator.js +0 -23
  106. package/dist/decorator/can.decorator.js.map +0 -1
  107. package/dist/decorator/policy.decorator.d.ts +0 -18
  108. package/dist/decorator/policy.decorator.d.ts.map +0 -1
  109. package/dist/decorator/policy.decorator.js +0 -28
  110. package/dist/decorator/policy.decorator.js.map +0 -1
  111. package/dist/guard/can.guard.d.ts +0 -31
  112. package/dist/guard/can.guard.d.ts.map +0 -1
  113. package/dist/guard/can.guard.js +0 -92
  114. package/dist/guard/can.guard.js.map +0 -1
  115. package/dist/guard/roles.guard.d.ts +0 -21
  116. package/dist/guard/roles.guard.d.ts.map +0 -1
  117. package/dist/guard/roles.guard.js +0 -50
  118. package/dist/guard/roles.guard.js.map +0 -1
  119. package/dist/policy-registry.d.ts +0 -46
  120. package/dist/policy-registry.d.ts.map +0 -1
  121. package/dist/policy-registry.js +0 -101
  122. package/dist/policy-registry.js.map +0 -1
package/dist/gate.d.ts CHANGED
@@ -1,271 +1,136 @@
1
+ import { type Ability, AuthorizationService } from '@nestjs/authorization';
1
2
  import { type Type } from '@nestjs/common';
2
- import { ModuleRef } from '@nestjs/core';
3
- import type { ContextAccessor } from './context-accessor.js';
4
- import type { DecisionProvider } from './decision-provider.js';
5
- import { type AuthzDecisionReason } from './diagnostics.js';
6
- import type { PermissionProvider } from './permission-provider.js';
7
- import { PolicyRegistry } from './policy-registry.js';
8
- import { type RoleProvider } from './role-provider.js';
3
+ import { PolicyIndex } from './policy-index.js';
4
+ import { AuthzRbac } from './rbac.js';
9
5
  import { type ScopeConstraint } from './scope.js';
10
6
  import type { AuthzModuleOptions, GateFn, Resource, User } from './types.js';
11
- declare const NO_USER: unique symbol;
12
- type MaybeUser = User | typeof NO_USER;
13
- /** A single item in a {@link Gate.allowsMany} batch. */
7
+ /** The arguments after the user of ability `A` on policy `P`. */
8
+ export type AbilityArgsOf<P, A extends keyof P> = P[A] extends (user: never, ...args: infer R) => unknown ? R : never;
9
+ /** A string ability, optionally on a resource (instance, or class for class-level abilities). */
14
10
  export interface BatchAbility {
15
11
  ability: string;
16
12
  resource?: Resource;
17
13
  }
18
- /** A single result from a {@link Gate.allowsMany} batch: the input plus its verdict. */
19
- export interface BatchResult {
14
+ /** An official policy check: `policy[ability](user, ...args)`. */
15
+ export interface BatchPolicyCheck {
16
+ policy: Type<unknown>;
20
17
  ability: string;
21
- resource?: Resource;
22
- allowed: boolean;
18
+ args?: readonly unknown[];
23
19
  }
20
+ /** One item of a {@link Gate.allowsMany} batch. */
21
+ export type BatchItem = BatchAbility | BatchPolicyCheck;
22
+ /** One result of a {@link Gate.allowsMany} batch: the item plus its verdict. */
23
+ export type BatchResult = BatchItem & {
24
+ allowed: boolean;
25
+ };
24
26
  /**
25
- * Laravel-style authorization Gate.
27
+ * A façade over the official `AuthorizationService` for service-layer checks, with what
28
+ * the official service does not have:
26
29
  *
27
- * Resolves an ability against either a registered `@Policy` method (by ability
28
- * name, matched against the resource's policy) or an ad-hoc gate defined via
29
- * {@link define}. Applies the global `superAdmin` before-hook and the per-policy
30
- * `before` hook with short-circuit semantics.
30
+ * - **string abilities**, Laravel-style: `gate.allows('update', post)` finds the policy
31
+ * linked to `Post` with `@PolicyFor(Post)`; `gate.allows('access-admin')` runs an
32
+ * ad-hoc gate from {@link define}; `gate.allows('posts.publish')` asks the persisted
33
+ * permissions. Asks `superAdmin` first, then the external decision point
34
+ * (`DECISION_PROVIDER`), then the policy — which has the final word: a persisted
35
+ * permission named like the ability does not bypass it — then the persisted
36
+ * permissions, then the ad-hoc gate.
37
+ * - **official policy checks**: `gate.allows(PostPolicy, 'update', post)`, exactly
38
+ * `AuthorizationService.can()`.
39
+ * - **batches** ({@link allowsMany}) sharing one permission fetch, **query scopes**
40
+ * ({@link scope}), **roles** ({@link hasRole}), an allow+deny decision event, and an
41
+ * ambient user when none is passed ({@link forUser} passes one): `@nestjs/authentication`'s
42
+ * `AuthenticationContext.user` when that package is installed, else nestjs-context's.
31
43
  *
32
- * The current user comes from the optional {@link ContextAccessor} (nestjs-context)
33
- * when present, or is supplied explicitly via {@link forUser}.
44
+ * Every policy decision is the official service's: the policy's own `before()`, then
45
+ * the ability, allowed only on a literal `true`.
34
46
  */
35
47
  export declare class Gate {
36
- private readonly policies;
37
- private readonly context?;
38
- private readonly moduleRef?;
39
- private readonly permissionProvider?;
40
- private readonly roleProvider?;
41
- private readonly decisionProvider?;
48
+ private readonly index;
49
+ private readonly rbac;
42
50
  private readonly gates;
43
51
  private readonly superAdmin;
44
- private readonly after;
45
- private readonly resolveUser;
46
- private readonly roleResolver;
47
- private contextResolved;
48
- private contextCached;
49
- private permissionProviderResolved;
50
- private permissionProviderCached;
51
- private roleProviderResolved;
52
- private roleProviderCached;
53
- private decisionProviderResolved;
54
- private decisionProviderCached;
55
- constructor(policies: PolicyRegistry, options: AuthzModuleOptions | undefined, context?: ContextAccessor | undefined, moduleRef?: ModuleRef | undefined, permissionProvider?: PermissionProvider | undefined, roleProvider?: RoleProvider | undefined, decisionProvider?: DecisionProvider | undefined);
56
- /**
57
- * Locate the context accessor. Prefers the value injected into this module;
58
- * falls back to a non-strict {@link ModuleRef} lookup so an accessor provided
59
- * by ANY module (e.g. a global ContextModule, or the app root) is still found.
60
- */
61
- private resolveContext;
62
- /**
63
- * Locate the optional {@link PermissionProvider} (the RBAC seam). Prefers the value
64
- * injected into this module; falls back to a non-strict {@link ModuleRef} lookup so a
65
- * provider registered by ANY module (e.g. the RBAC adapter's global module) is found.
66
- */
67
- private resolvePermissionProvider;
68
- /**
69
- * Locate the optional {@link RoleProvider} (the coarse role seam). Prefers the value
70
- * injected into this module; falls back to a non-strict {@link ModuleRef} lookup so a
71
- * provider registered by ANY module (e.g. the RBAC adapter's global module) is found.
72
- */
73
- private resolveRoleProvider;
74
- /**
75
- * Locate the optional {@link DecisionProvider} (the external-PDP seam). Same lookup strategy as
76
- * {@link resolvePermissionProvider}: injected value first, then a memoized non-strict scan.
77
- */
78
- private resolveDecisionProvider;
79
- /**
80
- * The per-request {@link PermissionCache}, stashed on the nestjs-context store so
81
- * every check within one HTTP request shares a single `getPermissions` fetch
82
- * (kills the N+1 a list page would otherwise cause). Returns `undefined` when no
83
- * context store is available (standalone use), in which case callers fall back to
84
- * a transient cache (e.g. one per `allowsMany` batch) or no memoization.
85
- */
86
- private resolveRequestCache;
87
- /** The nestjs-context store for the current request, or `undefined` when there is none. */
88
- private requestStore;
52
+ private readonly authz;
53
+ constructor(authz: AuthorizationService | undefined, index: PolicyIndex, rbac: AuthzRbac, options?: AuthzModuleOptions);
89
54
  /** Register an ad-hoc, model-less gate resolved by `ability` name. */
90
55
  define(ability: string, fn: GateFn): this;
91
56
  /** True when an ad-hoc gate is registered for `ability`. */
92
57
  hasGate(ability: string): boolean;
93
- /**
94
- * Names of every ad-hoc gate registered via {@link define}. Used by integrations
95
- * (e.g. `@dudousxd/nestjs-authz-inertia`) that enumerate the user's class-level
96
- * abilities to share them as Inertia props — no network round-trip needed.
97
- */
58
+ /** Names of every ad-hoc gate registered with {@link define}. */
98
59
  gateNames(): string[];
99
60
  /**
100
- * Bind an explicit user, bypassing the context accessor. Use when no
101
- * nestjs-context is wired, or to check a user other than the current one.
102
- *
103
- * A nullish user (`forUser(undefined)` / `forUser(null)`) is an explicit
104
- * anonymous request: it maps to the same deny path as an unauthenticated
105
- * context (`NO_USER`), so policies/gates are never invoked with `undefined` and
106
- * never throw. The `resolveUser` hook is NOT applied to `forUser` — the value
107
- * you pass is used verbatim.
61
+ * Bind an explicit user. `null`/`undefined` is a guest. The usual way to check in a
62
+ * service: pass the user your handler received.
108
63
  */
109
64
  forUser(user: User): BoundGate;
110
65
  /**
111
- * Resolve the current user from the context accessor, or `NO_USER`.
112
- * When a `resolveUser` hook is configured, hydrate the full entity from the
113
- * context's {@link UserRef}; a hook returning nullish maps to `NO_USER`. The
114
- * hydrated user is memoized on the request's context store by `type:id`, so the
115
- * hook runs once per request rather than once per check.
66
+ * The ambient user, for calls without {@link forUser}: `@nestjs/authentication`'s
67
+ * `AuthenticationContext.user` when that optional peer is installed and has one, else
68
+ * nestjs-context's user ref (hydrated by `resolveUser` when configured, once per
69
+ * request). `null` without either.
116
70
  */
117
71
  private currentUser;
72
+ allows<P, const A extends Ability<P>>(policy: Type<P>, ability: A, ...args: AbilityArgsOf<P, A>): Promise<boolean>;
118
73
  allows(ability: string, resource?: Resource): Promise<boolean>;
74
+ denies<P, const A extends Ability<P>>(policy: Type<P>, ability: A, ...args: AbilityArgsOf<P, A>): Promise<boolean>;
119
75
  denies(ability: string, resource?: Resource): Promise<boolean>;
120
- authorize(ability: string, resource?: Resource): Promise<void>;
121
76
  /**
122
- * Authorize MANY abilities for the current (context) user in a single pass. The
123
- * user is resolved ONCE and a single {@link PermissionCache} is shared across all
124
- * items, so a list page (N cards) costs one user resolution + at most one
125
- * permission fetch instead of N of each. Order is preserved; each result echoes
126
- * its input `ability`/`resource` plus the `allowed` verdict.
127
- *
128
- * Fault-isolating: an item whose ability is unresolved/ambiguous denies just
129
- * THAT item (it does not throw and abort the batch) — a batch is a best-effort
130
- * verdict list, not an enforcement gate.
77
+ * Like {@link allows}, but throws the official `AuthorizationError` on a denial, which
78
+ * the official module turns into a 401/403 (or the transport's error) when it leaves
79
+ * a handler.
131
80
  */
132
- allowsMany(items: BatchAbility[]): Promise<BatchResult[]>;
81
+ authorize<P, const A extends Ability<P>>(policy: Type<P>, ability: A, ...args: AbilityArgsOf<P, A>): Promise<void>;
82
+ authorize(ability: string, resource?: Resource): Promise<void>;
83
+ /** Check many abilities at once (one user, one permission fetch). A failing item denies. */
84
+ allowsMany(items: readonly BatchItem[]): Promise<BatchResult[]>;
133
85
  /**
134
- * Resolve the QUERY SCOPE constraint for the current (context) user against
135
- * `entity` — the `accessibleBy` / Pundit `policy_scope` concept. Returns an
136
- * ORM-neutral {@link ScopeConstraint} an adapter (e.g. the TypeORM `applyScope`
137
- * helper) turns into a parameterized `WHERE`.
138
- *
139
- * Consistent with the Gate's single-resource semantics:
140
- * - super-admin / before-grant / permission-provider grant → `allow-all`,
141
- * - anonymous, or no policy/scope → `deny-all` (default-deny),
142
- * - otherwise the policy's `scope` (or `viewAny`-style) constraint.
143
- *
144
- * `ability` (default `'viewAny'`) names the permission-provider check used for
145
- * the allow-all grant and the policy fallback method.
86
+ * The query scope of `entity` (a resource class linked with `@PolicyFor`, or the
87
+ * policy class itself) for the current user, from the policy's `scope(user, entity)`
88
+ * method (else the `ability` method, `viewAny` by default). See {@link ScopeConstraint}.
146
89
  */
147
90
  scope(entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
148
- /** True when the current user holds `role`. */
91
+ /** True when the current user holds `role` (a fact: `superAdmin` does not apply). */
149
92
  hasRole(role: string): Promise<boolean>;
150
- /** True when the current user holds ANY of `roles`. */
93
+ /** True when the current user holds any of `roles`. */
151
94
  hasAnyRole(roles: string[]): Promise<boolean>;
152
95
  /** @internal */
153
- allowsForUser(user: MaybeUser, ability: string, resource?: Resource): Promise<boolean>;
154
- /** @internal — batch check for an explicit/bound user (see {@link allowsMany}). */
155
- allowsManyForUser(user: MaybeUser, items: BatchAbility[]): Promise<BatchResult[]>;
156
- /**
157
- * Run a batch of checks against one already-resolved user, sharing a single
158
- * {@link PermissionCache} so the provider's `getPermissions` runs at most once.
159
- * Prefers the per-request cache (so the batch also coalesces with other checks in
160
- * the same request); falls back to a transient per-batch cache when standalone.
161
- */
162
- private checkMany;
96
+ allowsFor(user: User, first: string | Type<unknown>, rest: unknown[]): Promise<boolean>;
97
+ /** @internal */
98
+ authorizeFor(user: User, first: string | Type<unknown>, rest: unknown[]): Promise<void>;
99
+ /** @internal */
100
+ allowsManyFor(user: User, items: readonly BatchItem[]): Promise<BatchResult[]>;
163
101
  /**
164
- * One {@link DecisionProvider.decideMany} round-trip for a whole batch, when the provider
165
- * supports it. Returns `undefined` (→ per-item `decide`) otherwise. A batch-call failure makes
166
- * every item fall back to its own `decide` call rather than failing the batch.
102
+ * One `decideMany` round-trip to the external decision point for the string abilities
103
+ * of a batch, when it supports batching. Empty otherwise, and when the batch call fails
104
+ * (each item then asks `decide` on its own).
167
105
  */
168
106
  private prefetchDecisions;
169
- /** @internal — used by {@link BoundGate.authorize} to surface the deny reason/message. */
170
- decideForUser(user: MaybeUser, ability: string, resource?: Resource): Promise<{
171
- allowed: boolean;
172
- reason: AuthzDecisionReason;
173
- message?: string;
174
- }>;
175
107
  /** @internal */
176
- hasAnyRoleForUser(user: MaybeUser, roles: string[]): Promise<boolean>;
177
- /** @internal — used by {@link BoundGate.scope}. */
178
- scopeForUser(user: MaybeUser, entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
179
- /**
180
- * Resolve a query-scope constraint for `entity`, mirroring {@link resolveBase}'s
181
- * grant order so scoping stays consistent with single-resource decisions:
182
- *
183
- * 1. super-admin hook grants → `allow-all`;
184
- * 1b. decision provider `planScope` → its constraint (unless it abstains);
185
- * 2. (authenticated) permission-provider grant for `ability` → `allow-all`;
186
- * 3. the policy's `scope` (or `viewAny`-style) method → its constraint;
187
- * 4. otherwise (anonymous, no policy, no scope method) → `deny-all`.
188
- *
189
- * The policy `before` hook is also honored as an allow/deny grant before the
190
- * scope method runs, so a policy that broadly allows/denies in `before` scopes
191
- * the same way it decides.
192
- */
193
- private resolveScope;
194
- /**
195
- * Pick the policy's scope method: the conventional `scope`, else the `ability`
196
- * method (e.g. `viewAny`) when it is scope-shaped. Returns `undefined` when the
197
- * policy declares neither.
198
- */
199
- private resolveScopeMethod;
200
- /**
201
- * Whether the registered {@link PermissionProvider} grants `ability` for an authenticated `user` —
202
- * the RBAC "before" grant shared by the single-resource ({@link resolveBase}) and scope
203
- * ({@link resolveScope}) paths, single-sourced here so the grant order can't drift between them.
204
- *
205
- * Grant-only: a `false`/nullish result is "no grant", never a deny. When the provider lists the
206
- * user's granted permissions, segment-based wildcard matching runs in the core (a granted
207
- * `posts.*` satisfies `posts.update`, `*` satisfies anything) regardless of adapter; a nullish
208
- * list defers to the exact-match `hasPermission`. A set the provider marks
209
- * {@link PermissionProvider.exhaustivePermissions} answers the check on its own; otherwise an
210
- * unsatisfied set still defers to `hasPermission`. The granted set is fetched through `cache`
211
- * when one is supplied, else via a direct fetch.
212
- */
213
- private permissionProviderGrants;
214
- /**
215
- * Resolve the user's effective roles and test membership against `roles`. Returns
216
- * `false` for an anonymous (NO_USER) caller and whenever no source yields a role
217
- * (deny-by-default). Roles come from the UNION of the default/overridden
218
- * {@link RoleResolver} (reads the user object) and the optional {@link RoleProvider}
219
- * seam (a persisted store) — so an app needs neither to opt in.
220
- */
221
- private checkRoles;
222
- /**
223
- * The current user's effective role names (resolver ∪ provider). The provider's
224
- * roles are fetched through `cache` when one is supplied.
225
- */
226
- private rolesOf;
227
- private check;
228
- /**
229
- * Resolve a decision AND publish it for observers. Returns the full decision
230
- * (verdict + reason + optional deny message) so {@link authorize} can surface the
231
- * `reason`/`message` on the thrown `ForbiddenException`. {@link check} discards
232
- * everything but the verdict.
233
- */
108
+ hasAnyRoleFor(user: User, roles: string[]): Promise<boolean>;
109
+ /** @internal */
110
+ scopeFor(user: User, entity: Type<unknown>, ability: string): Promise<ScopeConstraint>;
111
+ /** Decide, publish the decision, and (in `authorize` mode) let the official service emit its denial. */
234
112
  private decide;
235
- /**
236
- * Resolve an ability to a final verdict, the path that decided it, and an optional
237
- * deny message. Runs the global `after` hook over the base decision (see
238
- * {@link AfterHook} for override semantics). Throws
239
- * {@link AbilityNotResolvedException}/{@link AmbiguousAbilityException} when no
240
- * decision can be reached (those paths emit no decision and skip `after`).
241
- */
242
- private resolve;
243
- /**
244
- * The pre-`after` resolution. `allowed` is `undefined` when the deciding path
245
- * (policy method / ad-hoc gate) returned a nullish value — "no opinion" — which
246
- * lets the {@link AfterHook} supply a verdict before the default-deny finalize.
247
- */
248
- private resolveBase;
249
- private resolvePolicy;
113
+ private decidePolicy;
114
+ private decideString;
115
+ /** The linked policy defining `ability` for `resource` (or for no resource, unambiguously). */
116
+ private policyFor;
250
117
  }
251
- /**
252
- * A {@link Gate} bound to an explicit user. Returned by {@link Gate.forUser}.
253
- */
118
+ /** A {@link Gate} bound to an explicit user. Returned by {@link Gate.forUser}. */
254
119
  export declare class BoundGate {
255
120
  private readonly gate;
256
121
  private readonly user;
257
- constructor(gate: Gate, user: MaybeUser);
122
+ constructor(gate: Gate, user: User);
123
+ allows<P, const A extends Ability<P>>(policy: Type<P>, ability: A, ...args: AbilityArgsOf<P, A>): Promise<boolean>;
258
124
  allows(ability: string, resource?: Resource): Promise<boolean>;
125
+ denies<P, const A extends Ability<P>>(policy: Type<P>, ability: A, ...args: AbilityArgsOf<P, A>): Promise<boolean>;
259
126
  denies(ability: string, resource?: Resource): Promise<boolean>;
260
- /** Batch-authorize many abilities for the bound user in one pass (see {@link Gate.allowsMany}). */
261
- allowsMany(items: BatchAbility[]): Promise<BatchResult[]>;
262
- /** Resolve the query-scope constraint for the bound user (see {@link Gate.scope}). */
263
- scope(entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
127
+ authorize<P, const A extends Ability<P>>(policy: Type<P>, ability: A, ...args: AbilityArgsOf<P, A>): Promise<void>;
264
128
  authorize(ability: string, resource?: Resource): Promise<void>;
265
- /** True when the bound user holds `role`. */
129
+ /** Batch-check for the bound user (see {@link Gate.allowsMany}). */
130
+ allowsMany(items: readonly BatchItem[]): Promise<BatchResult[]>;
131
+ /** The query scope for the bound user (see {@link Gate.scope}). */
132
+ scope(entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
266
133
  hasRole(role: string): Promise<boolean>;
267
- /** True when the bound user holds ANY of `roles`. */
268
134
  hasAnyRole(roles: string[]): Promise<boolean>;
269
135
  }
270
- export {};
271
136
  //# sourceMappingURL=gate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAsB,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EAAgC,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAOzE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,KAAK,eAAe,EAKrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,QAAQ,EAAkB,IAAI,EAAE,MAAM,YAAY,CAAC;AAE7F,iEAAiE;AACjE,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAC7D,IAAI,EAAE,KAAK,EACX,GAAG,IAAI,EAAE,MAAM,CAAC,KACb,OAAO,GACR,CAAC,GACD,KAAK,CAAC;AAEV,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC3B;AAED,mDAAmD;AACnD,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAExD,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAgB3D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBACa,IAAI;IAOb,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;gBAGD,KAAK,EAAE,oBAAoB,GAAG,SAAS,EAChE,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,SAAS,EACU,OAAO,CAAC,EAAE,kBAAkB;IAMxE,sEAAsE;IACtE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAKzC,4DAA4D;IAC5D,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIjC,iEAAiE;IACjE,SAAS,IAAI,MAAM,EAAE;IAIrB;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS;IAI9B;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAMnB,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAClC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,CAAC,EACV,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC3B,OAAO,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAK9D,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAClC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,CAAC,EACV,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC3B,OAAO,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAK9D;;;;OAIG;IACH,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EACrC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,CAAC,EACV,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAChB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9D,4FAA4F;IACtF,UAAU,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAIrE;;;;OAIG;IACG,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,SAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAIjF,qFAAqF;IAC/E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7C,uDAAuD;IACjD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAMnD,gBAAgB;IACV,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7F,gBAAgB;IACV,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAW7F,gBAAgB;IACV,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAoBpF;;;;OAIG;YACW,iBAAiB;IA6B/B,gBAAgB;IACV,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,gBAAgB;IACV,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAmC5F,wGAAwG;YAC1F,MAAM;YAuBN,YAAY;YA0BZ,YAAY;IAgD1B,+FAA+F;IAC/F,OAAO,CAAC,SAAS;CAiBlB;AAED,kFAAkF;AAClF,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI;IAG7B,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAClC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,CAAC,EACV,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC3B,OAAO,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAK9D,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAClC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,CAAC,EACV,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC3B,OAAO,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAK9D,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EACrC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,CAAC,EACV,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAChB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9D,oEAAoE;IACpE,UAAU,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI/D,mEAAmE;IACnE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,SAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAI3E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAG9C"}