@dudousxd/nestjs-authz-prisma 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/dist/authz-rbac.module.d.ts +1 -1
- package/dist/authz-rbac.module.d.ts.map +1 -1
- package/dist/authz-rbac.module.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/prisma-authz.store.d.ts +23 -10
- package/dist/prisma-authz.store.d.ts.map +1 -1
- package/dist/prisma-authz.store.js +44 -8
- package/dist/prisma-authz.store.js.map +1 -1
- package/dist/prisma-client.d.ts +38 -0
- package/dist/prisma-client.d.ts.map +1 -1
- package/dist/prisma-client.js +24 -0
- package/dist/prisma-client.js.map +1 -1
- package/dist/scope.d.ts +54 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +96 -0
- package/dist/scope.js.map +1 -0
- package/package.json +6 -2
- package/dist/types.d.ts +0 -11
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
# @dudousxd/nestjs-authz-prisma
|
|
2
2
|
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`61b6b92`](https://github.com/DavideCarvalho/nestjs-authz/commit/61b6b9241438b8f30811fcd17b0c0c98f08af3bf) - Internal refactors (behavior-preserving): single-source the ORM store contract (`UserRef`/`UserRefInput`/`UserAuthz`/`normalizeUserRef`) via a new `@dudousxd/nestjs-authz/store-kit` subpath that the typeorm/prisma/mikro-orm adapters re-export under their public names, so the definition can't drift across them. Also single-source the grant preamble and the SQL identifier guard in the core store path.
|
|
8
|
+
|
|
9
|
+
## 0.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#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.
|
|
14
|
+
|
|
15
|
+
### Permissions
|
|
16
|
+
|
|
17
|
+
- **Wildcard / hierarchical permissions.** Permission strings now support wildcard
|
|
18
|
+
and hierarchical matching (e.g. `posts:*` or `posts:read:*`), so a single granted
|
|
19
|
+
permission can authorize a family of related actions instead of enumerating each one.
|
|
20
|
+
|
|
21
|
+
### Authorization decisions
|
|
22
|
+
|
|
23
|
+
- **Deny reason / message surfaced on `ForbiddenException`.** When a check fails, the
|
|
24
|
+
reason for the denial is propagated onto the thrown `ForbiddenException`, making it
|
|
25
|
+
possible to return a meaningful message to the caller and to debug authorization
|
|
26
|
+
failures.
|
|
27
|
+
- **Gate `after` hook.** The Gate now exposes an `after` hook that runs once a decision
|
|
28
|
+
has been made, enabling cross-cutting concerns such as auditing, logging, and metrics.
|
|
29
|
+
|
|
30
|
+
### Batch authorization
|
|
31
|
+
|
|
32
|
+
- **`allowsMany`** for evaluating multiple permission checks in a single call.
|
|
33
|
+
- **Batch `/authz/can` endpoint** so clients can resolve many checks in one round trip.
|
|
34
|
+
- **`createCanBatch`** client helper that batches `can` calls transparently.
|
|
35
|
+
|
|
36
|
+
### Performance
|
|
37
|
+
|
|
38
|
+
- **Request-scoped permission cache.** Permissions resolved during a request are cached
|
|
39
|
+
for the lifetime of that request, avoiding repeated lookups on the hot path.
|
|
40
|
+
|
|
41
|
+
### RBAC adapters (TypeORM)
|
|
42
|
+
|
|
43
|
+
- **Direct user permissions** granted to a user independent of their roles.
|
|
44
|
+
- **Tenant-scoped roles** so the same role can be assigned per tenant in multi-tenant
|
|
45
|
+
deployments.
|
|
46
|
+
|
|
47
|
+
### Query scoping / policy filter (ABAC)
|
|
48
|
+
|
|
49
|
+
- **ORM-neutral constraint AST.** Policies can produce a portable constraint
|
|
50
|
+
representation describing which rows a subject may access.
|
|
51
|
+
- **Per-ORM application.** The constraint AST is translated and applied for
|
|
52
|
+
**TypeORM**, **MikroORM**, and **Prisma**, giving ABAC-style query scoping that
|
|
53
|
+
filters data at the database layer regardless of the ORM in use.
|
|
54
|
+
|
|
55
|
+
### Testing
|
|
56
|
+
|
|
57
|
+
- **New `@dudousxd/nestjs-authz-testing` package** with fakes and helpers for testing
|
|
58
|
+
authorization in consumer applications.
|
|
59
|
+
- **Postgres / MySQL testcontainers + contract tests** so the ORM stores are verified
|
|
60
|
+
against real database engines, and a shared contract suite keeps the adapters
|
|
61
|
+
behaviorally consistent.
|
|
62
|
+
|
|
63
|
+
### Housekeeping
|
|
64
|
+
|
|
65
|
+
- **Packaging hygiene** across the published packages.
|
|
66
|
+
|
|
3
67
|
## 0.2.0
|
|
4
68
|
|
|
5
69
|
### Minor Changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { UserRef } from '@dudousxd/nestjs-authz/store-kit';
|
|
1
2
|
import { type DynamicModule } from '@nestjs/common';
|
|
2
3
|
import { PrismaAuthzStore } from './prisma-authz.store.js';
|
|
3
4
|
import { type PrismaAuthzClientLike } from './prisma-client.js';
|
|
4
|
-
import type { UserRef } from './types.js';
|
|
5
5
|
/** Injection token holding the {@link PrismaAuthzStore} the RBAC module manages. */
|
|
6
6
|
export declare const AUTHZ_RBAC_STORE: unique symbol;
|
|
7
7
|
/** Injection token holding the resolved {@link AuthzRbacModuleOptions}. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-rbac.module.d.ts","sourceRoot":"","sources":["../src/authz-rbac.module.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,aAAa,EAQnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"authz-rbac.module.d.ts","sourceRoot":"","sources":["../src/authz-rbac.module.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EACL,KAAK,aAAa,EAQnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE/E,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,eAAoD,CAAC;AAClF,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,eAAsD,CAAC;AAEtF;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,GAAG,SAAS,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,oFAAoF;IACpF,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,CAAC;CAC9F;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAOvE;AAuED;;;;;;GAMG;AACH,qBACa,eAAe;IAC1B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,aAAa;IAa9D,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,2BAA2B,GAAG,aAAa;IAsBxE,OAAO,CAAC,MAAM,CAAC,eAAe;CAS/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authz-rbac.module.js","sourceRoot":"","sources":["../src/authz-rbac.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,OAAO,EACL,mBAAmB,EAEnB,aAAa,GAEd,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"authz-rbac.module.js","sourceRoot":"","sources":["../src/authz-rbac.module.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,7 @@ export { PrismaAuthzStore } from './prisma-authz.store.js';
|
|
|
3
3
|
export type { UserAuthz } from './prisma-authz.store.js';
|
|
4
4
|
export { AUTHZ_RBAC_OPTIONS, AUTHZ_RBAC_STORE, AuthzRbacModule, defaultUserRefMapper, } from './authz-rbac.module.js';
|
|
5
5
|
export type { AuthzRbacModuleAsyncOptions, AuthzRbacModuleOptions, UserRefMapper, } from './authz-rbac.module.js';
|
|
6
|
-
export type { UserRef, UserRefInput } from '
|
|
6
|
+
export type { UserRef, UserRefInput } from '@dudousxd/nestjs-authz/store-kit';
|
|
7
|
+
export { applyScope, compileScope } from './scope.js';
|
|
8
|
+
export type { PrismaWhere, ScopeResolver } from './scope.js';
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { PRISMA_CLIENT, } from './prisma-client.js';
|
|
2
2
|
export { PrismaAuthzStore } from './prisma-authz.store.js';
|
|
3
3
|
export { AUTHZ_RBAC_OPTIONS, AUTHZ_RBAC_STORE, AuthzRbacModule, defaultUserRefMapper, } from './authz-rbac.module.js';
|
|
4
|
+
export { applyScope, compileScope } from './scope.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAGd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,GAGd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
+
import { type UserAuthz, type UserRef } from '@dudousxd/nestjs-authz/store-kit';
|
|
1
2
|
import { type PrismaAuthzClientLike } from './prisma-client.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A user's effective permissions: the role names they hold and the flattened set of
|
|
5
|
-
* permission names granted by those roles.
|
|
6
|
-
*/
|
|
7
|
-
export interface UserAuthz {
|
|
8
|
-
roles: string[];
|
|
9
|
-
permissions: string[];
|
|
10
|
-
}
|
|
3
|
+
export type { UserAuthz };
|
|
11
4
|
/**
|
|
12
5
|
* Prisma-backed RBAC store. Receives the app-owned Prisma client via the
|
|
13
6
|
* {@link PRISMA_CLIENT} DI token — NO internal connection ownership, NO `@prisma/client`
|
|
@@ -42,8 +35,28 @@ export declare class PrismaAuthzStore {
|
|
|
42
35
|
removeRole(user: UserRef, roleName: string): Promise<void>;
|
|
43
36
|
/** The role names a user holds. */
|
|
44
37
|
getRolesForUser(user: UserRef): Promise<string[]>;
|
|
45
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* The flattened, distinct permission names a user has via their roles.
|
|
40
|
+
*
|
|
41
|
+
* Contract: returns the FULL deduped set of granted permission NAMES — including
|
|
42
|
+
* wildcard grants such as `posts.*`. This is NOT an existence check; callers
|
|
43
|
+
* ({@link userHasPermission}, {@link getUserAuthz}) depend on the complete set.
|
|
44
|
+
*
|
|
45
|
+
* Fast path: when the injected client exposes `$queryRaw`, assemble the set in a
|
|
46
|
+
* SINGLE database round-trip via one JOIN (3 round-trips → 1). On ANY failure
|
|
47
|
+
* (missing `$queryRaw`, custom `@@map` table names, non-Postgres identifier
|
|
48
|
+
* quoting, etc.) it degrades to {@link getPermissionsViaDelegates}, so correctness
|
|
49
|
+
* is preserved everywhere and only the common (Postgres + documented schema) case
|
|
50
|
+
* gets the speedup.
|
|
51
|
+
*/
|
|
46
52
|
getPermissionsForUser(user: UserRef): Promise<string[]>;
|
|
53
|
+
/**
|
|
54
|
+
* The original three-query implementation (userRole → rolePermission → permission),
|
|
55
|
+
* returning the same deduped permission-name set as {@link getPermissionsForUser}.
|
|
56
|
+
* Used directly when `$queryRaw` is unavailable, and as the fallback when the raw
|
|
57
|
+
* fast path throws.
|
|
58
|
+
*/
|
|
59
|
+
private getPermissionsViaDelegates;
|
|
47
60
|
/** A user's roles + effective permissions in one shot. */
|
|
48
61
|
getUserAuthz(user: UserRef): Promise<UserAuthz>;
|
|
49
62
|
/** True when the user holds `permission` through any of their roles. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-authz.store.d.ts","sourceRoot":"","sources":["../src/prisma-authz.store.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"prisma-authz.store.d.ts","sourceRoot":"","sources":["../src/prisma-authz.store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAoB,MAAM,kCAAkC,CAAC;AAClG,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAI/E,YAAY,EAAE,SAAS,EAAE,CAAC;AAO1B;;;;;;;GAOG;AACH,qBACa,gBAAgB;IAGzB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,qBAAqB;IAGhD;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAMnC,+EAA+E;IACzE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgB/C,qFAAqF;IAC/E,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAevC,UAAU;YAKV,gBAAgB;IAO9B,kFAAkF;IAC5E,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnF,gFAAgF;IAC1E,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASvF,iFAAiF;IAC3E,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhE,4EAA4E;IACtE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAShE,mCAAmC;IAC7B,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWvD;;;;;;;;;;;;;OAaG;IACG,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA0B7D;;;;;OAKG;YACW,0BAA0B;IAiBxC,0DAA0D;IACpD,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAQrD,wEAAwE;IAClE,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAI7E"}
|
|
@@ -11,18 +11,12 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
import { randomUUID } from 'node:crypto';
|
|
14
|
+
import { normalizeUserRef } from '@dudousxd/nestjs-authz/store-kit';
|
|
14
15
|
import { PRISMA_CLIENT } from './prisma-client.js';
|
|
15
16
|
// Optional Nest DI decorators — declared structurally so this package does not need a
|
|
16
17
|
// hard runtime dependency on @nestjs/common for the POJO store (the module supplies the
|
|
17
18
|
// real Inject token). The store is usable as a plain POJO: `new PrismaAuthzStore(client)`.
|
|
18
19
|
import { Inject, Injectable } from '@nestjs/common';
|
|
19
|
-
/** Normalize a {@link UserRef} to `{ type, id }` with `id` stringified. */
|
|
20
|
-
function normalizeUserRef(ref) {
|
|
21
|
-
if (typeof ref === 'string' || typeof ref === 'number') {
|
|
22
|
-
return { type: 'user', id: String(ref) };
|
|
23
|
-
}
|
|
24
|
-
return { type: ref.type ?? 'user', id: String(ref.id) };
|
|
25
|
-
}
|
|
26
20
|
/**
|
|
27
21
|
* Prisma-backed RBAC store. Receives the app-owned Prisma client via the
|
|
28
22
|
* {@link PRISMA_CLIENT} DI token — NO internal connection ownership, NO `@prisma/client`
|
|
@@ -144,9 +138,51 @@ let PrismaAuthzStore = class PrismaAuthzStore {
|
|
|
144
138
|
const roles = await this.client.role.findMany({ where: { id: { in: roleIds } } });
|
|
145
139
|
return roles.map((r) => r.name);
|
|
146
140
|
}
|
|
147
|
-
/**
|
|
141
|
+
/**
|
|
142
|
+
* The flattened, distinct permission names a user has via their roles.
|
|
143
|
+
*
|
|
144
|
+
* Contract: returns the FULL deduped set of granted permission NAMES — including
|
|
145
|
+
* wildcard grants such as `posts.*`. This is NOT an existence check; callers
|
|
146
|
+
* ({@link userHasPermission}, {@link getUserAuthz}) depend on the complete set.
|
|
147
|
+
*
|
|
148
|
+
* Fast path: when the injected client exposes `$queryRaw`, assemble the set in a
|
|
149
|
+
* SINGLE database round-trip via one JOIN (3 round-trips → 1). On ANY failure
|
|
150
|
+
* (missing `$queryRaw`, custom `@@map` table names, non-Postgres identifier
|
|
151
|
+
* quoting, etc.) it degrades to {@link getPermissionsViaDelegates}, so correctness
|
|
152
|
+
* is preserved everywhere and only the common (Postgres + documented schema) case
|
|
153
|
+
* gets the speedup.
|
|
154
|
+
*/
|
|
148
155
|
async getPermissionsForUser(user) {
|
|
149
156
|
const { type, id } = normalizeUserRef(user);
|
|
157
|
+
const queryRaw = this.client.$queryRaw;
|
|
158
|
+
if (typeof queryRaw === 'function') {
|
|
159
|
+
try {
|
|
160
|
+
// Single JOIN across the three documented `@@map` tables. Identifiers are
|
|
161
|
+
// literal + double-quoted (Postgres); the user `${type}`/`${id}` VALUES go
|
|
162
|
+
// through the tagged template as BOUND params — never string-concatenated.
|
|
163
|
+
const rows = await queryRaw `
|
|
164
|
+
SELECT DISTINCT p."name" AS name
|
|
165
|
+
FROM "authz_permissions" p
|
|
166
|
+
JOIN "authz_role_permission" rp ON rp."permissionId" = p."id"
|
|
167
|
+
JOIN "authz_user_role" ur ON ur."roleId" = rp."roleId"
|
|
168
|
+
WHERE ur."userType" = ${type} AND ur."userId" = ${id}
|
|
169
|
+
`;
|
|
170
|
+
return [...new Set(rows.map((r) => r.name))];
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// Raw path unsupported for this client/schema/dialect — fall back below.
|
|
174
|
+
return this.getPermissionsViaDelegates(type, id);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return this.getPermissionsViaDelegates(type, id);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The original three-query implementation (userRole → rolePermission → permission),
|
|
181
|
+
* returning the same deduped permission-name set as {@link getPermissionsForUser}.
|
|
182
|
+
* Used directly when `$queryRaw` is unavailable, and as the fallback when the raw
|
|
183
|
+
* fast path throws.
|
|
184
|
+
*/
|
|
185
|
+
async getPermissionsViaDelegates(type, id) {
|
|
150
186
|
const assignments = await this.client.userRole.findMany({
|
|
151
187
|
where: { userType: type, userId: id },
|
|
152
188
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-authz.store.js","sourceRoot":"","sources":["../src/prisma-authz.store.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAA8B,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"prisma-authz.store.js","sourceRoot":"","sources":["../src/prisma-authz.store.ts"],"names":[],"mappings":"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"}
|
package/dist/prisma-client.d.ts
CHANGED
|
@@ -54,6 +54,30 @@
|
|
|
54
54
|
*
|
|
55
55
|
* Apply it with `prisma migrate` / `prisma db push` — this adapter is
|
|
56
56
|
* consumer-managed and never runs DDL.
|
|
57
|
+
*
|
|
58
|
+
* ## Optional single-round-trip fast path (`$queryRaw`)
|
|
59
|
+
*
|
|
60
|
+
* `getPermissionsForUser` can assemble a user's granted-permission set in ONE
|
|
61
|
+
* database round-trip via a raw JOIN instead of the default three sequential
|
|
62
|
+
* delegate queries. To allow that, the interface exposes an OPTIONAL `$queryRaw`
|
|
63
|
+
* tagged-template method (see {@link PrismaAuthzClientLike.$queryRaw}).
|
|
64
|
+
*
|
|
65
|
+
* Why raw SQL and not a Prisma relation filter?
|
|
66
|
+
* - A relation filter (`permission.findMany({ where: { rolePermissions: { some } } })`)
|
|
67
|
+
* would force every consumer to declare a full back-relation graph across all four
|
|
68
|
+
* models in THEIR `schema.prisma`. That couples this adapter to the consumer's
|
|
69
|
+
* schema shape and breaks the package's "minimal structural client, no relations
|
|
70
|
+
* required" philosophy. REJECTED.
|
|
71
|
+
* - A `$queryRaw` JOIN needs NO relation fields in the consumer's schema — it works
|
|
72
|
+
* off the existing tables/columns documented above. This preserves the decoupled,
|
|
73
|
+
* relation-free design. CHOSEN.
|
|
74
|
+
*
|
|
75
|
+
* The trade-off: the raw SQL hard-codes the documented `@@map` table names plus the
|
|
76
|
+
* (camelCase, unquoted-in-schema → must be double-quoted) column names, so it is NOT
|
|
77
|
+
* portable to every SQL dialect or custom `@@map`. The store therefore treats the raw
|
|
78
|
+
* path as an OPTIONAL optimization and gracefully FALLS BACK to the three-query path
|
|
79
|
+
* on any failure — correctness is preserved everywhere; speed is gained on the common
|
|
80
|
+
* (Postgres + documented schema) case.
|
|
57
81
|
*/
|
|
58
82
|
/**
|
|
59
83
|
* Minimal structural view of a Prisma model delegate (the methods the store calls).
|
|
@@ -86,6 +110,20 @@ export interface PrismaAuthzClientLike {
|
|
|
86
110
|
permission: PrismaModelDelegate;
|
|
87
111
|
rolePermission: PrismaModelDelegate;
|
|
88
112
|
userRole: PrismaModelDelegate;
|
|
113
|
+
/**
|
|
114
|
+
* OPTIONAL tagged-template raw query, matching the real `PrismaClient.$queryRaw`
|
|
115
|
+
* signature. A real `PrismaClient` always provides it (so there is NO extra burden
|
|
116
|
+
* on consumers injecting one). It is declared OPTIONAL so that purely structural
|
|
117
|
+
* clients / in-memory fakes that omit it — or setups where the raw path is unsafe
|
|
118
|
+
* (non-Postgres quoting, custom `@@map` table names) — remain assignable and simply
|
|
119
|
+
* fall back to the three-query delegate path. See the file-level doc for the full
|
|
120
|
+
* raw-vs-relation rationale.
|
|
121
|
+
*
|
|
122
|
+
* The `any` value type mirrors `PrismaModelDelegate` above: a narrower
|
|
123
|
+
* `unknown`/`Record` would make a real `PrismaClient` not structurally assignable
|
|
124
|
+
* (arg/return-position variance), which is exactly what this package avoids.
|
|
125
|
+
*/
|
|
126
|
+
$queryRaw?<T = unknown>(query: TemplateStringsArray, ...values: any[]): Promise<T>;
|
|
89
127
|
}
|
|
90
128
|
/**
|
|
91
129
|
* DI token for the app-provided Prisma client ({@link PrismaAuthzClientLike})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-client.d.ts","sourceRoot":"","sources":["../src/prisma-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prisma-client.d.ts","sourceRoot":"","sources":["../src/prisma-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAElC,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE1C,SAAS,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE9C,QAAQ,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAE/C,UAAU,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,GAAG,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9D;AAED,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,UAAU,EAAE,mBAAmB,CAAC;IAChC,cAAc,EAAE,mBAAmB,CAAC;IACpC,QAAQ,EAAE,mBAAmB,CAAC;IAE9B;;;;;;;;;;;;OAYG;IAEH,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACpF;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,eAAqD,CAAC"}
|
package/dist/prisma-client.js
CHANGED
|
@@ -54,6 +54,30 @@
|
|
|
54
54
|
*
|
|
55
55
|
* Apply it with `prisma migrate` / `prisma db push` — this adapter is
|
|
56
56
|
* consumer-managed and never runs DDL.
|
|
57
|
+
*
|
|
58
|
+
* ## Optional single-round-trip fast path (`$queryRaw`)
|
|
59
|
+
*
|
|
60
|
+
* `getPermissionsForUser` can assemble a user's granted-permission set in ONE
|
|
61
|
+
* database round-trip via a raw JOIN instead of the default three sequential
|
|
62
|
+
* delegate queries. To allow that, the interface exposes an OPTIONAL `$queryRaw`
|
|
63
|
+
* tagged-template method (see {@link PrismaAuthzClientLike.$queryRaw}).
|
|
64
|
+
*
|
|
65
|
+
* Why raw SQL and not a Prisma relation filter?
|
|
66
|
+
* - A relation filter (`permission.findMany({ where: { rolePermissions: { some } } })`)
|
|
67
|
+
* would force every consumer to declare a full back-relation graph across all four
|
|
68
|
+
* models in THEIR `schema.prisma`. That couples this adapter to the consumer's
|
|
69
|
+
* schema shape and breaks the package's "minimal structural client, no relations
|
|
70
|
+
* required" philosophy. REJECTED.
|
|
71
|
+
* - A `$queryRaw` JOIN needs NO relation fields in the consumer's schema — it works
|
|
72
|
+
* off the existing tables/columns documented above. This preserves the decoupled,
|
|
73
|
+
* relation-free design. CHOSEN.
|
|
74
|
+
*
|
|
75
|
+
* The trade-off: the raw SQL hard-codes the documented `@@map` table names plus the
|
|
76
|
+
* (camelCase, unquoted-in-schema → must be double-quoted) column names, so it is NOT
|
|
77
|
+
* portable to every SQL dialect or custom `@@map`. The store therefore treats the raw
|
|
78
|
+
* path as an OPTIONAL optimization and gracefully FALLS BACK to the three-query path
|
|
79
|
+
* on any failure — correctness is preserved everywhere; speed is gained on the common
|
|
80
|
+
* (Postgres + documented schema) case.
|
|
57
81
|
*/
|
|
58
82
|
/**
|
|
59
83
|
* DI token for the app-provided Prisma client ({@link PrismaAuthzClientLike})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-client.js","sourceRoot":"","sources":["../src/prisma-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prisma-client.js","sourceRoot":"","sources":["../src/prisma-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AA8CH;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC"}
|
package/dist/scope.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ScopeConstraint } from '@dudousxd/nestjs-authz';
|
|
2
|
+
import type { Type } from '@nestjs/common';
|
|
3
|
+
/**
|
|
4
|
+
* The minimal scope-resolving surface shared by `Gate` and `BoundGate`. Accepting
|
|
5
|
+
* this (rather than `Gate`) lets the scope helpers take either a Gate (current/context
|
|
6
|
+
* user) or a `gate.forUser(...)` BoundGate without a cast. Mirrors the TypeORM and
|
|
7
|
+
* MikroORM adapters' `ScopeResolver` so all ORMs feel identical.
|
|
8
|
+
*/
|
|
9
|
+
export interface ScopeResolver {
|
|
10
|
+
scope(entity: Type<unknown>, ability?: string): Promise<ScopeConstraint>;
|
|
11
|
+
}
|
|
12
|
+
/** A Prisma `where` object (structurally typed; the consumer's generated input is narrower). */
|
|
13
|
+
export type PrismaWhere = Record<string, unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* Compile an ORM-neutral {@link ScopeConstraint} into a Prisma `where` object.
|
|
16
|
+
*
|
|
17
|
+
* Terminal/empty semantics (matching the core AST and the TypeORM/MikroORM adapters):
|
|
18
|
+
* - `allow-all` → `{}` (an empty where matches EVERY row);
|
|
19
|
+
* - `deny-all` → `{ OR: [] }` (an empty OR matches NO row);
|
|
20
|
+
* - empty `in` → no rows (`{ OR: [] }`); empty `nin` → all rows (`{}`);
|
|
21
|
+
* - empty `and` group → all rows; empty `or` group → no rows.
|
|
22
|
+
*
|
|
23
|
+
* Operator mapping:
|
|
24
|
+
* - `eq` → `{ field: { equals } }`; `ne` → `{ field: { not } }`;
|
|
25
|
+
* - `gt/gte/lt/lte` → `{ field: { gt/gte/lt/lte } }`;
|
|
26
|
+
* - `in/nin` → `{ field: { in/notIn: [...] } }` (a scalar value is wrapped to a single
|
|
27
|
+
* element);
|
|
28
|
+
* - `isNull` → `{ field: { equals: null } }`; `isNotNull` → `{ field: { not: null } }`;
|
|
29
|
+
* - `and`/`or` → `{ AND: [...] }` / `{ OR: [...] }`.
|
|
30
|
+
*
|
|
31
|
+
* SAFE: only VALUES come from the (untrusted) policy result and Prisma binds them as
|
|
32
|
+
* parameters. Field names become object keys (a column/relation path), so each is
|
|
33
|
+
* validated against {@link assertSafeIdentifier} — a hostile field throws.
|
|
34
|
+
*/
|
|
35
|
+
export declare function compileScope(constraint: ScopeConstraint): PrismaWhere;
|
|
36
|
+
/**
|
|
37
|
+
* Ergonomic entry point: resolve the query scope for the current (context) user via
|
|
38
|
+
* the {@link Gate} and return the Prisma `where` to pass to `model.findMany`.
|
|
39
|
+
* Equivalent to `compileScope(await gate.scope(entity, ability))`.
|
|
40
|
+
*
|
|
41
|
+
* Mirrors the TypeORM/MikroORM adapters' `applyScope` shape (gate + entity), but returns
|
|
42
|
+
* the `where` instead of mutating a query builder, because Prisma's idiomatic collection
|
|
43
|
+
* fetch is `prisma.post.findMany({ where })`:
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* const where = await applyScope(gate, Post); // current user's accessible posts
|
|
47
|
+
* const posts = await prisma.post.findMany({ where });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* Combine with extra criteria via Prisma's own `AND`:
|
|
51
|
+
* `prisma.post.findMany({ where: { AND: [where, { published: true }] } })`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function applyScope(gate: ScopeResolver, entity: Type<unknown>, ability?: string): Promise<PrismaWhere>;
|
|
54
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,eAAe,EAGhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC1E;AAED,gGAAgG;AAChG,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAkBlD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,eAAe,GAAG,WAAW,CA+BrE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,EACrB,OAAO,SAAY,GAClB,OAAO,CAAC,WAAW,CAAC,CAEtB"}
|
package/dist/scope.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { assertSafeIdentifier } from '@dudousxd/nestjs-authz';
|
|
2
|
+
/**
|
|
3
|
+
* An always-false predicate as a Prisma `where`. Prisma treats an EMPTY `OR` array as
|
|
4
|
+
* "match nothing" (an OR over zero alternatives can never be satisfied), which is the
|
|
5
|
+
* documented, portable way to express a deny-all filter — parallel to the core AST's
|
|
6
|
+
* "empty OR is the zero" rule and the TypeORM adapter's `1 = 0`.
|
|
7
|
+
*/
|
|
8
|
+
const ALWAYS_FALSE = { OR: [] };
|
|
9
|
+
/** Prisma filter-condition keys for the binary comparison operators. */
|
|
10
|
+
const BINARY_OPS = {
|
|
11
|
+
gt: 'gt',
|
|
12
|
+
gte: 'gte',
|
|
13
|
+
lt: 'lt',
|
|
14
|
+
lte: 'lte',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Compile an ORM-neutral {@link ScopeConstraint} into a Prisma `where` object.
|
|
18
|
+
*
|
|
19
|
+
* Terminal/empty semantics (matching the core AST and the TypeORM/MikroORM adapters):
|
|
20
|
+
* - `allow-all` → `{}` (an empty where matches EVERY row);
|
|
21
|
+
* - `deny-all` → `{ OR: [] }` (an empty OR matches NO row);
|
|
22
|
+
* - empty `in` → no rows (`{ OR: [] }`); empty `nin` → all rows (`{}`);
|
|
23
|
+
* - empty `and` group → all rows; empty `or` group → no rows.
|
|
24
|
+
*
|
|
25
|
+
* Operator mapping:
|
|
26
|
+
* - `eq` → `{ field: { equals } }`; `ne` → `{ field: { not } }`;
|
|
27
|
+
* - `gt/gte/lt/lte` → `{ field: { gt/gte/lt/lte } }`;
|
|
28
|
+
* - `in/nin` → `{ field: { in/notIn: [...] } }` (a scalar value is wrapped to a single
|
|
29
|
+
* element);
|
|
30
|
+
* - `isNull` → `{ field: { equals: null } }`; `isNotNull` → `{ field: { not: null } }`;
|
|
31
|
+
* - `and`/`or` → `{ AND: [...] }` / `{ OR: [...] }`.
|
|
32
|
+
*
|
|
33
|
+
* SAFE: only VALUES come from the (untrusted) policy result and Prisma binds them as
|
|
34
|
+
* parameters. Field names become object keys (a column/relation path), so each is
|
|
35
|
+
* validated against {@link assertSafeIdentifier} — a hostile field throws.
|
|
36
|
+
*/
|
|
37
|
+
export function compileScope(constraint) {
|
|
38
|
+
if (constraint.kind === 'all')
|
|
39
|
+
return {};
|
|
40
|
+
if (constraint.kind === 'none')
|
|
41
|
+
return { ...ALWAYS_FALSE };
|
|
42
|
+
const compileCondition = (c) => {
|
|
43
|
+
assertSafeIdentifier(c.field, `scope field "${c.field}"`);
|
|
44
|
+
if (c.op === 'eq')
|
|
45
|
+
return { [c.field]: { equals: c.value } };
|
|
46
|
+
if (c.op === 'ne')
|
|
47
|
+
return { [c.field]: { not: c.value } };
|
|
48
|
+
if (c.op === 'isNull')
|
|
49
|
+
return { [c.field]: { equals: null } };
|
|
50
|
+
if (c.op === 'isNotNull')
|
|
51
|
+
return { [c.field]: { not: null } };
|
|
52
|
+
if (c.op === 'in' || c.op === 'nin') {
|
|
53
|
+
const values = Array.isArray(c.value) ? c.value : [c.value];
|
|
54
|
+
// An empty `in` matches nothing; an empty `nin` matches everything.
|
|
55
|
+
if (values.length === 0)
|
|
56
|
+
return c.op === 'in' ? { ...ALWAYS_FALSE } : {};
|
|
57
|
+
const key = c.op === 'in' ? 'in' : 'notIn';
|
|
58
|
+
return { [c.field]: { [key]: values } };
|
|
59
|
+
}
|
|
60
|
+
const token = BINARY_OPS[c.op];
|
|
61
|
+
if (!token)
|
|
62
|
+
throw new Error(`Unsupported scope operator: ${c.op}`);
|
|
63
|
+
return { [c.field]: { [token]: c.value } };
|
|
64
|
+
};
|
|
65
|
+
const compileNode = (node) => {
|
|
66
|
+
if (node.kind === 'condition')
|
|
67
|
+
return compileCondition(node);
|
|
68
|
+
// An empty `and` is the identity (all rows); an empty `or` is the zero (no rows).
|
|
69
|
+
if (node.nodes.length === 0)
|
|
70
|
+
return node.kind === 'and' ? {} : { ...ALWAYS_FALSE };
|
|
71
|
+
const children = node.nodes.map(compileNode);
|
|
72
|
+
return node.kind === 'and' ? { AND: children } : { OR: children };
|
|
73
|
+
};
|
|
74
|
+
return compileNode(constraint);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Ergonomic entry point: resolve the query scope for the current (context) user via
|
|
78
|
+
* the {@link Gate} and return the Prisma `where` to pass to `model.findMany`.
|
|
79
|
+
* Equivalent to `compileScope(await gate.scope(entity, ability))`.
|
|
80
|
+
*
|
|
81
|
+
* Mirrors the TypeORM/MikroORM adapters' `applyScope` shape (gate + entity), but returns
|
|
82
|
+
* the `where` instead of mutating a query builder, because Prisma's idiomatic collection
|
|
83
|
+
* fetch is `prisma.post.findMany({ where })`:
|
|
84
|
+
*
|
|
85
|
+
* ```ts
|
|
86
|
+
* const where = await applyScope(gate, Post); // current user's accessible posts
|
|
87
|
+
* const posts = await prisma.post.findMany({ where });
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* Combine with extra criteria via Prisma's own `AND`:
|
|
91
|
+
* `prisma.post.findMany({ where: { AND: [where, { published: true }] } })`.
|
|
92
|
+
*/
|
|
93
|
+
export async function applyScope(gate, entity, ability = 'viewAny') {
|
|
94
|
+
return compileScope(await gate.scope(entity, ability));
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-authz-prisma",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Prisma RBAC persistence for @dudousxd/nestjs-authz — roles, permissions, and a Gate seam (zero connection ownership, structural client).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,12 +34,15 @@
|
|
|
34
34
|
"@nestjs/common": "^11.0.0",
|
|
35
35
|
"@nestjs/core": "^11.0.0",
|
|
36
36
|
"@nestjs/testing": "^11.0.0",
|
|
37
|
+
"@testcontainers/postgresql": "^12.0.3",
|
|
37
38
|
"@types/node": "^20.0.0",
|
|
39
|
+
"@types/pg": "^8.11.0",
|
|
40
|
+
"pg": "^8.21.0",
|
|
38
41
|
"reflect-metadata": "^0.2.2",
|
|
39
42
|
"rxjs": "^7.8.1",
|
|
40
43
|
"typescript": "^5.4.0",
|
|
41
44
|
"vitest": "^3.0.0",
|
|
42
|
-
"@dudousxd/nestjs-authz": "^0.
|
|
45
|
+
"@dudousxd/nestjs-authz": "^0.6.1"
|
|
43
46
|
},
|
|
44
47
|
"engines": {
|
|
45
48
|
"node": ">=20"
|
|
@@ -56,6 +59,7 @@
|
|
|
56
59
|
"scripts": {
|
|
57
60
|
"build": "tsc -p tsconfig.json",
|
|
58
61
|
"test": "vitest run --passWithNoTests",
|
|
62
|
+
"test:db:pg": "AUTHZ_TEST_DIALECT=postgres vitest run --config vitest.db.config.ts",
|
|
59
63
|
"test:watch": "vitest",
|
|
60
64
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
61
65
|
}
|
package/dist/types.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A reference to a user. Matches nestjs-context's `UserRef` shape (`{ type, id }`),
|
|
3
|
-
* but the store accepts either a full ref or a bare id (defaulting `type` to `'user'`).
|
|
4
|
-
*/
|
|
5
|
-
export interface UserRefInput {
|
|
6
|
-
type?: string;
|
|
7
|
-
id: string | number;
|
|
8
|
-
}
|
|
9
|
-
/** A user reference, or just its id (treated as `{ type: 'user', id }`). */
|
|
10
|
-
export type UserRef = UserRefInput | string | number;
|
|
11
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,4EAA4E;AAC5E,MAAM,MAAM,OAAO,GAAG,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC"}
|
package/dist/types.js
DELETED
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|