@dudousxd/nestjs-authz 0.5.1 → 0.6.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 +58 -0
- package/dist/can-endpoint.controller.d.ts +16 -0
- package/dist/can-endpoint.controller.d.ts.map +1 -1
- package/dist/can-endpoint.controller.js +54 -0
- package/dist/can-endpoint.controller.js.map +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/gate.d.ts +108 -2
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +307 -28
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/permission-cache.d.ts +33 -0
- package/dist/permission-cache.d.ts.map +1 -0
- package/dist/permission-cache.js +48 -0
- package/dist/permission-cache.js.map +1 -0
- package/dist/permission-matcher.d.ts +22 -0
- package/dist/permission-matcher.d.ts.map +1 -0
- package/dist/permission-matcher.js +55 -0
- package/dist/permission-matcher.js.map +1 -0
- package/dist/permission-provider.d.ts +18 -0
- package/dist/permission-provider.d.ts.map +1 -1
- package/dist/scope.d.ts +84 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +41 -0
- package/dist/scope.js.map +1 -0
- package/dist/types.d.ts +53 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,63 @@
|
|
|
1
1
|
# @dudousxd/nestjs-authz
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#9](https://github.com/DavideCarvalho/nestjs-authz/pull/9) [`07d01de`](https://github.com/DavideCarvalho/nestjs-authz/commit/07d01de286e7dfcae5fbeb10b7e8d48533214087) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Ecosystem improvements across the authz packages.
|
|
8
|
+
|
|
9
|
+
### Permissions
|
|
10
|
+
|
|
11
|
+
- **Wildcard / hierarchical permissions.** Permission strings now support wildcard
|
|
12
|
+
and hierarchical matching (e.g. `posts:*` or `posts:read:*`), so a single granted
|
|
13
|
+
permission can authorize a family of related actions instead of enumerating each one.
|
|
14
|
+
|
|
15
|
+
### Authorization decisions
|
|
16
|
+
|
|
17
|
+
- **Deny reason / message surfaced on `ForbiddenException`.** When a check fails, the
|
|
18
|
+
reason for the denial is propagated onto the thrown `ForbiddenException`, making it
|
|
19
|
+
possible to return a meaningful message to the caller and to debug authorization
|
|
20
|
+
failures.
|
|
21
|
+
- **Gate `after` hook.** The Gate now exposes an `after` hook that runs once a decision
|
|
22
|
+
has been made, enabling cross-cutting concerns such as auditing, logging, and metrics.
|
|
23
|
+
|
|
24
|
+
### Batch authorization
|
|
25
|
+
|
|
26
|
+
- **`allowsMany`** for evaluating multiple permission checks in a single call.
|
|
27
|
+
- **Batch `/authz/can` endpoint** so clients can resolve many checks in one round trip.
|
|
28
|
+
- **`createCanBatch`** client helper that batches `can` calls transparently.
|
|
29
|
+
|
|
30
|
+
### Performance
|
|
31
|
+
|
|
32
|
+
- **Request-scoped permission cache.** Permissions resolved during a request are cached
|
|
33
|
+
for the lifetime of that request, avoiding repeated lookups on the hot path.
|
|
34
|
+
|
|
35
|
+
### RBAC adapters (TypeORM)
|
|
36
|
+
|
|
37
|
+
- **Direct user permissions** granted to a user independent of their roles.
|
|
38
|
+
- **Tenant-scoped roles** so the same role can be assigned per tenant in multi-tenant
|
|
39
|
+
deployments.
|
|
40
|
+
|
|
41
|
+
### Query scoping / policy filter (ABAC)
|
|
42
|
+
|
|
43
|
+
- **ORM-neutral constraint AST.** Policies can produce a portable constraint
|
|
44
|
+
representation describing which rows a subject may access.
|
|
45
|
+
- **Per-ORM application.** The constraint AST is translated and applied for
|
|
46
|
+
**TypeORM**, **MikroORM**, and **Prisma**, giving ABAC-style query scoping that
|
|
47
|
+
filters data at the database layer regardless of the ORM in use.
|
|
48
|
+
|
|
49
|
+
### Testing
|
|
50
|
+
|
|
51
|
+
- **New `@dudousxd/nestjs-authz-testing` package** with fakes and helpers for testing
|
|
52
|
+
authorization in consumer applications.
|
|
53
|
+
- **Postgres / MySQL testcontainers + contract tests** so the ORM stores are verified
|
|
54
|
+
against real database engines, and a shared contract suite keeps the adapters
|
|
55
|
+
behaviorally consistent.
|
|
56
|
+
|
|
57
|
+
### Housekeeping
|
|
58
|
+
|
|
59
|
+
- **Packaging hygiene** across the published packages.
|
|
60
|
+
|
|
3
61
|
## 0.5.1
|
|
4
62
|
|
|
5
63
|
### Patch Changes
|
|
@@ -14,6 +14,22 @@ export interface CanRequestBody {
|
|
|
14
14
|
export interface CanResponseBody {
|
|
15
15
|
allowed: boolean;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Batch request body: an array of `{ ability, resource? }` items. The endpoint
|
|
19
|
+
* accepts EITHER a single {@link CanRequestBody} or this array — a list page can
|
|
20
|
+
* authorize all of its cards in ONE round-trip instead of N. Mirrors the payload
|
|
21
|
+
* the client's `createCanBatch` emits.
|
|
22
|
+
*/
|
|
23
|
+
export type CanBatchRequestBody = CanRequestBody[];
|
|
24
|
+
/** One batch result: echoes the item's `ability`/`resource` plus the verdict. */
|
|
25
|
+
export interface CanBatchResultItem {
|
|
26
|
+
ability: string;
|
|
27
|
+
resource?: {
|
|
28
|
+
type: string;
|
|
29
|
+
id?: string | number;
|
|
30
|
+
} | null;
|
|
31
|
+
allowed: boolean;
|
|
32
|
+
}
|
|
17
33
|
/**
|
|
18
34
|
* Build the opt-in fallback controller class, mounted at `path`. Kept as a
|
|
19
35
|
* factory so the route path is configurable via `AuthzModule.forRoot({ canEndpoint })`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"can-endpoint.controller.d.ts","sourceRoot":"","sources":["../src/can-endpoint.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAM/E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC1D;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"can-endpoint.controller.d.ts","sourceRoot":"","sources":["../src/can-endpoint.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAM/E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC1D;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,EAAE,CAAC;AAEnD,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAiH/D;AAED,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,cAAc,CAAC"}
|
|
@@ -42,6 +42,10 @@ export function createCanController(path) {
|
|
|
42
42
|
this.loaders = loaders;
|
|
43
43
|
}
|
|
44
44
|
async can(body) {
|
|
45
|
+
// Array body → batch path (one user/permission resolution for the whole list).
|
|
46
|
+
if (Array.isArray(body)) {
|
|
47
|
+
return this.canBatch(body);
|
|
48
|
+
}
|
|
45
49
|
const ability = body?.ability;
|
|
46
50
|
if (typeof ability !== 'string' || ability.length === 0) {
|
|
47
51
|
return { allowed: false };
|
|
@@ -60,6 +64,56 @@ export function createCanController(path) {
|
|
|
60
64
|
return { allowed: false };
|
|
61
65
|
}
|
|
62
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Batch verdicts for an array body. Rehydrates each item's resource shim (via
|
|
69
|
+
* `resourceLoaders`, same as the single path), then resolves the whole list in
|
|
70
|
+
* ONE pass via `gate.forUser(currentUser).allowsMany(...)` so the user and the
|
|
71
|
+
* permission set are resolved once. Each result echoes the original
|
|
72
|
+
* `ability`/`resource` so the client can map verdicts back to its cards. A
|
|
73
|
+
* not-found loader, an empty ability, or an unresolved ability denies that item
|
|
74
|
+
* (never fails the whole batch).
|
|
75
|
+
*/
|
|
76
|
+
async canBatch(items) {
|
|
77
|
+
// Validate + rehydrate each item up front. `verdicts[i] === false` already
|
|
78
|
+
// pins the outright-denials (bad ability / not-found resource); `undefined`
|
|
79
|
+
// means "send to the batch". `batchInput` carries the surviving items plus
|
|
80
|
+
// their original index so verdicts map back in order.
|
|
81
|
+
const verdicts = new Array(items.length).fill(undefined);
|
|
82
|
+
const echo = new Array(items.length);
|
|
83
|
+
const batchInput = [];
|
|
84
|
+
for (let i = 0; i < items.length; i++) {
|
|
85
|
+
const item = items[i];
|
|
86
|
+
echo[i] = item?.resource ?? undefined;
|
|
87
|
+
const ability = item?.ability;
|
|
88
|
+
if (typeof ability !== 'string' || ability.length === 0) {
|
|
89
|
+
verdicts[i] = false;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const target = await this.rehydrate(item?.resource ?? undefined);
|
|
93
|
+
if (target === null) {
|
|
94
|
+
// A registered loader produced nothing → not found → deny this item.
|
|
95
|
+
verdicts[i] = false;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
batchInput.push(target === undefined ? { index: i, ability } : { index: i, ability, resource: target });
|
|
99
|
+
}
|
|
100
|
+
// ONE pass over the surviving items: user + permission set resolved once.
|
|
101
|
+
// `allowsMany` is fault-isolating, so an unresolved ability denies just its item.
|
|
102
|
+
const results = await this.gate.allowsMany(batchInput.map((b) => b.resource === undefined
|
|
103
|
+
? { ability: b.ability }
|
|
104
|
+
: { ability: b.ability, resource: b.resource }));
|
|
105
|
+
results.forEach((r, k) => {
|
|
106
|
+
const original = batchInput[k];
|
|
107
|
+
if (original)
|
|
108
|
+
verdicts[original.index] = r.allowed;
|
|
109
|
+
});
|
|
110
|
+
return items.map((item, i) => {
|
|
111
|
+
const ability = typeof item?.ability === 'string' ? item.ability : '';
|
|
112
|
+
const allowed = verdicts[i] ?? false;
|
|
113
|
+
const resource = echo[i];
|
|
114
|
+
return resource == null ? { ability, allowed } : { ability, resource, allowed };
|
|
115
|
+
});
|
|
116
|
+
}
|
|
63
117
|
/**
|
|
64
118
|
* Turn the client's `{ type, id }` shim into the resource the gate authorizes.
|
|
65
119
|
* - No resource → `undefined` (class-level ability).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"can-endpoint.controller.js","sourceRoot":"","sources":["../src/can-endpoint.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAa,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"can-endpoint.controller.js","sourceRoot":"","sources":["../src/can-endpoint.controller.ts"],"names":[],"mappings":"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"}
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export interface AuthzDecisionDiagnostic {
|
|
|
30
30
|
resourceId: string | number | null;
|
|
31
31
|
}
|
|
32
32
|
/** The resolution path that produced a decision — the "why" behind a 403 (or a grant). */
|
|
33
|
-
export type AuthzDecisionReason = 'super-admin' | 'permission-provider' | 'policy-before' | 'policy' | 'gate' | 'anonymous';
|
|
33
|
+
export type AuthzDecisionReason = 'super-admin' | 'permission-provider' | 'policy-before' | 'policy' | 'gate' | 'after' | 'anonymous';
|
|
34
34
|
/**
|
|
35
35
|
* Publish a decision to the channel, but only when something is listening. Never
|
|
36
36
|
* throws — building the payload or notifying a subscriber must not break a check.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,yDAAkC,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,MAAM,EAAE,mBAAmB,CAAC;IAC5B,kGAAkG;IAClG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wFAAwF;IACxF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,0FAA0F;AAC1F,MAAM,MAAM,mBAAmB,GAC3B,aAAa,GACb,qBAAqB,GACrB,eAAe,GACf,QAAQ,GACR,MAAM,GACN,WAAW,CAAC;AAEhB;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAC7B,IAAI,CAcN"}
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,yDAAkC,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,CAAC,EAAE,CAAC,CAAC;IACL,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,MAAM,EAAE,mBAAmB,CAAC;IAC5B,kGAAkG;IAClG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wFAAwF;IACxF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,0FAA0F;AAC1F,MAAM,MAAM,mBAAmB,GAC3B,aAAa,GACb,qBAAqB,GACrB,eAAe,GACf,QAAQ,GACR,MAAM,GACN,OAAO,GACP,WAAW,CAAC;AAEhB;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAC7B,IAAI,CAcN"}
|
package/dist/diagnostics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAGhE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAGhE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAiCpE;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,OAAgB,EAChB,MAA2B,EAC3B,IAAU,EACV,QAA8B;IAE9B,IAAI,CAAC,oBAAoB,CAAC,cAAc;QAAE,OAAO;IACjD,MAAM,OAAO,GAA4B;QACvC,CAAC,EAAE,CAAC;QACJ,OAAO;QACP,OAAO;QACP,MAAM;QACN,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC;QACxB,YAAY,EAAE,YAAY,CAAC,QAAQ,CAAC;QACpC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC;KACjC,CAAC;IACF,gFAAgF;IAChF,+EAA+E;IAC/E,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,4FAA4F;AAC5F,SAAS,SAAS,CAAC,IAAU;IAC3B,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,WAAW,EAAE,IAAI,CAAuB,CAAC;QACvE,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC;QAClB,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC;YAAE,OAAO,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;QACvF,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpF,OAAO,GAAG,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,sGAAsG;AACtG,SAAS,YAAY,CAAC,QAA8B;IAClD,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAQ,QAA8B,CAAC,IAAI,IAAI,IAAI,CAAC;IACxF,OAAQ,QAAgD,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,CAAC;AACrF,CAAC;AAED,kFAAkF;AAClF,SAAS,UAAU,CAAC,QAA8B;IAChD,IAAI,QAAQ,IAAI,IAAI,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACpE,MAAM,EAAE,GAAI,QAAoC,CAAC,EAAE,CAAC;IACpD,OAAO,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACtE,CAAC"}
|
package/dist/gate.d.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
|
+
import { type Type } from '@nestjs/common';
|
|
1
2
|
import { ModuleRef } from '@nestjs/core';
|
|
2
3
|
import type { ContextAccessor } from './context-accessor.js';
|
|
4
|
+
import { type AuthzDecisionReason } from './diagnostics.js';
|
|
3
5
|
import type { PermissionProvider } from './permission-provider.js';
|
|
4
6
|
import { PolicyRegistry } from './policy-registry.js';
|
|
5
7
|
import { type RoleProvider } from './role-provider.js';
|
|
8
|
+
import { type ScopeConstraint } from './scope.js';
|
|
6
9
|
import type { AuthzModuleOptions, GateFn, Resource, User } from './types.js';
|
|
7
10
|
declare const NO_USER: unique symbol;
|
|
8
11
|
type MaybeUser = User | typeof NO_USER;
|
|
12
|
+
/** A single item in a {@link Gate.allowsMany} batch. */
|
|
13
|
+
export interface BatchAbility {
|
|
14
|
+
ability: string;
|
|
15
|
+
resource?: Resource;
|
|
16
|
+
}
|
|
17
|
+
/** A single result from a {@link Gate.allowsMany} batch: the input plus its verdict. */
|
|
18
|
+
export interface BatchResult {
|
|
19
|
+
ability: string;
|
|
20
|
+
resource?: Resource;
|
|
21
|
+
allowed: boolean;
|
|
22
|
+
}
|
|
9
23
|
/**
|
|
10
24
|
* Laravel-style authorization Gate.
|
|
11
25
|
*
|
|
@@ -25,6 +39,7 @@ export declare class Gate {
|
|
|
25
39
|
private readonly roleProvider?;
|
|
26
40
|
private readonly gates;
|
|
27
41
|
private readonly superAdmin;
|
|
42
|
+
private readonly after;
|
|
28
43
|
private readonly resolveUser;
|
|
29
44
|
private readonly roleResolver;
|
|
30
45
|
private contextResolved;
|
|
@@ -52,6 +67,14 @@ export declare class Gate {
|
|
|
52
67
|
* provider registered by ANY module (e.g. the RBAC adapter's global module) is found.
|
|
53
68
|
*/
|
|
54
69
|
private resolveRoleProvider;
|
|
70
|
+
/**
|
|
71
|
+
* The per-request {@link PermissionCache}, stashed on the nestjs-context store so
|
|
72
|
+
* every check within one HTTP request shares a single `getPermissions` fetch
|
|
73
|
+
* (kills the N+1 a list page would otherwise cause). Returns `undefined` when no
|
|
74
|
+
* context store is available (standalone use), in which case callers fall back to
|
|
75
|
+
* a transient cache (e.g. one per `allowsMany` batch) or no memoization.
|
|
76
|
+
*/
|
|
77
|
+
private resolveRequestCache;
|
|
55
78
|
/** Register an ad-hoc, model-less gate resolved by `ability` name. */
|
|
56
79
|
define(ability: string, fn: GateFn): this;
|
|
57
80
|
/** True when an ad-hoc gate is registered for `ability`. */
|
|
@@ -82,14 +105,78 @@ export declare class Gate {
|
|
|
82
105
|
allows(ability: string, resource?: Resource): Promise<boolean>;
|
|
83
106
|
denies(ability: string, resource?: Resource): Promise<boolean>;
|
|
84
107
|
authorize(ability: string, resource?: Resource): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Authorize MANY abilities for the current (context) user in a single pass. The
|
|
110
|
+
* user is resolved ONCE and a single {@link PermissionCache} is shared across all
|
|
111
|
+
* items, so a list page (N cards) costs one user resolution + at most one
|
|
112
|
+
* permission fetch instead of N of each. Order is preserved; each result echoes
|
|
113
|
+
* its input `ability`/`resource` plus the `allowed` verdict.
|
|
114
|
+
*
|
|
115
|
+
* Fault-isolating: an item whose ability is unresolved/ambiguous denies just
|
|
116
|
+
* THAT item (it does not throw and abort the batch) — a batch is a best-effort
|
|
117
|
+
* verdict list, not an enforcement gate.
|
|
118
|
+
*/
|
|
119
|
+
allowsMany(items: BatchAbility[]): Promise<BatchResult[]>;
|
|
120
|
+
/**
|
|
121
|
+
* Resolve the QUERY SCOPE constraint for the current (context) user against
|
|
122
|
+
* `entity` — the `accessibleBy` / Pundit `policy_scope` concept. Returns an
|
|
123
|
+
* ORM-neutral {@link ScopeConstraint} an adapter (e.g. the TypeORM `applyScope`
|
|
124
|
+
* helper) turns into a parameterized `WHERE`.
|
|
125
|
+
*
|
|
126
|
+
* Consistent with the Gate's single-resource semantics:
|
|
127
|
+
* - super-admin / before-grant / permission-provider grant → `allow-all`,
|
|
128
|
+
* - anonymous, or no policy/scope → `deny-all` (default-deny),
|
|
129
|
+
* - otherwise the policy's `scope` (or `viewAny`-style) constraint.
|
|
130
|
+
*
|
|
131
|
+
* `ability` (default `'viewAny'`) names the permission-provider check used for
|
|
132
|
+
* the allow-all grant and the policy fallback method.
|
|
133
|
+
*/
|
|
134
|
+
scope(entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
|
|
85
135
|
/** True when the current user holds `role`. */
|
|
86
136
|
hasRole(role: string): Promise<boolean>;
|
|
87
137
|
/** True when the current user holds ANY of `roles`. */
|
|
88
138
|
hasAnyRole(roles: string[]): Promise<boolean>;
|
|
89
139
|
/** @internal */
|
|
90
140
|
allowsForUser(user: MaybeUser, ability: string, resource?: Resource): Promise<boolean>;
|
|
141
|
+
/** @internal — batch check for an explicit/bound user (see {@link allowsMany}). */
|
|
142
|
+
allowsManyForUser(user: MaybeUser, items: BatchAbility[]): Promise<BatchResult[]>;
|
|
143
|
+
/**
|
|
144
|
+
* Run a batch of checks against one already-resolved user, sharing a single
|
|
145
|
+
* {@link PermissionCache} so the provider's `getPermissions` runs at most once.
|
|
146
|
+
* Prefers the per-request cache (so the batch also coalesces with other checks in
|
|
147
|
+
* the same request); falls back to a transient per-batch cache when standalone.
|
|
148
|
+
*/
|
|
149
|
+
private checkMany;
|
|
150
|
+
/** @internal — used by {@link BoundGate.authorize} to surface the deny reason/message. */
|
|
151
|
+
decideForUser(user: MaybeUser, ability: string, resource?: Resource): Promise<{
|
|
152
|
+
allowed: boolean;
|
|
153
|
+
reason: AuthzDecisionReason;
|
|
154
|
+
message?: string;
|
|
155
|
+
}>;
|
|
91
156
|
/** @internal */
|
|
92
157
|
hasAnyRoleForUser(user: MaybeUser, roles: string[]): Promise<boolean>;
|
|
158
|
+
/** @internal — used by {@link BoundGate.scope}. */
|
|
159
|
+
scopeForUser(user: MaybeUser, entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
|
|
160
|
+
/**
|
|
161
|
+
* Resolve a query-scope constraint for `entity`, mirroring {@link resolveBase}'s
|
|
162
|
+
* grant order so scoping stays consistent with single-resource decisions:
|
|
163
|
+
*
|
|
164
|
+
* 1. super-admin hook grants → `allow-all`;
|
|
165
|
+
* 2. (authenticated) permission-provider grant for `ability` → `allow-all`;
|
|
166
|
+
* 3. the policy's `scope` (or `viewAny`-style) method → its constraint;
|
|
167
|
+
* 4. otherwise (anonymous, no policy, no scope method) → `deny-all`.
|
|
168
|
+
*
|
|
169
|
+
* The policy `before` hook is also honored as an allow/deny grant before the
|
|
170
|
+
* scope method runs, so a policy that broadly allows/denies in `before` scopes
|
|
171
|
+
* the same way it decides.
|
|
172
|
+
*/
|
|
173
|
+
private resolveScope;
|
|
174
|
+
/**
|
|
175
|
+
* Pick the policy's scope method: the conventional `scope`, else the `ability`
|
|
176
|
+
* method (e.g. `viewAny`) when it is scope-shaped. Returns `undefined` when the
|
|
177
|
+
* policy declares neither.
|
|
178
|
+
*/
|
|
179
|
+
private resolveScopeMethod;
|
|
93
180
|
/**
|
|
94
181
|
* Resolve the user's effective roles and test membership against `roles`. Returns
|
|
95
182
|
* `false` for an anonymous (NO_USER) caller and whenever no source yields a role
|
|
@@ -102,11 +189,26 @@ export declare class Gate {
|
|
|
102
189
|
private rolesOf;
|
|
103
190
|
private check;
|
|
104
191
|
/**
|
|
105
|
-
* Resolve
|
|
192
|
+
* Resolve a decision AND publish it for observers. Returns the full decision
|
|
193
|
+
* (verdict + reason + optional deny message) so {@link authorize} can surface the
|
|
194
|
+
* `reason`/`message` on the thrown `ForbiddenException`. {@link check} discards
|
|
195
|
+
* everything but the verdict.
|
|
196
|
+
*/
|
|
197
|
+
private decide;
|
|
198
|
+
/**
|
|
199
|
+
* Resolve an ability to a final verdict, the path that decided it, and an optional
|
|
200
|
+
* deny message. Runs the global `after` hook over the base decision (see
|
|
201
|
+
* {@link AfterHook} for override semantics). Throws
|
|
106
202
|
* {@link AbilityNotResolvedException}/{@link AmbiguousAbilityException} when no
|
|
107
|
-
* decision can be reached (those paths emit no decision).
|
|
203
|
+
* decision can be reached (those paths emit no decision and skip `after`).
|
|
108
204
|
*/
|
|
109
205
|
private resolve;
|
|
206
|
+
/**
|
|
207
|
+
* The pre-`after` resolution. `allowed` is `undefined` when the deciding path
|
|
208
|
+
* (policy method / ad-hoc gate) returned a nullish value — "no opinion" — which
|
|
209
|
+
* lets the {@link AfterHook} supply a verdict before the default-deny finalize.
|
|
210
|
+
*/
|
|
211
|
+
private resolveBase;
|
|
110
212
|
private resolvePolicy;
|
|
111
213
|
}
|
|
112
214
|
/**
|
|
@@ -118,6 +220,10 @@ export declare class BoundGate {
|
|
|
118
220
|
constructor(gate: Gate, user: MaybeUser);
|
|
119
221
|
allows(ability: string, resource?: Resource): Promise<boolean>;
|
|
120
222
|
denies(ability: string, resource?: Resource): Promise<boolean>;
|
|
223
|
+
/** Batch-authorize many abilities for the bound user in one pass (see {@link Gate.allowsMany}). */
|
|
224
|
+
allowsMany(items: BatchAbility[]): Promise<BatchResult[]>;
|
|
225
|
+
/** Resolve the query-scope constraint for the bound user (see {@link Gate.scope}). */
|
|
226
|
+
scope(entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
|
|
121
227
|
authorize(ability: string, resource?: Resource): Promise<void>;
|
|
122
228
|
/** True when the bound user holds `role`. */
|
|
123
229
|
hasRole(role: string): Promise<boolean>;
|
package/dist/gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
|