@zenstackhq/runtime 1.0.0-beta.20 → 1.0.0-beta.21
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/constants.d.ts +0 -12
- package/constants.js +1 -13
- package/constants.js.map +1 -1
- package/enhancements/policy/handler.d.ts +13 -7
- package/enhancements/policy/handler.js +127 -100
- package/enhancements/policy/handler.js.map +1 -1
- package/enhancements/policy/index.d.ts +1 -1
- package/enhancements/policy/policy-utils.d.ts +7 -3
- package/enhancements/policy/policy-utils.js +211 -224
- package/enhancements/policy/policy-utils.js.map +1 -1
- package/enhancements/policy/promise.d.ts +5 -0
- package/enhancements/policy/promise.js +42 -0
- package/enhancements/policy/promise.js.map +1 -0
- package/enhancements/proxy.js +27 -21
- package/enhancements/proxy.js.map +1 -1
- package/enhancements/utils.js +1 -2
- package/enhancements/utils.js.map +1 -1
- package/package.json +1 -1
- package/types.d.ts +14 -13
- package/types.js.map +1 -1
- package/validation.d.ts +5 -0
- package/validation.js +13 -1
- package/validation.js.map +1 -1
- package/zod/index.d.ts +1 -0
- package/zod/index.js +1 -0
- package/zod/objects.d.ts +1 -0
- package/zod/objects.js +8 -0
|
@@ -214,143 +214,133 @@ class PolicyUtil {
|
|
|
214
214
|
* Injects model auth guard as where clause.
|
|
215
215
|
*/
|
|
216
216
|
injectAuthGuard(db, args, model, operation) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
let guard = this.getAuthGuard(db, model, operation);
|
|
218
|
+
if (this.isFalse(guard)) {
|
|
219
|
+
args.where = this.makeFalse();
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
if (operation === 'update' && args) {
|
|
223
|
+
// merge field-level policy guards
|
|
224
|
+
const fieldUpdateGuard = this.getFieldUpdateGuards(db, model, args);
|
|
225
|
+
if (fieldUpdateGuard.rejectedByField) {
|
|
226
|
+
// rejected
|
|
220
227
|
args.where = this.makeFalse();
|
|
221
228
|
return false;
|
|
222
229
|
}
|
|
223
|
-
if (
|
|
224
|
-
// merge
|
|
225
|
-
|
|
226
|
-
if (fieldUpdateGuard.rejectedByField) {
|
|
227
|
-
// rejected
|
|
228
|
-
args.where = this.makeFalse();
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
else if (fieldUpdateGuard.guard) {
|
|
232
|
-
// merge
|
|
233
|
-
guard = this.and(guard, fieldUpdateGuard.guard);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (args.where) {
|
|
237
|
-
// inject into relation fields:
|
|
238
|
-
// to-many: some/none/every
|
|
239
|
-
// to-one: direct-conditions/is/isNot
|
|
240
|
-
yield this.injectGuardForRelationFields(db, model, args.where, operation);
|
|
230
|
+
else if (fieldUpdateGuard.guard) {
|
|
231
|
+
// merge
|
|
232
|
+
guard = this.and(guard, fieldUpdateGuard.guard);
|
|
241
233
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
234
|
+
}
|
|
235
|
+
if (args.where) {
|
|
236
|
+
// inject into relation fields:
|
|
237
|
+
// to-many: some/none/every
|
|
238
|
+
// to-one: direct-conditions/is/isNot
|
|
239
|
+
this.injectGuardForRelationFields(db, model, args.where, operation);
|
|
240
|
+
}
|
|
241
|
+
args.where = this.and(args.where, guard);
|
|
242
|
+
return true;
|
|
245
243
|
}
|
|
246
244
|
injectGuardForRelationFields(db, model, payload, operation) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
const fieldInfo = yield (0, model_meta_1.resolveField)(this.modelMeta, model, field);
|
|
253
|
-
if (!fieldInfo || !fieldInfo.isDataModel) {
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
if (fieldInfo.isArray) {
|
|
257
|
-
yield this.injectGuardForToManyField(db, fieldInfo, subPayload, operation);
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
yield this.injectGuardForToOneField(db, fieldInfo, subPayload, operation);
|
|
261
|
-
}
|
|
245
|
+
for (const [field, subPayload] of Object.entries(payload)) {
|
|
246
|
+
if (!subPayload) {
|
|
247
|
+
continue;
|
|
262
248
|
}
|
|
263
|
-
|
|
249
|
+
const fieldInfo = (0, model_meta_1.resolveField)(this.modelMeta, model, field);
|
|
250
|
+
if (!fieldInfo || !fieldInfo.isDataModel) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (fieldInfo.isArray) {
|
|
254
|
+
this.injectGuardForToManyField(db, fieldInfo, subPayload, operation);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
this.injectGuardForToOneField(db, fieldInfo, subPayload, operation);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
264
260
|
}
|
|
265
261
|
injectGuardForToManyField(db, fieldInfo, payload, operation) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
});
|
|
262
|
+
const guard = this.getAuthGuard(db, fieldInfo.type, operation);
|
|
263
|
+
if (payload.some) {
|
|
264
|
+
this.injectGuardForRelationFields(db, fieldInfo.type, payload.some, operation);
|
|
265
|
+
// turn "some" into: { some: { AND: [guard, payload.some] } }
|
|
266
|
+
payload.some = this.and(payload.some, guard);
|
|
267
|
+
}
|
|
268
|
+
if (payload.none) {
|
|
269
|
+
this.injectGuardForRelationFields(db, fieldInfo.type, payload.none, operation);
|
|
270
|
+
// turn none into: { none: { AND: [guard, payload.none] } }
|
|
271
|
+
payload.none = this.and(payload.none, guard);
|
|
272
|
+
}
|
|
273
|
+
if (payload.every &&
|
|
274
|
+
typeof payload.every === 'object' &&
|
|
275
|
+
// ignore empty every clause
|
|
276
|
+
Object.keys(payload.every).length > 0) {
|
|
277
|
+
this.injectGuardForRelationFields(db, fieldInfo.type, payload.every, operation);
|
|
278
|
+
// turn "every" into: { none: { AND: [guard, { NOT: payload.every }] } }
|
|
279
|
+
if (!payload.none) {
|
|
280
|
+
payload.none = {};
|
|
281
|
+
}
|
|
282
|
+
payload.none = this.and(payload.none, guard, this.not(payload.every));
|
|
283
|
+
delete payload.every;
|
|
284
|
+
}
|
|
291
285
|
}
|
|
292
286
|
injectGuardForToOneField(db, fieldInfo, payload, operation) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (payload.is
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
payload.is = this.and(payload.is, guard);
|
|
300
|
-
}
|
|
301
|
-
if (payload.isNot) {
|
|
302
|
-
yield this.injectGuardForRelationFields(db, fieldInfo.type, payload.isNot, operation);
|
|
303
|
-
// turn "isNot" into: { isNot: { AND: [ originalIsNot, { NOT: guard } ] } }
|
|
304
|
-
payload.isNot = this.and(payload.isNot, this.not(guard));
|
|
305
|
-
delete payload.isNot;
|
|
306
|
-
}
|
|
287
|
+
const guard = this.getAuthGuard(db, fieldInfo.type, operation);
|
|
288
|
+
if (payload.is || payload.isNot) {
|
|
289
|
+
if (payload.is) {
|
|
290
|
+
this.injectGuardForRelationFields(db, fieldInfo.type, payload.is, operation);
|
|
291
|
+
// turn "is" into: { is: { AND: [ originalIs, guard ] }
|
|
292
|
+
payload.is = this.and(payload.is, guard);
|
|
307
293
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
// turn
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
payload.is = combined;
|
|
294
|
+
if (payload.isNot) {
|
|
295
|
+
this.injectGuardForRelationFields(db, fieldInfo.type, payload.isNot, operation);
|
|
296
|
+
// turn "isNot" into: { isNot: { AND: [ originalIsNot, { NOT: guard } ] } }
|
|
297
|
+
payload.isNot = this.and(payload.isNot, this.not(guard));
|
|
298
|
+
delete payload.isNot;
|
|
314
299
|
}
|
|
315
|
-
}
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
this.injectGuardForRelationFields(db, fieldInfo.type, payload, operation);
|
|
303
|
+
// turn direct conditions into: { is: { AND: [ originalConditions, guard ] } }
|
|
304
|
+
const combined = this.and((0, deepcopy_1.default)(payload), guard);
|
|
305
|
+
Object.keys(payload).forEach((key) => delete payload[key]);
|
|
306
|
+
payload.is = combined;
|
|
307
|
+
}
|
|
316
308
|
}
|
|
317
309
|
/**
|
|
318
310
|
* Injects auth guard for read operations.
|
|
319
311
|
*/
|
|
320
312
|
injectForRead(db, model, args) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
313
|
+
const injected = {};
|
|
314
|
+
if (!this.injectAuthGuard(db, injected, model, 'read')) {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
if (args.where) {
|
|
318
|
+
// inject into relation fields:
|
|
319
|
+
// to-many: some/none/every
|
|
320
|
+
// to-one: direct-conditions/is/isNot
|
|
321
|
+
this.injectGuardForRelationFields(db, model, args.where, 'read');
|
|
322
|
+
}
|
|
323
|
+
if (injected.where && Object.keys(injected.where).length > 0 && !this.isTrue(injected.where)) {
|
|
324
|
+
if (!args.where) {
|
|
325
|
+
args.where = injected.where;
|
|
325
326
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
// to-many: some/none/every
|
|
329
|
-
// to-one: direct-conditions/is/isNot
|
|
330
|
-
yield this.injectGuardForRelationFields(db, model, args.where, 'read');
|
|
327
|
+
else {
|
|
328
|
+
this.mergeWhereClause(args.where, injected.where);
|
|
331
329
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
330
|
+
}
|
|
331
|
+
// recursively inject read guard conditions into nested select, include, and _count
|
|
332
|
+
const hoistedConditions = this.injectNestedReadConditions(db, model, args);
|
|
333
|
+
// the injection process may generate conditions that need to be hoisted to the toplevel,
|
|
334
|
+
// if so, merge it with the existing where
|
|
335
|
+
if (hoistedConditions.length > 0) {
|
|
336
|
+
if (!args.where) {
|
|
337
|
+
args.where = this.and(...hoistedConditions);
|
|
339
338
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
// the injection process may generate conditions that need to be hoisted to the toplevel,
|
|
343
|
-
// if so, merge it with the existing where
|
|
344
|
-
if (hoistedConditions.length > 0) {
|
|
345
|
-
if (!args.where) {
|
|
346
|
-
args.where = this.and(...hoistedConditions);
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
this.mergeWhereClause(args.where, this.and(...hoistedConditions));
|
|
350
|
-
}
|
|
339
|
+
else {
|
|
340
|
+
this.mergeWhereClause(args.where, this.and(...hoistedConditions));
|
|
351
341
|
}
|
|
352
|
-
|
|
353
|
-
|
|
342
|
+
}
|
|
343
|
+
return true;
|
|
354
344
|
}
|
|
355
345
|
// flatten unique constraint filters
|
|
356
346
|
flattenGeneratedUniqueField(model, args) {
|
|
@@ -382,130 +372,126 @@ class PolicyUtil {
|
|
|
382
372
|
* Builds a reversed query for the given nested path.
|
|
383
373
|
*/
|
|
384
374
|
buildReversedQuery(context) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
375
|
+
let result, currQuery;
|
|
376
|
+
let currField;
|
|
377
|
+
for (let i = context.nestingPath.length - 1; i >= 0; i--) {
|
|
378
|
+
const { field, model, where } = context.nestingPath[i];
|
|
379
|
+
// never modify the original where because it's shared in the structure
|
|
380
|
+
const visitWhere = Object.assign({}, where);
|
|
381
|
+
if (model && where) {
|
|
382
|
+
// make sure composite unique condition is flattened
|
|
383
|
+
this.flattenGeneratedUniqueField(model, visitWhere);
|
|
384
|
+
}
|
|
385
|
+
if (!result) {
|
|
386
|
+
// first segment (bottom), just use its where clause
|
|
387
|
+
result = currQuery = Object.assign({}, visitWhere);
|
|
388
|
+
currField = field;
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
if (!currField) {
|
|
392
|
+
throw this.unknownError(`missing field in nested path`);
|
|
395
393
|
}
|
|
396
|
-
if (!
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
394
|
+
if (!currField.backLink) {
|
|
395
|
+
throw this.unknownError(`field ${currField.type}.${currField.name} doesn't have a backLink`);
|
|
396
|
+
}
|
|
397
|
+
const backLinkField = this.getModelField(currField.type, currField.backLink);
|
|
398
|
+
if (backLinkField === null || backLinkField === void 0 ? void 0 : backLinkField.isArray) {
|
|
399
|
+
// many-side of relationship, wrap with "some" query
|
|
400
|
+
currQuery[currField.backLink] = { some: Object.assign({}, visitWhere) };
|
|
400
401
|
}
|
|
401
402
|
else {
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if (!currField.backLink) {
|
|
406
|
-
throw this.unknownError(`field ${currField.type}.${currField.name} doesn't have a backLink`);
|
|
407
|
-
}
|
|
408
|
-
const backLinkField = this.getModelField(currField.type, currField.backLink);
|
|
409
|
-
if (backLinkField === null || backLinkField === void 0 ? void 0 : backLinkField.isArray) {
|
|
410
|
-
// many-side of relationship, wrap with "some" query
|
|
411
|
-
currQuery[currField.backLink] = { some: Object.assign({}, visitWhere) };
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
414
|
-
if (where && backLinkField.isRelationOwner && backLinkField.foreignKeyMapping) {
|
|
415
|
-
for (const [r, fk] of Object.entries(backLinkField.foreignKeyMapping)) {
|
|
416
|
-
currQuery[fk] = visitWhere[r];
|
|
417
|
-
}
|
|
418
|
-
if (i > 0) {
|
|
419
|
-
currQuery[currField.backLink] = {};
|
|
420
|
-
}
|
|
403
|
+
if (where && backLinkField.isRelationOwner && backLinkField.foreignKeyMapping) {
|
|
404
|
+
for (const [r, fk] of Object.entries(backLinkField.foreignKeyMapping)) {
|
|
405
|
+
currQuery[fk] = visitWhere[r];
|
|
421
406
|
}
|
|
422
|
-
|
|
423
|
-
currQuery[currField.backLink] =
|
|
407
|
+
if (i > 0) {
|
|
408
|
+
currQuery[currField.backLink] = {};
|
|
424
409
|
}
|
|
425
410
|
}
|
|
426
|
-
|
|
427
|
-
|
|
411
|
+
else {
|
|
412
|
+
currQuery[currField.backLink] = Object.assign({}, visitWhere);
|
|
413
|
+
}
|
|
428
414
|
}
|
|
415
|
+
currQuery = currQuery[currField.backLink];
|
|
416
|
+
currField = field;
|
|
429
417
|
}
|
|
430
|
-
|
|
431
|
-
|
|
418
|
+
}
|
|
419
|
+
return result;
|
|
432
420
|
}
|
|
433
421
|
injectNestedReadConditions(db, model, args) {
|
|
434
422
|
var _a;
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
injectTarget._count.select[k] = {};
|
|
452
|
-
}
|
|
423
|
+
const injectTarget = (_a = args.select) !== null && _a !== void 0 ? _a : args.include;
|
|
424
|
+
if (!injectTarget) {
|
|
425
|
+
return [];
|
|
426
|
+
}
|
|
427
|
+
if (injectTarget._count !== undefined) {
|
|
428
|
+
// _count needs to respect read policies of related models
|
|
429
|
+
if (injectTarget._count === true) {
|
|
430
|
+
// include count for all relations, expand to all fields
|
|
431
|
+
// so that we can inject guard conditions for each of them
|
|
432
|
+
injectTarget._count = { select: {} };
|
|
433
|
+
const modelFields = (0, model_meta_1.getFields)(this.modelMeta, model);
|
|
434
|
+
if (modelFields) {
|
|
435
|
+
for (const [k, v] of Object.entries(modelFields)) {
|
|
436
|
+
if (v.isDataModel && v.isArray) {
|
|
437
|
+
// create an entry for to-many relation
|
|
438
|
+
injectTarget._count.select[k] = {};
|
|
453
439
|
}
|
|
454
440
|
}
|
|
455
441
|
}
|
|
456
|
-
// inject conditions for each relation
|
|
457
|
-
for (const field of Object.keys(injectTarget._count.select)) {
|
|
458
|
-
if (typeof injectTarget._count.select[field] !== 'object') {
|
|
459
|
-
injectTarget._count.select[field] = {};
|
|
460
|
-
}
|
|
461
|
-
const fieldInfo = (0, model_meta_1.resolveField)(this.modelMeta, model, field);
|
|
462
|
-
if (!fieldInfo) {
|
|
463
|
-
continue;
|
|
464
|
-
}
|
|
465
|
-
// inject into the "where" clause inside select
|
|
466
|
-
yield this.injectAuthGuard(db, injectTarget._count.select[field], fieldInfo.type, 'read');
|
|
467
|
-
}
|
|
468
442
|
}
|
|
469
|
-
//
|
|
470
|
-
const
|
|
471
|
-
|
|
443
|
+
// inject conditions for each relation
|
|
444
|
+
for (const field of Object.keys(injectTarget._count.select)) {
|
|
445
|
+
if (typeof injectTarget._count.select[field] !== 'object') {
|
|
446
|
+
injectTarget._count.select[field] = {};
|
|
447
|
+
}
|
|
472
448
|
const fieldInfo = (0, model_meta_1.resolveField)(this.modelMeta, model, field);
|
|
473
|
-
if (!fieldInfo
|
|
474
|
-
// only care about relation fields
|
|
449
|
+
if (!fieldInfo) {
|
|
475
450
|
continue;
|
|
476
451
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
452
|
+
// inject into the "where" clause inside select
|
|
453
|
+
this.injectAuthGuard(db, injectTarget._count.select[field], fieldInfo.type, 'read');
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// collect filter conditions that should be hoisted to the toplevel
|
|
457
|
+
const hoistedConditions = [];
|
|
458
|
+
for (const field of (0, utils_1.getModelFields)(injectTarget)) {
|
|
459
|
+
const fieldInfo = (0, model_meta_1.resolveField)(this.modelMeta, model, field);
|
|
460
|
+
if (!fieldInfo || !fieldInfo.isDataModel) {
|
|
461
|
+
// only care about relation fields
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
let hoisted;
|
|
465
|
+
if (fieldInfo.isArray ||
|
|
466
|
+
// Injecting where at include/select level for nullable to-one relation is supported since Prisma 4.8.0
|
|
467
|
+
// https://github.com/prisma/prisma/discussions/20350
|
|
468
|
+
fieldInfo.isOptional) {
|
|
469
|
+
if (typeof injectTarget[field] !== 'object') {
|
|
470
|
+
injectTarget[field] = {};
|
|
493
471
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
}
|
|
472
|
+
// inject extra condition for to-many or nullable to-one relation
|
|
473
|
+
this.injectAuthGuard(db, injectTarget[field], fieldInfo.type, 'read');
|
|
474
|
+
// recurse
|
|
475
|
+
const subHoisted = this.injectNestedReadConditions(db, fieldInfo.type, injectTarget[field]);
|
|
476
|
+
if (subHoisted.length > 0) {
|
|
477
|
+
// we can convert it to a where at this level
|
|
478
|
+
injectTarget[field].where = this.and(injectTarget[field].where, ...subHoisted);
|
|
502
479
|
}
|
|
503
|
-
|
|
504
|
-
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
// hoist non-nullable to-one filter to the parent level
|
|
483
|
+
hoisted = this.getAuthGuard(db, fieldInfo.type, 'read');
|
|
484
|
+
// recurse
|
|
485
|
+
const subHoisted = this.injectNestedReadConditions(db, fieldInfo.type, injectTarget[field]);
|
|
486
|
+
if (subHoisted.length > 0) {
|
|
487
|
+
hoisted = this.and(hoisted, ...subHoisted);
|
|
505
488
|
}
|
|
506
489
|
}
|
|
507
|
-
|
|
508
|
-
|
|
490
|
+
if (hoisted && !this.isTrue(hoisted)) {
|
|
491
|
+
hoistedConditions.push({ [field]: hoisted });
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return hoistedConditions;
|
|
509
495
|
}
|
|
510
496
|
/**
|
|
511
497
|
* Given a model and a unique filter, checks the operation is allowed by policies and field validations.
|
|
@@ -619,7 +605,7 @@ class PolicyUtil {
|
|
|
619
605
|
this.flattenGeneratedUniqueField(model, uniqueFilter);
|
|
620
606
|
const readArgs = { select: selectInclude.select, include: selectInclude.include, where: uniqueFilter };
|
|
621
607
|
const error = this.deniedByPolicy(model, operation, 'result is not allowed to be read back', constants_1.CrudFailureReason.RESULT_NOT_READABLE);
|
|
622
|
-
const injectResult =
|
|
608
|
+
const injectResult = this.injectForRead(db, model, readArgs);
|
|
623
609
|
if (!injectResult) {
|
|
624
610
|
return { error, result: undefined };
|
|
625
611
|
}
|
|
@@ -805,12 +791,6 @@ class PolicyUtil {
|
|
|
805
791
|
if (typeof entityData !== 'object' || !entityData) {
|
|
806
792
|
return;
|
|
807
793
|
}
|
|
808
|
-
// strip auxiliary fields
|
|
809
|
-
for (const auxField of constants_1.AUXILIARY_FIELDS) {
|
|
810
|
-
if (auxField in entityData) {
|
|
811
|
-
delete entityData[auxField];
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
794
|
for (const [field, fieldData] of Object.entries(entityData)) {
|
|
815
795
|
if (fieldData === undefined) {
|
|
816
796
|
continue;
|
|
@@ -859,6 +839,13 @@ class PolicyUtil {
|
|
|
859
839
|
}
|
|
860
840
|
}
|
|
861
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
* Gets information for all fields of a model.
|
|
844
|
+
*/
|
|
845
|
+
getModelFields(model) {
|
|
846
|
+
model = (0, lower_case_first_1.lowerCaseFirst)(model);
|
|
847
|
+
return this.modelMeta.fields[model];
|
|
848
|
+
}
|
|
862
849
|
/**
|
|
863
850
|
* Gets information for a specific model field.
|
|
864
851
|
*/
|