@appxdigital/appx-core 0.1.121-beta.11 → 0.1.121-beta.5

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.
@@ -3,14 +3,6 @@ import { Operation } from '@prisma/client/runtime/library';
3
3
  export declare const PermissionPlaceholder: {
4
4
  USER_ID: any;
5
5
  };
6
- /**
7
- * Batch (`*Many`) actions inherit the singular rule when not declared
8
- * explicitly, so a config can define just `create` / `update` / `delete`.
9
- * One-directional: the singular is canonical (declaring only the `*Many`
10
- * variant does not enable the singular). Consumed by the Prisma proxy
11
- * (`selectPermission`) and the `RbacGuard`.
12
- */
13
- export declare const SINGULAR_ACTION: Record<string, string>;
14
6
  /** Detect delegate keys on an arbitrary Prisma client type C */
15
7
  type DelegateKeyOf<C> = {
16
8
  [K in keyof C]: C[K] extends {
@@ -1 +1 @@
1
- {"version":3,"file":"permissionsConfigTypes.d.ts","sourceRoot":"","sources":["../../../src/common/config/permissionsConfigTypes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAE,YAAY,IAAI,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAC,SAAS,EAAC,MAAM,gCAAgC,CAAC;AAEzD,eAAO,MAAM,qBAAqB,EAAE;IAChC,OAAO,EAAE,GAAG,CAAC;CAGhB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAIlD,CAAC;AAEF,gEAAgE;AAChE,KAAK,aAAa,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,GACb,CAAC,CAAC,CAAC,CAAC,SAAS;QAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;KAAC,GAAG,CAAC,GAAG,KAAK;CAC/D,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC;AAEpB,mDAAmD;AACnD,KAAK,iBAAiB,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC;AAE7C,8DAA8D;AAC9D,KAAK,QAAQ,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IACjD,iBAAiB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5D,4EAA4E;AAC5E,KAAK,cAAc,CACf,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IAErB,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,GAC5B,CAAC,SAAS,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAC/E,KAAK,CAAC;AAEpB,oDAAoD;AACpD,KAAK,WAAW,CACZ,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB,CAAC,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAE5B,0CAA0C;AAC1C,KAAK,UAAU,CACX,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB;KACC,CAAC,IAAI,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7B,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK;CACnE,CAAC,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;AAEpC,iEAAiE;AACjE,KAAK,aAAa,CACd,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAEzC,oFAAoF;AACpF,KAAK,MAAM,CACP,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EACrB,CAAC,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,IAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEtC,4DAA4D;AAC5D,KAAK,OAAO,CACR,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,EACrB,CAAC,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,IAE7B,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAA;CAAC,GAAG,CAAC,GACzC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS;IAAC,KAAK,EAAE,MAAM,CAAC,CAAA;CAAC,GAAG,CAAC,GACxC,KAAK,CAAC;AAElB,0DAA0D;AAC1D,KAAK,gBAAgB,CACjB,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,IACrB;KACC,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,GAAG,CAAC;CAC7C,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;AAEhC,6DAA6D;AAE7D,MAAM,MAAM,eAAe,CACvB,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,EACjC,CAAC,SAAS,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC,IAC5C,OAAO,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEjC,MAAM,WAAW,gBAAgB,CAC7B,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,EAC3D,CAAC,SAAS,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC;IAEjF,UAAU,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,eAAe,CACvB,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,IAE3D;KACK,CAAC,IAAI,gBAAgB,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC;CAC7E,GAAG;IACJ,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG;QACtB,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE,CAAC;QACjC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC/B,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,gBAAgB,CACxB,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,IAC3D;IACA,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAC7B,CAAC,SAAS,QAAQ,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,IAC3D;KACC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,KAAK,CAAC;CACzC,CAAC"}
1
+ {"version":3,"file":"permissionsConfigTypes.d.ts","sourceRoot":"","sources":["../../../src/common/config/permissionsConfigTypes.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SINGULAR_ACTION = exports.PermissionPlaceholder = void 0;
3
+ exports.PermissionPlaceholder = void 0;
4
4
  exports.PermissionPlaceholder = {
5
5
  USER_ID: '$USER_ID',
6
6
  };
7
- /**
8
- * Batch (`*Many`) actions inherit the singular rule when not declared
9
- * explicitly, so a config can define just `create` / `update` / `delete`.
10
- * One-directional: the singular is canonical (declaring only the `*Many`
11
- * variant does not enable the singular). Consumed by the Prisma proxy
12
- * (`selectPermission`) and the `RbacGuard`.
13
- */
14
- exports.SINGULAR_ACTION = {
15
- createMany: 'create',
16
- updateMany: 'update',
17
- deleteMany: 'delete',
18
- };
@@ -1,17 +1,3 @@
1
1
  export declare const PERMISSION_METADATA_KEY = "permission";
2
- export declare const EXPOSE_MODELS_METADATA_KEY = "expose_models";
3
2
  export declare const Permission: (action: string, expose_models?: string[]) => import("@nestjs/common").CustomDecorator<string>;
4
- /**
5
- * Expose one or more models for the duration of the request — WITHOUT requiring
6
- * a permission action. Unlike `@Permission(action, models)`, this sets no
7
- * action, so `RbacGuard` does not demand a role permission for the route. Use it
8
- * for a public / GUEST endpoint that must read a model the caller isn't
9
- * otherwise granted (e.g. an email-availability check) without having to add a
10
- * `GUEST` rule for that model. Exposure is scoped to the request: the listed
11
- * models skip row / field filtering only inside this handler.
12
- *
13
- * Combine with `@Permission(...)` if you also want an action check; both
14
- * sources of exposed models are merged.
15
- */
16
- export declare const ExposeModels: (...models: string[]) => import("@nestjs/common").CustomDecorator<string>;
17
3
  //# sourceMappingURL=permission.decorator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"permission.decorator.d.ts","sourceRoot":"","sources":["../../../src/common/decorators/permission.decorator.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,eAAe,CAAC;AACpD,eAAO,MAAM,0BAA0B,kBAAkB,CAAC;AAE1D,eAAO,MAAM,UAAU,WAAY,MAAM,kBAAiB,MAAM,EAAE,qDACD,CAAC;AAElE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,cAAe,MAAM,EAAE,qDACG,CAAC"}
1
+ {"version":3,"file":"permission.decorator.d.ts","sourceRoot":"","sources":["../../../src/common/decorators/permission.decorator.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,eAAe,CAAC;AAEpD,eAAO,MAAM,UAAU,WAAY,MAAM,kBAAiB,MAAM,EAAE,qDACD,CAAC"}
@@ -1,22 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExposeModels = exports.Permission = exports.EXPOSE_MODELS_METADATA_KEY = exports.PERMISSION_METADATA_KEY = void 0;
3
+ exports.Permission = exports.PERMISSION_METADATA_KEY = void 0;
4
4
  const common_1 = require("@nestjs/common");
5
5
  exports.PERMISSION_METADATA_KEY = 'permission';
6
- exports.EXPOSE_MODELS_METADATA_KEY = 'expose_models';
7
6
  const Permission = (action, expose_models = []) => (0, common_1.SetMetadata)(exports.PERMISSION_METADATA_KEY, { action, expose_models });
8
7
  exports.Permission = Permission;
9
- /**
10
- * Expose one or more models for the duration of the request — WITHOUT requiring
11
- * a permission action. Unlike `@Permission(action, models)`, this sets no
12
- * action, so `RbacGuard` does not demand a role permission for the route. Use it
13
- * for a public / GUEST endpoint that must read a model the caller isn't
14
- * otherwise granted (e.g. an email-availability check) without having to add a
15
- * `GUEST` rule for that model. Exposure is scoped to the request: the listed
16
- * models skip row / field filtering only inside this handler.
17
- *
18
- * Combine with `@Permission(...)` if you also want an action check; both
19
- * sources of exposed models are merged.
20
- */
21
- const ExposeModels = (...models) => (0, common_1.SetMetadata)(exports.EXPOSE_MODELS_METADATA_KEY, models);
22
- exports.ExposeModels = ExposeModels;
@@ -1 +1 @@
1
- {"version":3,"file":"rbac.guard.d.ts","sourceRoot":"","sources":["../../../src/common/guards/rbac.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,gBAAgB,EAInB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAC,qBAAqB,EAAmC,MAAM,kCAAkC,CAAC;AAEzG,qBACa,SAAU,YAAW,WAAW;IAErC,OAAO,CAAC,SAAS;IACiB,OAAO,CAAC,iBAAiB;gBADnD,SAAS,EAAE,SAAS,EACc,iBAAiB,EAAE,qBAAqB;IAGhF,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CA0CjE"}
1
+ {"version":3,"file":"rbac.guard.d.ts","sourceRoot":"","sources":["../../../src/common/guards/rbac.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,gBAAgB,EAInB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAC,qBAAqB,EAAkB,MAAM,kCAAkC,CAAC;AAExF,qBACa,SAAU,YAAW,WAAW;IAErC,OAAO,CAAC,SAAS;IACiB,OAAO,CAAC,iBAAiB;gBADnD,SAAS,EAAE,SAAS,EACc,iBAAiB,EAAE,qBAAqB;IAGhF,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CAoCjE"}
@@ -17,7 +17,6 @@ const common_1 = require("@nestjs/common");
17
17
  const core_1 = require("@nestjs/core");
18
18
  const permission_decorator_1 = require("../decorators/permission.decorator");
19
19
  const permissions_config_provider_1 = require("../config/permissions.config.provider");
20
- const permissionsConfigTypes_1 = require("../config/permissionsConfigTypes");
21
20
  let RbacGuard = exports.RbacGuard = class RbacGuard {
22
21
  constructor(reflector, permissionsConfig) {
23
22
  this.reflector = reflector;
@@ -39,13 +38,7 @@ let RbacGuard = exports.RbacGuard = class RbacGuard {
39
38
  if (!rolePermissions) {
40
39
  throw new common_1.ForbiddenException(`No permissions defined for role ${user.role} on model ${model}`);
41
40
  }
42
- // A `*Many` action inherits its singular rule when not defined explicitly
43
- // (createMany → create, updateMany → update, deleteMany → delete) — mirrors
44
- // the data-access proxy, so a config can declare just the singular form.
45
- let permission = rolePermissions[action];
46
- if (!permission && permissionsConfigTypes_1.SINGULAR_ACTION[action]) {
47
- permission = rolePermissions[permissionsConfigTypes_1.SINGULAR_ACTION[action]];
48
- }
41
+ const permission = rolePermissions[action];
49
42
  if (!permission) {
50
43
  throw new common_1.ForbiddenException(`Action ${action} not allowed for role ${user.role} on model ${model}`);
51
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prisma.interceptor.d.ts","sourceRoot":"","sources":["../../../src/common/interceptors/prisma.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,gBAAgB,EAAc,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAoB,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAC,UAAU,EAAa,MAAM,MAAM,CAAC;AAK5C,qBACa,iBAAkB,YAAW,eAAe;IAIjD,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,aAAa;IALzB,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;gBAG1B,aAAa,EAAE,aAAa,EACrC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa;IAKxC,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC;CAmF3E"}
1
+ {"version":3,"file":"prisma.interceptor.d.ts","sourceRoot":"","sources":["../../../src/common/interceptors/prisma.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,gBAAgB,EAAc,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAoB,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAC,UAAU,EAAa,MAAM,MAAM,CAAC;AAK5C,qBACa,iBAAkB,YAAW,eAAe;IAIjD,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,aAAa;IALzB,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;gBAG1B,aAAa,EAAE,aAAa,EACrC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa;IAKxC,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC;CA+E3E"}
@@ -31,15 +31,11 @@ let PrismaInterceptor = exports.PrismaInterceptor = class PrismaInterceptor {
31
31
  const req = handlerType === 'graphql'
32
32
  ? context.getArgByIndex(2) // GraphQL context
33
33
  : context.switchToHttp().getRequest(); // HTTP context
34
- // Attach expose_models metadata if needed. Models can come from
35
- // @Permission(action, models) or the standalone @ExposeModels(...); both
36
- // are merged so a route can expose models with or without a permission.
34
+ // Attach expose_models metadata if needed
37
35
  const permissionMetadata = this.reflector.get(permission_decorator_1.PERMISSION_METADATA_KEY, context.getHandler()) || {};
38
- const standaloneExposed = this.reflector.get(permission_decorator_1.EXPOSE_MODELS_METADATA_KEY, context.getHandler()) || [];
39
- const exposedModels = [...(permissionMetadata['expose_models'] || []), ...standaloneExposed];
40
36
  return new rxjs_1.Observable((observer) => {
41
37
  prisma_service_1.CorePrismaContext.run({
42
- exposedModels,
38
+ exposedModels: permissionMetadata['expose_models'] || [],
43
39
  }, () => {
44
40
  const useTransaction = this.reflector.get('useTransaction', context.getHandler()) ?? this.defaultUseTransaction === 'true';
45
41
  if (useTransaction) {
@@ -45,14 +45,7 @@ const utils_1 = require("./utils");
45
45
  * - a server-managed timestamp (`@default(now())` or `@updatedAt`),
46
46
  * - annotated `/// @NoWrite`, or
47
47
  * - annotated `/// @Role(none)` (readable by nobody ⇒ not CRUD-writable).
48
- *
49
- * Nested relation writes (CREATE DTOs only — `updateMany` takes scalar data):
50
- * Each relation gets a nested-write member exposing ONLY the operators the
51
- * data-access proxy authorizes: `create` (validated against the related
52
- * model's writable scalars) and `connect` (validated against the related
53
- * model's unique fields). Other operators (`set`/`disconnect`/`update`/…) are
54
- * deliberately NOT emitted, so the whitelist pipe rejects them. The proxy
55
- * enforces the matching ABAC rule for each (`create` rule / `connect` rule).
48
+ * Relation navigation fields are excluded; their scalar foreign keys are kept.
56
49
  */
57
50
  const cwd = process.cwd();
58
51
  // Read the consumer's generated Prisma client for the DMMF (authoritative
@@ -61,9 +54,6 @@ const cwd = process.cwd();
61
54
  const { Prisma } = require(path.join(cwd, 'node_modules', '@prisma/client'));
62
55
  const generatedDtoRoot = path.join(cwd, 'src/generated/dto');
63
56
  const modulesRoot = path.join(cwd, 'src/modules');
64
- const modelsByName = {};
65
- for (const m of Prisma.dmmf.datamodel.models)
66
- modelsByName[m.name] = m;
67
57
  function isNoWrite(doc) {
68
58
  if (!doc)
69
59
  return false;
@@ -108,7 +98,7 @@ function mapField(field) {
108
98
  return { validator: 'Allow', tsType: 'any' };
109
99
  }
110
100
  }
111
- function writableFields(model, omit = []) {
101
+ function writableFields(model) {
112
102
  return model.fields.filter((f) => {
113
103
  if (f.kind === 'object')
114
104
  return false; // relation navigation
@@ -118,32 +108,25 @@ function writableFields(model, omit = []) {
118
108
  return false;
119
109
  if (isNoWrite(f.documentation))
120
110
  return false;
121
- if (omit.includes(f.name))
122
- return false;
123
111
  return true;
124
112
  });
125
113
  }
126
- /** id + unique scalar fields (for a connect-by DTO). */
127
- function connectFields(model) {
128
- return model.fields.filter((f) => f.kind !== 'object' && (f.isId || f.isUnique));
129
- }
130
- /** The scalar FK column(s) the parent sets automatically — omit from a nested create. */
131
- function backFkColumns(relatedModel, relationName) {
132
- const inverse = relatedModel.fields.find((f) => f.kind === 'object' && f.relationName === relationName && (f.relationFromFields || []).length > 0);
133
- return inverse ? inverse.relationFromFields || [] : [];
134
- }
135
- /** Renders class-body lines for a set of scalar/enum fields; collects imports. */
136
- function renderScalarLines(fields, mode, validatorImports, enumImports) {
114
+ /** Renders a base DTO class body + its import block. */
115
+ function renderBaseDto(className, fields, mode) {
116
+ const validatorImports = new Set();
117
+ const enumImports = new Set();
137
118
  const lines = [];
138
119
  for (const field of fields) {
139
120
  const m = mapField(field);
140
121
  validatorImports.add(m.validator);
141
122
  if (m.enumArg)
142
123
  enumImports.add(m.enumArg);
143
- // update / connect: everything optional. create: optional if not required or defaulted.
144
- const optional = mode !== 'create' || !field.isRequired || field.hasDefaultValue;
124
+ // update: everything optional. create: optional if not required or has a default.
125
+ const optional = mode === 'update' || !field.isRequired || field.hasDefaultValue;
145
126
  const isList = field.isList;
146
127
  const tsType = isList ? `${m.tsType}[]` : m.tsType;
128
+ // Compose the validator decorator. @Allow takes no options; for other
129
+ // validators on a list field, add `{ each: true }` (+ @IsArray).
147
130
  let validatorDecorator;
148
131
  if (m.validator === 'Allow') {
149
132
  validatorDecorator = '@Allow()';
@@ -170,89 +153,19 @@ function renderScalarLines(fields, mode, validatorImports, enumImports) {
170
153
  lines.push(` ${field.name}${optional ? '?' : '!'}: ${tsType};`);
171
154
  lines.push('');
172
155
  }
173
- return lines;
174
- }
175
- function renderClass(className, bodyLines) {
176
- return `export class ${className} {\n` + (bodyLines.length ? bodyLines.join('\n') : '') + `}\n`;
177
- }
178
- /**
179
- * For a model's CREATE DTO, render the nested-write classes for each relation
180
- * plus the property lines to add to the parent class. Nested create classes are
181
- * scalars-only (no deeper relations) so there are no circular imports.
182
- */
183
- function renderRelationNestedWrites(model, validatorImports, enumImports, transformerImports) {
184
- const classes = [];
185
- const parentLines = [];
186
- const relations = model.fields.filter((f) => f.kind === 'object');
187
- for (const rel of relations) {
188
- const related = modelsByName[rel.type];
189
- if (!related)
190
- continue;
191
- const relCap = rel.name.charAt(0).toUpperCase() + rel.name.slice(1);
192
- const createCls = `${model.name}${relCap}CreateNestedDto`;
193
- const connectCls = `${model.name}${relCap}ConnectNestedDto`;
194
- const writeCls = `${model.name}${relCap}NestedWriteDto`;
195
- // create: related writable scalars minus the back-reference FK.
196
- const omit = backFkColumns(related, rel.relationName);
197
- classes.push(renderClass(createCls, renderScalarLines(writableFields(related, omit), 'create', validatorImports, enumImports)));
198
- // connect: related unique fields (all optional).
199
- const conn = connectFields(related);
200
- classes.push(renderClass(connectCls, renderScalarLines(conn, 'connect', validatorImports, enumImports)));
201
- // nested-write: create? / connect? only.
202
- transformerImports.add('Type');
203
- validatorImports.add('IsOptional');
204
- validatorImports.add('ValidateNested');
205
- const eachArg = rel.isList ? '{ each: true }' : '';
206
- const arrSuffix = rel.isList ? '[]' : '';
207
- if (rel.isList)
208
- validatorImports.add('IsArray');
209
- const opLines = [];
210
- for (const [op, cls] of [['create', createCls], ['connect', connectCls]]) {
211
- if (rel.isList)
212
- opLines.push(' @IsArray()');
213
- opLines.push(' @IsOptional()');
214
- opLines.push(` @ValidateNested(${eachArg})`);
215
- opLines.push(` @Type(() => ${cls})`);
216
- opLines.push(` ${op}?: ${cls}${arrSuffix};`);
217
- opLines.push('');
218
- }
219
- classes.push(renderClass(writeCls, opLines));
220
- // property on the parent CREATE DTO.
221
- parentLines.push(' @IsOptional()');
222
- parentLines.push(' @ValidateNested()');
223
- parentLines.push(` @Type(() => ${writeCls})`);
224
- parentLines.push(` ${rel.name}?: ${writeCls};`);
225
- parentLines.push('');
226
- }
227
- return { classes, parentLines };
228
- }
229
- /** Renders a base DTO file (nested relation writes on create only). */
230
- function renderBaseDto(className, model, mode) {
231
- const validatorImports = new Set();
232
- const enumImports = new Set();
233
- const transformerImports = new Set();
234
- const scalarLines = renderScalarLines(writableFields(model), mode, validatorImports, enumImports);
235
- let nested = { classes: [], parentLines: [] };
236
- if (mode === 'create') {
237
- nested = renderRelationNestedWrites(model, validatorImports, enumImports, transformerImports);
238
- }
239
- const parentClass = renderClass(className, [...scalarLines, ...nested.parentLines]);
240
156
  const importLines = [];
241
157
  if (validatorImports.size > 0) {
242
158
  importLines.push(`import { ${[...validatorImports].sort().join(', ')} } from 'class-validator';`);
243
159
  }
244
- if (transformerImports.size > 0) {
245
- importLines.push(`import { ${[...transformerImports].sort().join(', ')} } from 'class-transformer';`);
246
- }
247
160
  if (enumImports.size > 0) {
248
161
  importLines.push(`import { ${[...enumImports].sort().join(', ')} } from '@prisma/client';`);
249
162
  }
250
163
  return (utils_1.GENERATED_BANNER +
251
164
  '\n' +
252
165
  (importLines.length ? importLines.join('\n') + '\n\n' : '') +
253
- // nested classes first (referenced by @Type in the parent).
254
- (nested.classes.length ? nested.classes.join('\n') + '\n' : '') +
255
- parentClass);
166
+ `export class ${className} {\n` +
167
+ (lines.length ? lines.map((l) => l).join('\n') : '') +
168
+ `}\n`);
256
169
  }
257
170
  /** Renders the hand-owned subclass (generated once, then customizable). */
258
171
  function renderSubclassDto(subclass, baseClass, importPath) {
@@ -269,13 +182,14 @@ for (const model of Prisma.dmmf.datamodel.models) {
269
182
  const folder = (0, utils_1.pascalToKebabCase)(modelName); // kebab, e.g. project-member
270
183
  if (utils_1.IGNORE_FOLDERS.includes(folder))
271
184
  continue;
185
+ const fields = writableFields(model);
272
186
  for (const mode of ['create', 'update']) {
273
187
  const capMode = mode.charAt(0).toUpperCase() + mode.slice(1);
274
188
  const baseClass = `${capMode}${modelName}GeneratedDto`;
275
189
  const subclass = `${capMode}${modelName}Dto`;
276
190
  // Base (overwritten, gitignored).
277
191
  const basePath = path.join(generatedDtoRoot, folder, `${mode}-${folder}.generated.dto.ts`);
278
- (0, utils_1.writeGeneratedFile)(basePath, renderBaseDto(baseClass, model, mode));
192
+ (0, utils_1.writeGeneratedFile)(basePath, renderBaseDto(baseClass, fields, mode));
279
193
  // Subclass (once, hand-owned, committed).
280
194
  const subPath = path.join(modulesRoot, folder, 'dto', `${mode}-${folder}.dto.ts`);
281
195
  const importPath = `../../../generated/dto/${folder}/${mode}-${folder}.generated.dto`;
@@ -12,34 +12,7 @@ export type CorePrismaOptions = {
12
12
  BYPASS_OMISSION?: boolean;
13
13
  BYPASS_FILTERING?: boolean;
14
14
  };
15
- /** Look up a delegate method type without constraining the delegate `D`. */
16
- type MethodOf<D, K extends string> = K extends keyof D ? D[K] : never;
17
- /**
18
- * Re-aligns a Prisma model delegate `D` to the proxy's real contract. Single-
19
- * record methods that require a unique `where` can't carry the injected ABAC
20
- * conditions, so each is re-aliased to its filter-compatible equivalent and the
21
- * proxy transparently redirects the call at runtime:
22
- * - `findUnique` takes `findFirst`'s params/return; `findUniqueOrThrow` takes
23
- * `findFirstOrThrow`'s.
24
- * - `update` takes `updateMany`'s params and returns its result
25
- * (`BatchPayload`); `delete` takes `deleteMany`'s.
26
- */
27
- export type ProxiedDelegate<D> = Omit<D, 'findUnique' | 'findUniqueOrThrow' | 'update' | 'delete'> & {
28
- findUnique: MethodOf<D, 'findFirst'>;
29
- findUniqueOrThrow: MethodOf<D, 'findFirstOrThrow'>;
30
- update: MethodOf<D, 'updateMany'>;
31
- delete: MethodOf<D, 'deleteMany'>;
32
- };
33
- export type CorePrismaModel<M extends ModelKey> = ProxiedDelegate<RuntimeClient[M]>;
34
- /**
35
- * Applies {@link ProxiedDelegate} across every model delegate on a Prisma
36
- * client, leaving non-delegate members (`$transaction`, `$connect`, …) intact.
37
- */
38
- export type CorePrismaClient<C> = {
39
- [K in keyof C]: C[K] extends {
40
- findMany: (...args: any[]) => any;
41
- } ? ProxiedDelegate<C[K]> : C[K];
42
- };
15
+ export type CorePrismaModel<M extends ModelKey> = Exclude<RuntimeClient[M], 'findUnique' | 'findUniqueOrThrow' | 'delete' | 'update'>;
43
16
  export declare class PrismaService {
44
17
  private readonly permissionsConfig;
45
18
  private fieldConfigs;
@@ -63,7 +36,7 @@ export declare class PrismaService {
63
36
  * @param model
64
37
  */
65
38
  getModelDelegate<M extends ModelKey>(model: M): CorePrismaModel<M>;
66
- get model(): CorePrismaClient<RuntimeClient>;
39
+ get model(): RuntimeClient;
67
40
  get user(): CorePrismaModel<'user'>;
68
41
  get session(): CorePrismaModel<'session'>;
69
42
  get userRefreshToken(): any;
@@ -114,26 +87,6 @@ export declare class PrismaService {
114
87
  * cannot evaluate, rather than silently allowing the insert.
115
88
  */
116
89
  private enforceCreateConditions;
117
- /**
118
- * Recursively authorizes nested relation writes in a `create` payload. Only
119
- * an explicit allowlist of operators is permitted, each checked against ABAC;
120
- * every other operator is rejected (fail closed).
121
- *
122
- * Runs on the create path only — `updateMany` / `createMany` (what update /
123
- * createMany resolve to) accept scalar data, so nested relation writes reach
124
- * Prisma solely via `create()`.
125
- *
126
- * - `create` → the child must satisfy the related model's `create` rule
127
- * (recurses, so deeper nesting is authorized too).
128
- * - `connect` → the target must satisfy the related model's `connect` rule.
129
- * `connect` is a DEDICATED action: being allowed to READ a record does not
130
- * authorize associating it.
131
- */
132
- private enforceNestedWrites;
133
- /** Authorizes each operator inside one relation's nested-write object. */
134
- private enforceNestedRelationOps;
135
- /** A `connect` requires an explicit `connect` permission on the target model. */
136
- private assertConnectAllowed;
137
90
  /**
138
91
  * True only in an explicit local-development environment. Deliberately NOT
139
92
  * `!== 'production'` — staging and other envs should behave like production
@@ -1 +1 @@
1
- {"version":3,"file":"prisma.service.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prisma.service.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":"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"}
@@ -16,7 +16,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.PrismaService = exports.CorePrismaContext = void 0;
17
17
  const common_1 = require("@nestjs/common");
18
18
  const client_1 = require("@prisma/client");
19
- const permissionsConfigTypes_1 = require("../common/config/permissionsConfigTypes");
20
19
  const nestjs_request_context_1 = require("nestjs-request-context");
21
20
  const node_async_hooks_1 = require("node:async_hooks");
22
21
  exports.CorePrismaContext = new node_async_hooks_1.AsyncLocalStorage();
@@ -73,19 +72,16 @@ let PrismaService = exports.PrismaService = PrismaService_1 = class PrismaServic
73
72
  this.debug(`Proxying ${String(propKey)}.${String(methodKey)}() for role ${userRole}`);
74
73
  const contextModel = nestjs_request_context_1.RequestContext.currentContext?.req.prisma?.[propKey] || model;
75
74
  return async (params = {}, options) => {
76
- // Single-record methods can't carry the injected ABAC where-
77
- // conditions, so redirect them to their filter-compatible
78
- // equivalents. The proxied types remove/re-alias these, so this
79
- // matches what a typed caller can express: update() runs
80
- // updateMany, delete() runs deleteMany, and a findUnique lookup
81
- // becomes a findFirst with conditions applied.
82
- const redirect = {
75
+ // Blacklisted methods, should not be used to ensure permission filtering is applied
76
+ let blacklist = {
83
77
  findUnique: 'findFirst',
84
78
  findUniqueOrThrow: 'findFirstOrThrow',
85
79
  delete: 'deleteMany',
86
80
  update: 'updateMany',
87
81
  };
88
- methodKey = redirect[methodKey.toString()] ?? methodKey;
82
+ if (blacklist[methodKey.toString()]) {
83
+ throw new Error(`The method ${methodKey.toString()} is not compatible with permission filtering and is not allowed. Please use ${blacklist[methodKey.toString()]}} instead.`);
84
+ }
89
85
  // delete, deleteMany, update and updateMany methods should not apply field omission because they are not selecting fields
90
86
  if (!options?.BYPASS_OMISSION && !['delete', 'deleteMany', 'update', 'updateMany', 'create', 'createMany'].includes(methodKey.toString())) {
91
87
  params = this.applyFieldOmission(String(propKey), userRole, params);
@@ -98,9 +94,6 @@ let PrismaService = exports.PrismaService = PrismaService_1 = class PrismaServic
98
94
  // Conditions can't be pushed into a WHERE on insert, so
99
95
  // validate the incoming data satisfies them before insert.
100
96
  await this.enforceCreateConditions(String(propKey), userRole, params, user, methodKey.toString());
101
- // Authorize any nested relation writes (create/connect) in
102
- // the payload; reject every other nested operator.
103
- await this.enforceNestedWrites(String(propKey), params.data, user, userRole);
104
97
  }
105
98
  else {
106
99
  params = this.applyWhereConditions(String(propKey), userRole, params, user, methodKey);
@@ -482,85 +475,6 @@ let PrismaService = exports.PrismaService = PrismaService_1 = class PrismaServic
482
475
  }
483
476
  }
484
477
  }
485
- /**
486
- * Recursively authorizes nested relation writes in a `create` payload. Only
487
- * an explicit allowlist of operators is permitted, each checked against ABAC;
488
- * every other operator is rejected (fail closed).
489
- *
490
- * Runs on the create path only — `updateMany` / `createMany` (what update /
491
- * createMany resolve to) accept scalar data, so nested relation writes reach
492
- * Prisma solely via `create()`.
493
- *
494
- * - `create` → the child must satisfy the related model's `create` rule
495
- * (recurses, so deeper nesting is authorized too).
496
- * - `connect` → the target must satisfy the related model's `connect` rule.
497
- * `connect` is a DEDICATED action: being allowed to READ a record does not
498
- * authorize associating it.
499
- */
500
- async enforceNestedWrites(modelName, data, user, userRole) {
501
- if (!data || typeof data !== 'object')
502
- return;
503
- const rows = Array.isArray(data) ? data : [data];
504
- for (const row of rows) {
505
- if (!row || typeof row !== 'object')
506
- continue;
507
- for (const key of Object.keys(row)) {
508
- const relation = this.getRelation(modelName, key);
509
- if (!relation)
510
- continue; // scalar / FK field — not a relation nav key
511
- const ops = row[key];
512
- if (!ops || typeof ops !== 'object')
513
- continue;
514
- await this.enforceNestedRelationOps(relation.model, key, ops, user, userRole, modelName);
515
- }
516
- }
517
- }
518
- /** Authorizes each operator inside one relation's nested-write object. */
519
- async enforceNestedRelationOps(relatedModel, field, ops, user, userRole, parentModel) {
520
- const ALLOWED = ['create', 'connect'];
521
- for (const op of Object.keys(ops)) {
522
- if (!ALLOWED.includes(op)) {
523
- throw new common_1.ForbiddenException(`Nested '${op}' on relation '${field}' of ${parentModel} is not supported through the data-access proxy. ` +
524
- `Only ${ALLOWED.join(' / ')} are permitted; perform other nested writes in an explicit endpoint with its own authorization.`);
525
- }
526
- const value = ops[op];
527
- const items = Array.isArray(value) ? value : [value];
528
- if (op === 'create') {
529
- for (const child of items) {
530
- await this.enforceCreateConditions(relatedModel, userRole, { data: child }, user, 'create');
531
- await this.enforceNestedWrites(relatedModel, child, user, userRole);
532
- }
533
- }
534
- else {
535
- for (const target of items) {
536
- await this.assertConnectAllowed(relatedModel, target, user, userRole, field);
537
- }
538
- }
539
- }
540
- }
541
- /** A `connect` requires an explicit `connect` permission on the target model. */
542
- async assertConnectAllowed(relatedModel, where, user, userRole, field) {
543
- const normalizedName = relatedModel.toLowerCase().trim();
544
- const exposedModels = (exports.CorePrismaContext.getStore()?.exposedModels || []).map((m) => m.toLowerCase());
545
- if (exposedModels.includes(normalizedName))
546
- return;
547
- const connectPerm = this.normalizedPermissionsConfig[normalizedName]?.[userRole]?.['connect'];
548
- if (!connectPerm) {
549
- throw new common_1.ForbiddenException(`Not allowed to connect ${relatedModel} (via '${field}'): role ${userRole} has no 'connect' permission on ${relatedModel}.`);
550
- }
551
- if (connectPerm === 'ALL')
552
- return;
553
- const conditions = connectPerm.conditions;
554
- const resolved = conditions
555
- ? PrismaService_1._buildConditions(Array.isArray(conditions) ? { AND: conditions } : conditions, user)
556
- : {};
557
- const delegate = relatedModel.charAt(0).toLowerCase() + relatedModel.slice(1);
558
- const client = nestjs_request_context_1.RequestContext.currentContext?.req.prisma || this.rawClient;
559
- const found = await client[delegate].findFirst({ where: { AND: [where || {}, resolved] } });
560
- if (!found) {
561
- throw new common_1.ForbiddenException(`Not allowed to connect ${relatedModel} (via '${field}'): the target does not satisfy the 'connect' permission conditions for role ${userRole}.`);
562
- }
563
- }
564
478
  /**
565
479
  * True only in an explicit local-development environment. Deliberately NOT
566
480
  * `!== 'production'` — staging and other envs should behave like production
@@ -854,14 +768,6 @@ let PrismaService = exports.PrismaService = PrismaService_1 = class PrismaServic
854
768
  actionPermissions = permissions['findFirst'];
855
769
  }
856
770
  }
857
- // A `*Many` action inherits the singular rule when not set explicitly
858
- // (updateMany → update, deleteMany → delete). `update()` / `delete()`
859
- // redirect to their `*Many` form, so this is what makes a config that
860
- // declares only `update` / `delete` apply to them.
861
- if (!actionPermissions && permissionsConfigTypes_1.SINGULAR_ACTION[action] && permissions[permissionsConfigTypes_1.SINGULAR_ACTION[action]]) {
862
- this.debug(`Using '${permissionsConfigTypes_1.SINGULAR_ACTION[action]}' permissions for '${action}' action on model '${modelName}' and role ${userRole}`, 'info');
863
- actionPermissions = permissions[permissionsConfigTypes_1.SINGULAR_ACTION[action]];
864
- }
865
771
  return actionPermissions;
866
772
  }
867
773
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appxdigital/appx-core",
3
- "version": "0.1.121-beta.11",
3
+ "version": "0.1.121-beta.5",
4
4
  "description": "Appx Core is a library that provides a set of tools to help you build your application faster.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -99,11 +99,7 @@
99
99
  "rxjs": "~7.8.1"
100
100
  },
101
101
  "files": [
102
- "dist",
103
- "docs",
104
- "CHANGELOG.md",
105
- "PRERELEASES.md",
106
- "RELEASING.md"
102
+ "dist"
107
103
  ],
108
104
  "engines": {
109
105
  "npm": ">=10.0.0",