@dudousxd/nestjs-authz 0.8.0 → 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.
- 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 -209
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +209 -577
- 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/permission-cache.d.ts +18 -9
- package/dist/permission-cache.d.ts.map +1 -1
- package/dist/permission-cache.js +87 -24
- package/dist/permission-cache.js.map +1 -1
- package/dist/permission-matcher.d.ts +13 -0
- package/dist/permission-matcher.d.ts.map +1 -1
- package/dist/permission-matcher.js +38 -2
- package/dist/permission-matcher.js.map +1 -1
- package/dist/permission-provider.d.ts +11 -0
- package/dist/permission-provider.d.ts.map +1 -1
- 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 -169
- package/dist/types.d.ts.map +1 -1
- package/package.json +19 -10
- package/skills/authz-enforcement/SKILL.md +67 -131
- package/skills/authz-policies/SKILL.md +43 -117
- package/skills/authz-query-scopes/SKILL.md +16 -9
- package/skills/authz-rbac-seams/SKILL.md +39 -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
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
import type { ExecutionContext, Type } from '@nestjs/common';
|
|
2
|
+
/** Per-call hints `byId(Resource, { param })` passes to the resolver. */
|
|
3
|
+
export interface ResourceResolveHints {
|
|
4
|
+
/** The route param holding the id, when `byId` named one. */
|
|
5
|
+
param?: string;
|
|
6
|
+
}
|
|
2
7
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Class-level abilities (no resource class on `@Can`) never call the resolver.
|
|
8
|
+
* Loads the resource a `byId(Resource)` argument resolver hands to the policy
|
|
9
|
+
* (`@Can(PostPolicy, 'update', byId(Post))`). Register one, typically ORM-backed, with
|
|
10
|
+
* `AuthzModule.forRoot({ resourceResolver })`. Return `undefined` for "not found":
|
|
11
|
+
* `byId` then refuses the call with a 403 before the policy runs.
|
|
9
12
|
*/
|
|
10
13
|
export interface ResourceResolver {
|
|
11
|
-
|
|
12
|
-
* Load the resource instance for `resource` in the given request context.
|
|
13
|
-
* Return `undefined` to signal "not found" — the guard treats a missing
|
|
14
|
-
* resource as a denial.
|
|
15
|
-
*/
|
|
16
|
-
resolve(resource: Type<unknown>, ctx: ExecutionContext): Promise<object | undefined> | object | undefined;
|
|
14
|
+
resolve(resource: Type<unknown>, ctx: ExecutionContext, hints?: ResourceResolveHints): Promise<object | undefined> | object | undefined;
|
|
17
15
|
}
|
|
18
16
|
/**
|
|
19
|
-
* Default resolver: reads the route `:id` param and produces a lightweight
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
17
|
+
* Default resolver: reads the route `:id` param and produces a lightweight `{ id }`
|
|
18
|
+
* object whose prototype is the resource class's, enough for ownership checks on
|
|
19
|
+
* `resource.id` without an ORM. Register your own {@link ResourceResolver} to load
|
|
20
|
+
* real entities.
|
|
23
21
|
*/
|
|
24
22
|
export declare class IdParamResourceResolver implements ResourceResolver {
|
|
25
23
|
private readonly param;
|
|
26
24
|
constructor(param?: string);
|
|
27
|
-
resolve(resource: Type<unknown>, ctx: ExecutionContext): object | undefined;
|
|
25
|
+
resolve(resource: Type<unknown>, ctx: ExecutionContext, hints?: ResourceResolveHints): object | undefined;
|
|
28
26
|
}
|
|
29
27
|
//# sourceMappingURL=resource-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-resolver.d.ts","sourceRoot":"","sources":["../src/resource-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"resource-resolver.d.ts","sourceRoot":"","sources":["../src/resource-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE7D,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CACL,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,EACvB,GAAG,EAAE,gBAAgB,EACrB,KAAK,CAAC,EAAE,oBAAoB,GAC3B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;CACrD;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,GAAE,MAAa;IAEjD,OAAO,CACL,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,EACvB,GAAG,EAAE,gBAAgB,EACrB,KAAK,CAAC,EAAE,oBAAoB,GAC3B,MAAM,GAAG,SAAS;CAStB"}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Default resolver: reads the route `:id` param and produces a lightweight
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Default resolver: reads the route `:id` param and produces a lightweight `{ id }`
|
|
3
|
+
* object whose prototype is the resource class's, enough for ownership checks on
|
|
4
|
+
* `resource.id` without an ORM. Register your own {@link ResourceResolver} to load
|
|
5
|
+
* real entities.
|
|
6
6
|
*/
|
|
7
7
|
export class IdParamResourceResolver {
|
|
8
8
|
param;
|
|
9
9
|
constructor(param = 'id') {
|
|
10
10
|
this.param = param;
|
|
11
11
|
}
|
|
12
|
-
resolve(resource, ctx) {
|
|
12
|
+
resolve(resource, ctx, hints) {
|
|
13
|
+
if (ctx.getType() !== 'http')
|
|
14
|
+
return undefined;
|
|
13
15
|
const req = ctx.switchToHttp().getRequest();
|
|
14
|
-
const id = req?.params?.[this.param];
|
|
16
|
+
const id = req?.params?.[hints?.param ?? this.param];
|
|
15
17
|
if (id === undefined)
|
|
16
18
|
return undefined;
|
|
17
|
-
// Construct a shaped instance so `instance.constructor === resource`, which
|
|
18
|
-
// is how PolicyRegistry maps an instance back to its policy.
|
|
19
19
|
const instance = Object.create(resource.prototype);
|
|
20
20
|
instance.id = id;
|
|
21
21
|
return instance;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-resolver.js","sourceRoot":"","sources":["../src/resource-resolver.ts"],"names":[],"mappings":"AAsBA;;;;;GAKG;AACH,MAAM,OAAO,uBAAuB;IACL;IAA7B,YAA6B,QAAgB,IAAI;QAApB,UAAK,GAAL,KAAK,CAAe;IAAG,CAAC;IAErD,OAAO,
|
|
1
|
+
{"version":3,"file":"resource-resolver.js","sourceRoot":"","sources":["../src/resource-resolver.ts"],"names":[],"mappings":"AAsBA;;;;;GAKG;AACH,MAAM,OAAO,uBAAuB;IACL;IAA7B,YAA6B,QAAgB,IAAI;QAApB,UAAK,GAAL,KAAK,CAAe;IAAG,CAAC;IAErD,OAAO,CACL,QAAuB,EACvB,GAAqB,EACrB,KAA4B;QAE5B,IAAI,GAAG,CAAC,OAAO,EAAE,KAAK,MAAM;YAAE,OAAO,SAAS,CAAC;QAC/C,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAwC,CAAC;QAClF,MAAM,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAA4B,CAAC;QAC9E,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import type { DecisionProvider } from './decision-provider.js';
|
|
3
|
+
import { type ResourceResolver } from './resource-resolver.js';
|
|
4
|
+
import type { SuperAdminHook } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* What `@Can()` argument resolvers and policy base classes need from the app but
|
|
7
|
+
* cannot inject: the official resolvers run with only the `ExecutionContext`, and a
|
|
8
|
+
* policy base class cannot add constructor parameters to its subclasses. `AuthzModule`
|
|
9
|
+
* fills this in when it boots. One application per process is the expected case; with
|
|
10
|
+
* several, the last one to boot wins.
|
|
11
|
+
*/
|
|
12
|
+
interface AuthzRuntime {
|
|
13
|
+
resourceResolver: ResourceResolver;
|
|
14
|
+
superAdmin: SuperAdminHook | undefined;
|
|
15
|
+
/** The external decision point, looked up lazily (an adapter may register it late). */
|
|
16
|
+
decisionProvider: () => DecisionProvider | undefined;
|
|
17
|
+
getUser: (context: ExecutionContext) => unknown;
|
|
18
|
+
}
|
|
19
|
+
/** @internal Called by `AuthzModule` at boot, and by the testing helpers. */
|
|
20
|
+
export declare function configureAuthzRuntime(patch: Partial<AuthzRuntime>): void;
|
|
21
|
+
/** @internal Restore the defaults (tests). */
|
|
22
|
+
export declare function resetAuthzRuntime(): void;
|
|
23
|
+
/** @internal */
|
|
24
|
+
export declare function authzRuntime(): Readonly<AuthzRuntime>;
|
|
25
|
+
/**
|
|
26
|
+
* The user the official guard sees for this call: the `getUser` given to
|
|
27
|
+
* `AuthorizationModule.forRoot()`, else the official `defaultGetUser`. `null` for a guest.
|
|
28
|
+
*/
|
|
29
|
+
export declare function currentUserOf(context: ExecutionContext): Promise<unknown>;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;GAMG;AACH,UAAU,YAAY;IACpB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,UAAU,EAAE,cAAc,GAAG,SAAS,CAAC;IACvC,uFAAuF;IACvF,gBAAgB,EAAE,MAAM,gBAAgB,GAAG,SAAS,CAAC;IACrD,OAAO,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC;CACjD;AAWD,6EAA6E;AAC7E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAKxE;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC;AAED,gBAAgB;AAChB,wBAAgB,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC,CAErD;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAG/E"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { defaultGetUser } from '@nestjs/authorization';
|
|
2
|
+
import { IdParamResourceResolver } from './resource-resolver.js';
|
|
3
|
+
const noDecisionProvider = () => undefined;
|
|
4
|
+
const runtime = {
|
|
5
|
+
resourceResolver: new IdParamResourceResolver(),
|
|
6
|
+
superAdmin: undefined,
|
|
7
|
+
decisionProvider: noDecisionProvider,
|
|
8
|
+
getUser: defaultGetUser,
|
|
9
|
+
};
|
|
10
|
+
/** @internal Called by `AuthzModule` at boot, and by the testing helpers. */
|
|
11
|
+
export function configureAuthzRuntime(patch) {
|
|
12
|
+
if (patch.resourceResolver)
|
|
13
|
+
runtime.resourceResolver = patch.resourceResolver;
|
|
14
|
+
if ('superAdmin' in patch)
|
|
15
|
+
runtime.superAdmin = patch.superAdmin;
|
|
16
|
+
if (patch.decisionProvider)
|
|
17
|
+
runtime.decisionProvider = patch.decisionProvider;
|
|
18
|
+
if (patch.getUser)
|
|
19
|
+
runtime.getUser = patch.getUser;
|
|
20
|
+
}
|
|
21
|
+
/** @internal Restore the defaults (tests). */
|
|
22
|
+
export function resetAuthzRuntime() {
|
|
23
|
+
runtime.resourceResolver = new IdParamResourceResolver();
|
|
24
|
+
runtime.superAdmin = undefined;
|
|
25
|
+
runtime.decisionProvider = noDecisionProvider;
|
|
26
|
+
runtime.getUser = defaultGetUser;
|
|
27
|
+
}
|
|
28
|
+
/** @internal */
|
|
29
|
+
export function authzRuntime() {
|
|
30
|
+
return runtime;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The user the official guard sees for this call: the `getUser` given to
|
|
34
|
+
* `AuthorizationModule.forRoot()`, else the official `defaultGetUser`. `null` for a guest.
|
|
35
|
+
*/
|
|
36
|
+
export async function currentUserOf(context) {
|
|
37
|
+
const user = await runtime.getUser(context);
|
|
38
|
+
return user === undefined || user === false ? null : user;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,uBAAuB,EAAyB,MAAM,wBAAwB,CAAC;AAkBxF,MAAM,kBAAkB,GAAG,GAAiC,EAAE,CAAC,SAAS,CAAC;AAEzE,MAAM,OAAO,GAAiB;IAC5B,gBAAgB,EAAE,IAAI,uBAAuB,EAAE;IAC/C,UAAU,EAAE,SAAS;IACrB,gBAAgB,EAAE,kBAAkB;IACpC,OAAO,EAAE,cAAc;CACxB,CAAC;AAEF,6EAA6E;AAC7E,MAAM,UAAU,qBAAqB,CAAC,KAA4B;IAChE,IAAI,KAAK,CAAC,gBAAgB;QAAE,OAAO,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;IAC9E,IAAI,YAAY,IAAI,KAAK;QAAE,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IACjE,IAAI,KAAK,CAAC,gBAAgB;QAAE,OAAO,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;IAC9E,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AACrD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,iBAAiB;IAC/B,OAAO,CAAC,gBAAgB,GAAG,IAAI,uBAAuB,EAAE,CAAC;IACzD,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAC/B,OAAO,CAAC,gBAAgB,GAAG,kBAAkB,CAAC;IAC9C,OAAO,CAAC,OAAO,GAAG,cAAc,CAAC;AACnC,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAyB;IAC3D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC"}
|
package/dist/tokens.d.ts
CHANGED
|
@@ -17,12 +17,8 @@ export declare const RESOURCE_RESOLVER: symbol;
|
|
|
17
17
|
* or empty, the endpoint behaves exactly as before (class-level / ad-hoc only).
|
|
18
18
|
*/
|
|
19
19
|
export declare const RESOURCE_HYDRATOR: symbol;
|
|
20
|
-
/** Metadata key
|
|
21
|
-
export
|
|
22
|
-
/** Metadata key for `@Can(ability, Resource?)` — stores the ability descriptor on a route. */
|
|
23
|
-
export declare const CAN_METADATA = "nestjs-authz:can";
|
|
24
|
-
/** Metadata key for `@Roles(...roles)` — stores the allowed role names on a route. */
|
|
25
|
-
export declare const ROLES_METADATA = "nestjs-authz:roles";
|
|
20
|
+
/** Metadata key of the `@PolicyFor(Resource)` link on a policy class. */
|
|
21
|
+
export { POLICY_RESOURCE_METADATA } from './links.js';
|
|
26
22
|
/**
|
|
27
23
|
* Cross-lib injection token for an optional {@link PermissionProvider} — the seam the
|
|
28
24
|
* RBAC adapter (`@dudousxd/nestjs-authz-typeorm`) registers so that a model-less,
|
|
@@ -31,8 +27,8 @@ export declare const ROLES_METADATA = "nestjs-authz:roles";
|
|
|
31
27
|
*
|
|
32
28
|
* `Symbol.for(key)` uses the global symbol registry so an RBAC package registering
|
|
33
29
|
* this same key resolves to the SAME symbol instance without importing core internals.
|
|
34
|
-
* The token is consulted with `@Optional()` — when absent,
|
|
35
|
-
*
|
|
30
|
+
* The token is consulted with `@Optional()` — when absent, an unknown string ability
|
|
31
|
+
* still throws.
|
|
36
32
|
*/
|
|
37
33
|
export declare const PERMISSION_PROVIDER: symbol;
|
|
38
34
|
/**
|
package/dist/tokens.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAEA,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,QAAiC,CAAC;AAEnE,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAE1E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAE1E,
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAEA,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,QAAiC,CAAC;AAEnE,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAE1E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAE1E,yEAAyE;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,QAA6C,CAAC;AAE9E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,QAAuC,CAAC;AAElE;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAE1E;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAAoC,CAAC"}
|
package/dist/tokens.js
CHANGED
|
@@ -18,12 +18,8 @@ export const RESOURCE_RESOLVER = capability('authz', 'resource-resolver');
|
|
|
18
18
|
* or empty, the endpoint behaves exactly as before (class-level / ad-hoc only).
|
|
19
19
|
*/
|
|
20
20
|
export const RESOURCE_HYDRATOR = capability('authz', 'resource-hydrator');
|
|
21
|
-
/** Metadata key
|
|
22
|
-
export
|
|
23
|
-
/** Metadata key for `@Can(ability, Resource?)` — stores the ability descriptor on a route. */
|
|
24
|
-
export const CAN_METADATA = 'nestjs-authz:can';
|
|
25
|
-
/** Metadata key for `@Roles(...roles)` — stores the allowed role names on a route. */
|
|
26
|
-
export const ROLES_METADATA = 'nestjs-authz:roles';
|
|
21
|
+
/** Metadata key of the `@PolicyFor(Resource)` link on a policy class. */
|
|
22
|
+
export { POLICY_RESOURCE_METADATA } from './links.js';
|
|
27
23
|
/**
|
|
28
24
|
* Cross-lib injection token for an optional {@link PermissionProvider} — the seam the
|
|
29
25
|
* RBAC adapter (`@dudousxd/nestjs-authz-typeorm`) registers so that a model-less,
|
|
@@ -32,8 +28,8 @@ export const ROLES_METADATA = 'nestjs-authz:roles';
|
|
|
32
28
|
*
|
|
33
29
|
* `Symbol.for(key)` uses the global symbol registry so an RBAC package registering
|
|
34
30
|
* this same key resolves to the SAME symbol instance without importing core internals.
|
|
35
|
-
* The token is consulted with `@Optional()` — when absent,
|
|
36
|
-
*
|
|
31
|
+
* The token is consulted with `@Optional()` — when absent, an unknown string ability
|
|
32
|
+
* still throws.
|
|
37
33
|
*/
|
|
38
34
|
export const PERMISSION_PROVIDER = capability('authz', 'permission-provider');
|
|
39
35
|
/**
|
package/dist/tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAEnE,uFAAuF;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AAE1E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AAE1E,
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAEnE,uFAAuF;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AAE1E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AAE1E,yEAAyE;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AAElE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,217 +1,100 @@
|
|
|
1
1
|
import type { Type } from '@nestjs/common';
|
|
2
2
|
import type { UserRef } from './context-accessor.js';
|
|
3
3
|
import type { ResourceResolver } from './resource-resolver.js';
|
|
4
|
-
/**
|
|
5
|
-
* A resource instance passed to policy methods. `unknown` because authz never
|
|
6
|
-
* inspects the resource itself — the policy method does.
|
|
7
|
-
*/
|
|
4
|
+
/** A resource passed to a policy ability. authz never inspects it; the policy does. */
|
|
8
5
|
export type Resource = object;
|
|
9
6
|
/**
|
|
10
|
-
* The
|
|
11
|
-
*
|
|
7
|
+
* The user a policy or gate sees: whatever authentication produced, `null` for a
|
|
8
|
+
* guest. authz does not model it.
|
|
12
9
|
*/
|
|
13
10
|
export type User = unknown;
|
|
14
11
|
/**
|
|
15
|
-
*
|
|
16
|
-
* boolean
|
|
17
|
-
*
|
|
18
|
-
* and published on the diagnostics decision. Returning a bare boolean is unchanged.
|
|
19
|
-
*
|
|
20
|
-
* Mirrors Laravel's `Response::allow()/deny('message')`.
|
|
12
|
+
* A verdict with an optional reason. What a {@link DecisionProvider} may answer instead of
|
|
13
|
+
* a bare boolean. Only `allowed` is used: `@nestjs/authorization` has no deny-with-reason, so a
|
|
14
|
+
* route denial is the official 403 and the `message` is dropped (README, "Migrating from 0.8").
|
|
21
15
|
*/
|
|
22
16
|
export interface PolicyResponse {
|
|
23
17
|
allowed: boolean;
|
|
24
18
|
message?: string;
|
|
25
19
|
}
|
|
26
|
-
/**
|
|
27
|
-
* What a policy method / gate / hook may return: a bare boolean (unchanged) or the
|
|
28
|
-
* richer {@link PolicyResponse}. Hooks additionally allow `void`/`undefined` to mean
|
|
29
|
-
* "no opinion — fall through".
|
|
30
|
-
*/
|
|
20
|
+
/** A bare boolean or a {@link PolicyResponse}. */
|
|
31
21
|
export type PolicyResult = boolean | PolicyResponse;
|
|
22
|
+
/** An ad-hoc, model-less gate registered with `gate.define(name, fn)`. */
|
|
23
|
+
export type GateFn = (user: User, resource?: Resource) => boolean | Promise<boolean>;
|
|
32
24
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
25
|
+
* The global super-admin hook. `true` grants any check; anything else falls through.
|
|
26
|
+
* Policies honor it when they extend `AuthzPolicy` (or call `superAdminBefore` from
|
|
27
|
+
* their `before()`); `RolePolicy` and `PermissionPolicy` do. The `Gate`'s string
|
|
28
|
+
* abilities and `gate.scope()` ask it first.
|
|
36
29
|
*/
|
|
37
|
-
export type
|
|
38
|
-
/**
|
|
39
|
-
* Optional per-policy `before` hook. Runs before the ability method.
|
|
40
|
-
* - return `true` → allow (short-circuit)
|
|
41
|
-
* - return `false` → deny (short-circuit)
|
|
42
|
-
* - return `void`/`undefined` → fall through to the ability method
|
|
43
|
-
*/
|
|
44
|
-
export type PolicyBeforeHook = (user: User, ability: string) => PolicyResult | undefined | Promise<PolicyResult | undefined>;
|
|
45
|
-
/** A policy instance is an arbitrary object whose methods are abilities. */
|
|
46
|
-
export type PolicyInstance = Record<string, unknown> & {
|
|
47
|
-
before?: PolicyBeforeHook;
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* An ad-hoc gate: a model-less ability resolved by name via `gate.define`.
|
|
51
|
-
* May return a bare boolean (unchanged) or a richer {@link PolicyResponse}.
|
|
52
|
-
*/
|
|
53
|
-
export type GateFn = (user: User, resource?: Resource) => PolicyResult | Promise<PolicyResult>;
|
|
54
|
-
/**
|
|
55
|
-
* Global `after` hook. Mirrors Laravel's `Gate::after()`: runs AFTER policy/gate
|
|
56
|
-
* resolution and may observe or override the decision.
|
|
57
|
-
*
|
|
58
|
-
* `result` is the verdict produced by the policy/gate (`true`/`false`), or
|
|
59
|
-
* `undefined` when the policy/gate returned a nullish value (it had "no opinion").
|
|
60
|
-
*
|
|
61
|
-
* Override semantics (Laravel-idiomatic): the hook's return value REPLACES the
|
|
62
|
-
* decision ONLY when the policy/gate produced no explicit verdict (`result` is
|
|
63
|
-
* `undefined`). When the policy/gate DID decide (returned a boolean), `after` is
|
|
64
|
-
* purely an observer and its return value is ignored — so it can never silently
|
|
65
|
-
* overturn an explicit allow/deny. Returning `void`/`undefined` always leaves the
|
|
66
|
-
* decision untouched. Like a policy, it may return a {@link PolicyResponse} to
|
|
67
|
-
* attach a deny message.
|
|
68
|
-
*/
|
|
69
|
-
export type AfterHook = (user: User, ability: string, result: boolean | undefined, resource?: Resource) => PolicyResult | undefined | Promise<PolicyResult | undefined>;
|
|
30
|
+
export type SuperAdminHook = (user: User, ability: string,
|
|
70
31
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* constructor. Returning nullish signals "not found" (the endpoint denies). May be async.
|
|
32
|
+
* What the check targets: the resource of a single check (the policy's first
|
|
33
|
+
* argument), or the entity class for `gate.scope(...)`. `undefined` for a model-less
|
|
34
|
+
* ability. Lets the hook scope the bypass (e.g. to one tenant's resources).
|
|
75
35
|
*/
|
|
36
|
+
resource?: Resource) => boolean | null | undefined | Promise<boolean | null | undefined>;
|
|
37
|
+
/** Loads the real entity for a client `{ type, id }` reference (the `POST /authz/can` endpoint). */
|
|
76
38
|
export type ResourceLoader = (id: string | number) => unknown | Promise<unknown>;
|
|
77
|
-
/**
|
|
78
|
-
* Resource loaders keyed by the resource `type` name as emitted by the client/codegen
|
|
79
|
-
* (e.g. `'Post'`). See {@link AuthzModuleOptions.resourceLoaders}.
|
|
80
|
-
*/
|
|
39
|
+
/** Resource loaders keyed by the resource `type` name the client sends (e.g. `'Post'`). */
|
|
81
40
|
export type ResourceLoaderMap = Record<string, ResourceLoader>;
|
|
82
41
|
/**
|
|
83
|
-
*
|
|
84
|
-
* `
|
|
42
|
+
* What happens to a route that declares no `@Can()` (nor `Can.Anyone()` / `@Public()`):
|
|
43
|
+
* - `'deny'` (default): nothing special; the official `AuthorizationGuard` denies it.
|
|
44
|
+
* - `'allow'`: the migration mode. `AuthzModule` registers its own global {@link AuthzGuard},
|
|
45
|
+
* which enforces the official requirements exactly as the official guard does and lets
|
|
46
|
+
* unannotated routes through. Needs `AuthorizationModule.forRoot({ globalGuard: false })`.
|
|
85
47
|
*/
|
|
86
|
-
export type
|
|
87
|
-
/**
|
|
88
|
-
|
|
89
|
-
* class for `gate.scope(...)`. `undefined` for a model-less ability.
|
|
90
|
-
*/
|
|
91
|
-
resource?: Resource) => PolicyResult | undefined | Promise<PolicyResult | undefined>;
|
|
92
|
-
export interface AuthzModuleOptions {
|
|
48
|
+
export type UnannotatedRoutes = 'allow' | 'deny';
|
|
49
|
+
/** Options that decide what the module registers, so they are static (read before any factory runs). */
|
|
50
|
+
export interface AuthzModuleStaticOptions {
|
|
93
51
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* this is optional.
|
|
52
|
+
* Opt-in `POST /authz/can` endpoint for client checks that are not hydrated. `true`
|
|
53
|
+
* mounts it at `authz/can`; a string at that path. Off by default.
|
|
97
54
|
*/
|
|
98
|
-
|
|
55
|
+
canEndpoint?: boolean | string;
|
|
99
56
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* ⚠️ IMPORTANT — what `user` is: on the **context path** (no `forUser`), the
|
|
104
|
-
* `user` passed here is the raw {@link UserRef} from nestjs-context — just
|
|
105
|
-
* `{ type, id }`, NOT your hydrated user entity. So `superAdmin: u => u.isAdmin`
|
|
106
|
-
* will NOT fire from a route/`gate.allows(...)` unless you also configure
|
|
107
|
-
* {@link AuthzModuleOptions.resolveUser} to hydrate the full entity. On the
|
|
108
|
-
* explicit `gate.forUser(entity)` path you receive exactly what you passed.
|
|
57
|
+
* Class decorators applied to every controller this module mounts (the `POST /authz/can`
|
|
58
|
+
* endpoint), after its own: `[UseGuards(JwtAuthGuard), ApiTags('authz')]`. The controllers
|
|
59
|
+
* are open to the official guard by default (`Can.Anyone()`); a `@Can()` here restricts them.
|
|
109
60
|
*/
|
|
61
|
+
decorators?: ClassDecorator[];
|
|
62
|
+
/** See {@link UnannotatedRoutes}. Default `'deny'`. */
|
|
63
|
+
unannotated?: UnannotatedRoutes;
|
|
64
|
+
}
|
|
65
|
+
export interface AuthzModuleOptions extends AuthzModuleStaticOptions {
|
|
66
|
+
/** The global super-admin hook. See {@link SuperAdminHook}. */
|
|
110
67
|
superAdmin?: SuperAdminHook;
|
|
111
68
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* untouched. See {@link AfterHook}.
|
|
118
|
-
*
|
|
119
|
-
* Receives the same (possibly un-hydrated) `user` as {@link superAdmin} on the
|
|
120
|
-
* context path — apply {@link resolveUser} if you need the full entity.
|
|
121
|
-
*/
|
|
122
|
-
after?: AfterHook;
|
|
123
|
-
/**
|
|
124
|
-
* Optional hook to hydrate the full user entity from the context's
|
|
125
|
-
* {@link UserRef} (`{ type, id }`) before policies / `before` / `superAdmin`
|
|
126
|
-
* run. WITHOUT this hook, the context path passes only `{ type, id }` to those
|
|
127
|
-
* functions (it does not load your `User` row), so property checks such as
|
|
128
|
-
* `superAdmin: u => u.isAdmin` or `post.authorId === user.id` against a real
|
|
129
|
-
* column will not see hydrated fields. Provide `resolveUser` to load the entity
|
|
130
|
-
* (e.g. from your ORM) keyed by the ref. Returning `undefined` is treated as
|
|
131
|
-
* "no user" (deny path), identical to an anonymous request.
|
|
132
|
-
*
|
|
133
|
-
* Only affects the context path; `gate.forUser(entity)` always uses the value
|
|
134
|
-
* you pass directly and never invokes this hook.
|
|
69
|
+
* Hydrates the full user from nestjs-context's `{ type, id }` ref for `Gate` calls
|
|
70
|
+
* made without a user (`gate.allows(...)` rather than `gate.forUser(user)`), when
|
|
71
|
+
* `@nestjs/authentication`'s `AuthenticationContext` has no user to offer. Runs once
|
|
72
|
+
* per `type:id` per request (nestjs-context store). Routes never use it: the official
|
|
73
|
+
* guard reads the user with its own `getUser`.
|
|
135
74
|
*/
|
|
136
75
|
resolveUser?: (ref: UserRef) => User | undefined | Promise<User | undefined>;
|
|
137
76
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* (`string[]`) OR `user.role` (`string | string[]`) off the user object, so
|
|
141
|
-
* role-checks work with ZERO RBAC tables. Provide this to derive roles from a
|
|
142
|
-
* different shape. When the optional `ROLE_PROVIDER` seam is ALSO registered, the
|
|
143
|
-
* Gate unions both sources' roles.
|
|
144
|
-
*
|
|
145
|
-
* On the context path the resolver receives whatever the context produced (the
|
|
146
|
-
* raw {@link UserRef} unless `resolveUser` hydrated the entity); on the explicit
|
|
147
|
-
* `gate.forUser(entity)` path it receives exactly what you passed.
|
|
77
|
+
* Derives roles from the user object. Default: `user.roles` (`string[]`) or
|
|
78
|
+
* `user.role` (`string | string[]`). Unioned with the RBAC adapter's role store.
|
|
148
79
|
*/
|
|
149
80
|
resolveRoles?: (user: User) => string[] | undefined | Promise<string[] | undefined>;
|
|
150
|
-
/**
|
|
151
|
-
* Override the default {@link ResourceResolver} used to load an instance for
|
|
152
|
-
* `@Can(ability, Resource)` routes. Defaults to {@link IdParamResourceResolver}
|
|
153
|
-
* (reads the route `:id` param), registered automatically by `forRoot`. Apps
|
|
154
|
-
* needing real ORM entities provide their own here (or bind the
|
|
155
|
-
* `RESOURCE_RESOLVER` token directly).
|
|
156
|
-
*/
|
|
81
|
+
/** Loads the resource for `byId(Resource)`. Default: {@link IdParamResourceResolver}. */
|
|
157
82
|
resourceResolver?: ResourceResolver;
|
|
158
|
-
/**
|
|
159
|
-
* Route param name the default {@link IdParamResourceResolver} reads to build
|
|
160
|
-
* the resource shim. Defaults to `'id'`. Ignored when {@link resourceResolver}
|
|
161
|
-
* is supplied.
|
|
162
|
-
*/
|
|
83
|
+
/** Route param the default resolver reads. Default `'id'`. */
|
|
163
84
|
idParam?: string;
|
|
164
|
-
/**
|
|
165
|
-
* Opt-in `POST /authz/can` fallback endpoint. **Off by default.** When enabled,
|
|
166
|
-
* registers a controller that runs `gate.allows(ability, resource?)` for the
|
|
167
|
-
* current (context) user and returns `{ allowed: boolean }`. This is the
|
|
168
|
-
* last-resort path the codegen-emitted `can()` helper targets.
|
|
169
|
-
*
|
|
170
|
-
* - `true` → mount at the default path `authz/can`.
|
|
171
|
-
* - `string` → mount at that path (e.g. `'api/authz/can'`).
|
|
172
|
-
* - `false`/omitted → no endpoint is registered.
|
|
173
|
-
*
|
|
174
|
-
* Prefer the no-request paths (shared Inertia props, per-resource `can` maps)
|
|
175
|
-
* — this endpoint exists only for abilities not already hydrated on the client.
|
|
176
|
-
*/
|
|
177
|
-
canEndpoint?: boolean | string;
|
|
178
|
-
/**
|
|
179
|
-
* Resource loaders keyed by the resource `type` name the client/codegen emits
|
|
180
|
-
* (e.g. `'Post'`). They close the per-instance gap in the {@link canEndpoint}
|
|
181
|
-
* fallback: when the endpoint receives `{ ability, resource: { type, id } }` and a
|
|
182
|
-
* loader is registered for `type`, it `await`s `loader(id)` and authorizes the REAL
|
|
183
|
-
* entity — so an instance-bound `@Policy` matches by constructor and its method runs
|
|
184
|
-
* with the loaded resource. A loader returning nullish is treated as "not found"
|
|
185
|
-
* (the endpoint denies). Types WITHOUT a loader keep the prior behavior (class-level
|
|
186
|
-
* / ad-hoc only; a resource-bound ability still denies). Opt-in: unset → unchanged.
|
|
187
|
-
*
|
|
188
|
-
* ```ts
|
|
189
|
-
* resourceLoaders: { Post: (id) => postRepo.findOneBy({ id: Number(id) }) }
|
|
190
|
-
* ```
|
|
191
|
-
*/
|
|
85
|
+
/** Loaders that turn the endpoint's `{ type, id }` into the real entity, keyed by type. */
|
|
192
86
|
resourceLoaders?: ResourceLoaderMap;
|
|
193
87
|
}
|
|
194
88
|
export interface AuthzModuleOptionsFactory {
|
|
195
89
|
createAuthzOptions(): Promise<AuthzModuleOptions> | AuthzModuleOptions;
|
|
196
90
|
}
|
|
197
|
-
export interface AuthzModuleAsyncOptions {
|
|
91
|
+
export interface AuthzModuleAsyncOptions extends AuthzModuleStaticOptions {
|
|
198
92
|
imports?: unknown[];
|
|
199
93
|
useExisting?: Type<AuthzModuleOptionsFactory>;
|
|
200
94
|
useClass?: Type<AuthzModuleOptionsFactory>;
|
|
201
95
|
useFactory?: (...args: unknown[]) => Promise<AuthzModuleOptions> | AuthzModuleOptions;
|
|
202
96
|
inject?: unknown[];
|
|
203
|
-
/**
|
|
204
|
-
* Opt-in `POST /authz/can` fallback endpoint (see {@link AuthzModuleOptions.canEndpoint}).
|
|
205
|
-
* Declared statically here because controllers are registered at module-definition
|
|
206
|
-
* time, before the async options factory resolves. Off by default.
|
|
207
|
-
*/
|
|
208
|
-
canEndpoint?: boolean | string;
|
|
209
|
-
/**
|
|
210
|
-
* Resource loaders for the {@link canEndpoint} fallback
|
|
211
|
-
* (see {@link AuthzModuleOptions.resourceLoaders}). May also be returned from the
|
|
212
|
-
* async options factory; either way the endpoint reads them from the resolved
|
|
213
|
-
* options, so this declaration is for the rarer case of supplying them statically.
|
|
214
|
-
*/
|
|
97
|
+
/** See {@link AuthzModuleOptions.resourceLoaders}. */
|
|
215
98
|
resourceLoaders?: ResourceLoaderMap;
|
|
216
99
|
}
|
|
217
100
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-authz",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Extras on top of @nestjs/authorization: persisted RBAC policies, @Can helpers (byId, roles, permission), a Gate with batch checks and ad-hoc gates, super-admin, query scoping.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"acl",
|
|
22
22
|
"rbac",
|
|
23
23
|
"tanstack-intent",
|
|
24
|
-
"cerbos"
|
|
24
|
+
"cerbos",
|
|
25
|
+
"nestjs-authorization"
|
|
25
26
|
],
|
|
26
27
|
"author": "Davi Carvalho <davi@goflip.ai>",
|
|
27
28
|
"type": "module",
|
|
@@ -55,24 +56,32 @@
|
|
|
55
56
|
},
|
|
56
57
|
"peerDependencies": {
|
|
57
58
|
"@dudousxd/nestjs-context": ">=0.1.0",
|
|
58
|
-
"@nestjs/
|
|
59
|
-
"@nestjs/
|
|
60
|
-
"
|
|
59
|
+
"@nestjs/authentication": "^0.1.5",
|
|
60
|
+
"@nestjs/authorization": "^0.1.3",
|
|
61
|
+
"@nestjs/common": "^12.0.0",
|
|
62
|
+
"@nestjs/core": "^12.0.0",
|
|
63
|
+
"reflect-metadata": ">=0.1.13",
|
|
64
|
+
"rxjs": "^7.1.0"
|
|
61
65
|
},
|
|
62
66
|
"peerDependenciesMeta": {
|
|
63
67
|
"@dudousxd/nestjs-context": {
|
|
64
68
|
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"@nestjs/authentication": {
|
|
71
|
+
"optional": true
|
|
65
72
|
}
|
|
66
73
|
},
|
|
67
74
|
"devDependencies": {
|
|
68
75
|
"@cerbos/http": "0.29.0",
|
|
76
|
+
"@nestjs/authentication": "0.1.5",
|
|
77
|
+
"@nestjs/authorization": "0.1.3",
|
|
69
78
|
"@nestjs/common": "12.0.1",
|
|
70
79
|
"@nestjs/core": "12.0.1",
|
|
71
80
|
"@nestjs/platform-express": "12.0.1",
|
|
72
81
|
"@nestjs/testing": "12.0.1",
|
|
73
82
|
"@tanstack/intent": "0.4.0",
|
|
74
83
|
"@types/express": "4.17.25",
|
|
75
|
-
"@types/node": "20.
|
|
84
|
+
"@types/node": "22.20.5",
|
|
76
85
|
"@types/supertest": "6.0.3",
|
|
77
86
|
"express": "4.22.2",
|
|
78
87
|
"reflect-metadata": "0.2.2",
|
|
@@ -82,12 +91,12 @@
|
|
|
82
91
|
"vitest": "3.2.7"
|
|
83
92
|
},
|
|
84
93
|
"engines": {
|
|
85
|
-
"node": ">=
|
|
94
|
+
"node": ">=22"
|
|
86
95
|
},
|
|
87
96
|
"scripts": {
|
|
88
|
-
"build": "tsc -p tsconfig.json",
|
|
97
|
+
"build": "tsc -p tsconfig.json --incremental false",
|
|
89
98
|
"test": "vitest run --passWithNoTests",
|
|
90
99
|
"test:watch": "vitest",
|
|
91
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
100
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json"
|
|
92
101
|
}
|
|
93
102
|
}
|