@appxdigital/appx-core 0.1.78 → 0.1.80

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.
@@ -69,6 +69,40 @@ export declare class PrismaService {
69
69
  * @throws ForbiddenException if no valid `where` conditions are present after applying permissions.
70
70
  */
71
71
  private applyWhereConditions;
72
+ /**
73
+ * Extracts the `where` conditions from a `select` object.
74
+ * Documentation specifies this structure, however depending on the relation it might not be possible.
75
+ const result = await prisma.user.findFirst({
76
+ select: {
77
+ posts: {
78
+ where: {
79
+ published: false,
80
+ },
81
+ select: {
82
+ title: true,
83
+ },
84
+ },
85
+ },
86
+ })
87
+
88
+ * Instead, do it this way:
89
+ const result = await prisma.user.findFirst({
90
+ where: {
91
+ posts: {
92
+ published: false,
93
+ },
94
+ },
95
+ select: {
96
+ posts: {
97
+ select: {
98
+ title: true,
99
+ },
100
+ },
101
+ },
102
+ })
103
+
104
+ */
105
+ private extractWhereFromSelect;
72
106
  getRelationType(parentModel: string, relatedField: string): {
73
107
  relation: null;
74
108
  identifier: null;
@@ -1 +1 @@
1
- {"version":3,"file":"prisma.service.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AAI9E,OAAO,KAAK,EAAC,YAAY,IAAI,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAElE,KAAK,QAAQ,GAAG,MAAM,aAAa,CAAC;AAEpC,qBACa,aAAa;IAOY,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IANpE,OAAO,CAAC,YAAY,CAA2B;IAC/C,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,CAAC,UAAU,CAAc;gBAG5B,YAAY,EAAE,YAAY,EACqB,iBAAiB,EAAE,qBAAqB;IAO3F,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC;IAIpE,WAAW;IA4CX;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAYhE,IAAI,KAAK,IAAI,aAAa,CAUzB;IAED,IAAI,IAAI,IAAI,aAAa,CAAC,MAAM,CAAC,CAEhC;IAED,IAAI,OAAO,IAAI,aAAa,CAAC,SAAS,CAAC,CAEtC;IAED,IAAI,gBAAgB,QAEnB;IAED;;;OAGG;IACH,WAAW;IASX;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;IA4B/B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAsD9B,OAAO,CAAC,YAAY;IAMpB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAiC1B,IAAI,2BAA2B,QAM9B;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAqG5B,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;;;IAoCzD;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAQvB;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAkDzB;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;CAgB9B"}
1
+ {"version":3,"file":"prisma.service.d.ts","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAC,qBAAqB,EAAC,MAAM,yCAAyC,CAAC;AAI9E,OAAO,KAAK,EAAC,YAAY,IAAI,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAElE,KAAK,QAAQ,GAAG,MAAM,aAAa,CAAC;AAEpC,qBACa,aAAa;IAOY,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IANpE,OAAO,CAAC,YAAY,CAA2B;IAC/C,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,CAAC,UAAU,CAAc;gBAG5B,YAAY,EAAE,YAAY,EACqB,iBAAiB,EAAE,qBAAqB;IAO3F,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC;IAIpE,WAAW;IA8CX;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAYhE,IAAI,KAAK,IAAI,aAAa,CAUzB;IAED,IAAI,IAAI,IAAI,aAAa,CAAC,MAAM,CAAC,CAEhC;IAED,IAAI,OAAO,IAAI,aAAa,CAAC,SAAS,CAAC,CAEtC;IAED,IAAI,gBAAgB,QAEnB;IAED;;;OAGG;IACH,WAAW;IASX;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;IA4B/B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAsD9B,OAAO,CAAC,YAAY;IAMpB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAiC1B,IAAI,2BAA2B,QAM9B;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAkG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,OAAO,CAAC,sBAAsB;IAuB9B,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;;;IAoCzD;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAQvB;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAkDzB;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;CAiB9B"}
@@ -82,6 +82,8 @@ let PrismaService = class PrismaService {
82
82
  params = this.applyFieldOmission(String(propKey), userRole, params);
83
83
  if (!options?.BYPASS_FILTERING) {
84
84
  params = this.applyWhereConditions(String(propKey), userRole, params, user, methodKey);
85
+ // Extract where conditions from inside select
86
+ params = this.extractWhereFromSelect(params);
85
87
  // findUnique should be findFirst for where conditions to work properly
86
88
  if (methodKey === 'findUnique')
87
89
  methodKey = 'findFirst';
@@ -314,7 +316,22 @@ let PrismaService = class PrismaService {
314
316
  continue;
315
317
  }
316
318
  if (permissionsConfig[model.toLowerCase()]) {
317
- this.applyWhereConditions(model, userRole, args.select[model], user, action);
319
+ /* Where conditions are applied outside of the select. Example as per documentation:
320
+ const result = await prisma.user.findFirst({
321
+ select: {
322
+ posts: {
323
+ where: {
324
+ published: false,
325
+ },
326
+ select: {
327
+ title: true,
328
+ },
329
+ },
330
+ },
331
+ })
332
+ */
333
+ args.select[model].where = this.applyWhereConditions(model, userRole, args.select[model], user, action).where;
334
+ delete args.select[model].select.where;
318
335
  }
319
336
  else {
320
337
  throw new common_1.ForbiddenException(`No permissions found for model ${model} and role ${userRole}`);
@@ -330,9 +347,11 @@ let PrismaService = class PrismaService {
330
347
  }
331
348
  const whereClause = this.buildConditions(actionPermissions.conditions, user);
332
349
  if (!args.where) {
333
- args.where = {};
350
+ args.where = whereClause;
351
+ }
352
+ else {
353
+ args.where = { AND: [args.where, whereClause] };
334
354
  }
335
- args.where = { AND: [args.where, whereClause] };
336
355
  //TODO Test this in more scenarios, it may need to be more robust, it's a quick fix but I must make sure it wont be abused by adding a model with this type of relation to bypass something it shouldn't
337
356
  if (Object.keys(args.where).length === 0 && !belongsToQueue?.length) {
338
357
  throw new common_1.ForbiddenException(`You are not authorized to access this record`);
@@ -348,22 +367,57 @@ let PrismaService = class PrismaService {
348
367
  ]
349
368
  }
350
369
  };
351
- //TODO This may no longer be of use, since we are defaulting to not returning the parent if it includes a model the user has no access to.
352
- // if (relatedPermissions?.conditions) {
353
- // const relatedWhere = this.buildConditions(relatedPermissions.conditions, user);
354
- // const foreignKey = relation.identifier;
355
- // const foreignKeyValue = args.where?.[foreignKey];
356
- // const requiredValue = relatedWhere[foreignKey] || relatedWhere.id;
357
- //
358
- //
359
- // if (requiredValue !== undefined && foreignKeyValue !== requiredValue) {
360
- // throw new common_1.ForbiddenException(
361
- // `Access denied: You are requesting ${modelName.toUpperCase()} with an associated ${relatedModel.toUpperCase()}, ` +
362
- // `but your permissions only allow access to ${relatedModel.toUpperCase()} where ${foreignKey} is ${requiredValue}. ` +
363
- // `The requested record has ${foreignKey} = ${foreignKeyValue}.`
364
- // );
365
- // }
366
- // }
370
+ }
371
+ return args;
372
+ }
373
+ /**
374
+ * Extracts the `where` conditions from a `select` object.
375
+ * Documentation specifies this structure, however depending on the relation it might not be possible.
376
+ const result = await prisma.user.findFirst({
377
+ select: {
378
+ posts: {
379
+ where: {
380
+ published: false,
381
+ },
382
+ select: {
383
+ title: true,
384
+ },
385
+ },
386
+ },
387
+ })
388
+
389
+ * Instead, do it this way:
390
+ const result = await prisma.user.findFirst({
391
+ where: {
392
+ posts: {
393
+ published: false,
394
+ },
395
+ },
396
+ select: {
397
+ posts: {
398
+ select: {
399
+ title: true,
400
+ },
401
+ },
402
+ },
403
+ })
404
+
405
+ */
406
+ extractWhereFromSelect(args) {
407
+ if (!args || !args.select) {
408
+ return args;
409
+ }
410
+ const whereConditions = {};
411
+ for (const key in args.select) {
412
+ if (args.select[key] && typeof args.select[key] === 'object') {
413
+ if (args.select[key].where) {
414
+ whereConditions[key] = args.select[key].where;
415
+ delete args.select[key].where;
416
+ }
417
+ }
418
+ }
419
+ if (Object.keys(whereConditions).length > 0) {
420
+ args.where = { ...args.where, ...whereConditions };
367
421
  }
368
422
  return args;
369
423
  }
@@ -507,7 +561,8 @@ let PrismaService = class PrismaService {
507
561
  throw new Error(`Model information not found for ${parentModelName}`);
508
562
  }
509
563
  if (modelInfo.relationFields.includes(relationKey)) {
510
- return modelInfo.fieldTypes[relationKey].toLowerCase();
564
+ // Remove [] and ? from the field type to get the related model name TODO assumes that there are no other relation qualifiers
565
+ return modelInfo.fieldTypes[relationKey].toLowerCase().replace('[]', '').replace('?', '');
511
566
  }
512
567
  throw new Error(`Relation key ${relationKey} not found in model ${parentModelName}`);
513
568
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appxdigital/appx-core",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
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",