@zenstackhq/runtime 2.0.0-beta.1 → 2.0.0-beta.10
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/enhancements/create-enhancement.d.ts +1 -1
- package/enhancements/create-enhancement.js +14 -19
- package/enhancements/create-enhancement.js.map +1 -1
- package/enhancements/delegate.js +3 -1
- package/enhancements/delegate.js.map +1 -1
- package/enhancements/logger.js +11 -1
- package/enhancements/logger.js.map +1 -1
- package/enhancements/omit.js +1 -1
- package/enhancements/omit.js.map +1 -1
- package/enhancements/password.js +3 -2
- package/enhancements/password.js.map +1 -1
- package/enhancements/policy/handler.d.ts +5 -8
- package/enhancements/policy/handler.js +161 -164
- package/enhancements/policy/handler.js.map +1 -1
- package/enhancements/policy/policy-utils.d.ts +8 -0
- package/enhancements/policy/policy-utils.js +57 -22
- package/enhancements/policy/policy-utils.js.map +1 -1
- package/enhancements/promise.d.ts +15 -0
- package/enhancements/promise.js +100 -0
- package/enhancements/promise.js.map +1 -0
- package/enhancements/proxy.d.ts +3 -1
- package/enhancements/proxy.js +39 -77
- package/enhancements/proxy.js.map +1 -1
- package/enhancements/query-utils.d.ts +1 -1
- package/enhancements/query-utils.js.map +1 -1
- package/enhancements/types.d.ts +6 -0
- package/enhancements/utils.d.ts +1 -1
- package/enhancements/utils.js +6 -25
- package/enhancements/utils.js.map +1 -1
- package/enhancements/where-visitor.js +1 -1
- package/enhancements/where-visitor.js.map +1 -1
- package/model-meta.d.ts +1 -0
- package/model-meta.js +10 -0
- package/models.d.ts +1 -0
- package/package.json +12 -4
- package/enhancements/policy/promise.d.ts +0 -5
- package/enhancements/policy/promise.js +0 -42
- package/enhancements/policy/promise.js.map +0 -1
- package/prisma.d.ts +0 -1
|
@@ -32,10 +32,10 @@ const zod_validation_error_1 = require("zod-validation-error");
|
|
|
32
32
|
const constants_1 = require("../../constants");
|
|
33
33
|
const cross_1 = require("../../cross");
|
|
34
34
|
const logger_1 = require("../logger");
|
|
35
|
+
const promise_1 = require("../promise");
|
|
35
36
|
const query_utils_1 = require("../query-utils");
|
|
36
37
|
const utils_1 = require("../utils");
|
|
37
38
|
const policy_utils_1 = require("./policy-utils");
|
|
38
|
-
const promise_1 = require("./promise");
|
|
39
39
|
/**
|
|
40
40
|
* Prisma proxy handler for injecting access policy check.
|
|
41
41
|
*/
|
|
@@ -62,7 +62,7 @@ class PolicyProxyHandler {
|
|
|
62
62
|
if (!args.where) {
|
|
63
63
|
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'where field is required in query argument');
|
|
64
64
|
}
|
|
65
|
-
return this.
|
|
65
|
+
return this.findWithFluent('findUnique', args, () => null);
|
|
66
66
|
}
|
|
67
67
|
findUniqueOrThrow(args) {
|
|
68
68
|
if (!args) {
|
|
@@ -71,110 +71,55 @@ class PolicyProxyHandler {
|
|
|
71
71
|
if (!args.where) {
|
|
72
72
|
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'where field is required in query argument');
|
|
73
73
|
}
|
|
74
|
-
return this.
|
|
74
|
+
return this.findWithFluent('findUniqueOrThrow', args, () => {
|
|
75
75
|
throw this.policyUtils.notFound(this.model);
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
findFirst(args) {
|
|
79
|
-
return this.
|
|
79
|
+
return this.findWithFluent('findFirst', args, () => null);
|
|
80
80
|
}
|
|
81
81
|
findFirstOrThrow(args) {
|
|
82
|
-
return this.
|
|
82
|
+
return this.findWithFluent('findFirstOrThrow', args, () => {
|
|
83
83
|
throw this.policyUtils.notFound(this.model);
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
findMany(args) {
|
|
87
87
|
return (0, promise_1.createDeferredPromise)(() => this.doFind(args, 'findMany', () => []));
|
|
88
88
|
}
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
this.addFluentFunctions(result, this.model, args === null || args === void 0 ? void 0 : args.where, resolveRoot ? result : undefined);
|
|
94
|
-
return result;
|
|
89
|
+
// make a find query promise with fluent API call stubs installed
|
|
90
|
+
findWithFluent(method, args, handleRejection) {
|
|
91
|
+
args = this.policyUtils.clone(args);
|
|
92
|
+
return (0, promise_1.createFluentPromise)(() => this.doFind(args, method, handleRejection), args, this.options.modelMeta, this.model);
|
|
95
93
|
}
|
|
96
94
|
doFind(args, actionName, handleRejection) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
const origArgs = args;
|
|
97
|
+
const _args = this.policyUtils.clone(args);
|
|
98
|
+
if (!this.policyUtils.injectForRead(this.prisma, this.model, _args)) {
|
|
99
|
+
if (this.shouldLogQuery) {
|
|
100
|
+
this.logger.info(`[policy] \`${actionName}\` ${this.model}: unconditionally denied`);
|
|
101
|
+
}
|
|
102
|
+
return handleRejection();
|
|
103
|
+
}
|
|
104
|
+
this.policyUtils.injectReadCheckSelect(this.model, _args);
|
|
100
105
|
if (this.shouldLogQuery) {
|
|
101
|
-
this.logger.info(`[policy] \`${actionName}\` ${this.model}
|
|
106
|
+
this.logger.info(`[policy] \`${actionName}\` ${this.model}:\n${(0, utils_1.formatObject)(_args)}`);
|
|
102
107
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (this.shouldLogQuery) {
|
|
107
|
-
this.logger.info(`[policy] \`${actionName}\` ${this.model}:\n${(0, utils_1.formatObject)(_args)}`);
|
|
108
|
-
}
|
|
109
|
-
return new Promise((resolve, reject) => {
|
|
110
|
-
this.modelClient[actionName](_args).then((value) => {
|
|
111
|
-
this.policyUtils.postProcessForRead(value, this.model, origArgs);
|
|
112
|
-
resolve(value);
|
|
113
|
-
}, (err) => reject(err));
|
|
108
|
+
const result = yield this.modelClient[actionName](_args);
|
|
109
|
+
this.policyUtils.postProcessForRead(result, this.model, origArgs);
|
|
110
|
+
return result;
|
|
114
111
|
});
|
|
115
112
|
}
|
|
116
|
-
// returns a fluent API call function
|
|
117
|
-
fluentCall(filter, fieldInfo, rootPromise) {
|
|
118
|
-
return (args) => {
|
|
119
|
-
args = this.policyUtils.clone(args);
|
|
120
|
-
// combine the parent filter with the current one
|
|
121
|
-
const backLinkField = this.requireBackLink(fieldInfo);
|
|
122
|
-
const condition = backLinkField.isArray
|
|
123
|
-
? { [backLinkField.name]: { some: filter } }
|
|
124
|
-
: { [backLinkField.name]: { is: filter } };
|
|
125
|
-
args.where = this.policyUtils.and(args.where, condition);
|
|
126
|
-
const promise = (0, promise_1.createDeferredPromise)(() => {
|
|
127
|
-
// Promise for fetching
|
|
128
|
-
const fetchFluent = (resolve, reject) => {
|
|
129
|
-
const handler = this.makeHandler(fieldInfo.type);
|
|
130
|
-
if (fieldInfo.isArray) {
|
|
131
|
-
// fluent call stops here
|
|
132
|
-
handler.findMany(args).then((value) => resolve(value), (err) => reject(err));
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
handler.findFirst(args).then((value) => resolve(value), (err) => reject(err));
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
return new Promise((resolve, reject) => {
|
|
139
|
-
if (rootPromise) {
|
|
140
|
-
// if a root promise exists, resolve it before fluent API call,
|
|
141
|
-
// so that fluent calls start with `findUniqueOrThrow` and `findFirstOrThrow`
|
|
142
|
-
// can throw error properly if the root promise is rejected
|
|
143
|
-
rootPromise.then(() => fetchFluent(resolve, reject), (err) => reject(err));
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
fetchFluent(resolve, reject);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
if (!fieldInfo.isArray) {
|
|
151
|
-
// prepare for a chained fluent API call
|
|
152
|
-
this.addFluentFunctions(promise, fieldInfo.type, args.where, rootPromise);
|
|
153
|
-
}
|
|
154
|
-
return promise;
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
// add fluent API functions to the given promise
|
|
158
|
-
addFluentFunctions(promise, model, filter, rootPromise) {
|
|
159
|
-
const fields = this.policyUtils.getModelFields(model);
|
|
160
|
-
if (fields) {
|
|
161
|
-
for (const [field, fieldInfo] of Object.entries(fields)) {
|
|
162
|
-
if (fieldInfo.isDataModel) {
|
|
163
|
-
promise[field] = this.fluentCall(filter, fieldInfo, rootPromise);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
113
|
//#endregion
|
|
169
114
|
//#region Create
|
|
170
115
|
create(args) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
116
|
+
if (!args) {
|
|
117
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
118
|
+
}
|
|
119
|
+
if (!args.data) {
|
|
120
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'data field is required in query argument');
|
|
121
|
+
}
|
|
122
|
+
return (0, promise_1.createDeferredPromise)(() => __awaiter(this, void 0, void 0, function* () {
|
|
178
123
|
this.policyUtils.tryReject(this.prisma, this.model, 'create');
|
|
179
124
|
const origArgs = args;
|
|
180
125
|
args = this.policyUtils.clone(args);
|
|
@@ -217,7 +162,7 @@ class PolicyProxyHandler {
|
|
|
217
162
|
else {
|
|
218
163
|
return result;
|
|
219
164
|
}
|
|
220
|
-
});
|
|
165
|
+
}));
|
|
221
166
|
}
|
|
222
167
|
// create with nested write
|
|
223
168
|
doCreate(model, args, db) {
|
|
@@ -337,7 +282,8 @@ class PolicyProxyHandler {
|
|
|
337
282
|
const key = getEntityKey(model, scalarData);
|
|
338
283
|
// only check if entity is created, not connected
|
|
339
284
|
if (!connectedEntities.has(key) && !postCreateChecks.has(key)) {
|
|
340
|
-
|
|
285
|
+
const idFields = this.policyUtils.getIdFieldValues(model, scalarData);
|
|
286
|
+
postCreateChecks.set(key, { model, operation: 'create', uniqueFilter: idFields });
|
|
341
287
|
}
|
|
342
288
|
});
|
|
343
289
|
// return only the ids of the top-level entity
|
|
@@ -399,13 +345,13 @@ class PolicyProxyHandler {
|
|
|
399
345
|
}
|
|
400
346
|
}
|
|
401
347
|
createMany(args) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
348
|
+
if (!args) {
|
|
349
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
350
|
+
}
|
|
351
|
+
if (!args.data) {
|
|
352
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'data field is required in query argument');
|
|
353
|
+
}
|
|
354
|
+
return (0, promise_1.createDeferredPromise)(() => __awaiter(this, void 0, void 0, function* () {
|
|
409
355
|
this.policyUtils.tryReject(this.prisma, this.model, 'create');
|
|
410
356
|
args = this.policyUtils.clone(args);
|
|
411
357
|
// go through create items, statically check input to determine if post-create
|
|
@@ -441,7 +387,7 @@ class PolicyProxyHandler {
|
|
|
441
387
|
return result;
|
|
442
388
|
}));
|
|
443
389
|
}
|
|
444
|
-
});
|
|
390
|
+
}));
|
|
445
391
|
}
|
|
446
392
|
doCreateMany(model, args, db) {
|
|
447
393
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -449,7 +395,7 @@ class PolicyProxyHandler {
|
|
|
449
395
|
// for post-create checks. Instead, do a "create" for each item and collect the results.
|
|
450
396
|
let createResult = yield Promise.all((0, cross_1.enumerate)(args.data).map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
451
397
|
if (args.skipDuplicates) {
|
|
452
|
-
if (yield this.hasDuplicatedUniqueConstraint(model, item, db)) {
|
|
398
|
+
if (yield this.hasDuplicatedUniqueConstraint(model, item, undefined, db)) {
|
|
453
399
|
if (this.shouldLogQuery) {
|
|
454
400
|
this.logger.info(`[policy] \`createMany\` skipping duplicate ${(0, utils_1.formatObject)(item)}`);
|
|
455
401
|
}
|
|
@@ -473,17 +419,59 @@ class PolicyProxyHandler {
|
|
|
473
419
|
};
|
|
474
420
|
});
|
|
475
421
|
}
|
|
476
|
-
hasDuplicatedUniqueConstraint(model, createData, db) {
|
|
422
|
+
hasDuplicatedUniqueConstraint(model, createData, upstreamQuery, db) {
|
|
477
423
|
return __awaiter(this, void 0, void 0, function* () {
|
|
478
424
|
// check unique constraint conflicts
|
|
479
425
|
// we can't rely on try/catch/ignore constraint violation error: https://github.com/prisma/prisma/issues/20496
|
|
480
426
|
// TODO: for simple cases we should be able to translate it to an `upsert` with empty `update` payload
|
|
427
|
+
var _a;
|
|
481
428
|
// for each unique constraint, check if the input item has all fields set, and if so, check if
|
|
482
429
|
// an entity already exists, and ignore accordingly
|
|
483
430
|
const uniqueConstraints = this.policyUtils.getUniqueConstraints(model);
|
|
484
431
|
for (const constraint of Object.values(uniqueConstraints)) {
|
|
485
|
-
|
|
486
|
-
|
|
432
|
+
// the unique filter used to check existence
|
|
433
|
+
const uniqueFilter = {};
|
|
434
|
+
// unique constraint fields not covered yet
|
|
435
|
+
const remainingConstraintFields = new Set(constraint.fields);
|
|
436
|
+
// collect constraint fields from the create data
|
|
437
|
+
for (const [k, v] of Object.entries(createData)) {
|
|
438
|
+
if (v === undefined) {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
if (remainingConstraintFields.has(k)) {
|
|
442
|
+
uniqueFilter[k] = v;
|
|
443
|
+
remainingConstraintFields.delete(k);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// collect constraint fields from the upstream query
|
|
447
|
+
if (upstreamQuery) {
|
|
448
|
+
for (const [k, v] of Object.entries(upstreamQuery)) {
|
|
449
|
+
if (v === undefined) {
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (remainingConstraintFields.has(k)) {
|
|
453
|
+
uniqueFilter[k] = v;
|
|
454
|
+
remainingConstraintFields.delete(k);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
// check if the upstream query contains a relation field which covers
|
|
458
|
+
// a foreign key field constraint
|
|
459
|
+
const fieldInfo = (0, cross_1.requireField)(this.modelMeta, model, k);
|
|
460
|
+
if (!fieldInfo.isDataModel) {
|
|
461
|
+
// only care about relation fields
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
// merge the upstream query into the unique filter
|
|
465
|
+
uniqueFilter[k] = v;
|
|
466
|
+
// mark the corresponding foreign key fields as covered
|
|
467
|
+
const fkMapping = (_a = fieldInfo.foreignKeyMapping) !== null && _a !== void 0 ? _a : {};
|
|
468
|
+
for (const fk of Object.values(fkMapping)) {
|
|
469
|
+
remainingConstraintFields.delete(fk);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (remainingConstraintFields.size === 0) {
|
|
474
|
+
// all constraint fields set, check existence
|
|
487
475
|
const existing = yield this.policyUtils.checkExistence(db, model, uniqueFilter);
|
|
488
476
|
if (existing) {
|
|
489
477
|
return true;
|
|
@@ -501,16 +489,16 @@ class PolicyProxyHandler {
|
|
|
501
489
|
// "updateMany" works against a set of entities, entities not passing policy check are silently
|
|
502
490
|
// ignored
|
|
503
491
|
update(args) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
492
|
+
if (!args) {
|
|
493
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
494
|
+
}
|
|
495
|
+
if (!args.where) {
|
|
496
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'where field is required in query argument');
|
|
497
|
+
}
|
|
498
|
+
if (!args.data) {
|
|
499
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'data field is required in query argument');
|
|
500
|
+
}
|
|
501
|
+
return (0, promise_1.createDeferredPromise)(() => __awaiter(this, void 0, void 0, function* () {
|
|
514
502
|
args = this.policyUtils.clone(args);
|
|
515
503
|
const { result, error } = yield this.queryUtils.transaction(this.prisma, (tx) => __awaiter(this, void 0, void 0, function* () {
|
|
516
504
|
// proceed with nested writes and collect post-write checks
|
|
@@ -526,23 +514,28 @@ class PolicyProxyHandler {
|
|
|
526
514
|
else {
|
|
527
515
|
return result;
|
|
528
516
|
}
|
|
529
|
-
});
|
|
517
|
+
}));
|
|
530
518
|
}
|
|
531
519
|
doUpdate(args, db) {
|
|
532
520
|
return __awaiter(this, void 0, void 0, function* () {
|
|
533
521
|
// collected post-update checks
|
|
534
522
|
const postWriteChecks = [];
|
|
535
523
|
// registers a post-update check task
|
|
536
|
-
const _registerPostUpdateCheck = (model,
|
|
524
|
+
const _registerPostUpdateCheck = (model, preUpdateLookupFilter, postUpdateLookupFilter) => __awaiter(this, void 0, void 0, function* () {
|
|
537
525
|
// both "post-update" rules and Zod schemas require a post-update check
|
|
538
526
|
if (this.policyUtils.hasAuthGuard(model, 'postUpdate') || this.policyUtils.getZodSchema(model)) {
|
|
539
527
|
// select pre-update field values
|
|
540
528
|
let preValue;
|
|
541
529
|
const preValueSelect = this.policyUtils.getPreValueSelect(model);
|
|
542
530
|
if (preValueSelect && Object.keys(preValueSelect).length > 0) {
|
|
543
|
-
preValue = yield db[model].findFirst({ where:
|
|
531
|
+
preValue = yield db[model].findFirst({ where: preUpdateLookupFilter, select: preValueSelect });
|
|
544
532
|
}
|
|
545
|
-
postWriteChecks.push({
|
|
533
|
+
postWriteChecks.push({
|
|
534
|
+
model,
|
|
535
|
+
operation: 'postUpdate',
|
|
536
|
+
uniqueFilter: postUpdateLookupFilter,
|
|
537
|
+
preValue,
|
|
538
|
+
});
|
|
546
539
|
}
|
|
547
540
|
});
|
|
548
541
|
// We can't let the native "update" to handle nested "create" because we can't get back what
|
|
@@ -594,7 +587,7 @@ class PolicyProxyHandler {
|
|
|
594
587
|
select: this.policyUtils.makeIdSelection(backLinkField.type),
|
|
595
588
|
};
|
|
596
589
|
// fetch the upstream entity
|
|
597
|
-
if (this.
|
|
590
|
+
if (this.shouldLogQuery) {
|
|
598
591
|
this.logger.info(`[policy] \`findUniqueOrThrow\` ${model}: looking up upstream entity of ${backLinkField.type}, ${(0, utils_1.formatObject)(upstreamQuery)}`);
|
|
599
592
|
}
|
|
600
593
|
const upstreamEntity = yield this.prisma[backLinkField.type].findUniqueOrThrow(upstreamQuery);
|
|
@@ -615,7 +608,10 @@ class PolicyProxyHandler {
|
|
|
615
608
|
const _createMany = (model, args, context) => __awaiter(this, void 0, void 0, function* () {
|
|
616
609
|
for (const item of (0, cross_1.enumerate)(args.data)) {
|
|
617
610
|
if (args.skipDuplicates) {
|
|
618
|
-
|
|
611
|
+
// get a reversed query to include fields inherited from upstream mutation,
|
|
612
|
+
// it'll be merged with the create payload for unique constraint checking
|
|
613
|
+
const upstreamQuery = this.policyUtils.buildReversedQuery(context);
|
|
614
|
+
if (yield this.hasDuplicatedUniqueConstraint(model, item, upstreamQuery, db)) {
|
|
619
615
|
if (this.shouldLogQuery) {
|
|
620
616
|
this.logger.info(`[policy] \`createMany\` skipping duplicate ${(0, utils_1.formatObject)(item)}`);
|
|
621
617
|
}
|
|
@@ -643,7 +639,7 @@ class PolicyProxyHandler {
|
|
|
643
639
|
}
|
|
644
640
|
yield this.policyUtils.checkPolicyForUnique(model, args, 'update', db, checkArgs);
|
|
645
641
|
// register post-update check
|
|
646
|
-
yield _registerPostUpdateCheck(model, args);
|
|
642
|
+
yield _registerPostUpdateCheck(model, args, args);
|
|
647
643
|
}
|
|
648
644
|
}
|
|
649
645
|
});
|
|
@@ -684,17 +680,17 @@ class PolicyProxyHandler {
|
|
|
684
680
|
// check pre-update guard
|
|
685
681
|
yield this.policyUtils.checkPolicyForUnique(model, uniqueFilter, 'update', db, args);
|
|
686
682
|
// handles the case where id fields are updated
|
|
687
|
-
const
|
|
683
|
+
const postUpdateIds = this.policyUtils.clone(existing);
|
|
688
684
|
for (const key of Object.keys(existing)) {
|
|
689
685
|
const updateValue = args.data ? args.data[key] : args[key];
|
|
690
686
|
if (typeof updateValue === 'string' ||
|
|
691
687
|
typeof updateValue === 'number' ||
|
|
692
688
|
typeof updateValue === 'bigint') {
|
|
693
|
-
|
|
689
|
+
postUpdateIds[key] = updateValue;
|
|
694
690
|
}
|
|
695
691
|
}
|
|
696
692
|
// register post-update check
|
|
697
|
-
yield _registerPostUpdateCheck(model,
|
|
693
|
+
yield _registerPostUpdateCheck(model, existing, postUpdateIds);
|
|
698
694
|
}
|
|
699
695
|
}),
|
|
700
696
|
updateMany: (model, args, context) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -766,7 +762,7 @@ class PolicyProxyHandler {
|
|
|
766
762
|
// check pre-update guard
|
|
767
763
|
yield this.policyUtils.checkPolicyForUnique(model, uniqueFilter, 'update', db, args);
|
|
768
764
|
// register post-update check
|
|
769
|
-
yield _registerPostUpdateCheck(model, uniqueFilter);
|
|
765
|
+
yield _registerPostUpdateCheck(model, uniqueFilter, uniqueFilter);
|
|
770
766
|
// convert upsert to update
|
|
771
767
|
const convertedUpdate = {
|
|
772
768
|
where: args.where,
|
|
@@ -877,13 +873,17 @@ class PolicyProxyHandler {
|
|
|
877
873
|
}
|
|
878
874
|
}
|
|
879
875
|
updateMany(args) {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
876
|
+
if (!args) {
|
|
877
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
878
|
+
}
|
|
879
|
+
if (!args.data) {
|
|
880
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'data field is required in query argument');
|
|
881
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options, 'query argument is required');
|
|
882
|
+
}
|
|
883
|
+
if (!args.data) {
|
|
884
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.options, 'data field is required in query argument');
|
|
885
|
+
}
|
|
886
|
+
return (0, promise_1.createDeferredPromise)(() => {
|
|
887
887
|
this.policyUtils.tryReject(this.prisma, this.model, 'update');
|
|
888
888
|
args = this.policyUtils.clone(args);
|
|
889
889
|
this.policyUtils.injectAuthGuardAsWhere(this.prisma, args, this.model, 'update');
|
|
@@ -927,19 +927,19 @@ class PolicyProxyHandler {
|
|
|
927
927
|
});
|
|
928
928
|
}
|
|
929
929
|
upsert(args) {
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
930
|
+
if (!args) {
|
|
931
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
932
|
+
}
|
|
933
|
+
if (!args.where) {
|
|
934
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'where field is required in query argument');
|
|
935
|
+
}
|
|
936
|
+
if (!args.create) {
|
|
937
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'create field is required in query argument');
|
|
938
|
+
}
|
|
939
|
+
if (!args.update) {
|
|
940
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'update field is required in query argument');
|
|
941
|
+
}
|
|
942
|
+
return (0, promise_1.createDeferredPromise)(() => __awaiter(this, void 0, void 0, function* () {
|
|
943
943
|
this.policyUtils.tryReject(this.prisma, this.model, 'create');
|
|
944
944
|
this.policyUtils.tryReject(this.prisma, this.model, 'update');
|
|
945
945
|
args = this.policyUtils.clone(args);
|
|
@@ -967,20 +967,20 @@ class PolicyProxyHandler {
|
|
|
967
967
|
else {
|
|
968
968
|
return result;
|
|
969
969
|
}
|
|
970
|
-
});
|
|
970
|
+
}));
|
|
971
971
|
}
|
|
972
972
|
//#endregion
|
|
973
973
|
//#region Delete
|
|
974
974
|
// "delete" works against a single entity, and is rejected if the entity fails policy check.
|
|
975
975
|
// "deleteMany" works against a set of entities, entities that fail policy check are filtered out.
|
|
976
976
|
delete(args) {
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
977
|
+
if (!args) {
|
|
978
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
979
|
+
}
|
|
980
|
+
if (!args.where) {
|
|
981
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'where field is required in query argument');
|
|
982
|
+
}
|
|
983
|
+
return (0, promise_1.createDeferredPromise)(() => __awaiter(this, void 0, void 0, function* () {
|
|
984
984
|
this.policyUtils.tryReject(this.prisma, this.model, 'delete');
|
|
985
985
|
const { result, error } = yield this.queryUtils.transaction(this.prisma, (tx) => __awaiter(this, void 0, void 0, function* () {
|
|
986
986
|
// do a read-back before delete
|
|
@@ -1004,10 +1004,10 @@ class PolicyProxyHandler {
|
|
|
1004
1004
|
else {
|
|
1005
1005
|
return result;
|
|
1006
1006
|
}
|
|
1007
|
-
});
|
|
1007
|
+
}));
|
|
1008
1008
|
}
|
|
1009
1009
|
deleteMany(args) {
|
|
1010
|
-
return
|
|
1010
|
+
return (0, promise_1.createDeferredPromise)(() => {
|
|
1011
1011
|
this.policyUtils.tryReject(this.prisma, this.model, 'delete');
|
|
1012
1012
|
// inject policy conditions
|
|
1013
1013
|
args = args !== null && args !== void 0 ? args : {};
|
|
@@ -1022,10 +1022,10 @@ class PolicyProxyHandler {
|
|
|
1022
1022
|
//#endregion
|
|
1023
1023
|
//#region Aggregation
|
|
1024
1024
|
aggregate(args) {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1025
|
+
if (!args) {
|
|
1026
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
1027
|
+
}
|
|
1028
|
+
return (0, promise_1.createDeferredPromise)(() => {
|
|
1029
1029
|
args = this.policyUtils.clone(args);
|
|
1030
1030
|
// inject policy conditions
|
|
1031
1031
|
this.policyUtils.injectAuthGuardAsWhere(this.prisma, args, this.model, 'read');
|
|
@@ -1036,10 +1036,10 @@ class PolicyProxyHandler {
|
|
|
1036
1036
|
});
|
|
1037
1037
|
}
|
|
1038
1038
|
groupBy(args) {
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1039
|
+
if (!args) {
|
|
1040
|
+
throw (0, utils_1.prismaClientValidationError)(this.prisma, this.prismaModule, 'query argument is required');
|
|
1041
|
+
}
|
|
1042
|
+
return (0, promise_1.createDeferredPromise)(() => {
|
|
1043
1043
|
args = this.policyUtils.clone(args);
|
|
1044
1044
|
// inject policy conditions
|
|
1045
1045
|
this.policyUtils.injectAuthGuardAsWhere(this.prisma, args, this.model, 'read');
|
|
@@ -1050,7 +1050,7 @@ class PolicyProxyHandler {
|
|
|
1050
1050
|
});
|
|
1051
1051
|
}
|
|
1052
1052
|
count(args) {
|
|
1053
|
-
return
|
|
1053
|
+
return (0, promise_1.createDeferredPromise)(() => {
|
|
1054
1054
|
// inject policy conditions
|
|
1055
1055
|
args = args ? this.policyUtils.clone(args) : {};
|
|
1056
1056
|
this.policyUtils.injectAuthGuardAsWhere(this.prisma, args, this.model, 'read');
|
|
@@ -1063,7 +1063,7 @@ class PolicyProxyHandler {
|
|
|
1063
1063
|
//#endregion
|
|
1064
1064
|
//#region Subscribe (Prisma Pulse)
|
|
1065
1065
|
subscribe(args) {
|
|
1066
|
-
return
|
|
1066
|
+
return (0, promise_1.createDeferredPromise)(() => {
|
|
1067
1067
|
const readGuard = this.policyUtils.getAuthGuard(this.prisma, this.model, 'read');
|
|
1068
1068
|
if (this.policyUtils.isTrue(readGuard)) {
|
|
1069
1069
|
// no need to inject
|
|
@@ -1112,12 +1112,9 @@ class PolicyProxyHandler {
|
|
|
1112
1112
|
}
|
|
1113
1113
|
runPostWriteChecks(postWriteChecks, db) {
|
|
1114
1114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1115
|
-
yield Promise.all(postWriteChecks.map((
|
|
1115
|
+
yield Promise.all(postWriteChecks.map((_a) => __awaiter(this, [_a], void 0, function* ({ model, operation, uniqueFilter, preValue }) { return this.policyUtils.checkPolicyForUnique(model, uniqueFilter, operation, db, undefined, preValue); })));
|
|
1116
1116
|
});
|
|
1117
1117
|
}
|
|
1118
|
-
makeHandler(model) {
|
|
1119
|
-
return new PolicyProxyHandler(this.prisma, model, this.options, this.context);
|
|
1120
|
-
}
|
|
1121
1118
|
requireBackLink(fieldInfo) {
|
|
1122
1119
|
(0, tiny_invariant_1.default)(fieldInfo.backLink, `back link not found for field ${fieldInfo.name}`);
|
|
1123
1120
|
return (0, cross_1.requireField)(this.modelMeta, fieldInfo.type, fieldInfo.backLink);
|