@dudousxd/nestjs-authz 0.8.1 → 0.9.1
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/CHANGELOG.md +115 -0
- package/README.md +279 -0
- package/dist/authz.guard.d.ts +48 -0
- package/dist/authz.guard.d.ts.map +1 -0
- package/dist/authz.guard.js +144 -0
- package/dist/authz.guard.js.map +1 -0
- package/dist/can-endpoint.controller.d.ts +0 -19
- package/dist/can-endpoint.controller.d.ts.map +1 -1
- package/dist/can-endpoint.controller.js +18 -9
- package/dist/can-endpoint.controller.js.map +1 -1
- package/dist/decision-provider.d.ts +25 -16
- package/dist/decision-provider.d.ts.map +1 -1
- package/dist/decision-provider.js +11 -1
- package/dist/decision-provider.js.map +1 -1
- package/dist/decisions.d.ts +24 -0
- package/dist/decisions.d.ts.map +1 -0
- package/dist/decisions.js +87 -0
- package/dist/decisions.js.map +1 -0
- package/dist/decorator/roles.decorator.d.ts +6 -12
- package/dist/decorator/roles.decorator.d.ts.map +1 -1
- package/dist/decorator/roles.decorator.js +13 -15
- package/dist/decorator/roles.decorator.js.map +1 -1
- package/dist/diagnostics.d.ts +15 -5
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +3 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/errors/exceptions.d.ts +0 -8
- package/dist/errors/exceptions.d.ts.map +1 -1
- package/dist/errors/exceptions.js +0 -14
- package/dist/errors/exceptions.js.map +1 -1
- package/dist/gate.d.ts +83 -218
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +209 -611
- package/dist/gate.js.map +1 -1
- package/dist/helpers.d.ts +46 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +89 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +28 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -13
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +39 -0
- package/dist/links.d.ts.map +1 -0
- package/dist/links.js +57 -0
- package/dist/links.js.map +1 -0
- package/dist/module.d.ts +23 -22
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +129 -158
- package/dist/module.js.map +1 -1
- package/dist/official.d.ts +39 -0
- package/dist/official.d.ts.map +1 -0
- package/dist/official.js +44 -0
- package/dist/official.js.map +1 -0
- package/dist/policies/authz-policy.d.ts +42 -0
- package/dist/policies/authz-policy.d.ts.map +1 -0
- package/dist/policies/authz-policy.js +80 -0
- package/dist/policies/authz-policy.js.map +1 -0
- package/dist/policies/gate.policy.d.ts +18 -0
- package/dist/policies/gate.policy.d.ts.map +1 -0
- package/dist/policies/gate.policy.js +37 -0
- package/dist/policies/gate.policy.js.map +1 -0
- package/dist/policies/index.d.ts +5 -0
- package/dist/policies/index.d.ts.map +1 -0
- package/dist/policies/index.js +5 -0
- package/dist/policies/index.js.map +1 -0
- package/dist/policies/permission.policy.d.ts +27 -0
- package/dist/policies/permission.policy.d.ts.map +1 -0
- package/dist/policies/permission.policy.js +61 -0
- package/dist/policies/permission.policy.js.map +1 -0
- package/dist/policies/role.policy.d.ts +27 -0
- package/dist/policies/role.policy.d.ts.map +1 -0
- package/dist/policies/role.policy.js +51 -0
- package/dist/policies/role.policy.js.map +1 -0
- package/dist/policy-index.d.ts +51 -0
- package/dist/policy-index.d.ts.map +1 -0
- package/dist/policy-index.js +135 -0
- package/dist/policy-index.js.map +1 -0
- package/dist/rbac.d.ts +92 -0
- package/dist/rbac.d.ts.map +1 -0
- package/dist/rbac.js +293 -0
- package/dist/rbac.js.map +1 -0
- package/dist/resource-resolver.d.ts +15 -17
- package/dist/resource-resolver.d.ts.map +1 -1
- package/dist/resource-resolver.js +8 -8
- package/dist/resource-resolver.js.map +1 -1
- package/dist/runtime.d.ts +31 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +40 -0
- package/dist/runtime.js.map +1 -0
- package/dist/tokens.d.ts +4 -8
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +4 -8
- package/dist/tokens.js.map +1 -1
- package/dist/types.d.ts +52 -171
- package/dist/types.d.ts.map +1 -1
- package/package.json +20 -11
- package/skills/authz-enforcement/SKILL.md +67 -135
- package/skills/authz-policies/SKILL.md +43 -117
- package/skills/authz-query-scopes/SKILL.md +16 -9
- package/skills/authz-rbac-seams/SKILL.md +29 -12
- package/skills/authz-setup/SKILL.md +45 -106
- package/dist/decorator/can.decorator.d.ts +0 -29
- package/dist/decorator/can.decorator.d.ts.map +0 -1
- package/dist/decorator/can.decorator.js +0 -23
- package/dist/decorator/can.decorator.js.map +0 -1
- package/dist/decorator/policy.decorator.d.ts +0 -18
- package/dist/decorator/policy.decorator.d.ts.map +0 -1
- package/dist/decorator/policy.decorator.js +0 -28
- package/dist/decorator/policy.decorator.js.map +0 -1
- package/dist/guard/can.guard.d.ts +0 -31
- package/dist/guard/can.guard.d.ts.map +0 -1
- package/dist/guard/can.guard.js +0 -92
- package/dist/guard/can.guard.js.map +0 -1
- package/dist/guard/roles.guard.d.ts +0 -21
- package/dist/guard/roles.guard.d.ts.map +0 -1
- package/dist/guard/roles.guard.js +0 -50
- package/dist/guard/roles.guard.js.map +0 -1
- package/dist/policy-registry.d.ts +0 -46
- package/dist/policy-registry.d.ts.map +0 -1
- package/dist/policy-registry.js +0 -101
- package/dist/policy-registry.js.map +0 -1
package/dist/module.js
CHANGED
|
@@ -11,226 +11,197 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
var AuthzModule_1;
|
|
14
|
+
import { AUTHORIZATION_MODULE_OPTIONS, defaultGetUser, } from '@nestjs/authorization';
|
|
14
15
|
import { Inject, Injectable, Module, Optional, } from '@nestjs/common';
|
|
15
|
-
import { APP_GUARD,
|
|
16
|
+
import { APP_GUARD, APP_INTERCEPTOR, DiscoveryModule } from '@nestjs/core';
|
|
17
|
+
import { AuthzGuard, AuthzGuardStartupCheck } from './authz.guard.js';
|
|
16
18
|
import { DEFAULT_CAN_ENDPOINT_PATH, createCanController } from './can-endpoint.controller.js';
|
|
17
|
-
import {
|
|
19
|
+
import { AuthzDecisionPublisher } from './decisions.js';
|
|
18
20
|
import { Gate } from './gate.js';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
21
|
+
import { OFFICIAL_CAN_ANYONE_METADATA } from './official.js';
|
|
22
|
+
import { GatePolicy } from './policies/gate.policy.js';
|
|
23
|
+
import { PermissionPolicy } from './policies/permission.policy.js';
|
|
24
|
+
import { RolePolicy } from './policies/role.policy.js';
|
|
25
|
+
import { PolicyIndex } from './policy-index.js';
|
|
26
|
+
import { AuthzRbac } from './rbac.js';
|
|
22
27
|
import { IdParamResourceResolver } from './resource-resolver.js';
|
|
28
|
+
import { configureAuthzRuntime } from './runtime.js';
|
|
23
29
|
import { AUTHZ_MODULE_OPTIONS, RESOURCE_HYDRATOR, RESOURCE_RESOLVER } from './tokens.js';
|
|
24
30
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* Explicit policies are read from the RESOLVED {@link AUTHZ_MODULE_OPTIONS} (so a
|
|
29
|
-
* `forRootAsync` `useFactory`/`useClass` that returns `policies: [...]` registers
|
|
30
|
-
* them too) and resolved as provider instances via {@link ModuleRef}.
|
|
31
|
+
* Hands the official `@Can()` argument resolvers and `AuthzPolicy` what they cannot
|
|
32
|
+
* inject: the resource resolver, the `superAdmin` hook, the external decision point,
|
|
33
|
+
* and the official `getUser`.
|
|
31
34
|
*/
|
|
32
|
-
let
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
moduleRef;
|
|
35
|
+
let AuthzRuntimeBootstrap = class AuthzRuntimeBootstrap {
|
|
36
|
+
resolver;
|
|
37
|
+
rbac;
|
|
36
38
|
options;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.
|
|
40
|
-
this.
|
|
39
|
+
official;
|
|
40
|
+
constructor(resolver, rbac, options, official) {
|
|
41
|
+
this.resolver = resolver;
|
|
42
|
+
this.rbac = rbac;
|
|
41
43
|
this.options = options;
|
|
44
|
+
this.official = official;
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
seen.add(PolicyClass);
|
|
52
|
-
this.registry.register(instance);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
// 2. Auto-discovered @Policy-decorated providers.
|
|
56
|
-
for (const wrapper of this.discovery.getProviders()) {
|
|
57
|
-
const instance = wrapper.instance;
|
|
58
|
-
if (!instance || typeof instance !== 'object')
|
|
59
|
-
continue;
|
|
60
|
-
const ctor = instance.constructor;
|
|
61
|
-
if (!ctor || seen.has(ctor))
|
|
62
|
-
continue;
|
|
63
|
-
if (getPolicyResource(instance)) {
|
|
64
|
-
seen.add(ctor);
|
|
65
|
-
this.registry.register(instance);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Resolve a policy class to an instance. Prefers an existing provider (so DI
|
|
71
|
-
* deps are honored); falls back to instantiating it through the container when
|
|
72
|
-
* the class was passed via `forRootAsync` options but not registered as a
|
|
73
|
-
* provider anywhere.
|
|
74
|
-
*/
|
|
75
|
-
async resolvePolicyInstance(PolicyClass) {
|
|
76
|
-
try {
|
|
77
|
-
return this.moduleRef.get(PolicyClass, { strict: false });
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// not a registered provider — instantiate via the container.
|
|
81
|
-
}
|
|
82
|
-
try {
|
|
83
|
-
return await this.moduleRef.create(PolicyClass);
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
46
|
+
onModuleInit() {
|
|
47
|
+
configureAuthzRuntime({
|
|
48
|
+
resourceResolver: this.resolver,
|
|
49
|
+
superAdmin: this.options?.superAdmin,
|
|
50
|
+
decisionProvider: () => this.rbac.decisions(),
|
|
51
|
+
// Always set: an app without its own `getUser` must not keep a previous app's.
|
|
52
|
+
getUser: this.official?.getUser ?? defaultGetUser,
|
|
53
|
+
});
|
|
88
54
|
}
|
|
89
55
|
};
|
|
90
|
-
|
|
56
|
+
AuthzRuntimeBootstrap = __decorate([
|
|
91
57
|
Injectable(),
|
|
58
|
+
__param(0, Inject(RESOURCE_RESOLVER)),
|
|
59
|
+
__param(2, Optional()),
|
|
60
|
+
__param(2, Inject(AUTHZ_MODULE_OPTIONS)),
|
|
92
61
|
__param(3, Optional()),
|
|
93
|
-
__param(3, Inject(
|
|
94
|
-
__metadata("design:paramtypes", [
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
62
|
+
__param(3, Inject(AUTHORIZATION_MODULE_OPTIONS)),
|
|
63
|
+
__metadata("design:paramtypes", [Object, AuthzRbac, Object, Object])
|
|
64
|
+
], AuthzRuntimeBootstrap);
|
|
65
|
+
/** The static options, which a `forRootAsync()` factory returning them would silently drop. */
|
|
66
|
+
const STATIC_OPTIONS = ['unannotated', 'decorators'];
|
|
67
|
+
function checkFactoryOptions(options) {
|
|
68
|
+
for (const key of STATIC_OPTIONS) {
|
|
69
|
+
if (options?.[key] !== undefined) {
|
|
70
|
+
throw new Error(`AuthzModule: \`${key}\` is in the options the forRootAsync() factory returned. It goes at the top level of forRootAsync(), next to useFactory, because it decides what the module registers.`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return options;
|
|
74
|
+
}
|
|
75
|
+
const EXPORTS = [
|
|
76
|
+
Gate,
|
|
77
|
+
AuthzGuard,
|
|
78
|
+
PolicyIndex,
|
|
79
|
+
AuthzRbac,
|
|
80
|
+
RolePolicy,
|
|
81
|
+
PermissionPolicy,
|
|
82
|
+
GatePolicy,
|
|
83
|
+
AUTHZ_MODULE_OPTIONS,
|
|
84
|
+
RESOURCE_RESOLVER,
|
|
85
|
+
RESOURCE_HYDRATOR,
|
|
86
|
+
];
|
|
87
|
+
/**
|
|
88
|
+
* The extras on top of `@nestjs/authorization`. Import it next to the official module:
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* imports: [
|
|
92
|
+
* AuthorizationModule.forRoot(), // the official guard, @Can, AuthorizationService
|
|
93
|
+
* AuthzModule.forRoot({ superAdmin: (u) => u?.isRoot === true }),
|
|
94
|
+
* ]
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* Registers `RolePolicy`, `PermissionPolicy` and `GatePolicy` (official policies), the
|
|
98
|
+
* `Gate`, the resource resolver `byId()` uses, and the allow+deny decision event.
|
|
99
|
+
* It needs the official module to be global (its default).
|
|
100
|
+
*/
|
|
98
101
|
let AuthzModule = AuthzModule_1 = class AuthzModule {
|
|
99
102
|
static forRoot(options = {}) {
|
|
100
|
-
const policyProviders = (options.policies ?? []).map((P) => P);
|
|
101
103
|
return {
|
|
102
104
|
module: AuthzModule_1,
|
|
103
105
|
global: true,
|
|
104
106
|
imports: [DiscoveryModule],
|
|
105
|
-
controllers: AuthzModule_1.
|
|
107
|
+
controllers: AuthzModule_1.controllers(options),
|
|
106
108
|
providers: [
|
|
107
109
|
{ provide: AUTHZ_MODULE_OPTIONS, useValue: options },
|
|
108
|
-
...
|
|
109
|
-
|
|
110
|
-
Gate,
|
|
111
|
-
CanGuard,
|
|
112
|
-
{ provide: APP_GUARD, useExisting: CanGuard },
|
|
113
|
-
RolesGuard,
|
|
114
|
-
{ provide: APP_GUARD, useExisting: RolesGuard },
|
|
115
|
-
...AuthzModule_1.resourceResolverProviders(),
|
|
116
|
-
...AuthzModule_1.resourceHydratorProviders(),
|
|
117
|
-
...AuthzModule_1.bootstrapProviders(),
|
|
118
|
-
],
|
|
119
|
-
exports: [
|
|
120
|
-
Gate,
|
|
121
|
-
PolicyRegistry,
|
|
122
|
-
CanGuard,
|
|
123
|
-
RolesGuard,
|
|
124
|
-
AUTHZ_MODULE_OPTIONS,
|
|
125
|
-
RESOURCE_RESOLVER,
|
|
126
|
-
RESOURCE_HYDRATOR,
|
|
127
|
-
...(options.policies ?? []),
|
|
110
|
+
...AuthzModule_1.common(),
|
|
111
|
+
...AuthzModule_1.guards(options),
|
|
128
112
|
],
|
|
113
|
+
exports: EXPORTS,
|
|
129
114
|
};
|
|
130
115
|
}
|
|
131
116
|
static forRootAsync(options) {
|
|
132
|
-
const asyncProvider = AuthzModule_1.buildAsyncOptionsProvider(options);
|
|
133
|
-
const asyncProviders = Array.isArray(asyncProvider) ? asyncProvider : [asyncProvider];
|
|
134
117
|
return {
|
|
135
118
|
module: AuthzModule_1,
|
|
136
119
|
global: true,
|
|
137
120
|
imports: [DiscoveryModule, ...(options.imports ?? [])],
|
|
138
|
-
controllers: AuthzModule_1.
|
|
121
|
+
controllers: AuthzModule_1.controllers(options),
|
|
139
122
|
providers: [
|
|
140
|
-
...
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
CanGuard,
|
|
144
|
-
{ provide: APP_GUARD, useExisting: CanGuard },
|
|
145
|
-
RolesGuard,
|
|
146
|
-
{ provide: APP_GUARD, useExisting: RolesGuard },
|
|
147
|
-
...AuthzModule_1.resourceResolverProviders(),
|
|
148
|
-
...AuthzModule_1.resourceHydratorProviders(),
|
|
149
|
-
...AuthzModule_1.bootstrapProviders(),
|
|
150
|
-
],
|
|
151
|
-
exports: [
|
|
152
|
-
Gate,
|
|
153
|
-
PolicyRegistry,
|
|
154
|
-
CanGuard,
|
|
155
|
-
RolesGuard,
|
|
156
|
-
AUTHZ_MODULE_OPTIONS,
|
|
157
|
-
RESOURCE_RESOLVER,
|
|
158
|
-
RESOURCE_HYDRATOR,
|
|
123
|
+
...AuthzModule_1.asyncOptionsProviders(options),
|
|
124
|
+
...AuthzModule_1.common(),
|
|
125
|
+
...AuthzModule_1.guards(options),
|
|
159
126
|
],
|
|
127
|
+
exports: EXPORTS,
|
|
160
128
|
};
|
|
161
129
|
}
|
|
162
|
-
|
|
163
|
-
* Register a default {@link ResourceResolver} bound to {@link RESOURCE_RESOLVER}
|
|
164
|
-
* so `@Can('update', Post)` works out-of-the-box on a clean install (no manual
|
|
165
|
-
* resolver wiring needed). Reads the resolved options so a `resourceResolver`
|
|
166
|
-
* override / `idParam` knob from forRoot OR forRootAsync is honored.
|
|
167
|
-
*/
|
|
168
|
-
static resourceResolverProviders() {
|
|
130
|
+
static common() {
|
|
169
131
|
return [
|
|
132
|
+
PolicyIndex,
|
|
133
|
+
AuthzRbac,
|
|
134
|
+
Gate,
|
|
135
|
+
RolePolicy,
|
|
136
|
+
PermissionPolicy,
|
|
137
|
+
GatePolicy,
|
|
170
138
|
{
|
|
171
139
|
provide: RESOURCE_RESOLVER,
|
|
172
140
|
useFactory: (options) => options?.resourceResolver ?? new IdParamResourceResolver(options?.idParam),
|
|
173
141
|
inject: [{ token: AUTHZ_MODULE_OPTIONS, optional: true }],
|
|
174
142
|
},
|
|
175
|
-
];
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Bind the {@link RESOURCE_HYDRATOR} token to the resolved options'
|
|
179
|
-
* `resourceLoaders` map so the opt-in `POST /authz/can` endpoint can rehydrate a
|
|
180
|
-
* `{ type, id }` shim into the REAL entity before authorizing. Reads the resolved
|
|
181
|
-
* options so the map from forRoot OR a forRootAsync factory is honored. Resolves to
|
|
182
|
-
* `undefined` when no `resourceLoaders` are configured (endpoint behavior unchanged).
|
|
183
|
-
*/
|
|
184
|
-
static resourceHydratorProviders() {
|
|
185
|
-
return [
|
|
186
143
|
{
|
|
187
144
|
provide: RESOURCE_HYDRATOR,
|
|
188
145
|
useFactory: (options) => options?.resourceLoaders,
|
|
189
146
|
inject: [{ token: AUTHZ_MODULE_OPTIONS, optional: true }],
|
|
190
147
|
},
|
|
148
|
+
AuthzGuard,
|
|
149
|
+
AuthzRuntimeBootstrap,
|
|
150
|
+
AuthzDecisionPublisher,
|
|
151
|
+
{ provide: APP_INTERCEPTOR, useExisting: AuthzDecisionPublisher },
|
|
191
152
|
];
|
|
192
153
|
}
|
|
193
154
|
/**
|
|
194
|
-
*
|
|
195
|
-
*
|
|
155
|
+
* `unannotated: 'allow'`: the migration guard, registered globally, and the check that the
|
|
156
|
+
* official global guard is off. Static, so it is read from `forRoot()` / the top level of
|
|
157
|
+
* `forRootAsync()`, never from the factory.
|
|
196
158
|
*/
|
|
197
|
-
static
|
|
198
|
-
|
|
159
|
+
static guards(options) {
|
|
160
|
+
const mode = options.unannotated ?? 'deny';
|
|
161
|
+
if (mode !== 'allow' && mode !== 'deny') {
|
|
162
|
+
throw new Error(`AuthzModule: \`unannotated\` must be 'allow' or 'deny', got ${String(mode)}.`);
|
|
163
|
+
}
|
|
164
|
+
if (mode === 'deny')
|
|
165
|
+
return [];
|
|
166
|
+
return [AuthzGuardStartupCheck, { provide: APP_GUARD, useExisting: AuthzGuard }];
|
|
199
167
|
}
|
|
200
168
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
169
|
+
* The controllers this module mounts, each a fresh class (so `decorators` never leak between
|
|
170
|
+
* registrations), open to the official guard, then decorated with `decorators`.
|
|
203
171
|
*/
|
|
204
|
-
static
|
|
172
|
+
static controllers(options) {
|
|
173
|
+
const { canEndpoint, decorators = [] } = options;
|
|
205
174
|
if (!canEndpoint)
|
|
206
175
|
return [];
|
|
207
176
|
const path = typeof canEndpoint === 'string' ? canEndpoint : DEFAULT_CAN_ENDPOINT_PATH;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
provide: AUTHZ_MODULE_OPTIONS,
|
|
214
|
-
useFactory: options.useFactory,
|
|
215
|
-
inject: (options.inject ?? []),
|
|
216
|
-
};
|
|
177
|
+
const controller = createCanController(path);
|
|
178
|
+
Reflect.defineMetadata(OFFICIAL_CAN_ANYONE_METADATA, true, controller);
|
|
179
|
+
// Applied in order, after the module's own, like a stack written above the class.
|
|
180
|
+
for (const decorate of [...decorators].reverse()) {
|
|
181
|
+
decorate(controller);
|
|
217
182
|
}
|
|
218
|
-
|
|
183
|
+
return [controller];
|
|
184
|
+
}
|
|
185
|
+
static asyncOptionsProviders(options) {
|
|
186
|
+
const { useFactory } = options;
|
|
187
|
+
if (useFactory) {
|
|
219
188
|
return [
|
|
220
|
-
{ provide: options.useClass, useClass: options.useClass },
|
|
221
189
|
{
|
|
222
190
|
provide: AUTHZ_MODULE_OPTIONS,
|
|
223
|
-
useFactory: async (
|
|
224
|
-
inject:
|
|
191
|
+
useFactory: async (...args) => checkFactoryOptions(await useFactory(...args)),
|
|
192
|
+
inject: (options.inject ?? []),
|
|
225
193
|
},
|
|
226
194
|
];
|
|
227
195
|
}
|
|
228
|
-
const
|
|
229
|
-
return
|
|
230
|
-
provide:
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
196
|
+
const factory = (options.useClass ?? options.useExisting);
|
|
197
|
+
return [
|
|
198
|
+
...(options.useClass ? [{ provide: options.useClass, useClass: options.useClass }] : []),
|
|
199
|
+
{
|
|
200
|
+
provide: AUTHZ_MODULE_OPTIONS,
|
|
201
|
+
useFactory: async (f) => checkFactoryOptions(await f.createAuthzOptions()),
|
|
202
|
+
inject: [factory],
|
|
203
|
+
},
|
|
204
|
+
];
|
|
234
205
|
}
|
|
235
206
|
};
|
|
236
207
|
AuthzModule = AuthzModule_1 = __decorate([
|
package/dist/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,OAAO,EAEL,MAAM,EACN,UAAU,EACV,MAAM,EAEN,QAAQ,GAGT,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import type { ExecutionContext, Type } from '@nestjs/common';
|
|
3
|
+
/**
|
|
4
|
+
* The metadata keys `@nestjs/authorization` reads and writes. The package does not
|
|
5
|
+
* export them, so they are spelled here, once. `test/official-contract.spec.ts`
|
|
6
|
+
* fails if the official package stops honoring metadata written under these keys.
|
|
7
|
+
*/
|
|
8
|
+
export declare const OFFICIAL_POLICY_METADATA = "authorization:policy";
|
|
9
|
+
/** Written by the official `@Can()`: an array of {@link OfficialCanRequirement}, read top-down. */
|
|
10
|
+
export declare const OFFICIAL_CAN_METADATA = "authorization:can";
|
|
11
|
+
/** Written by the official `Can.Anyone()`. */
|
|
12
|
+
export declare const OFFICIAL_CAN_ANYONE_METADATA = "authorization:can-anyone";
|
|
13
|
+
/**
|
|
14
|
+
* Written by `@nestjs/authentication`'s `@Public()` (`true`) and `@Authenticate()` (`false`).
|
|
15
|
+
* A registry symbol, which the official guard reads without depending on that package.
|
|
16
|
+
*/
|
|
17
|
+
export declare const OFFICIAL_PUBLIC_METADATA: unique symbol;
|
|
18
|
+
/** One official `@Can()` requirement, as stored in the metadata. */
|
|
19
|
+
export interface OfficialCanRequirement {
|
|
20
|
+
policy: Type<unknown>;
|
|
21
|
+
ability: string;
|
|
22
|
+
args?: (context: ExecutionContext) => readonly unknown[] | Promise<readonly unknown[]>;
|
|
23
|
+
}
|
|
24
|
+
/** True when `value` is a class marked with the official `@Policy()`. */
|
|
25
|
+
export declare function isOfficialPolicy(value: unknown): value is Type<unknown>;
|
|
26
|
+
/** The official `@Can()` requirements declared directly on `target` (a class or a method). */
|
|
27
|
+
export declare function readCanRequirements(target: object): OfficialCanRequirement[];
|
|
28
|
+
/**
|
|
29
|
+
* The requirements the official guard enforces on `handler` of `type`: the class's
|
|
30
|
+
* first, then the method's, the class's dropped when the method is opened with
|
|
31
|
+
* `Can.Anyone()` or `@Public()`. Mirrors the official `routeChecks()`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function routeRequirements(type: Type<unknown>, handler: object): OfficialCanRequirement[];
|
|
34
|
+
/**
|
|
35
|
+
* `dependency`, or a clear error when `@nestjs/authorization`'s `AuthorizationModule` is not
|
|
36
|
+
* imported: without it Nest only reports an unresolvable constructor argument of `consumer`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function requireOfficial<T>(dependency: T | undefined, name: string, consumer: string): T;
|
|
39
|
+
//# sourceMappingURL=official.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"official.d.ts","sourceRoot":"","sources":["../src/official.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAC/D,mGAAmG;AACnG,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,8CAA8C;AAC9C,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,eAA8C,CAAC;AAEpF,oEAAoE;AACpE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;CACxF;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAIvE;AAED,8FAA8F;AAC9F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAKhG;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,CAK/F"}
|
package/dist/official.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
/**
|
|
3
|
+
* The metadata keys `@nestjs/authorization` reads and writes. The package does not
|
|
4
|
+
* export them, so they are spelled here, once. `test/official-contract.spec.ts`
|
|
5
|
+
* fails if the official package stops honoring metadata written under these keys.
|
|
6
|
+
*/
|
|
7
|
+
export const OFFICIAL_POLICY_METADATA = 'authorization:policy';
|
|
8
|
+
/** Written by the official `@Can()`: an array of {@link OfficialCanRequirement}, read top-down. */
|
|
9
|
+
export const OFFICIAL_CAN_METADATA = 'authorization:can';
|
|
10
|
+
/** Written by the official `Can.Anyone()`. */
|
|
11
|
+
export const OFFICIAL_CAN_ANYONE_METADATA = 'authorization:can-anyone';
|
|
12
|
+
/**
|
|
13
|
+
* Written by `@nestjs/authentication`'s `@Public()` (`true`) and `@Authenticate()` (`false`).
|
|
14
|
+
* A registry symbol, which the official guard reads without depending on that package.
|
|
15
|
+
*/
|
|
16
|
+
export const OFFICIAL_PUBLIC_METADATA = Symbol.for('@nestjs/authentication:public');
|
|
17
|
+
/** True when `value` is a class marked with the official `@Policy()`. */
|
|
18
|
+
export function isOfficialPolicy(value) {
|
|
19
|
+
return (typeof value === 'function' && Reflect.getMetadata(OFFICIAL_POLICY_METADATA, value) === true);
|
|
20
|
+
}
|
|
21
|
+
/** The official `@Can()` requirements declared directly on `target` (a class or a method). */
|
|
22
|
+
export function readCanRequirements(target) {
|
|
23
|
+
return Reflect.getMetadata(OFFICIAL_CAN_METADATA, target) ?? [];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The requirements the official guard enforces on `handler` of `type`: the class's
|
|
27
|
+
* first, then the method's, the class's dropped when the method is opened with
|
|
28
|
+
* `Can.Anyone()` or `@Public()`. Mirrors the official `routeChecks()`.
|
|
29
|
+
*/
|
|
30
|
+
export function routeRequirements(type, handler) {
|
|
31
|
+
const methodOpen = Reflect.getMetadata(OFFICIAL_PUBLIC_METADATA, handler) === true ||
|
|
32
|
+
Reflect.getMetadata(OFFICIAL_CAN_ANYONE_METADATA, handler) === true;
|
|
33
|
+
return [...(methodOpen ? [] : readCanRequirements(type)), ...readCanRequirements(handler)];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* `dependency`, or a clear error when `@nestjs/authorization`'s `AuthorizationModule` is not
|
|
37
|
+
* imported: without it Nest only reports an unresolvable constructor argument of `consumer`.
|
|
38
|
+
*/
|
|
39
|
+
export function requireOfficial(dependency, name, consumer) {
|
|
40
|
+
if (dependency !== undefined && dependency !== null)
|
|
41
|
+
return dependency;
|
|
42
|
+
throw new Error(`AuthzModule: ${consumer} needs ${name} from @nestjs/authorization, which is not available. Import AuthorizationModule.forRoot() (global, its default) next to AuthzModule: imports: [AuthorizationModule.forRoot(), AuthzModule.forRoot()].`);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=official.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"official.js","sourceRoot":"","sources":["../src/official.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAG1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,sBAAsB,CAAC;AAC/D,mGAAmG;AACnG,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC;AACzD,8CAA8C;AAC9C,MAAM,CAAC,MAAM,4BAA4B,GAAG,0BAA0B,CAAC;AACvE;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;AASpF,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,CACL,OAAO,KAAK,KAAK,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC,wBAAwB,EAAE,KAAK,CAAC,KAAK,IAAI,CAC7F,CAAC;AACJ,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,OAAQ,OAAO,CAAC,WAAW,CAAC,qBAAqB,EAAE,MAAM,CAA8B,IAAI,EAAE,CAAC;AAChG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAmB,EAAE,OAAe;IACpE,MAAM,UAAU,GACd,OAAO,CAAC,WAAW,CAAC,wBAAwB,EAAE,OAAO,CAAC,KAAK,IAAI;QAC/D,OAAO,CAAC,WAAW,CAAC,4BAA4B,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAI,UAAyB,EAAE,IAAY,EAAE,QAAgB;IAC1F,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC;IACvE,MAAM,IAAI,KAAK,CACb,gBAAgB,QAAQ,UAAU,IAAI,uMAAuM,CAC9O,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal Runs `fn` (the `Gate` handing a string check to the official service) knowing
|
|
3
|
+
* `superAdmin` did not grant `ability` and the decision point abstained, so the policy's
|
|
4
|
+
* {@link superAdminBefore} / {@link decisionProviderBefore} skip asking them again.
|
|
5
|
+
*/
|
|
6
|
+
export declare function withAskedCheck<T>(user: unknown, ability: string, args: readonly unknown[], fn: () => Promise<T>): Promise<T>;
|
|
7
|
+
/**
|
|
8
|
+
* Asks the `superAdmin` hook given to `AuthzModule.forRoot()`. `true` grants; anything
|
|
9
|
+
* else falls through. Call it from your own `before()` when a policy cannot extend
|
|
10
|
+
* {@link AuthzPolicy}.
|
|
11
|
+
*/
|
|
12
|
+
export declare function superAdminBefore(user: unknown, ability: string, resource?: object): Promise<true | undefined>;
|
|
13
|
+
/**
|
|
14
|
+
* Asks the external decision point (`DECISION_PROVIDER`, e.g. the Cerbos adapter), when
|
|
15
|
+
* one is registered: `true` allows, `false` denies, `undefined` abstains (no provider, or
|
|
16
|
+
* it has no opinion). Call it from your own `before()` when a policy cannot extend
|
|
17
|
+
* {@link AuthzPolicy}.
|
|
18
|
+
*/
|
|
19
|
+
export declare function decisionProviderBefore(user: unknown, ability: string, resource?: object): Promise<boolean | undefined>;
|
|
20
|
+
/**
|
|
21
|
+
* Base class for official policies that honor the global `superAdmin` hook and the
|
|
22
|
+
* optional external decision point.
|
|
23
|
+
*
|
|
24
|
+
* The official guard runs only each policy's own `before()`, so a global "super-admins
|
|
25
|
+
* may do anything" needs every policy to ask. Extend this class and they do:
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* @Policy()
|
|
29
|
+
* export class PostPolicy extends AuthzPolicy {
|
|
30
|
+
* update(user: User | null, post: Post) { return post.authorId === user?.id; }
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* `before()` asks `superAdmin(user, ability, resource)` (a `true` allows), then the
|
|
35
|
+
* `DECISION_PROVIDER` when one is registered (its allow or deny is final, `undefined`
|
|
36
|
+
* abstains), then lets the ability decide. The resource is the check's first argument.
|
|
37
|
+
* To add your own `before()`, override it and call `super.before(...)` first.
|
|
38
|
+
*/
|
|
39
|
+
export declare abstract class AuthzPolicy {
|
|
40
|
+
before(user: unknown, ability: string, ...args: unknown[]): boolean | undefined | Promise<boolean | undefined>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=authz-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz-policy.d.ts","sourceRoot":"","sources":["../../src/policies/authz-policy.ts"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAEZ;AAaD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAI3B;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAI9B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,8BAAsB,WAAW;IAC/B,MAAM,CACJ,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;CAOtD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { normalizeVerdict } from '../decision-provider.js';
|
|
3
|
+
import { authzRuntime } from '../runtime.js';
|
|
4
|
+
/** The resource of a policy check: its first argument, when that is an object or a class. */
|
|
5
|
+
function resourceOf(args) {
|
|
6
|
+
const first = args[0];
|
|
7
|
+
return (typeof first === 'object' && first !== null) || typeof first === 'function'
|
|
8
|
+
? first
|
|
9
|
+
: undefined;
|
|
10
|
+
}
|
|
11
|
+
const asked = new AsyncLocalStorage();
|
|
12
|
+
/**
|
|
13
|
+
* @internal Runs `fn` (the `Gate` handing a string check to the official service) knowing
|
|
14
|
+
* `superAdmin` did not grant `ability` and the decision point abstained, so the policy's
|
|
15
|
+
* {@link superAdminBefore} / {@link decisionProviderBefore} skip asking them again.
|
|
16
|
+
*/
|
|
17
|
+
export function withAskedCheck(user, ability, args, fn) {
|
|
18
|
+
return asked.run({ user: user ?? null, ability, resource: resourceOf(args) }, fn);
|
|
19
|
+
}
|
|
20
|
+
/** True when the `Gate` already asked about exactly this check (see {@link withAskedCheck}). */
|
|
21
|
+
function alreadyAsked(user, ability, resource) {
|
|
22
|
+
const check = asked.getStore();
|
|
23
|
+
return (check !== undefined &&
|
|
24
|
+
check.user === (user ?? null) &&
|
|
25
|
+
check.ability === ability &&
|
|
26
|
+
check.resource === resource);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Asks the `superAdmin` hook given to `AuthzModule.forRoot()`. `true` grants; anything
|
|
30
|
+
* else falls through. Call it from your own `before()` when a policy cannot extend
|
|
31
|
+
* {@link AuthzPolicy}.
|
|
32
|
+
*/
|
|
33
|
+
export async function superAdminBefore(user, ability, resource) {
|
|
34
|
+
const hook = authzRuntime().superAdmin;
|
|
35
|
+
if (!hook || alreadyAsked(user, ability, resource))
|
|
36
|
+
return undefined;
|
|
37
|
+
return (await hook(user ?? null, ability, resource)) === true ? true : undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Asks the external decision point (`DECISION_PROVIDER`, e.g. the Cerbos adapter), when
|
|
41
|
+
* one is registered: `true` allows, `false` denies, `undefined` abstains (no provider, or
|
|
42
|
+
* it has no opinion). Call it from your own `before()` when a policy cannot extend
|
|
43
|
+
* {@link AuthzPolicy}.
|
|
44
|
+
*/
|
|
45
|
+
export async function decisionProviderBefore(user, ability, resource) {
|
|
46
|
+
const provider = authzRuntime().decisionProvider();
|
|
47
|
+
if (!provider || alreadyAsked(user, ability, resource))
|
|
48
|
+
return undefined;
|
|
49
|
+
return normalizeVerdict(await provider.decide(user ?? null, ability, resource)).allowed;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Base class for official policies that honor the global `superAdmin` hook and the
|
|
53
|
+
* optional external decision point.
|
|
54
|
+
*
|
|
55
|
+
* The official guard runs only each policy's own `before()`, so a global "super-admins
|
|
56
|
+
* may do anything" needs every policy to ask. Extend this class and they do:
|
|
57
|
+
*
|
|
58
|
+
* ```ts
|
|
59
|
+
* @Policy()
|
|
60
|
+
* export class PostPolicy extends AuthzPolicy {
|
|
61
|
+
* update(user: User | null, post: Post) { return post.authorId === user?.id; }
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* `before()` asks `superAdmin(user, ability, resource)` (a `true` allows), then the
|
|
66
|
+
* `DECISION_PROVIDER` when one is registered (its allow or deny is final, `undefined`
|
|
67
|
+
* abstains), then lets the ability decide. The resource is the check's first argument.
|
|
68
|
+
* To add your own `before()`, override it and call `super.before(...)` first.
|
|
69
|
+
*/
|
|
70
|
+
export class AuthzPolicy {
|
|
71
|
+
before(user, ability, ...args) {
|
|
72
|
+
const resource = resourceOf(args);
|
|
73
|
+
return (async () => {
|
|
74
|
+
if (await superAdminBefore(user, ability, resource))
|
|
75
|
+
return true;
|
|
76
|
+
return decisionProviderBefore(user, ability, resource);
|
|
77
|
+
})();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=authz-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz-policy.js","sourceRoot":"","sources":["../../src/policies/authz-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,6FAA6F;AAC7F,SAAS,UAAU,CAAC,IAAwB;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,OAAO,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,OAAO,KAAK,KAAK,UAAU;QACjF,CAAC,CAAE,KAAgB;QACnB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AASD,MAAM,KAAK,GAAG,IAAI,iBAAiB,EAAc,CAAC;AAElD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAa,EACb,OAAe,EACf,IAAwB,EACxB,EAAoB;IAEpB,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACpF,CAAC;AAED,gGAAgG;AAChG,SAAS,YAAY,CAAC,IAAa,EAAE,OAAe,EAAE,QAA4B;IAChF,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC/B,OAAO,CACL,KAAK,KAAK,SAAS;QACnB,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC;QAC7B,KAAK,CAAC,OAAO,KAAK,OAAO;QACzB,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAC5B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAa,EACb,OAAe,EACf,QAAiB;IAEjB,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC,UAAU,CAAC;IACvC,IAAI,CAAC,IAAI,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IACrE,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACnF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAa,EACb,OAAe,EACf,QAAiB;IAEjB,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC,gBAAgB,EAAE,CAAC;IACnD,IAAI,CAAC,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IACzE,OAAO,gBAAgB,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;AAC1F,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAgB,WAAW;IAC/B,MAAM,CACJ,IAAa,EACb,OAAe,EACf,GAAG,IAAe;QAElB,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,IAAI,EAAE;YACjB,IAAI,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAC;YACjE,OAAO,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzD,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Gate } from '../gate.js';
|
|
2
|
+
/**
|
|
3
|
+
* The `Gate`'s string abilities as an official policy: ad-hoc gates from
|
|
4
|
+
* `gate.define()`, named permissions, and `ability` + resource checks through the
|
|
5
|
+
* resource's linked policy.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* gate.define('access-admin', (user) => user.isStaff);
|
|
9
|
+
*
|
|
10
|
+
* @Can(GatePolicy, 'allows', ability('access-admin'))
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare class GatePolicy {
|
|
14
|
+
private readonly gate;
|
|
15
|
+
constructor(gate: Gate);
|
|
16
|
+
allows(user: unknown, ability: string, resource?: object): Promise<boolean>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=gate.policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.policy.d.ts","sourceRoot":"","sources":["../../src/policies/gate.policy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC;;;;;;;;;;GAUG;AACH,qBACa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAEvC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG5E"}
|