@dudousxd/nestjs-authz-inertia 0.1.3 → 0.2.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 +22 -0
- package/README.md +17 -12
- package/dist/authorize-resource.d.ts +2 -2
- package/dist/authorize-resource.d.ts.map +1 -1
- package/dist/authorize-resource.js.map +1 -1
- package/dist/authz-denial.filter.d.ts +2 -2
- package/dist/authz-denial.filter.d.ts.map +1 -1
- package/dist/authz-denial.filter.js +9 -5
- package/dist/authz-denial.filter.js.map +1 -1
- package/dist/authz-inertia.interceptor.d.ts +2 -2
- package/dist/authz-inertia.interceptor.d.ts.map +1 -1
- package/dist/authz-inertia.interceptor.js +4 -4
- package/dist/authz-inertia.interceptor.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/resolve-abilities.d.ts +13 -18
- package/dist/resolve-abilities.d.ts.map +1 -1
- package/dist/resolve-abilities.js +21 -27
- package/dist/resolve-abilities.js.map +1 -1
- package/dist/share.d.ts +2 -2
- package/dist/share.d.ts.map +1 -1
- package/dist/share.js.map +1 -1
- package/dist/types.d.ts +4 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +32 -31
- package/dist/client.d.ts +0 -10
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -9
- package/dist/client.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @dudousxd/nestjs-authz-inertia
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#67](https://github.com/DavideCarvalho/nestjs-authz/pull/67) [`32e967f`](https://github.com/DavideCarvalho/nestjs-authz/commit/32e967ffbcd68a97e8effc77af9c16bbbafdc918) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Share the class-level abilities of every official `@Policy()` (linked with `@PolicyFor` or not,
|
|
8
|
+
keyed `<resource>.<method>`), checked through the official `AuthorizationService` for the user
|
|
9
|
+
the official guard reads. `resolveClassAbilities` / `createAuthzShare` take a `PolicyIndex`
|
|
10
|
+
(was `PolicyRegistry`) and accept `gate.forUser(user)`. The denial filter also redirects the
|
|
11
|
+
official guard's 401 to `loginUrl`; without nestjs-context a 403 now goes to `forbiddenUrl`.
|
|
12
|
+
Requires `@dudousxd/nestjs-authz` 0.9, NestJS 12 and Node 22+.
|
|
13
|
+
|
|
14
|
+
**Removed:** the `@dudousxd/nestjs-authz-inertia/client` subpath, which only re-exported the
|
|
15
|
+
client package. Import `AbilityStore`, `createCan`, `hydrateFromInertiaProps` and
|
|
16
|
+
`hydrateResource` from `@dudousxd/nestjs-authz-client` directly.
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- [#67](https://github.com/DavideCarvalho/nestjs-authz/pull/67) [`32e967f`](https://github.com/DavideCarvalho/nestjs-authz/commit/32e967ffbcd68a97e8effc77af9c16bbbafdc918) Thanks [@DavideCarvalho](https://github.com/DavideCarvalho)! - Fix packages that could be published without files their `exports` point to. `tsc` builds no longer use a `.tsbuildinfo` that can outlive `dist/` and skip emitting files. A new `check:exports` step (also `prepack`) fails the release if any `exports`/`main`/`types` path is missing.
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`32e967f`](https://github.com/DavideCarvalho/nestjs-authz/commit/32e967ffbcd68a97e8effc77af9c16bbbafdc918)]:
|
|
23
|
+
- @dudousxd/nestjs-authz-client@0.2.2
|
|
24
|
+
|
|
3
25
|
## 0.1.3
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -17,8 +17,10 @@ Authorization decisions reach the front end through three tiers. Prefer the earl
|
|
|
17
17
|
|
|
18
18
|
### Tier 1 — Shared props (no request)
|
|
19
19
|
|
|
20
|
-
Every Inertia render carries the
|
|
21
|
-
|
|
20
|
+
Every Inertia render carries the user's **class-level abilities** (all ad-hoc gates + the
|
|
21
|
+
abilities of every official `@Policy()` that take no record, like `create`/`viewAny`) under
|
|
22
|
+
`props.auth.can`. The user is the one the official guard reads (`getUser`, default
|
|
23
|
+
`request.user`), and each check runs through the official `AuthorizationService`:
|
|
22
24
|
|
|
23
25
|
```jsonc
|
|
24
26
|
{ "auth": { "can": { "post.create": true, "access-admin": false } } }
|
|
@@ -32,7 +34,8 @@ interceptor shares the map on every Inertia request:
|
|
|
32
34
|
```ts
|
|
33
35
|
@Module({
|
|
34
36
|
imports: [
|
|
35
|
-
|
|
37
|
+
AuthorizationModule.forRoot(),
|
|
38
|
+
AuthzModule.forRoot(),
|
|
36
39
|
InertiaModule.forRoot({ /* ... */ }),
|
|
37
40
|
AuthzInertiaModule.forRoot(), // shares props.auth.can automatically
|
|
38
41
|
],
|
|
@@ -45,12 +48,13 @@ export class AppModule {}
|
|
|
45
48
|
|
|
46
49
|
```ts
|
|
47
50
|
InertiaModule.forRoot({
|
|
48
|
-
share: createAuthzShare(gate,
|
|
51
|
+
share: createAuthzShare(gate.forUser(user), policyIndex),
|
|
49
52
|
})
|
|
50
53
|
```
|
|
51
54
|
|
|
52
55
|
Both resolve abilities by direct in-process `gate.allows(...)` calls — no HTTP round-trip.
|
|
53
|
-
The ability name defaults to `"<resourceLower>.<method>"` (e.g. `post.create`)
|
|
56
|
+
The ability name defaults to `"<resourceLower>.<method>"` (e.g. `post.create`), where the
|
|
57
|
+
resource is the class linked with `@PolicyFor(Post)`, else the policy name without `Policy`; pass
|
|
54
58
|
`abilityNamer: (_, m) => m` for bare method names, or a custom `propKey`.
|
|
55
59
|
|
|
56
60
|
### Tier 2 — Per-resource `can` map (no request)
|
|
@@ -60,7 +64,7 @@ map onto the resource in your controller:
|
|
|
60
64
|
|
|
61
65
|
```ts
|
|
62
66
|
const post = await this.posts.find(id);
|
|
63
|
-
const can = await authorizeResource(this.gate, post, ['update', 'delete']);
|
|
67
|
+
const can = await authorizeResource(this.gate.forUser(user), post, ['update', 'delete']);
|
|
64
68
|
return this.inertia.render('Post/Show', { post: { ...post, can } });
|
|
65
69
|
// → { post: { id, title, can: { update: true, delete: false } } }
|
|
66
70
|
```
|
|
@@ -77,12 +81,13 @@ AuthzModule.forRoot({ canEndpoint: true }) // POST /authz/can → { allowed }
|
|
|
77
81
|
// or a custom path: canEndpoint: 'api/authz/can'
|
|
78
82
|
```
|
|
79
83
|
|
|
80
|
-
It runs `gate.allows(ability, resource?)` for the
|
|
84
|
+
It runs `gate.allows(ability, resource?)` for the caller (read the way the official guard
|
|
85
|
+
reads it) and returns
|
|
81
86
|
`{ allowed }`. Off by default. This is the path the codegen-emitted `can()` targets.
|
|
82
87
|
|
|
83
88
|
> **Class-level by default; per-instance with a loader.** Out of the box the endpoint resolves
|
|
84
89
|
> **class-level abilities and ad-hoc gates** only — the `{ type, id }` shim it receives never
|
|
85
|
-
> matches a `@
|
|
90
|
+
> matches a policy linked with `@PolicyFor` by constructor, so a **resource-bound** ability that misses the cache and
|
|
86
91
|
> falls through to `/authz/can` will **deny**. To make per-instance decisions resolve at tier 3,
|
|
87
92
|
> register `resourceLoaders` keyed by the resource `type`:
|
|
88
93
|
>
|
|
@@ -93,18 +98,18 @@ It runs `gate.allows(ability, resource?)` for the current context user and retur
|
|
|
93
98
|
> })
|
|
94
99
|
> ```
|
|
95
100
|
>
|
|
96
|
-
> The endpoint then loads the real entity before authorizing, so the
|
|
101
|
+
> The endpoint then loads the real entity before authorizing, so the linked policy matches
|
|
97
102
|
> and decides correctly (a loader returning nullish → deny / not found). Prefer hydrating via
|
|
98
103
|
> tiers 1-2 (shared props / `authorizeResource`) when you can; use `resourceLoaders` for the
|
|
99
104
|
> abilities that genuinely need a tier-3 round-trip.
|
|
100
105
|
|
|
101
106
|
## Client store (framework-neutral)
|
|
102
107
|
|
|
103
|
-
`@dudousxd/nestjs-authz-
|
|
104
|
-
framework dependency — `-react` and the codegen client reuse it.
|
|
108
|
+
The store lives in `@dudousxd/nestjs-authz-client`: a tiny in-memory store + resolver with no
|
|
109
|
+
framework dependency — `-react` and the codegen client reuse it. Install it next to this package.
|
|
105
110
|
|
|
106
111
|
```ts
|
|
107
|
-
import { AbilityStore, hydrateFromInertiaProps, hydrateResource, createCan } from '@dudousxd/nestjs-authz-
|
|
112
|
+
import { AbilityStore, hydrateFromInertiaProps, hydrateResource, createCan } from '@dudousxd/nestjs-authz-client';
|
|
108
113
|
|
|
109
114
|
const store = new AbilityStore();
|
|
110
115
|
hydrateFromInertiaProps(store, page.props); // tier 1: props.auth.can
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Gate, Resource } from '@dudousxd/nestjs-authz';
|
|
1
|
+
import type { BoundGate, Gate, Resource } from '@dudousxd/nestjs-authz';
|
|
2
2
|
import type { CanMap } from './resolve-abilities.js';
|
|
3
3
|
/**
|
|
4
4
|
* Resolve a per-INSTANCE `can` map for one resource, with NO HTTP round-trip:
|
|
@@ -18,7 +18,7 @@ import type { CanMap } from './resolve-abilities.js';
|
|
|
18
18
|
*
|
|
19
19
|
* @returns e.g. `{ update: true, delete: false }`
|
|
20
20
|
*/
|
|
21
|
-
export declare function authorizeResource(gate: Gate, resource: Resource, abilities: string[]): Promise<CanMap>;
|
|
21
|
+
export declare function authorizeResource(gate: Gate | BoundGate, resource: Resource, abilities: string[]): Promise<CanMap>;
|
|
22
22
|
/**
|
|
23
23
|
* Like {@link authorizeResource}, but resolves for an explicit user via
|
|
24
24
|
* `gate.forUser(user)` instead of the current context user. Useful outside a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorize-resource.d.ts","sourceRoot":"","sources":["../src/authorize-resource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"authorize-resource.d.ts","sourceRoot":"","sources":["../src/authorize-resource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,MAAM,CAAC,CAWjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorize-resource.js","sourceRoot":"","sources":["../src/authorize-resource.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,
|
|
1
|
+
{"version":3,"file":"authorize-resource.js","sourceRoot":"","sources":["../src/authorize-resource.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAsB,EACtB,QAAkB,EAClB,SAAmB;IAEnB,MAAM,GAAG,GAAW,EAAE,CAAC;IACvB,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,IAAU,EACV,IAAa,EACb,QAAkB,EAClB,SAAmB;IAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,GAAG,GAAW,EAAE,CAAC;IACvB,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ContextAccessor } from '@dudousxd/nestjs-authz';
|
|
2
|
-
import { type ArgumentsHost, type ExceptionFilter, ForbiddenException } from '@nestjs/common';
|
|
2
|
+
import { type ArgumentsHost, type ExceptionFilter, ForbiddenException, UnauthorizedException } from '@nestjs/common';
|
|
3
3
|
import type { AuthzInertiaOptions } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Default redirect target for an UNAUTHENTICATED Inertia denial.
|
|
@@ -32,7 +32,7 @@ export declare class AuthzDenialFilter implements ExceptionFilter {
|
|
|
32
32
|
private readonly options;
|
|
33
33
|
private readonly context?;
|
|
34
34
|
constructor(options?: AuthzInertiaOptions, context?: ContextAccessor | undefined);
|
|
35
|
-
catch(exception: ForbiddenException, host: ArgumentsHost): void;
|
|
35
|
+
catch(exception: ForbiddenException | UnauthorizedException, host: ArgumentsHost): void;
|
|
36
36
|
/**
|
|
37
37
|
* Pick the redirect target from auth-state. An undefined `userRef()` (or no
|
|
38
38
|
* context accessor at all) is treated as unauthenticated.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-denial.filter.d.ts","sourceRoot":"","sources":["../src/authz-denial.filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EACL,KAAK,aAAa,EAElB,KAAK,eAAe,EACpB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"authz-denial.filter.d.ts","sourceRoot":"","sources":["../src/authz-denial.filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EACL,KAAK,aAAa,EAElB,KAAK,eAAe,EACpB,kBAAkB,EAIlB,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAsB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E;;GAEG;AACH,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,qBAAqB,SAAS,CAAC;AAE5C;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBACa,iBAAkB,YAAW,eAAe;IAIrD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAGxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAHR,OAAO,GAAE,mBAAwB,EAGjC,OAAO,CAAC,EAAE,eAAe,YAAA;IAG5C,KAAK,CAAC,SAAS,EAAE,kBAAkB,GAAG,qBAAqB,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;IA2BvF;;;OAGG;IACH,OAAO,CAAC,qBAAqB;CAY9B"}
|
|
@@ -11,7 +11,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
import { CONTEXT_ACCESSOR } from '@dudousxd/nestjs-authz';
|
|
14
|
-
import { Catch, ForbiddenException, Inject, Optional, } from '@nestjs/common';
|
|
14
|
+
import { Catch, ForbiddenException, Inject, Optional, UnauthorizedException, } from '@nestjs/common';
|
|
15
15
|
import { AUTHZ_INERTIA_OPTIONS } from './tokens.js';
|
|
16
16
|
/**
|
|
17
17
|
* Default redirect target for an UNAUTHENTICATED Inertia denial.
|
|
@@ -65,23 +65,27 @@ let AuthzDenialFilter = class AuthzDenialFilter {
|
|
|
65
65
|
denial.handler(exception, host);
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
|
-
const target = this.resolveRedirectTarget(denial);
|
|
68
|
+
const target = this.resolveRedirectTarget(denial, exception);
|
|
69
69
|
sendRedirect(res, 303, target);
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
72
|
* Pick the redirect target from auth-state. An undefined `userRef()` (or no
|
|
73
73
|
* context accessor at all) is treated as unauthenticated.
|
|
74
74
|
*/
|
|
75
|
-
resolveRedirectTarget(denial) {
|
|
75
|
+
resolveRedirectTarget(denial, exception) {
|
|
76
76
|
const loginUrl = denial.loginUrl ?? DEFAULT_LOGIN_URL;
|
|
77
77
|
const forbiddenUrl = denial.forbiddenUrl ?? DEFAULT_FORBIDDEN_URL;
|
|
78
|
-
|
|
78
|
+
// The official guard answers a guest with a 401 and a signed-in user with a 403. A
|
|
79
|
+
// 403 for a guest (a `byId()` miss, a custom guard) still goes to the login page when
|
|
80
|
+
// nestjs-context says nobody is signed in.
|
|
81
|
+
const authenticated = !(exception instanceof UnauthorizedException) &&
|
|
82
|
+
(this.context === undefined || this.context.userRef() !== undefined);
|
|
79
83
|
const target = authenticated ? forbiddenUrl : loginUrl;
|
|
80
84
|
return toSafePath(target, authenticated ? DEFAULT_FORBIDDEN_URL : DEFAULT_LOGIN_URL);
|
|
81
85
|
}
|
|
82
86
|
};
|
|
83
87
|
AuthzDenialFilter = __decorate([
|
|
84
|
-
Catch(ForbiddenException),
|
|
88
|
+
Catch(ForbiddenException, UnauthorizedException),
|
|
85
89
|
__param(0, Optional()),
|
|
86
90
|
__param(0, Inject(AUTHZ_INERTIA_OPTIONS)),
|
|
87
91
|
__param(1, Optional()),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-denial.filter.js","sourceRoot":"","sources":["../src/authz-denial.filter.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,gBAAgB,EAAwB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAEL,KAAK,EAEL,kBAAkB,
|
|
1
|
+
{"version":3,"file":"authz-denial.filter.js","sourceRoot":"","sources":["../src/authz-denial.filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Gate,
|
|
1
|
+
import { Gate, PolicyIndex } from '@dudousxd/nestjs-authz';
|
|
2
2
|
import { type CallHandler, type ExecutionContext, type NestInterceptor } from '@nestjs/common';
|
|
3
3
|
import type { Observable } from 'rxjs';
|
|
4
4
|
import type { AuthzInertiaOptions } from './types.js';
|
|
@@ -15,7 +15,7 @@ export declare class AuthzInertiaInterceptor implements NestInterceptor {
|
|
|
15
15
|
private readonly policies;
|
|
16
16
|
private readonly options;
|
|
17
17
|
private readonly propKey;
|
|
18
|
-
constructor(gate: Gate, policies:
|
|
18
|
+
constructor(gate: Gate, policies: PolicyIndex, options?: AuthzInertiaOptions);
|
|
19
19
|
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
20
20
|
}
|
|
21
21
|
//# sourceMappingURL=authz-inertia.interceptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-inertia.interceptor.d.ts","sourceRoot":"","sources":["../src/authz-inertia.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"authz-inertia.interceptor.d.ts","sourceRoot":"","sources":["../src/authz-inertia.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAiB,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EAGrB,KAAK,eAAe,EAErB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAKvC,OAAO,KAAK,EAAE,mBAAmB,EAAsB,MAAM,YAAY,CAAC;AAE1E;;;;;;;GAOG;AACH,qBACa,uBAAwB,YAAW,eAAe;IAI3D,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAGzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAP1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGd,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,WAAW,EAGrB,OAAO,GAAE,mBAAwB;IAKpD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;CAyB7E"}
|
|
@@ -10,7 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
|
-
import { Gate,
|
|
13
|
+
import { Gate, PolicyIndex, currentUserOf } from '@dudousxd/nestjs-authz';
|
|
14
14
|
import { Inject, Injectable, Optional, } from '@nestjs/common';
|
|
15
15
|
import { from, switchMap } from 'rxjs';
|
|
16
16
|
import { resolveClassAbilities } from './resolve-abilities.js';
|
|
@@ -42,7 +42,7 @@ let AuthzInertiaInterceptor = class AuthzInertiaInterceptor {
|
|
|
42
42
|
const inertia = req?.inertia;
|
|
43
43
|
if (!inertia || typeof inertia.share !== 'function')
|
|
44
44
|
return next.handle();
|
|
45
|
-
return from(resolveClassAbilities(this.gate, this.policies, {
|
|
45
|
+
return from(currentUserOf(context).then((user) => resolveClassAbilities(this.gate.forUser(user), this.policies, {
|
|
46
46
|
...(this.options.abilities !== undefined ? { abilities: this.options.abilities } : {}),
|
|
47
47
|
...(this.options.abilityNamer !== undefined
|
|
48
48
|
? { abilityNamer: this.options.abilityNamer }
|
|
@@ -50,7 +50,7 @@ let AuthzInertiaInterceptor = class AuthzInertiaInterceptor {
|
|
|
50
50
|
...(this.options.includeBareMethodNames !== undefined
|
|
51
51
|
? { includeBareMethodNames: this.options.includeBareMethodNames }
|
|
52
52
|
: {}),
|
|
53
|
-
})).pipe(switchMap((can) => {
|
|
53
|
+
}))).pipe(switchMap((can) => {
|
|
54
54
|
inertia.share({ [this.propKey]: { can } });
|
|
55
55
|
return next.handle();
|
|
56
56
|
}));
|
|
@@ -61,7 +61,7 @@ AuthzInertiaInterceptor = __decorate([
|
|
|
61
61
|
__param(2, Optional()),
|
|
62
62
|
__param(2, Inject(AUTHZ_INERTIA_OPTIONS)),
|
|
63
63
|
__metadata("design:paramtypes", [Gate,
|
|
64
|
-
|
|
64
|
+
PolicyIndex, Object])
|
|
65
65
|
], AuthzInertiaInterceptor);
|
|
66
66
|
export { AuthzInertiaInterceptor };
|
|
67
67
|
//# sourceMappingURL=authz-inertia.interceptor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-inertia.interceptor.js","sourceRoot":"","sources":["../src/authz-inertia.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"authz-inertia.interceptor.js","sourceRoot":"","sources":["../src/authz-inertia.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAGL,MAAM,EACN,UAAU,EAEV,QAAQ,GACT,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGpD;;;;;;;GAOG;AAEI,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAIf;IACA;IAGA;IAPF,OAAO,CAAS;IAEjC,YACmB,IAAU,EACV,QAAqB,EAGrB,UAA+B,EAAE;QAJjC,SAAI,GAAJ,IAAI,CAAM;QACV,aAAQ,GAAR,QAAQ,CAAa;QAGrB,YAAO,GAAP,OAAO,CAA0B;QAElD,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,gBAAgB,CAAC;IACtD,CAAC;IAED,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,IAAI,OAAO,CAAC,OAAO,EAAE,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvD,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAsB,CAAC;QACpE,MAAM,OAAO,GAAG,GAAG,EAAE,OAAO,CAAC;QAC7B,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QAE1E,OAAO,IAAI,CACT,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACnC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE;YAC5D,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS;gBACzC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;gBAC7C,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,KAAK,SAAS;gBACnD,CAAC,CAAC,EAAE,sBAAsB,EAAE,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE;gBACjE,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CACH,CACF,CAAC,IAAI,CACJ,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;YAChB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;CACF,CAAA;AAtCY,uBAAuB;IADnC,UAAU,EAAE;IAOR,WAAA,QAAQ,EAAE,CAAA;IACV,WAAA,MAAM,CAAC,qBAAqB,CAAC,CAAA;qCAHP,IAAI;QACA,WAAW;GAL7B,uBAAuB,CAsCnC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.2.0";
|
|
2
2
|
export { AuthzInertiaModule } from './module.js';
|
|
3
3
|
export { AuthzInertiaInterceptor } from './authz-inertia.interceptor.js';
|
|
4
4
|
export { AuthzDenialFilter, DEFAULT_LOGIN_URL, DEFAULT_FORBIDDEN_URL, } from './authz-denial.filter.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.2.0';
|
|
2
2
|
export { AuthzInertiaModule } from './module.js';
|
|
3
3
|
export { AuthzInertiaInterceptor } from './authz-inertia.interceptor.js';
|
|
4
4
|
export { AuthzDenialFilter, DEFAULT_LOGIN_URL, DEFAULT_FORBIDDEN_URL, } from './authz-denial.filter.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Gate,
|
|
1
|
+
import type { BoundGate, Gate, PolicyIndex } from '@dudousxd/nestjs-authz';
|
|
2
2
|
import type { CanMap } from '@dudousxd/nestjs-authz-client';
|
|
3
3
|
/**
|
|
4
4
|
* A flat record of `ability -> verdict`, e.g. `{ 'posts.create': true }`.
|
|
@@ -7,10 +7,10 @@ import type { CanMap } from '@dudousxd/nestjs-authz-client';
|
|
|
7
7
|
*/
|
|
8
8
|
export type { CanMap };
|
|
9
9
|
/**
|
|
10
|
-
* How an ability
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* How an ability key is built from a policy's resource name and method name when
|
|
11
|
+
* listing class-level abilities. The resource name is the class linked with
|
|
12
|
+
* `@PolicyFor(Resource)`, else the policy class name without `Policy` (`PostPolicy` →
|
|
13
|
+
* `Post`).
|
|
14
14
|
*/
|
|
15
15
|
export type AbilityNamer = (resourceName: string, method: string) => string;
|
|
16
16
|
/**
|
|
@@ -38,21 +38,16 @@ export interface ResolveAbilitiesOptions {
|
|
|
38
38
|
includeBareMethodNames?: boolean;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* Resolve
|
|
42
|
-
*
|
|
43
|
-
* call against the in-process Gate.
|
|
41
|
+
* Resolve a user's CLASS-LEVEL abilities into a flat `{ ability: boolean }` map, with no
|
|
42
|
+
* HTTP round-trip. Pass `gate.forUser(user)`; a bare `Gate` checks its ambient user.
|
|
44
43
|
*
|
|
45
44
|
* Sources, in order:
|
|
46
|
-
* 1. Ad-hoc gates registered
|
|
47
|
-
* 2.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* class would write a bogus class-level verdict.
|
|
45
|
+
* 1. Ad-hoc gates registered with `gate.define(...)`.
|
|
46
|
+
* 2. The abilities of every official `@Policy()` that take no argument after the user
|
|
47
|
+
* (`create(user)`, `viewAny(user)`), checked through the official
|
|
48
|
+
* `AuthorizationService` (so each policy's `before()` applies). Abilities that take a
|
|
49
|
+
* record (`update(user, post)`) are per-instance: share them with `authorizeResource`.
|
|
52
50
|
* 3. Any extra `options.abilities` names.
|
|
53
|
-
*
|
|
54
|
-
* Gates are checked by name; policy methods are checked by passing the resource
|
|
55
|
-
* class as the dispatch target (Gate resolves the class-level policy method).
|
|
56
51
|
*/
|
|
57
|
-
export declare function resolveClassAbilities(gate: Gate, policies:
|
|
52
|
+
export declare function resolveClassAbilities(gate: Gate | BoundGate, policies: PolicyIndex, options?: ResolveAbilitiesOptions): Promise<CanMap>;
|
|
58
53
|
//# sourceMappingURL=resolve-abilities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-abilities.d.ts","sourceRoot":"","sources":["../src/resolve-abilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"resolve-abilities.d.ts","sourceRoot":"","sources":["../src/resolve-abilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAG5D;;;;GAIG;AACH,YAAY,EAAE,MAAM,EAAE,CAAC;AAEvB;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,YACS,CAAC;AAE5C,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,MAAM,CAAC,CA0BjB"}
|
|
@@ -5,37 +5,29 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export const defaultAbilityNamer = (resourceName, method) => `${resourceName.toLowerCase()}.${method}`;
|
|
7
7
|
/**
|
|
8
|
-
* Resolve
|
|
9
|
-
*
|
|
10
|
-
* call against the in-process Gate.
|
|
8
|
+
* Resolve a user's CLASS-LEVEL abilities into a flat `{ ability: boolean }` map, with no
|
|
9
|
+
* HTTP round-trip. Pass `gate.forUser(user)`; a bare `Gate` checks its ambient user.
|
|
11
10
|
*
|
|
12
11
|
* Sources, in order:
|
|
13
|
-
* 1. Ad-hoc gates registered
|
|
14
|
-
* 2.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* class would write a bogus class-level verdict.
|
|
12
|
+
* 1. Ad-hoc gates registered with `gate.define(...)`.
|
|
13
|
+
* 2. The abilities of every official `@Policy()` that take no argument after the user
|
|
14
|
+
* (`create(user)`, `viewAny(user)`), checked through the official
|
|
15
|
+
* `AuthorizationService` (so each policy's `before()` applies). Abilities that take a
|
|
16
|
+
* record (`update(user, post)`) are per-instance: share them with `authorizeResource`.
|
|
19
17
|
* 3. Any extra `options.abilities` names.
|
|
20
|
-
*
|
|
21
|
-
* Gates are checked by name; policy methods are checked by passing the resource
|
|
22
|
-
* class as the dispatch target (Gate resolves the class-level policy method).
|
|
23
18
|
*/
|
|
24
19
|
export async function resolveClassAbilities(gate, policies, options = {}) {
|
|
25
20
|
const namer = options.abilityNamer ?? defaultAbilityNamer;
|
|
26
21
|
const out = {};
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
out[ability] = await safeAllows(gate, ability);
|
|
22
|
+
const names = new Set([...gateNamesOf(gate), ...(options.abilities ?? [])]);
|
|
23
|
+
for (const ability of names) {
|
|
24
|
+
out[ability] = await safely(() => gate.allows(ability));
|
|
31
25
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const resourceName = resource.name ?? 'Resource';
|
|
26
|
+
for (const { policy, resource, abilities } of policies.classAbilities()) {
|
|
27
|
+
const resourceName = resource?.name ?? policy.name.replace(/Policy$/, '');
|
|
35
28
|
for (const method of abilities) {
|
|
36
29
|
const key = namer(resourceName, method);
|
|
37
|
-
|
|
38
|
-
out[key] = await safeAllows(gate, method, resource);
|
|
30
|
+
out[key] = await safely(() => gate.allows.call(gate, policy, method));
|
|
39
31
|
if (options.includeBareMethodNames && out[method] === undefined) {
|
|
40
32
|
out[method] = out[key];
|
|
41
33
|
}
|
|
@@ -43,13 +35,15 @@ export async function resolveClassAbilities(gate, policies, options = {}) {
|
|
|
43
35
|
}
|
|
44
36
|
return out;
|
|
45
37
|
}
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
38
|
+
/** The ad-hoc gate names, from a `Gate` or the `Gate` behind a `BoundGate`. */
|
|
39
|
+
function gateNamesOf(gate) {
|
|
40
|
+
const owner = gate.gate ?? gate;
|
|
41
|
+
return typeof owner.gateNames === 'function' ? owner.gateNames() : [];
|
|
42
|
+
}
|
|
43
|
+
/** A check that throws (unresolved ability, unregistered policy) shares `false`. */
|
|
44
|
+
async function safely(check) {
|
|
51
45
|
try {
|
|
52
|
-
return await
|
|
46
|
+
return await check();
|
|
53
47
|
}
|
|
54
48
|
catch {
|
|
55
49
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-abilities.js","sourceRoot":"","sources":["../src/resolve-abilities.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolve-abilities.js","sourceRoot":"","sources":["../src/resolve-abilities.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,CACxE,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,MAAM,EAAE,CAAC;AAqB5C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAsB,EACtB,QAAqB,EACrB,UAAmC,EAAE;IAErC,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,IAAI,mBAAmB,CAAC;IAC1D,MAAM,GAAG,GAAW,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpF,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;QAC5B,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC;QACxE,MAAM,YAAY,GAAG,QAAQ,EAAE,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC1E,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YACxC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC,GAAG,EAAE,CAC1B,IAAI,CAAC,MAA4D,CAAC,IAAI,CACrE,IAAI,EACJ,MAAM,EACN,MAAM,CACP,CACF,CAAC;YACF,IAAI,OAAO,CAAC,sBAAsB,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;gBAChE,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+EAA+E;AAC/E,SAAS,WAAW,CAAC,IAAsB;IACzC,MAAM,KAAK,GAAI,IAAmC,CAAC,IAAI,IAAK,IAAa,CAAC;IAC1E,OAAO,OAAO,KAAK,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,oFAAoF;AACpF,KAAK,UAAU,MAAM,CAAC,KAA6B;IACjD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/share.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Gate,
|
|
1
|
+
import type { BoundGate, Gate, PolicyIndex } from '@dudousxd/nestjs-authz';
|
|
2
2
|
import { type ResolveAbilitiesOptions } from './resolve-abilities.js';
|
|
3
3
|
/** Default prop namespace: `props.auth.can`. */
|
|
4
4
|
export declare const DEFAULT_PROP_KEY = "auth";
|
|
@@ -24,5 +24,5 @@ export interface CreateAuthzShareOptions extends ResolveAbilitiesOptions {
|
|
|
24
24
|
* render and merges the result into every page's shared props. The client store's
|
|
25
25
|
* `hydrateFromInertiaProps` then reads `props.auth.can`.
|
|
26
26
|
*/
|
|
27
|
-
export declare function createAuthzShare(gate: Gate, policies:
|
|
27
|
+
export declare function createAuthzShare(gate: Gate | BoundGate, policies: PolicyIndex, options?: CreateAuthzShareOptions): () => Promise<Record<string, unknown>>;
|
|
28
28
|
//# sourceMappingURL=share.d.ts.map
|
package/dist/share.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"share.d.ts","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,KAAK,uBAAuB,EAAyB,MAAM,wBAAwB,CAAC;AAE7F,gDAAgD;AAChD,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,uBAA4B,GACpC,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAMxC"}
|
package/dist/share.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share.js","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,gDAAgD;AAChD,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAOvC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,
|
|
1
|
+
{"version":3,"file":"share.js","sourceRoot":"","sources":["../src/share.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,gDAAgD;AAChD,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAOvC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAsB,EACtB,QAAqB,EACrB,UAAmC,EAAE;IAErC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACpD,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,GAAG,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;IAChC,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ArgumentsHost, ForbiddenException } from '@nestjs/common';
|
|
1
|
+
import type { ArgumentsHost, ForbiddenException, UnauthorizedException } from '@nestjs/common';
|
|
2
2
|
import type { AbilityNamer, CanMap } from './resolve-abilities.js';
|
|
3
3
|
/**
|
|
4
4
|
* Configures the {@link AuthzDenialFilter}: how authorization denials
|
|
5
|
-
* (
|
|
5
|
+
* (the official guard's `UnauthorizedException` / `ForbiddenException`) render on Inertia requests. Non-Inertia
|
|
6
6
|
* (REST) requests are unaffected — they keep the normal 403 JSON.
|
|
7
7
|
*/
|
|
8
8
|
export interface AuthzDenialOptions {
|
|
@@ -14,7 +14,7 @@ export interface AuthzDenialOptions {
|
|
|
14
14
|
*/
|
|
15
15
|
enabled?: boolean;
|
|
16
16
|
/**
|
|
17
|
-
* Redirect target for an UNAUTHENTICATED denial (no
|
|
17
|
+
* Redirect target for an UNAUTHENTICATED denial (a 401, or a 403 while nestjs-context has no user).
|
|
18
18
|
*
|
|
19
19
|
* Default: `'/login'`.
|
|
20
20
|
*/
|
|
@@ -31,7 +31,7 @@ export interface AuthzDenialOptions {
|
|
|
31
31
|
* `ForbiddenException` and the `ArgumentsHost`. When provided, it replaces the
|
|
32
32
|
* default redirect behavior for Inertia requests.
|
|
33
33
|
*/
|
|
34
|
-
handler?: (exception: ForbiddenException, host: ArgumentsHost) => void;
|
|
34
|
+
handler?: (exception: ForbiddenException | UnauthorizedException, host: ArgumentsHost) => void;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Minimal structural mirror of the request object carrying `req.inertia`, set by
|
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,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,kBAAkB,GAAG,qBAAqB,EAAE,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CAChG;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;CAChD;AAED,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-authz-inertia",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Inertia.js integration for @dudousxd/nestjs-authz — share a user's abilities as props so client `can()` checks need no network request.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -8,6 +8,19 @@
|
|
|
8
8
|
"url": "git+https://github.com/DavideCarvalho/nestjs-authz.git",
|
|
9
9
|
"directory": "packages/inertia"
|
|
10
10
|
},
|
|
11
|
+
"homepage": "https://davidecarvalho.github.io/aviary/docs/authz",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/DavideCarvalho/nestjs-authz/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"nestjs",
|
|
17
|
+
"authorization",
|
|
18
|
+
"authz",
|
|
19
|
+
"inertia",
|
|
20
|
+
"inertia.js",
|
|
21
|
+
"abilities",
|
|
22
|
+
"can"
|
|
23
|
+
],
|
|
11
24
|
"author": "Davi Carvalho <davi@goflip.ai>",
|
|
12
25
|
"type": "module",
|
|
13
26
|
"main": "./dist/index.js",
|
|
@@ -17,11 +30,6 @@
|
|
|
17
30
|
"types": "./dist/index.d.ts",
|
|
18
31
|
"import": "./dist/index.js",
|
|
19
32
|
"default": "./dist/index.js"
|
|
20
|
-
},
|
|
21
|
-
"./client": {
|
|
22
|
-
"types": "./dist/client.d.ts",
|
|
23
|
-
"import": "./dist/client.js",
|
|
24
|
-
"default": "./dist/client.js"
|
|
25
33
|
}
|
|
26
34
|
},
|
|
27
35
|
"files": [
|
|
@@ -30,14 +38,15 @@
|
|
|
30
38
|
"CHANGELOG.md"
|
|
31
39
|
],
|
|
32
40
|
"dependencies": {
|
|
33
|
-
"@dudousxd/nestjs-authz-client": "^0.2.
|
|
41
|
+
"@dudousxd/nestjs-authz-client": "^0.2.2"
|
|
34
42
|
},
|
|
35
43
|
"peerDependencies": {
|
|
36
|
-
"@dudousxd/nestjs-authz": ">=0.
|
|
44
|
+
"@dudousxd/nestjs-authz": ">=0.9.0 <0.10.0",
|
|
37
45
|
"@dudousxd/nestjs-context": ">=0.1.0",
|
|
38
46
|
"@dudousxd/nestjs-inertia": ">=1.0.0",
|
|
39
|
-
"@nestjs/
|
|
40
|
-
"@nestjs/
|
|
47
|
+
"@nestjs/authorization": "^0.1.3",
|
|
48
|
+
"@nestjs/common": "^12.0.0",
|
|
49
|
+
"@nestjs/core": "^12.0.0",
|
|
41
50
|
"reflect-metadata": ">=0.1.13"
|
|
42
51
|
},
|
|
43
52
|
"peerDependenciesMeta": {
|
|
@@ -46,31 +55,23 @@
|
|
|
46
55
|
}
|
|
47
56
|
},
|
|
48
57
|
"devDependencies": {
|
|
49
|
-
"@dudousxd/nestjs-inertia": "
|
|
50
|
-
"@nestjs/
|
|
51
|
-
"@nestjs/
|
|
52
|
-
"@nestjs/
|
|
53
|
-
"@
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
58
|
+
"@dudousxd/nestjs-inertia": "1.8.2",
|
|
59
|
+
"@nestjs/authorization": "0.1.3",
|
|
60
|
+
"@nestjs/common": "12.0.1",
|
|
61
|
+
"@nestjs/core": "12.0.1",
|
|
62
|
+
"@nestjs/testing": "12.0.1",
|
|
63
|
+
"@types/node": "22.20.5",
|
|
64
|
+
"reflect-metadata": "0.2.2",
|
|
65
|
+
"rxjs": "7.8.2",
|
|
66
|
+
"typescript": "5.9.3",
|
|
67
|
+
"vitest": "3.2.7",
|
|
68
|
+
"@dudousxd/nestjs-authz": "^0.9.1"
|
|
59
69
|
},
|
|
60
70
|
"engines": {
|
|
61
|
-
"node": ">=
|
|
71
|
+
"node": ">=22"
|
|
62
72
|
},
|
|
63
|
-
"keywords": [
|
|
64
|
-
"nestjs",
|
|
65
|
-
"authorization",
|
|
66
|
-
"authz",
|
|
67
|
-
"inertia",
|
|
68
|
-
"inertia.js",
|
|
69
|
-
"abilities",
|
|
70
|
-
"can"
|
|
71
|
-
],
|
|
72
73
|
"scripts": {
|
|
73
|
-
"build": "tsc -p tsconfig.json",
|
|
74
|
+
"build": "tsc -p tsconfig.json --incremental false",
|
|
74
75
|
"test": "vitest run --passWithNoTests",
|
|
75
76
|
"test:watch": "vitest",
|
|
76
77
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
package/dist/client.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Re-export of the framework-neutral ability store, now canonicalized in
|
|
3
|
-
* {@link @dudousxd/nestjs-authz-client}. Kept here so the long-standing
|
|
4
|
-
* `@dudousxd/nestjs-authz-inertia/client` entry point continues to work.
|
|
5
|
-
*
|
|
6
|
-
* @module client
|
|
7
|
-
*/
|
|
8
|
-
export { AbilityStore, createCan, hydrateFromInertiaProps, hydrateResource, } from '@dudousxd/nestjs-authz-client';
|
|
9
|
-
export type { CanMap, ResourceRef, HydratableProps, FallbackMode, AbilityStoreOptions, CanResolver, } from '@dudousxd/nestjs-authz-client';
|
|
10
|
-
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,SAAS,EACT,uBAAuB,EACvB,eAAe,GAChB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,MAAM,EACN,WAAW,EACX,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,WAAW,GACZ,MAAM,+BAA+B,CAAC"}
|
package/dist/client.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Re-export of the framework-neutral ability store, now canonicalized in
|
|
3
|
-
* {@link @dudousxd/nestjs-authz-client}. Kept here so the long-standing
|
|
4
|
-
* `@dudousxd/nestjs-authz-inertia/client` entry point continues to work.
|
|
5
|
-
*
|
|
6
|
-
* @module client
|
|
7
|
-
*/
|
|
8
|
-
export { AbilityStore, createCan, hydrateFromInertiaProps, hydrateResource, } from '@dudousxd/nestjs-authz-client';
|
|
9
|
-
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,YAAY,EACZ,SAAS,EACT,uBAAuB,EACvB,eAAe,GAChB,MAAM,+BAA+B,CAAC"}
|