@cerebruminc/yates 3.7.2 → 3.8.1-beta.dangerous.0cfc5d9

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/dist/index.js CHANGED
@@ -1,8 +1,4 @@
1
1
  "use strict";
2
- var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3
- if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4
- return cooked;
5
- };
6
2
  var __assign = (this && this.__assign) || function () {
7
3
  __assign = Object.assign || function(t) {
8
4
  for (var s, i = 1, n = arguments.length; i < n; i++) {
@@ -14,29 +10,6 @@ var __assign = (this && this.__assign) || function () {
14
10
  };
15
11
  return __assign.apply(this, arguments);
16
12
  };
17
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- var desc = Object.getOwnPropertyDescriptor(m, k);
20
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
- desc = { enumerable: true, get: function() { return m[k]; } };
22
- }
23
- Object.defineProperty(o, k2, desc);
24
- }) : (function(o, m, k, k2) {
25
- if (k2 === undefined) k2 = k;
26
- o[k2] = m[k];
27
- }));
28
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
- Object.defineProperty(o, "default", { enumerable: true, value: v });
30
- }) : function(o, v) {
31
- o["default"] = v;
32
- });
33
- var __importStar = (this && this.__importStar) || function (mod) {
34
- if (mod && mod.__esModule) return mod;
35
- var result = {};
36
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
37
- __setModuleDefault(result, mod);
38
- return result;
39
- };
40
13
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
41
14
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
42
15
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -100,72 +73,16 @@ var __read = (this && this.__read) || function (o, n) {
100
73
  }
101
74
  return ar;
102
75
  };
103
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
104
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
105
- if (ar || !(i in from)) {
106
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
107
- ar[i] = from[i];
108
- }
109
- }
110
- return to.concat(ar || Array.prototype.slice.call(from));
111
- };
112
76
  var __importDefault = (this && this.__importDefault) || function (mod) {
113
77
  return (mod && mod.__esModule) ? mod : { "default": mod };
114
78
  };
115
79
  Object.defineProperty(exports, "__esModule", { value: true });
116
- exports.setup = exports.createRoles = exports.createClient = exports.getBatchId = exports.createRoleName = exports.createAbilityName = exports.sanitizeSlug = void 0;
117
- var crypto = __importStar(require("crypto"));
80
+ exports.setup = exports.__private = exports.Yates = exports.sanitizeSlug = void 0;
118
81
  var debug_1 = __importDefault(require("debug"));
119
82
  var cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
120
83
  var difference_1 = __importDefault(require("lodash/difference"));
121
- var flatMap_1 = __importDefault(require("lodash/flatMap"));
122
- var map_1 = __importDefault(require("lodash/map"));
123
- var toPairs_1 = __importDefault(require("lodash/toPairs"));
124
- var expressions_1 = require("./expressions");
125
84
  var VALID_OPERATIONS = ["SELECT", "UPDATE", "INSERT", "DELETE"];
126
85
  var debug = (0, debug_1.default)("yates");
127
- /**
128
- * This function is used to take a lock that is automatically released at the end of the current transaction.
129
- * This is very convenient for ensuring we don't hit concurrency issues when running setup code.
130
- */
131
- var takeLock = function (prisma) {
132
- return prisma.$executeRawUnsafe("SELECT pg_advisory_xact_lock(2142616474639426746);");
133
- };
134
- /*
135
- * This function creates a table used to track the abilities that have been
136
- * defined in the system. We can use this to see if an ability needs to be updated.
137
- * We can't look up the pg policy table for this, as pg performs formatting on
138
- * the expression, making it very hard to check if the two expressions are equivalent.
139
- *
140
- * We also need to create a schema for this table, as we don't want to pollute the public schema.
141
- * If we use the public schema, we could potentially conflict with a user's table and we will
142
- * also cause issues for Prisma's migrate tooling, as it will detect a DB drift.
143
- */
144
- var setupAbilityTable = function (prisma) {
145
- return prisma.$transaction([
146
- takeLock(prisma),
147
- prisma.$executeRawUnsafe("\n\t\tCREATE SCHEMA IF NOT EXISTS _yates;\n\t\t"),
148
- prisma.$executeRawUnsafe("\n\t\tCREATE TABLE IF NOT EXISTS _yates._yates_abilities (\n\t\t\tid SERIAL PRIMARY KEY,\n\t\t\tability_model TEXT NOT NULL,\n\t\t\tability_name TEXT NOT NULL,\n\t\t\tability_policy_name TEXT NOT NULL UNIQUE,\n\t\t\tability_description TEXT NOT NULL,\n\t\t\tability_operation TEXT NOT NULL,\n\t\t\tability_expression TEXT NOT NULL,\n\t\t\tcreated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n\t\t\tupdated_at TIMESTAMP\n\t\t);\n\t"),
149
- ]);
150
- };
151
- var upsertAbility = function (prisma, ability) {
152
- var ability_model = ability.ability_model, ability_name = ability.ability_name, ability_policy_name = ability.ability_policy_name, ability_description = ability.ability_description, ability_operation = ability.ability_operation, ability_expression = ability.ability_expression;
153
- return prisma.$queryRaw(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n\t\tINSERT INTO _yates._yates_abilities (ability_model, ability_name, ability_policy_name, ability_description, ability_operation, ability_expression)\n\t\tVALUES (", ", ", ", ", ", ", ", ", ", ", ")\n\t\tON CONFLICT (ability_policy_name) DO UPDATE\n\t\tSET ability_model = EXCLUDED.ability_model, ability_name = EXCLUDED.ability_name, ability_description = EXCLUDED.ability_description, ability_operation = EXCLUDED.ability_operation, ability_expression = EXCLUDED.ability_expression, updated_at = now();\n\t"], ["\n\t\tINSERT INTO _yates._yates_abilities (ability_model, ability_name, ability_policy_name, ability_description, ability_operation, ability_expression)\n\t\tVALUES (", ", ", ", ", ", ", ", ", ", ", ")\n\t\tON CONFLICT (ability_policy_name) DO UPDATE\n\t\tSET ability_model = EXCLUDED.ability_model, ability_name = EXCLUDED.ability_name, ability_description = EXCLUDED.ability_description, ability_operation = EXCLUDED.ability_operation, ability_expression = EXCLUDED.ability_expression, updated_at = now();\n\t"])), ability_model, ability_name, ability_policy_name, ability_description, ability_operation, ability_expression);
154
- };
155
- /**
156
- * In PostgreSQL, the maximum length for a role or policy name is 63 bytes.
157
- * This limitation is derived from the value of the NAMEDATALEN configuration parameter,
158
- * which is set to 64 bytes by default. One byte is reserved for the null-terminator,
159
- * leaving 63 bytes for the actual role name.
160
- * This function hashes the ability name to ensure it is within the 63 byte limit.
161
- */
162
- var hashWithPrefix = function (prefix, abilityName) {
163
- var hash = crypto.createHash("sha256");
164
- hash.update(abilityName);
165
- var hashedAbilityName = hash.digest("hex");
166
- var maxLength = 63 - prefix.length;
167
- return prefix + hashedAbilityName.slice(0, maxLength);
168
- };
169
86
  // Sanitize a single string by ensuring the it has only lowercase alpha characters and underscores
170
87
  var sanitizeSlug = function (slug) {
171
88
  return slug
@@ -174,684 +91,1358 @@ var sanitizeSlug = function (slug) {
174
91
  .replace(/[^a-z0-9_]/gi, "");
175
92
  };
176
93
  exports.sanitizeSlug = sanitizeSlug;
177
- var createAbilityName = function (model, ability) {
178
- return (0, exports.sanitizeSlug)(hashWithPrefix("yates_ability_", "".concat(model, "_").concat(ability)));
94
+ var OPERATION_MAP = {
95
+ findUnique: "SELECT",
96
+ findUniqueOrThrow: "SELECT",
97
+ findFirst: "SELECT",
98
+ findFirstOrThrow: "SELECT",
99
+ findMany: "SELECT",
100
+ count: "SELECT",
101
+ aggregate: "SELECT",
102
+ groupBy: "SELECT",
103
+ create: "INSERT",
104
+ createMany: "INSERT",
105
+ update: "UPDATE",
106
+ updateMany: "UPDATE",
107
+ delete: "DELETE",
108
+ deleteMany: "DELETE",
109
+ upsert: "UPDATE",
110
+ };
111
+ var UNIQUE_OPERATIONS = new Set([
112
+ "findUnique",
113
+ "findUniqueOrThrow",
114
+ "update",
115
+ "delete",
116
+ "upsert",
117
+ ]);
118
+ var SELECT_OPERATIONS = new Set([
119
+ "findUnique",
120
+ "findUniqueOrThrow",
121
+ "findFirst",
122
+ "findFirstOrThrow",
123
+ "findMany",
124
+ "count",
125
+ "aggregate",
126
+ "groupBy",
127
+ ]);
128
+ var isPlainObject = function (value) {
129
+ return !!value && typeof value === "object" && !Array.isArray(value);
130
+ };
131
+ var lowerModelName = function (model) {
132
+ return model.length ? "".concat(model[0].toLowerCase()).concat(model.slice(1)) : model;
133
+ };
134
+ var isFieldRef = function (value) {
135
+ return isPlainObject(value) &&
136
+ typeof value.modelName === "string" &&
137
+ typeof value.name === "string";
138
+ };
139
+ var isEmptyWhere = function (where) {
140
+ return !where || (isPlainObject(where) && Object.keys(where).length === 0);
141
+ };
142
+ var combineAbilityFilters = function (filters) {
143
+ if (filters.length === 0)
144
+ return null;
145
+ if (filters.some(function (filter) { return isEmptyWhere(filter); }))
146
+ return {};
147
+ if (filters.length === 1)
148
+ return filters[0];
149
+ return { OR: filters };
150
+ };
151
+ var mergeWhere = function (base, extra) {
152
+ var _a;
153
+ if (!extra || isEmptyWhere(extra))
154
+ return (_a = base !== null && base !== void 0 ? base : extra) !== null && _a !== void 0 ? _a : undefined;
155
+ if (!base || isEmptyWhere(base))
156
+ return extra;
157
+ return { AND: [base, extra] };
179
158
  };
180
- exports.createAbilityName = createAbilityName;
181
- var createRoleName = function (name) {
182
- return (0, exports.sanitizeSlug)(hashWithPrefix("yates_role_", "".concat(name)));
159
+ var getFluentSelectionField = function (runtimeDataModel, model, args) {
160
+ var selection = args.select;
161
+ if (!isPlainObject(selection))
162
+ return null;
163
+ var keys = Object.keys(selection);
164
+ if (keys.length !== 1)
165
+ return null;
166
+ var field = keys[0];
167
+ var modelData = runtimeDataModel.models[model];
168
+ var fieldData = modelData === null || modelData === void 0 ? void 0 : modelData.fields.find(function (f) { return f.name === field; });
169
+ if (!fieldData || fieldData.kind !== "object")
170
+ return null;
171
+ return field;
183
172
  };
184
- exports.createRoleName = createRoleName;
185
- var getDefaultAbilities = function (models) {
186
- var e_1, _a;
187
- var abilities = {};
173
+ var getIdField = function (runtimeDataModel, model) {
174
+ var _a;
175
+ var modelData = runtimeDataModel.models[model];
176
+ if (!modelData)
177
+ return null;
178
+ var idField = modelData.fields.find(function (field) { return field.isId; });
179
+ return (_a = idField === null || idField === void 0 ? void 0 : idField.name) !== null && _a !== void 0 ? _a : null;
180
+ };
181
+ var denyWhere = function (runtimeDataModel, model) {
182
+ var _a;
183
+ var idField = getIdField(runtimeDataModel, model);
184
+ if (idField) {
185
+ return _a = {},
186
+ _a[idField] = {
187
+ in: [],
188
+ },
189
+ _a;
190
+ }
191
+ throw new Error("Model \"".concat(model, "\" has no @id field. Yates requires an ID to safely deny queries."));
192
+ };
193
+ var validateContext = function (context) {
194
+ var e_1, _a, e_2, _b;
195
+ if (!context)
196
+ return;
188
197
  try {
189
- for (var models_1 = __values(models), models_1_1 = models_1.next(); !models_1_1.done; models_1_1 = models_1.next()) {
190
- var model = models_1_1.value;
191
- abilities[model] = {
192
- create: {
193
- description: "Create ".concat(model),
194
- expression: "true",
195
- operation: "INSERT",
196
- model: model,
197
- slug: "create",
198
- },
199
- read: {
200
- description: "Read ".concat(model),
201
- expression: "true",
202
- operation: "SELECT",
203
- model: model,
204
- slug: "read",
205
- },
206
- update: {
207
- description: "Update ".concat(model),
208
- expression: "true",
209
- operation: "UPDATE",
210
- model: model,
211
- slug: "update",
212
- },
213
- delete: {
214
- description: "Delete ".concat(model),
215
- expression: "true",
216
- operation: "DELETE",
217
- model: model,
218
- slug: "delete",
219
- },
220
- };
198
+ for (var _c = __values(Object.keys(context)), _d = _c.next(); !_d.done; _d = _c.next()) {
199
+ var key = _d.value;
200
+ if (!key.match(/^[a-z_\.]+$/)) {
201
+ throw new Error("Context variable \"".concat(key, "\" contains invalid characters. Context variables must only contain lowercase letters, numbers, periods and underscores."));
202
+ }
203
+ var value = context[key];
204
+ if (typeof value !== "number" &&
205
+ typeof value !== "string" &&
206
+ !Array.isArray(value)) {
207
+ throw new Error("Context variable \"".concat(key, "\" must be a string, number or array. Got ").concat(typeof value));
208
+ }
209
+ if (Array.isArray(value)) {
210
+ try {
211
+ for (var _e = (e_2 = void 0, __values(value)), _f = _e.next(); !_f.done; _f = _e.next()) {
212
+ var entry = _f.value;
213
+ if (typeof entry !== "string") {
214
+ throw new Error("Context variable \"".concat(key, "\" must be an array of strings. Got ").concat(typeof entry));
215
+ }
216
+ }
217
+ }
218
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
219
+ finally {
220
+ try {
221
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
222
+ }
223
+ finally { if (e_2) throw e_2.error; }
224
+ }
225
+ }
221
226
  }
222
227
  }
223
228
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
224
229
  finally {
225
230
  try {
226
- if (models_1_1 && !models_1_1.done && (_a = models_1.return)) _a.call(models_1);
231
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
227
232
  }
228
233
  finally { if (e_1) throw e_1.error; }
229
234
  }
230
- return abilities;
231
235
  };
232
- // @ts-ignore
233
- function getBatchId(query) {
234
- if (query.action !== "findUnique" && query.action !== "findUniqueOrThrow") {
235
- return undefined;
236
+ var permissionError = function (model, operation) {
237
+ return new Error("You do not have permission to perform this action: ".concat(model, ".").concat(operation, "(...)"));
238
+ };
239
+ var updateNotFoundError = function () { return new Error("Record to update not found"); };
240
+ var deleteNotFoundError = function () { return new Error("Record to delete does not exist"); };
241
+ var matchesScalarFilter = function (value, filter, data) {
242
+ if (!isPlainObject(filter)) {
243
+ if (isFieldRef(filter)) {
244
+ return value === data[filter.name];
245
+ }
246
+ return value === filter;
236
247
  }
237
- var parts = [];
238
- if (query.modelName) {
239
- parts.push(query.modelName);
248
+ if ("equals" in filter) {
249
+ var target = filter.equals;
250
+ if (isFieldRef(target)) {
251
+ return value === data[target.name];
252
+ }
253
+ return value === target;
240
254
  }
241
- if (query.query.arguments) {
242
- parts.push(buildKeysString(query.query.arguments));
255
+ if ("in" in filter) {
256
+ return Array.isArray(filter.in) && filter.in.includes(value);
243
257
  }
244
- parts.push(buildKeysString(query.query.selection));
245
- return parts.join("");
246
- }
247
- exports.getBatchId = getBatchId;
248
- function buildKeysString(obj) {
249
- var keysArray = Object.keys(obj)
250
- .sort()
251
- .map(function (key) {
252
- // @ts-ignore
253
- var value = obj[key];
254
- if (typeof value === "object" && value !== null) {
255
- return "(".concat(key, " ").concat(buildKeysString(value), ")");
256
- }
257
- return key;
258
- });
259
- return "(".concat(keysArray.join(" "), ")");
260
- }
261
- // This uses client extensions to set the role and context for the current user so that RLS can be applied
262
- var createClient = function (prisma, getContext, options) {
263
- if (options === void 0) { options = {}; }
264
- // Set default options
265
- var _a = options.txMaxWait, txMaxWait = _a === void 0 ? 30000 : _a, _b = options.txTimeout, txTimeout = _b === void 0 ? 30000 : _b;
266
- // By default, Prisma will batch requests by the transaction ID if it is present.
267
- // This behaviour prevents automatic batching from working when using Yates, since all queries are executed inside an interactive transaction.
268
- // To get around this we by monkey patching the batching function to use the Yates ID as the batch ID.
269
- // To get the batching to work we also need to ensure that all the requests we might want to batch together are generated inside the same tick.
270
- // This means that all the requests per-tick that have the same role and context values will be batched together,
271
- // allowing the in-built prisma batch optimizations to work for us.
272
- // This is why we use process.nextTick and the tickActive flag to ensure we only tick once at a time.
273
- // See:
274
- // - https://github.com/prisma/prisma/blob/5.21.1/packages/client/src/runtime/RequestHandler.ts#L122
275
- // - https://www.prisma.io/docs/orm/prisma-client/queries/query-optimization-performance
276
- prisma._requestHandler.dataloader.options.batchBy = function (request) {
277
- var _a;
278
- var batchIdPQ = getBatchId(request.protocolQuery);
279
- if ((_a = request.transaction) === null || _a === void 0 ? void 0 : _a.id) {
280
- return "transaction-".concat(request.transaction.id).concat(batchIdPQ ? "-".concat(batchIdPQ) : "");
281
- }
282
- return getBatchId(request.protocolQuery);
283
- };
284
- var tickActive = false;
285
- var batches = {};
286
- // This function is called once per tick, and processes all the batches that have been created during that tick.
287
- // Each batch represents a unique role + context combination, and contains all the requests that need to be executed with that role + context.
288
- var dispatchBatches = function () {
289
- var e_2, _a;
290
- var _loop_1 = function (key, batch) {
291
- delete batches[key];
292
- // Because batch transactions inside a prisma client query extension can run out of order if used with async middleware,
293
- // we need to run the logic inside an interactive transaction, however this brings a different set of problems in that the
294
- // main query will no longer automatically run inside the transaction. We resolve this issue by manually executing the prisma request.
295
- // See https://github.com/prisma/prisma/issues/18276
296
- prisma
297
- .$transaction(function (tx) { return __awaiter(void 0, void 0, void 0, function () {
298
- var _a, _b, _c, key_1, value, e_3_1, txId, results;
299
- var e_3, _d;
300
- return __generator(this, function (_e) {
301
- switch (_e.label) {
302
- case 0:
303
- // Switch to the user role, We can't use a prepared statement here, due to limitations in PG not allowing prepared statements to be used in SET LOCAL ROLE
304
- return [4 /*yield*/, tx.$queryRawUnsafe("SET LOCAL ROLE ".concat(batch.pgRole))];
305
- case 1:
306
- // Switch to the user role, We can't use a prepared statement here, due to limitations in PG not allowing prepared statements to be used in SET LOCAL ROLE
307
- _e.sent();
308
- _e.label = 2;
309
- case 2:
310
- _e.trys.push([2, 7, 8, 9]);
311
- _a = __values((0, toPairs_1.default)(batch.context)), _b = _a.next();
312
- _e.label = 3;
313
- case 3:
314
- if (!!_b.done) return [3 /*break*/, 6];
315
- _c = __read(_b.value, 2), key_1 = _c[0], value = _c[1];
316
- return [4 /*yield*/, tx.$queryRaw(templateObject_2 || (templateObject_2 = __makeTemplateObject(["SELECT set_config(", ", ", ", true);"], ["SELECT set_config(", ", ", ", true);"])), key_1, value.toString())];
317
- case 4:
318
- _e.sent();
319
- _e.label = 5;
320
- case 5:
321
- _b = _a.next();
322
- return [3 /*break*/, 3];
323
- case 6: return [3 /*break*/, 9];
324
- case 7:
325
- e_3_1 = _e.sent();
326
- e_3 = { error: e_3_1 };
327
- return [3 /*break*/, 9];
328
- case 8:
329
- try {
330
- if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
331
- }
332
- finally { if (e_3) throw e_3.error; }
333
- return [7 /*endfinally*/];
334
- case 9:
335
- txId = tx[Symbol.for("prisma.client.transaction.id")];
336
- return [4 /*yield*/, Promise.all(batch.requests.map(function (request) {
337
- return prisma._executeRequest(__assign(__assign({}, request.params), { transaction: {
338
- kind: "itx",
339
- id: txId,
340
- } }));
341
- }))];
342
- case 10:
343
- results = _e.sent();
344
- return [2 /*return*/, results];
345
- }
346
- });
347
- }); }, {
348
- maxWait: txMaxWait,
349
- timeout: txTimeout,
350
- })
351
- .then(function (results) {
352
- results.forEach(function (result, index) {
353
- batch.requests[index].resolve(result);
354
- });
355
- })
356
- .catch(function (e) {
357
- var e_4, _a;
358
- try {
359
- for (var _b = (e_4 = void 0, __values(batch.requests)), _c = _b.next(); !_c.done; _c = _b.next()) {
360
- var request = _c.value;
361
- request.reject(e);
258
+ if ("notIn" in filter) {
259
+ return Array.isArray(filter.notIn) && !filter.notIn.includes(value);
260
+ }
261
+ if ("lt" in filter)
262
+ return value < filter.lt;
263
+ if ("lte" in filter)
264
+ return value <= filter.lte;
265
+ if ("gt" in filter)
266
+ return value > filter.gt;
267
+ if ("gte" in filter)
268
+ return value >= filter.gte;
269
+ if ("contains" in filter)
270
+ return typeof value === "string" && value.includes(filter.contains);
271
+ if ("startsWith" in filter)
272
+ return typeof value === "string" && value.startsWith(filter.startsWith);
273
+ if ("endsWith" in filter)
274
+ return typeof value === "string" && value.endsWith(filter.endsWith);
275
+ if ("not" in filter)
276
+ return !matchesScalarFilter(value, filter.not, data);
277
+ return value === filter;
278
+ };
279
+ var getRelationConstraints = function (data, fieldData) {
280
+ var e_3, _a;
281
+ var _b, _c;
282
+ var constraints = [];
283
+ var relationInput = data[fieldData.name];
284
+ if (isPlainObject(relationInput)) {
285
+ var connect = relationInput.connect;
286
+ if (connect) {
287
+ var items = Array.isArray(connect) ? connect : [connect];
288
+ try {
289
+ for (var items_1 = __values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
290
+ var item = items_1_1.value;
291
+ if (isPlainObject(item)) {
292
+ constraints.push(item);
362
293
  }
363
294
  }
364
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
365
- finally {
366
- try {
367
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
368
- }
369
- finally { if (e_4) throw e_4.error; }
295
+ }
296
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
297
+ finally {
298
+ try {
299
+ if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
370
300
  }
371
- delete batches[key];
372
- });
373
- };
374
- try {
375
- for (var _b = __values(Object.entries(batches)), _c = _b.next(); !_c.done; _c = _b.next()) {
376
- var _d = __read(_c.value, 2), key = _d[0], batch = _d[1];
377
- _loop_1(key, batch);
301
+ finally { if (e_3) throw e_3.error; }
378
302
  }
379
303
  }
380
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
381
- finally {
382
- try {
383
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
384
- }
385
- finally { if (e_2) throw e_2.error; }
304
+ }
305
+ var fromFields = (_b = fieldData.relationFromFields) !== null && _b !== void 0 ? _b : [];
306
+ var toFields = (_c = fieldData.relationToFields) !== null && _c !== void 0 ? _c : [];
307
+ if (fromFields.length > 0) {
308
+ var hasAll = fromFields.every(function (field) { return data[field] !== undefined && data[field] !== null; });
309
+ if (hasAll) {
310
+ var where_1 = {};
311
+ fromFields.forEach(function (fromField, index) {
312
+ var _a;
313
+ var toField = (_a = toFields[index]) !== null && _a !== void 0 ? _a : fromField;
314
+ where_1[toField] = data[fromField];
315
+ });
316
+ constraints.push(where_1);
386
317
  }
387
- };
388
- var client = prisma.$extends({
389
- name: "Yates client",
390
- query: {
391
- $allModels: {
392
- $allOperations: function (params) {
393
- return __awaiter(this, void 0, void 0, function () {
394
- var model, args, query, operation, ctx, role, context, pgRole, _a, _b, k, _c, _d, v, txId, hash, __internalParams;
395
- var e_5, _e, e_6, _f;
396
- return __generator(this, function (_g) {
397
- model = params.model, args = params.args, query = params.query, operation = params.operation;
398
- if (!model) {
399
- // If the model is not defined, we can't apply RLS
400
- // This can occur when you are making a call with Prisma's $queryRaw method
401
- return [2 /*return*/, query(args)];
402
- }
403
- ctx = getContext();
404
- // If ctx is null, the middleware is explicitly skipped
405
- if (ctx === null) {
406
- return [2 /*return*/, query(args)];
407
- }
408
- role = ctx.role, context = ctx.context;
409
- pgRole = (0, exports.createRoleName)(role);
410
- if (context) {
411
- try {
412
- for (_a = __values(Object.keys(context)), _b = _a.next(); !_b.done; _b = _a.next()) {
413
- k = _b.value;
414
- if (!k.match(/^[a-z_\.]+$/)) {
415
- throw new Error("Context variable \"".concat(k, "\" contains invalid characters. Context variables must only contain lowercase letters, numbers, periods and underscores."));
416
- }
417
- if (typeof context[k] !== "number" &&
418
- typeof context[k] !== "string" &&
419
- !Array.isArray(context[k])) {
420
- throw new Error("Context variable \"".concat(k, "\" must be a string, number or array. Got ").concat(typeof context[k]));
421
- }
422
- if (Array.isArray(context[k])) {
423
- try {
424
- for (_c = (e_6 = void 0, __values(context[k])), _d = _c.next(); !_d.done; _d = _c.next()) {
425
- v = _d.value;
426
- if (typeof v !== "string") {
427
- throw new Error("Context variable \"".concat(k, "\" must be an array of strings. Got ").concat(typeof v));
428
- }
429
- }
430
- }
431
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
432
- finally {
433
- try {
434
- if (_d && !_d.done && (_f = _c.return)) _f.call(_c);
435
- }
436
- finally { if (e_6) throw e_6.error; }
437
- }
438
- // Cast to a JSON string so that it can be used in RLS expressions
439
- context[k] = JSON.stringify(context[k]);
440
- }
441
- }
442
- }
443
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
444
- finally {
445
- try {
446
- if (_b && !_b.done && (_e = _a.return)) _e.call(_a);
447
- }
448
- finally { if (e_5) throw e_5.error; }
449
- }
450
- }
451
- txId = hashWithPrefix("yates_tx_", JSON.stringify(ctx));
452
- hash = txId;
453
- if (!batches[hash]) {
454
- // Create a new batch for this role + context combination
455
- batches[hash] = {
456
- pgRole: pgRole,
457
- context: context,
458
- requests: [],
459
- };
460
- // make sure, that we only tick once at a time
461
- if (!tickActive) {
462
- tickActive = true;
463
- process.nextTick(function () {
464
- dispatchBatches();
465
- tickActive = false;
466
- });
467
- }
468
- }
469
- __internalParams = params.__internalParams;
470
- // Add the request to the batch, and return a promise that will be resolved or rejected in dispatchBatches
471
- return [2 /*return*/, new Promise(function (resolve, reject) {
472
- batches[hash].requests.push({
473
- params: __internalParams,
474
- query: query,
475
- args: args,
476
- resolve: resolve,
477
- reject: reject,
478
- });
479
- }).catch(function (e) {
480
- var _a;
481
- // Normalize RLS errors to make them a bit more readable.
482
- if ((_a = e.message) === null || _a === void 0 ? void 0 : _a.includes("new row violates row-level security policy for table")) {
483
- throw new Error("You do not have permission to perform this action: ".concat(model, ".").concat(operation, "(...)"));
484
- }
485
- throw e;
486
- })];
487
- });
488
- });
489
- },
490
- },
491
- },
492
- });
493
- return client;
318
+ }
319
+ return constraints.length > 0 ? constraints : null;
494
320
  };
495
- exports.createClient = createClient;
496
- var setRLS = function (prisma, table, roleName, slug, ability) { return __awaiter(void 0, void 0, void 0, function () {
497
- var operation, rawExpression, description;
498
- return __generator(this, function (_a) {
499
- switch (_a.label) {
321
+ var matchesRelationFilter = function (prisma, runtimeDataModel, fieldData, data, condition) { return __awaiter(void 0, void 0, void 0, function () {
322
+ var relatedModel, constraints, relationInput, hasIs, hasIsNot, relationWhere_1, isNegated, constraintWhere_1, combinedWhere_1, delegate_1, record, hasSome, hasEvery, hasNone, operator, relationWhere, constraintWhere, combinedWhere, delegate, record, record, results;
323
+ var _a, _b, _c, _d;
324
+ var _e, _f, _g, _h, _j, _k, _l, _m;
325
+ return __generator(this, function (_o) {
326
+ switch (_o.label) {
500
327
  case 0:
501
- operation = ability.operation, rawExpression = ability.expression, description = ability.description;
502
- if (!rawExpression) {
503
- throw new Error("Expression must be defined for RLS abilities");
328
+ relatedModel = fieldData.type;
329
+ constraints = (_e = getRelationConstraints(data, fieldData)) !== null && _e !== void 0 ? _e : [];
330
+ relationInput = isPlainObject(condition) ? condition : {};
331
+ if (!!fieldData.isList) return [3 /*break*/, 2];
332
+ hasIs = isPlainObject(condition) && "is" in condition;
333
+ hasIsNot = isPlainObject(condition) && "isNot" in condition;
334
+ relationWhere_1 = hasIs
335
+ ? relationInput.is
336
+ : hasIsNot
337
+ ? relationInput.isNot
338
+ : condition;
339
+ isNegated = hasIsNot;
340
+ if (relationWhere_1 === null) {
341
+ return [2 /*return*/, isNegated ? constraints.length > 0 : constraints.length === 0];
504
342
  }
505
- // Take a lock and run the RLS setup in a transaction to prevent conflicts
506
- // in a multi-server environment
507
- return [4 /*yield*/, prisma.$transaction(function (tx) { return __awaiter(void 0, void 0, void 0, function () {
508
- var policyName, existingAbilities, existingAbility, shouldUpdateAbilityTable, expression, expression;
509
- return __generator(this, function (_a) {
510
- switch (_a.label) {
511
- case 0: return [4 /*yield*/, takeLock(tx)];
512
- case 1:
513
- _a.sent();
514
- policyName = roleName;
515
- return [4 /*yield*/, tx.$queryRaw(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n\t\t\tselect * from _yates._yates_abilities where ability_model = ", " and ability_policy_name = ", "\n\t\t"], ["\n\t\t\tselect * from _yates._yates_abilities where ability_model = ", " and ability_policy_name = ", "\n\t\t"])), table, policyName)];
516
- case 2:
517
- existingAbilities = _a.sent();
518
- existingAbility = existingAbilities[0];
519
- shouldUpdateAbilityTable = false;
520
- if (!!existingAbility) return [3 /*break*/, 8];
521
- debug("Creating RLS policy for", roleName, "on", table, "for", operation);
522
- return [4 /*yield*/, (0, expressions_1.expressionToSQL)(rawExpression, table)];
523
- case 3:
524
- expression = _a.sent();
525
- if (!(operation === "INSERT")) return [3 /*break*/, 5];
526
- return [4 /*yield*/, tx.$queryRawUnsafe("\n\t\t\t\tCREATE POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" FOR ").concat(operation, " TO ").concat(roleName, " WITH CHECK (").concat(expression, ");\n\t\t\t"))];
527
- case 4:
528
- _a.sent();
529
- return [3 /*break*/, 7];
530
- case 5: return [4 /*yield*/, tx.$queryRawUnsafe("\n\t\t\t\tCREATE POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" FOR ").concat(operation, " TO ").concat(roleName, " USING (").concat(expression, ");\n\t\t\t"))];
531
- case 6:
532
- _a.sent();
533
- _a.label = 7;
534
- case 7:
535
- shouldUpdateAbilityTable = true;
536
- return [3 /*break*/, 14];
537
- case 8:
538
- if (!(existingAbility.ability_expression !== rawExpression.toString())) return [3 /*break*/, 14];
539
- debug("Updating RLS policy for", roleName, "on", table, "for", operation);
540
- return [4 /*yield*/, (0, expressions_1.expressionToSQL)(rawExpression, table)];
541
- case 9:
542
- expression = _a.sent();
543
- if (!(operation === "INSERT")) return [3 /*break*/, 11];
544
- return [4 /*yield*/, tx.$queryRawUnsafe("\n\t\t\t\tALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " WITH CHECK (").concat(expression, ");\n\t\t\t"))];
545
- case 10:
546
- _a.sent();
547
- return [3 /*break*/, 13];
548
- case 11: return [4 /*yield*/, tx.$queryRawUnsafe("\n\t\t\t\tALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " USING (").concat(expression, ");\n\t\t\t"))];
549
- case 12:
550
- _a.sent();
551
- _a.label = 13;
552
- case 13:
553
- shouldUpdateAbilityTable = true;
554
- _a.label = 14;
555
- case 14:
556
- if (!shouldUpdateAbilityTable) return [3 /*break*/, 16];
557
- return [4 /*yield*/, upsertAbility(tx, {
558
- ability_model: table,
559
- ability_name: slug,
560
- ability_policy_name: policyName,
561
- ability_description: description !== null && description !== void 0 ? description : "",
562
- ability_operation: operation,
563
- // We store the string representation of the expression so that
564
- // we can compare it later without having to recompute the SQL
565
- ability_expression: rawExpression.toString(),
566
- })];
567
- case 15:
568
- _a.sent();
569
- _a.label = 16;
570
- case 16: return [2 /*return*/];
571
- }
572
- });
573
- }); })];
343
+ if (constraints.length === 0)
344
+ return [2 /*return*/, false];
345
+ constraintWhere_1 = constraints.length === 1 ? constraints[0] : { OR: constraints };
346
+ combinedWhere_1 = (_f = mergeWhere(relationWhere_1 !== null && relationWhere_1 !== void 0 ? relationWhere_1 : {}, constraintWhere_1)) !== null && _f !== void 0 ? _f : constraintWhere_1;
347
+ delegate_1 = prisma[lowerModelName(relatedModel)];
348
+ return [4 /*yield*/, delegate_1.findFirst({
349
+ where: combinedWhere_1,
350
+ select: (_a = {}, _a[(_g = getIdField(runtimeDataModel, relatedModel)) !== null && _g !== void 0 ? _g : "id"] = true, _a),
351
+ })];
574
352
  case 1:
575
- // Take a lock and run the RLS setup in a transaction to prevent conflicts
576
- // in a multi-server environment
577
- _a.sent();
578
- return [2 /*return*/];
353
+ record = _o.sent();
354
+ return [2 /*return*/, isNegated ? !record : !!record];
355
+ case 2:
356
+ hasSome = isPlainObject(condition) && "some" in condition;
357
+ hasEvery = isPlainObject(condition) && "every" in condition;
358
+ hasNone = isPlainObject(condition) && "none" in condition;
359
+ operator = hasEvery ? "every" : hasNone ? "none" : "some";
360
+ relationWhere = (_h = relationInput[operator]) !== null && _h !== void 0 ? _h : condition;
361
+ if (constraints.length === 0) {
362
+ if (operator === "none")
363
+ return [2 /*return*/, true];
364
+ if (operator === "every")
365
+ return [2 /*return*/, true];
366
+ return [2 /*return*/, false];
367
+ }
368
+ constraintWhere = constraints.length === 1 ? constraints[0] : { OR: constraints };
369
+ combinedWhere = (_j = mergeWhere(relationWhere !== null && relationWhere !== void 0 ? relationWhere : {}, constraintWhere)) !== null && _j !== void 0 ? _j : constraintWhere;
370
+ delegate = prisma[lowerModelName(relatedModel)];
371
+ if (!(operator === "some")) return [3 /*break*/, 4];
372
+ return [4 /*yield*/, delegate.findFirst({
373
+ where: combinedWhere,
374
+ select: (_b = {}, _b[(_k = getIdField(runtimeDataModel, relatedModel)) !== null && _k !== void 0 ? _k : "id"] = true, _b),
375
+ })];
376
+ case 3:
377
+ record = _o.sent();
378
+ return [2 /*return*/, !!record];
379
+ case 4:
380
+ if (!(operator === "none")) return [3 /*break*/, 6];
381
+ return [4 /*yield*/, delegate.findFirst({
382
+ where: combinedWhere,
383
+ select: (_c = {}, _c[(_l = getIdField(runtimeDataModel, relatedModel)) !== null && _l !== void 0 ? _l : "id"] = true, _c),
384
+ })];
385
+ case 5:
386
+ record = _o.sent();
387
+ return [2 /*return*/, !record];
388
+ case 6: return [4 /*yield*/, delegate.findMany({
389
+ where: combinedWhere,
390
+ select: (_d = {}, _d[(_m = getIdField(runtimeDataModel, relatedModel)) !== null && _m !== void 0 ? _m : "id"] = true, _d),
391
+ })];
392
+ case 7:
393
+ results = _o.sent();
394
+ return [2 /*return*/, results.length === constraints.length];
579
395
  }
580
396
  });
581
397
  }); };
582
- var createRoles = function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
583
- var runtimeDataModel, models, diff, defaultAbilities, abilities, models_2, models_2_1, model, ability, operation, roles, pgRoles, existingAbilities, pgPolicies, migratedAbilities, _c, _d, _e, _i, model, table, _loop_2, _f, _g, _h, _j, slug, _loop_3, _k, _l, _m, _o, key;
584
- var e_7, _p;
585
- var _q;
586
- var prisma = _b.prisma, customAbilities = _b.customAbilities, getRoles = _b.getRoles;
587
- return __generator(this, function (_r) {
588
- switch (_r.label) {
398
+ var matchesCreateWhere = function (prisma, runtimeDataModel, model, data, where) { return __awaiter(void 0, void 0, void 0, function () {
399
+ var clauses, checks, clauses, checks, clauses, checks, _loop_1, _a, _b, _c, field, condition, state_1, e_4_1;
400
+ var e_4, _d;
401
+ return __generator(this, function (_e) {
402
+ switch (_e.label) {
589
403
  case 0:
590
- runtimeDataModel = prisma
591
- ._runtimeDataModel;
592
- models = Object.keys(runtimeDataModel.models).map(function (m) { return runtimeDataModel.models[m].dbName || m; });
593
- if (customAbilities) {
594
- diff = (0, difference_1.default)(Object.keys(customAbilities), models);
595
- if (diff.length) {
596
- throw new Error("Invalid models in custom abilities: ".concat(diff.join(", ")));
597
- }
598
- }
599
- defaultAbilities = getDefaultAbilities(models);
600
- abilities = (0, cloneDeep_1.default)(defaultAbilities);
601
- try {
602
- for (models_2 = __values(models), models_2_1 = models_2.next(); !models_2_1.done; models_2_1 = models_2.next()) {
603
- model = models_2_1.value;
604
- if (customAbilities === null || customAbilities === void 0 ? void 0 : customAbilities[model]) {
605
- for (ability in customAbilities[model]) {
606
- operation =
607
- // biome-ignore lint/style/noNonNullAssertion: TODO fix this
608
- (_q = customAbilities[model][ability]) === null || _q === void 0 ? void 0 : _q.operation;
609
- if (!operation)
610
- continue;
611
- // biome-ignore lint/style/noNonNullAssertion: TODO fix this
612
- abilities[model][ability] = __assign(__assign({}, customAbilities[model][ability]), { operation: operation, model: model, slug: ability });
613
- }
614
- }
615
- }
616
- }
617
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
618
- finally {
619
- try {
620
- if (models_2_1 && !models_2_1.done && (_p = models_2.return)) _p.call(models_2);
621
- }
622
- finally { if (e_7) throw e_7.error; }
623
- }
624
- debug("Setting up ability table");
625
- return [4 /*yield*/, setupAbilityTable(prisma)];
404
+ if (!where.AND) return [3 /*break*/, 2];
405
+ clauses = Array.isArray(where.AND) ? where.AND : [where.AND];
406
+ return [4 /*yield*/, Promise.all(clauses.map(function (clause) {
407
+ return matchesCreateWhere(prisma, runtimeDataModel, model, data, clause);
408
+ }))];
626
409
  case 1:
627
- _r.sent();
628
- roles = getRoles(abilities);
629
- return [4 /*yield*/, prisma.$queryRawUnsafe("\n\t\tselect * from pg_catalog.pg_roles where rolname like 'yates%'\n\t")];
410
+ checks = _e.sent();
411
+ if (!checks.every(Boolean))
412
+ return [2 /*return*/, false];
413
+ _e.label = 2;
630
414
  case 2:
631
- pgRoles = _r.sent();
632
- return [4 /*yield*/, prisma.$queryRawUnsafe("\n\t\tselect * from _yates._yates_abilities;\n\t")];
415
+ if (!where.OR) return [3 /*break*/, 4];
416
+ clauses = Array.isArray(where.OR) ? where.OR : [where.OR];
417
+ return [4 /*yield*/, Promise.all(clauses.map(function (clause) {
418
+ return matchesCreateWhere(prisma, runtimeDataModel, model, data, clause);
419
+ }))];
633
420
  case 3:
634
- existingAbilities = _r.sent();
635
- if (!(existingAbilities.length === 0)) return [3 /*break*/, 6];
636
- debug('No existing abilities found, importing from "pg_policies" table');
637
- return [4 /*yield*/, prisma.$queryRawUnsafe("\n\t\t\tselect * from pg_catalog.pg_policies where policyname like 'yates%'\n\t\t")];
421
+ checks = _e.sent();
422
+ if (!checks.some(Boolean))
423
+ return [2 /*return*/, false];
424
+ _e.label = 4;
638
425
  case 4:
639
- pgPolicies = _r.sent();
640
- if (!pgPolicies.length) return [3 /*break*/, 6];
641
- migratedAbilities = pgPolicies.map(function (policy) {
642
- var _a, _b;
643
- return ({
644
- ability_model: policy.tablename,
645
- ability_name: policy.policyname,
646
- ability_policy_name: policy.policyname,
647
- ability_description: "",
648
- ability_operation: policy.cmd,
649
- ability_expression: (_b = (_a = policy.qual) !== null && _a !== void 0 ? _a : policy.with_check) !== null && _b !== void 0 ? _b : "",
650
- });
651
- });
652
- return [4 /*yield*/, prisma.$transaction(__spreadArray([
653
- takeLock(prisma)
654
- ], __read(migratedAbilities.map(function (ma) { return upsertAbility(prisma, ma); })), false))];
426
+ if (!where.NOT) return [3 /*break*/, 6];
427
+ clauses = Array.isArray(where.NOT) ? where.NOT : [where.NOT];
428
+ return [4 /*yield*/, Promise.all(clauses.map(function (clause) {
429
+ return matchesCreateWhere(prisma, runtimeDataModel, model, data, clause);
430
+ }))];
655
431
  case 5:
656
- _r.sent();
657
- existingAbilities.push.apply(existingAbilities, __spreadArray([], __read(migratedAbilities), false));
658
- _r.label = 6;
432
+ checks = _e.sent();
433
+ if (checks.some(Boolean))
434
+ return [2 /*return*/, false];
435
+ _e.label = 6;
659
436
  case 6:
660
- _c = abilities;
661
- _d = [];
662
- for (_e in _c)
663
- _d.push(_e);
664
- _i = 0;
665
- _r.label = 7;
437
+ _loop_1 = function (field, condition) {
438
+ var modelData, fieldData, ok, value;
439
+ return __generator(this, function (_f) {
440
+ switch (_f.label) {
441
+ case 0:
442
+ if (field === "AND" || field === "OR" || field === "NOT")
443
+ return [2 /*return*/, "continue"];
444
+ modelData = runtimeDataModel.models[model];
445
+ fieldData = modelData === null || modelData === void 0 ? void 0 : modelData.fields.find(function (f) { return f.name === field; });
446
+ if (!fieldData)
447
+ return [2 /*return*/, "continue"];
448
+ if (!(fieldData.kind === "object")) return [3 /*break*/, 2];
449
+ return [4 /*yield*/, matchesRelationFilter(prisma, runtimeDataModel, fieldData, data, condition)];
450
+ case 1:
451
+ ok = _f.sent();
452
+ if (!ok)
453
+ return [2 /*return*/, { value: false }];
454
+ return [2 /*return*/, "continue"];
455
+ case 2:
456
+ value = data[field];
457
+ if (!matchesScalarFilter(value, condition, data))
458
+ return [2 /*return*/, { value: false }];
459
+ return [2 /*return*/];
460
+ }
461
+ });
462
+ };
463
+ _e.label = 7;
666
464
  case 7:
667
- if (!(_i < _d.length)) return [3 /*break*/, 13];
668
- _e = _d[_i];
669
- if (!(_e in _c)) return [3 /*break*/, 12];
670
- model = _e;
671
- table = model;
672
- return [4 /*yield*/, prisma.$transaction([
673
- takeLock(prisma),
674
- prisma.$queryRawUnsafe("ALTER table \"".concat(table, "\" enable row level security;")),
675
- ])];
465
+ _e.trys.push([7, 12, 13, 14]);
466
+ _a = __values(Object.entries(where)), _b = _a.next();
467
+ _e.label = 8;
676
468
  case 8:
677
- _r.sent();
678
- _loop_2 = function (slug) {
679
- var ability, roleName;
680
- return __generator(this, function (_s) {
681
- switch (_s.label) {
469
+ if (!!_b.done) return [3 /*break*/, 11];
470
+ _c = __read(_b.value, 2), field = _c[0], condition = _c[1];
471
+ return [5 /*yield**/, _loop_1(field, condition)];
472
+ case 9:
473
+ state_1 = _e.sent();
474
+ if (typeof state_1 === "object")
475
+ return [2 /*return*/, state_1.value];
476
+ _e.label = 10;
477
+ case 10:
478
+ _b = _a.next();
479
+ return [3 /*break*/, 8];
480
+ case 11: return [3 /*break*/, 14];
481
+ case 12:
482
+ e_4_1 = _e.sent();
483
+ e_4 = { error: e_4_1 };
484
+ return [3 /*break*/, 14];
485
+ case 13:
486
+ try {
487
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
488
+ }
489
+ finally { if (e_4) throw e_4.error; }
490
+ return [7 /*endfinally*/];
491
+ case 14: return [2 /*return*/, true];
492
+ }
493
+ });
494
+ }); };
495
+ var extractModelFields = function (runtimeDataModel, model) {
496
+ var _a;
497
+ var modelData = runtimeDataModel.models[model];
498
+ return (_a = modelData === null || modelData === void 0 ? void 0 : modelData.fields) !== null && _a !== void 0 ? _a : [];
499
+ };
500
+ var buildRowHelper = function (prisma, runtimeDataModel, model) {
501
+ return (function (col) {
502
+ var _a;
503
+ var modelData = runtimeDataModel.models[model];
504
+ if (!modelData) {
505
+ throw new Error("Could not retrieve model data for '".concat(model, "'"));
506
+ }
507
+ var fieldData = modelData.fields.find(function (field) { return field.name === col; });
508
+ if (!fieldData) {
509
+ throw new Error("Could not retrieve field data from Prisma Client for field '".concat(model, ".").concat(col, "'"));
510
+ }
511
+ var delegate = prisma[lowerModelName(model)];
512
+ var fieldRef = (_a = delegate === null || delegate === void 0 ? void 0 : delegate.fields) === null || _a === void 0 ? void 0 : _a[col];
513
+ if (!fieldRef) {
514
+ throw new Error("Could not resolve field reference for '".concat(model, ".").concat(col, "'"));
515
+ }
516
+ return fieldRef;
517
+ });
518
+ };
519
+ var buildContextHelper = function (context) {
520
+ return (function (key) {
521
+ return context ? context[key] : undefined;
522
+ });
523
+ };
524
+ var resolveExpression = function (prisma, runtimeDataModel, model, expression, context) { return __awaiter(void 0, void 0, void 0, function () {
525
+ var row, ctx;
526
+ return __generator(this, function (_a) {
527
+ switch (_a.label) {
528
+ case 0:
529
+ if (!expression)
530
+ return [2 /*return*/, {}];
531
+ if (typeof expression !== "function")
532
+ return [2 /*return*/, expression];
533
+ row = buildRowHelper(prisma, runtimeDataModel, model);
534
+ ctx = buildContextHelper(context);
535
+ return [4 /*yield*/, expression(prisma, row, ctx)];
536
+ case 1: return [2 /*return*/, (_a.sent())];
537
+ }
538
+ });
539
+ }); };
540
+ var dedupeAbilityList = function (abilityList) {
541
+ var seen = new Set();
542
+ return abilityList.filter(function (ability) {
543
+ if (seen.has(ability)) {
544
+ return false;
545
+ }
546
+ seen.add(ability);
547
+ return true;
548
+ });
549
+ };
550
+ var buildRoleAbilities = function (roles, allAbilities) {
551
+ var e_5, _a;
552
+ var roleAbilities = {};
553
+ try {
554
+ for (var _b = __values(Object.entries(roles)), _c = _b.next(); !_c.done; _c = _b.next()) {
555
+ var _d = __read(_c.value, 2), role = _d[0], abilities = _d[1];
556
+ var abilityList = abilities === "*"
557
+ ? allAbilities
558
+ : abilities;
559
+ roleAbilities[role] = dedupeAbilityList(abilityList);
560
+ }
561
+ }
562
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
563
+ finally {
564
+ try {
565
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
566
+ }
567
+ finally { if (e_5) throw e_5.error; }
568
+ }
569
+ return roleAbilities;
570
+ };
571
+ var getAbilityFilters = function (prisma, runtimeDataModel, roleAbilities, role, model, operation, context) { return __awaiter(void 0, void 0, void 0, function () {
572
+ var abilities, relevant;
573
+ return __generator(this, function (_a) {
574
+ abilities = roleAbilities[role] || [];
575
+ relevant = abilities.filter(function (ability) { return ability.model === model && ability.operation === operation; });
576
+ if (relevant.length === 0) {
577
+ return [2 /*return*/, []];
578
+ }
579
+ return [2 /*return*/, Promise.all(relevant.map(function (ability) {
580
+ return resolveExpression(prisma, runtimeDataModel, model, ability.expression, context);
581
+ }))];
582
+ });
583
+ }); };
584
+ var applyReadSelections = function (prisma, runtimeDataModel, roleAbilities, role, model, args, context) { return __awaiter(void 0, void 0, void 0, function () {
585
+ var _a, _b, key, selection, _loop_2, _c, _d, _e, field, value, e_6_1, e_7_1;
586
+ var e_7, _f, e_6, _g;
587
+ var _h;
588
+ return __generator(this, function (_j) {
589
+ switch (_j.label) {
590
+ case 0:
591
+ _j.trys.push([0, 11, 12, 13]);
592
+ _a = __values(["include", "select"]), _b = _a.next();
593
+ _j.label = 1;
594
+ case 1:
595
+ if (!!_b.done) return [3 /*break*/, 10];
596
+ key = _b.value;
597
+ selection = args[key];
598
+ if (!selection || !isPlainObject(selection))
599
+ return [3 /*break*/, 9];
600
+ _loop_2 = function (field, value) {
601
+ var fields, fieldMeta, relatedModel, abilityFilters, abilityWhere, nextArgs;
602
+ return __generator(this, function (_k) {
603
+ switch (_k.label) {
682
604
  case 0:
683
- ability =
684
- // biome-ignore lint/style/noNonNullAssertion: TODO fix this
685
- abilities[model][slug];
686
- if (!VALID_OPERATIONS.includes(ability.operation)) {
687
- throw new Error("Invalid operation: ".concat(ability.operation));
605
+ fields = extractModelFields(runtimeDataModel, model);
606
+ fieldMeta = fields.find(function (f) { return f.name === field; });
607
+ if (!fieldMeta || fieldMeta.kind !== "object")
608
+ return [2 /*return*/, "continue"];
609
+ relatedModel = fieldMeta.type;
610
+ return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, relatedModel, "SELECT", context)];
611
+ case 1:
612
+ abilityFilters = _k.sent();
613
+ if (!abilityFilters || abilityFilters.length === 0) {
614
+ selection[field] = false;
615
+ return [2 /*return*/, "continue"];
616
+ }
617
+ abilityWhere = combineAbilityFilters(abilityFilters);
618
+ nextArgs = value === true ? {} : __assign({}, value);
619
+ if (fieldMeta.isList) {
620
+ nextArgs.where =
621
+ (_h = mergeWhere(nextArgs.where, abilityWhere)) !== null && _h !== void 0 ? _h : nextArgs.where;
688
622
  }
689
- roleName = (0, exports.createAbilityName)(model, slug);
690
- if (!pgRoles.find(function (role) { return role.rolname === roleName; })) return [3 /*break*/, 1];
691
- debug("Role already exists", roleName, model, slug);
692
- return [3 /*break*/, 3];
693
- case 1: return [4 /*yield*/, prisma.$transaction([
694
- takeLock(prisma),
695
- prisma.$queryRawUnsafe("\n\t\t\t\t\tdo\n\t\t\t\t\t$$\n\t\t\t\t\tbegin\n\t\t\t\t\tif not exists (select * from pg_catalog.pg_roles where rolname = '".concat(roleName, "') then \n\t\t\t\t\t\tcreate role ").concat(roleName, ";\n\t\t\t\t\tend if;\n\t\t\t\t\tend\n\t\t\t\t\t$$\n\t\t\t\t\t;\n\t\t\t\t")),
696
- prisma.$queryRawUnsafe("\n\t\t\t\t\tGRANT ".concat(ability.operation, " ON \"").concat(table, "\" TO ").concat(roleName, ";\n\t\t\t\t")),
697
- ])];
623
+ return [4 /*yield*/, applyReadSelections(prisma, runtimeDataModel, roleAbilities, role, relatedModel, nextArgs, context)];
698
624
  case 2:
699
- _s.sent();
700
- _s.label = 3;
701
- case 3:
702
- if (!ability.expression) return [3 /*break*/, 5];
703
- return [4 /*yield*/, setRLS(prisma, table, roleName, slug, ability)];
704
- case 4:
705
- _s.sent();
706
- _s.label = 5;
707
- case 5: return [2 /*return*/];
625
+ _k.sent();
626
+ selection[field] = nextArgs;
627
+ return [2 /*return*/];
708
628
  }
709
629
  });
710
630
  };
711
- _f = abilities[model];
712
- _g = [];
713
- for (_h in _f)
714
- _g.push(_h);
715
- _j = 0;
716
- _r.label = 9;
631
+ _j.label = 2;
632
+ case 2:
633
+ _j.trys.push([2, 7, 8, 9]);
634
+ _c = (e_6 = void 0, __values(Object.entries(selection))), _d = _c.next();
635
+ _j.label = 3;
636
+ case 3:
637
+ if (!!_d.done) return [3 /*break*/, 6];
638
+ _e = __read(_d.value, 2), field = _e[0], value = _e[1];
639
+ return [5 /*yield**/, _loop_2(field, value)];
640
+ case 4:
641
+ _j.sent();
642
+ _j.label = 5;
643
+ case 5:
644
+ _d = _c.next();
645
+ return [3 /*break*/, 3];
646
+ case 6: return [3 /*break*/, 9];
647
+ case 7:
648
+ e_6_1 = _j.sent();
649
+ e_6 = { error: e_6_1 };
650
+ return [3 /*break*/, 9];
651
+ case 8:
652
+ try {
653
+ if (_d && !_d.done && (_g = _c.return)) _g.call(_c);
654
+ }
655
+ finally { if (e_6) throw e_6.error; }
656
+ return [7 /*endfinally*/];
717
657
  case 9:
718
- if (!(_j < _g.length)) return [3 /*break*/, 12];
719
- _h = _g[_j];
720
- if (!(_h in _f)) return [3 /*break*/, 11];
721
- slug = _h;
722
- return [5 /*yield**/, _loop_2(slug)];
723
- case 10:
724
- _r.sent();
725
- _r.label = 11;
658
+ _b = _a.next();
659
+ return [3 /*break*/, 1];
660
+ case 10: return [3 /*break*/, 13];
726
661
  case 11:
727
- _j++;
728
- return [3 /*break*/, 9];
662
+ e_7_1 = _j.sent();
663
+ e_7 = { error: e_7_1 };
664
+ return [3 /*break*/, 13];
729
665
  case 12:
730
- _i++;
731
- return [3 /*break*/, 7];
732
- case 13:
733
- _loop_3 = function (key) {
734
- var role, wildCardAbilities, roleAbilities, rlsRoles, userRoles, oldRoles, policies;
735
- return __generator(this, function (_t) {
736
- switch (_t.label) {
666
+ try {
667
+ if (_b && !_b.done && (_f = _a.return)) _f.call(_a);
668
+ }
669
+ finally { if (e_7) throw e_7.error; }
670
+ return [7 /*endfinally*/];
671
+ case 13: return [2 /*return*/];
672
+ }
673
+ });
674
+ }); };
675
+ var assertCreateAllowed = function (prisma, runtimeDataModel, roleAbilities, role, model, data, context) { return __awaiter(void 0, void 0, void 0, function () {
676
+ var abilityFilters, abilityWhere;
677
+ var _a;
678
+ return __generator(this, function (_b) {
679
+ switch (_b.label) {
680
+ case 0: return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, model, "INSERT", context)];
681
+ case 1:
682
+ abilityFilters = (_a = (_b.sent())) !== null && _a !== void 0 ? _a : [];
683
+ abilityWhere = combineAbilityFilters(abilityFilters);
684
+ if (!abilityWhere) {
685
+ throw permissionError(model, "create");
686
+ }
687
+ if (isEmptyWhere(abilityWhere))
688
+ return [2 /*return*/];
689
+ return [4 /*yield*/, matchesCreateWhere(prisma, runtimeDataModel, model, data, abilityWhere)];
690
+ case 2:
691
+ if (!(_b.sent())) {
692
+ throw permissionError(model, "create");
693
+ }
694
+ return [2 /*return*/];
695
+ }
696
+ });
697
+ }); };
698
+ var assertRecordAllowed = function (prisma, runtimeDataModel, roleAbilities, role, model, operation, where, context) { return __awaiter(void 0, void 0, void 0, function () {
699
+ var abilityFilters, abilityWhere, combinedWhere, delegate, record;
700
+ var _a;
701
+ var _b, _c, _d;
702
+ return __generator(this, function (_e) {
703
+ switch (_e.label) {
704
+ case 0: return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, model, operation, context)];
705
+ case 1:
706
+ abilityFilters = (_b = (_e.sent())) !== null && _b !== void 0 ? _b : [];
707
+ abilityWhere = combineAbilityFilters(abilityFilters);
708
+ if (!abilityWhere) {
709
+ return [2 /*return*/, false];
710
+ }
711
+ combinedWhere = (_c = mergeWhere(where, abilityWhere)) !== null && _c !== void 0 ? _c : where;
712
+ delegate = prisma[lowerModelName(model)];
713
+ return [4 /*yield*/, delegate.findFirst({
714
+ where: combinedWhere,
715
+ select: (_a = {}, _a[(_d = getIdField(runtimeDataModel, model)) !== null && _d !== void 0 ? _d : "id"] = true, _a),
716
+ })];
717
+ case 2:
718
+ record = _e.sent();
719
+ return [2 /*return*/, !!record];
720
+ }
721
+ });
722
+ }); };
723
+ var applyNestedWrites = function (prisma, runtimeDataModel, roleAbilities, role, model, data, context) { return __awaiter(void 0, void 0, void 0, function () {
724
+ var fields, _loop_3, _a, _b, _c, field, value, e_8_1;
725
+ var e_8, _d;
726
+ var _e, _f, _g, _h, _j, _k;
727
+ return __generator(this, function (_l) {
728
+ switch (_l.label) {
729
+ case 0:
730
+ if (!isPlainObject(data))
731
+ return [2 /*return*/];
732
+ fields = extractModelFields(runtimeDataModel, model);
733
+ _loop_3 = function (field, value) {
734
+ var fieldMeta, relatedModel, handleCreate, handleUpdate, handleDelete, items, items_2, items_2_1, item, filters, abilityWhere, e_9_1, items, items_3, items_3_1, item, where, canUpdate, e_10_1, items, items_4, items_4_1, item, filters, abilityWhere, _m, _o, key, merged, _p, _q, key, e_11_1;
735
+ var e_9, _r, e_10, _s, e_11, _t, e_12, _u, e_13, _v;
736
+ return __generator(this, function (_w) {
737
+ switch (_w.label) {
737
738
  case 0:
738
- role = (0, exports.createRoleName)(key);
739
- return [4 /*yield*/, prisma.$executeRawUnsafe("\n\t\t\tdo\n\t\t\t$$\n\t\t\tbegin\n\t\t\tif not exists (select * from pg_catalog.pg_roles where rolname = '".concat(role, "') then \n\t\t\t\tcreate role ").concat(role, ";\n\t\t\tend if;\n\t\t\tend\n\t\t\t$$\n\t\t\t;\n\t\t"))];
740
- case 1:
741
- _t.sent();
742
- wildCardAbilities = (0, flatMap_1.default)(defaultAbilities, function (model, modelName) {
743
- return (0, map_1.default)(model, function (_params, slug) {
744
- return (0, exports.createAbilityName)(modelName, slug);
739
+ fieldMeta = fields.find(function (f) { return f.name === field; });
740
+ if (!fieldMeta || fieldMeta.kind !== "object")
741
+ return [2 /*return*/, "continue"];
742
+ relatedModel = fieldMeta.type;
743
+ if (!isPlainObject(value))
744
+ return [2 /*return*/, "continue"];
745
+ handleCreate = function (createValue) { return __awaiter(void 0, void 0, void 0, function () {
746
+ var items, items_5, items_5_1, item, e_14_1;
747
+ var e_14, _a;
748
+ return __generator(this, function (_b) {
749
+ switch (_b.label) {
750
+ case 0:
751
+ items = Array.isArray(createValue) ? createValue : [createValue];
752
+ _b.label = 1;
753
+ case 1:
754
+ _b.trys.push([1, 7, 8, 9]);
755
+ items_5 = __values(items), items_5_1 = items_5.next();
756
+ _b.label = 2;
757
+ case 2:
758
+ if (!!items_5_1.done) return [3 /*break*/, 6];
759
+ item = items_5_1.value;
760
+ if (!isPlainObject(item)) return [3 /*break*/, 5];
761
+ return [4 /*yield*/, assertCreateAllowed(prisma, runtimeDataModel, roleAbilities, role, relatedModel, item, context)];
762
+ case 3:
763
+ _b.sent();
764
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, relatedModel, item, context)];
765
+ case 4:
766
+ _b.sent();
767
+ _b.label = 5;
768
+ case 5:
769
+ items_5_1 = items_5.next();
770
+ return [3 /*break*/, 2];
771
+ case 6: return [3 /*break*/, 9];
772
+ case 7:
773
+ e_14_1 = _b.sent();
774
+ e_14 = { error: e_14_1 };
775
+ return [3 /*break*/, 9];
776
+ case 8:
777
+ try {
778
+ if (items_5_1 && !items_5_1.done && (_a = items_5.return)) _a.call(items_5);
779
+ }
780
+ finally { if (e_14) throw e_14.error; }
781
+ return [7 /*endfinally*/];
782
+ case 9: return [2 /*return*/];
783
+ }
745
784
  });
746
- });
747
- roleAbilities = roles[key];
748
- rlsRoles = roleAbilities === "*"
749
- ? wildCardAbilities
750
- : roleAbilities.map(function (ability) {
751
- // biome-ignore lint/style/noNonNullAssertion: TODO fix this
752
- return (0, exports.createAbilityName)(ability.model, ability.slug);
785
+ }); };
786
+ handleUpdate = function (updateValue) { return __awaiter(void 0, void 0, void 0, function () {
787
+ var items, items_6, items_6_1, item, where, allowed, e_15_1;
788
+ var e_15, _a;
789
+ var _b;
790
+ return __generator(this, function (_c) {
791
+ switch (_c.label) {
792
+ case 0:
793
+ items = Array.isArray(updateValue) ? updateValue : [updateValue];
794
+ _c.label = 1;
795
+ case 1:
796
+ _c.trys.push([1, 7, 8, 9]);
797
+ items_6 = __values(items), items_6_1 = items_6.next();
798
+ _c.label = 2;
799
+ case 2:
800
+ if (!!items_6_1.done) return [3 /*break*/, 6];
801
+ item = items_6_1.value;
802
+ if (!isPlainObject(item))
803
+ return [3 /*break*/, 5];
804
+ where = (_b = item.where) !== null && _b !== void 0 ? _b : {};
805
+ return [4 /*yield*/, assertRecordAllowed(prisma, runtimeDataModel, roleAbilities, role, relatedModel, "UPDATE", where, context)];
806
+ case 3:
807
+ allowed = _c.sent();
808
+ if (!allowed) {
809
+ throw updateNotFoundError();
810
+ }
811
+ if (!item.data) return [3 /*break*/, 5];
812
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, relatedModel, item.data, context)];
813
+ case 4:
814
+ _c.sent();
815
+ _c.label = 5;
816
+ case 5:
817
+ items_6_1 = items_6.next();
818
+ return [3 /*break*/, 2];
819
+ case 6: return [3 /*break*/, 9];
820
+ case 7:
821
+ e_15_1 = _c.sent();
822
+ e_15 = { error: e_15_1 };
823
+ return [3 /*break*/, 9];
824
+ case 8:
825
+ try {
826
+ if (items_6_1 && !items_6_1.done && (_a = items_6.return)) _a.call(items_6);
827
+ }
828
+ finally { if (e_15) throw e_15.error; }
829
+ return [7 /*endfinally*/];
830
+ case 9: return [2 /*return*/];
831
+ }
832
+ });
833
+ }); };
834
+ handleDelete = function (deleteValue) { return __awaiter(void 0, void 0, void 0, function () {
835
+ var items, items_7, items_7_1, item, where, allowed, e_16_1;
836
+ var e_16, _a;
837
+ return __generator(this, function (_b) {
838
+ switch (_b.label) {
839
+ case 0:
840
+ items = Array.isArray(deleteValue) ? deleteValue : [deleteValue];
841
+ _b.label = 1;
842
+ case 1:
843
+ _b.trys.push([1, 6, 7, 8]);
844
+ items_7 = __values(items), items_7_1 = items_7.next();
845
+ _b.label = 2;
846
+ case 2:
847
+ if (!!items_7_1.done) return [3 /*break*/, 5];
848
+ item = items_7_1.value;
849
+ where = isPlainObject(item) ? item : {};
850
+ return [4 /*yield*/, assertRecordAllowed(prisma, runtimeDataModel, roleAbilities, role, relatedModel, "DELETE", where, context)];
851
+ case 3:
852
+ allowed = _b.sent();
853
+ if (!allowed) {
854
+ throw deleteNotFoundError();
855
+ }
856
+ _b.label = 4;
857
+ case 4:
858
+ items_7_1 = items_7.next();
859
+ return [3 /*break*/, 2];
860
+ case 5: return [3 /*break*/, 8];
861
+ case 6:
862
+ e_16_1 = _b.sent();
863
+ e_16 = { error: e_16_1 };
864
+ return [3 /*break*/, 8];
865
+ case 7:
866
+ try {
867
+ if (items_7_1 && !items_7_1.done && (_a = items_7.return)) _a.call(items_7);
868
+ }
869
+ finally { if (e_16) throw e_16.error; }
870
+ return [7 /*endfinally*/];
871
+ case 8: return [2 /*return*/];
872
+ }
753
873
  });
754
- debug("Setting up role", key, role, "with abilities", rlsRoles.join(", "));
755
- // Note: We need to GRANT all on schema public so that we can resolve relation queries with prisma, as they will sometimes use a join table.
756
- // This is not ideal, but because we are using RLS, it's not a security risk. Any table with RLS also needs a corresponding policy for the role to have access.
757
- return [4 /*yield*/, prisma.$transaction([
758
- takeLock(prisma),
759
- prisma.$executeRawUnsafe("GRANT ALL ON ALL TABLES IN SCHEMA public TO ".concat(role, ";")),
760
- prisma.$executeRawUnsafe("\n\t\t\t\tGRANT ALL ON ALL SEQUENCES IN SCHEMA public TO ".concat(role, ";\n\t\t\t")),
761
- prisma.$executeRawUnsafe("\n\t\t\t\tGRANT ALL ON SCHEMA public TO ".concat(role, ";\n\t\t\t")),
762
- prisma.$queryRawUnsafe("GRANT ".concat(rlsRoles.join(", "), " TO ").concat(role)),
763
- ])];
874
+ }); };
875
+ if (!value.create) return [3 /*break*/, 2];
876
+ return [4 /*yield*/, handleCreate(value.create)];
877
+ case 1:
878
+ _w.sent();
879
+ _w.label = 2;
764
880
  case 2:
765
- // Note: We need to GRANT all on schema public so that we can resolve relation queries with prisma, as they will sometimes use a join table.
766
- // This is not ideal, but because we are using RLS, it's not a security risk. Any table with RLS also needs a corresponding policy for the role to have access.
767
- _t.sent();
768
- return [4 /*yield*/, prisma.$queryRawUnsafe("\n\t\t\tWITH RECURSIVE cte AS (\n\t\t\t\tSELECT oid FROM pg_roles where rolname = '".concat(role, "'\n\t\t\t\tUNION ALL\n\t\t\t\tSELECT m.roleid\n\t\t\t\tFROM cte\n\t\t\t\tJOIN pg_auth_members m ON m.member = cte.oid\n\t\t\t\t)\n\t\t\tSELECT oid, oid::regrole::text AS rolename FROM cte where oid::regrole::text != '").concat(role, "'; \n\t "))];
881
+ if (!((_e = value.createMany) === null || _e === void 0 ? void 0 : _e.data)) return [3 /*break*/, 4];
882
+ return [4 /*yield*/, handleCreate(value.createMany.data)];
769
883
  case 3:
770
- userRoles = _t.sent();
771
- oldRoles = userRoles
772
- .filter(function (_a) {
773
- var rolename = _a.rolename;
774
- return !rlsRoles.includes(rolename);
775
- })
776
- .map(function (_a) {
777
- var rolename = _a.rolename;
778
- return rolename;
779
- });
780
- if (!oldRoles.length) return [3 /*break*/, 8];
781
- // Now revoke old roles from the user role
782
- debug("Revoking old roles", key, role, oldRoles.join(", "));
783
- return [4 /*yield*/, prisma.$executeRawUnsafe("REVOKE ".concat(oldRoles.join(", "), " FROM ").concat(role))];
884
+ _w.sent();
885
+ _w.label = 4;
784
886
  case 4:
785
- _t.sent();
786
- return [4 /*yield*/, prisma.$queryRawUnsafe("SELECT * FROM pg_catalog.pg_policies WHERE policyname IN (".concat(oldRoles
787
- .map(function (or) { return "'".concat(or, "'"); })
788
- .join(", "), ")"))];
887
+ if (!value.update) return [3 /*break*/, 6];
888
+ return [4 /*yield*/, handleUpdate(value.update)];
789
889
  case 5:
790
- policies = _t.sent();
791
- return [4 /*yield*/, prisma.$transaction(__spreadArray([
792
- takeLock(prisma)
793
- ], __read(policies.map(function (oldPolicy) {
794
- return prisma.$executeRawUnsafe("DROP POLICY ".concat(oldPolicy.policyname, " ON \"").concat(oldPolicy.tablename, "\""));
795
- })), false))];
890
+ _w.sent();
891
+ _w.label = 6;
796
892
  case 6:
797
- _t.sent();
798
- debug("Revoked old rows from ability table", oldRoles.join(", "));
799
- return [4 /*yield*/, prisma.$executeRawUnsafe("DELETE FROM _yates._yates_abilities WHERE ability_policy_name IN (".concat(oldRoles
800
- .map(function (or) { return "'".concat(or, "'"); })
801
- .join(", "), ")"))];
893
+ if (!value.updateMany) return [3 /*break*/, 15];
894
+ items = Array.isArray(value.updateMany)
895
+ ? value.updateMany
896
+ : [value.updateMany];
897
+ _w.label = 7;
802
898
  case 7:
803
- _t.sent();
804
- _t.label = 8;
805
- case 8: return [2 /*return*/];
899
+ _w.trys.push([7, 13, 14, 15]);
900
+ items_2 = (e_9 = void 0, __values(items)), items_2_1 = items_2.next();
901
+ _w.label = 8;
902
+ case 8:
903
+ if (!!items_2_1.done) return [3 /*break*/, 12];
904
+ item = items_2_1.value;
905
+ if (!isPlainObject(item))
906
+ return [3 /*break*/, 11];
907
+ return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, relatedModel, "UPDATE", context)];
908
+ case 9:
909
+ filters = (_f = (_w.sent())) !== null && _f !== void 0 ? _f : [];
910
+ abilityWhere = combineAbilityFilters(filters);
911
+ if (!abilityWhere) {
912
+ item.where = denyWhere(runtimeDataModel, relatedModel);
913
+ }
914
+ else {
915
+ item.where = (_h = mergeWhere((_g = item.where) !== null && _g !== void 0 ? _g : {}, abilityWhere)) !== null && _h !== void 0 ? _h : item.where;
916
+ }
917
+ if (!item.data) return [3 /*break*/, 11];
918
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, relatedModel, item.data, context)];
919
+ case 10:
920
+ _w.sent();
921
+ _w.label = 11;
922
+ case 11:
923
+ items_2_1 = items_2.next();
924
+ return [3 /*break*/, 8];
925
+ case 12: return [3 /*break*/, 15];
926
+ case 13:
927
+ e_9_1 = _w.sent();
928
+ e_9 = { error: e_9_1 };
929
+ return [3 /*break*/, 15];
930
+ case 14:
931
+ try {
932
+ if (items_2_1 && !items_2_1.done && (_r = items_2.return)) _r.call(items_2);
933
+ }
934
+ finally { if (e_9) throw e_9.error; }
935
+ return [7 /*endfinally*/];
936
+ case 15:
937
+ if (!value.upsert) return [3 /*break*/, 29];
938
+ items = Array.isArray(value.upsert) ? value.upsert : [value.upsert];
939
+ _w.label = 16;
940
+ case 16:
941
+ _w.trys.push([16, 27, 28, 29]);
942
+ items_3 = (e_10 = void 0, __values(items)), items_3_1 = items_3.next();
943
+ _w.label = 17;
944
+ case 17:
945
+ if (!!items_3_1.done) return [3 /*break*/, 26];
946
+ item = items_3_1.value;
947
+ if (!isPlainObject(item))
948
+ return [3 /*break*/, 25];
949
+ where = (_j = item.where) !== null && _j !== void 0 ? _j : {};
950
+ return [4 /*yield*/, assertRecordAllowed(prisma, runtimeDataModel, roleAbilities, role, relatedModel, "UPDATE", where, context)];
951
+ case 18:
952
+ canUpdate = _w.sent();
953
+ if (!canUpdate) return [3 /*break*/, 21];
954
+ if (!item.update) return [3 /*break*/, 20];
955
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, relatedModel, item.update, context)];
956
+ case 19:
957
+ _w.sent();
958
+ _w.label = 20;
959
+ case 20: return [3 /*break*/, 25];
960
+ case 21:
961
+ if (!item.create) return [3 /*break*/, 24];
962
+ return [4 /*yield*/, assertCreateAllowed(prisma, runtimeDataModel, roleAbilities, role, relatedModel, item.create, context)];
963
+ case 22:
964
+ _w.sent();
965
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, relatedModel, item.create, context)];
966
+ case 23:
967
+ _w.sent();
968
+ return [3 /*break*/, 25];
969
+ case 24: throw updateNotFoundError();
970
+ case 25:
971
+ items_3_1 = items_3.next();
972
+ return [3 /*break*/, 17];
973
+ case 26: return [3 /*break*/, 29];
974
+ case 27:
975
+ e_10_1 = _w.sent();
976
+ e_10 = { error: e_10_1 };
977
+ return [3 /*break*/, 29];
978
+ case 28:
979
+ try {
980
+ if (items_3_1 && !items_3_1.done && (_s = items_3.return)) _s.call(items_3);
981
+ }
982
+ finally { if (e_10) throw e_10.error; }
983
+ return [7 /*endfinally*/];
984
+ case 29:
985
+ if (!value.delete) return [3 /*break*/, 31];
986
+ return [4 /*yield*/, handleDelete(value.delete)];
987
+ case 30:
988
+ _w.sent();
989
+ _w.label = 31;
990
+ case 31:
991
+ if (!value.deleteMany) return [3 /*break*/, 39];
992
+ items = Array.isArray(value.deleteMany)
993
+ ? value.deleteMany
994
+ : [value.deleteMany];
995
+ _w.label = 32;
996
+ case 32:
997
+ _w.trys.push([32, 37, 38, 39]);
998
+ items_4 = (e_11 = void 0, __values(items)), items_4_1 = items_4.next();
999
+ _w.label = 33;
1000
+ case 33:
1001
+ if (!!items_4_1.done) return [3 /*break*/, 36];
1002
+ item = items_4_1.value;
1003
+ if (!isPlainObject(item))
1004
+ return [3 /*break*/, 35];
1005
+ return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, relatedModel, "DELETE", context)];
1006
+ case 34:
1007
+ filters = (_k = (_w.sent())) !== null && _k !== void 0 ? _k : [];
1008
+ abilityWhere = combineAbilityFilters(filters);
1009
+ if (!abilityWhere) {
1010
+ try {
1011
+ for (_m = (e_12 = void 0, __values(Object.keys(item))), _o = _m.next(); !_o.done; _o = _m.next()) {
1012
+ key = _o.value;
1013
+ delete item[key];
1014
+ }
1015
+ }
1016
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
1017
+ finally {
1018
+ try {
1019
+ if (_o && !_o.done && (_u = _m.return)) _u.call(_m);
1020
+ }
1021
+ finally { if (e_12) throw e_12.error; }
1022
+ }
1023
+ Object.assign(item, denyWhere(runtimeDataModel, relatedModel));
1024
+ }
1025
+ else {
1026
+ merged = mergeWhere((0, cloneDeep_1.default)(item), abilityWhere);
1027
+ if (merged && merged !== item) {
1028
+ try {
1029
+ for (_p = (e_13 = void 0, __values(Object.keys(item))), _q = _p.next(); !_q.done; _q = _p.next()) {
1030
+ key = _q.value;
1031
+ delete item[key];
1032
+ }
1033
+ }
1034
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
1035
+ finally {
1036
+ try {
1037
+ if (_q && !_q.done && (_v = _p.return)) _v.call(_p);
1038
+ }
1039
+ finally { if (e_13) throw e_13.error; }
1040
+ }
1041
+ Object.assign(item, merged);
1042
+ }
1043
+ }
1044
+ _w.label = 35;
1045
+ case 35:
1046
+ items_4_1 = items_4.next();
1047
+ return [3 /*break*/, 33];
1048
+ case 36: return [3 /*break*/, 39];
1049
+ case 37:
1050
+ e_11_1 = _w.sent();
1051
+ e_11 = { error: e_11_1 };
1052
+ return [3 /*break*/, 39];
1053
+ case 38:
1054
+ try {
1055
+ if (items_4_1 && !items_4_1.done && (_t = items_4.return)) _t.call(items_4);
1056
+ }
1057
+ finally { if (e_11) throw e_11.error; }
1058
+ return [7 /*endfinally*/];
1059
+ case 39: return [2 /*return*/];
806
1060
  }
807
1061
  });
808
1062
  };
809
- _k = roles;
810
- _l = [];
811
- for (_m in _k)
812
- _l.push(_m);
813
- _o = 0;
814
- _r.label = 14;
815
- case 14:
816
- if (!(_o < _l.length)) return [3 /*break*/, 17];
817
- _m = _l[_o];
818
- if (!(_m in _k)) return [3 /*break*/, 16];
819
- key = _m;
820
- return [5 /*yield**/, _loop_3(key)];
821
- case 15:
822
- _r.sent();
823
- _r.label = 16;
824
- case 16:
825
- _o++;
826
- return [3 /*break*/, 14];
827
- case 17: return [2 /*return*/];
1063
+ _l.label = 1;
1064
+ case 1:
1065
+ _l.trys.push([1, 6, 7, 8]);
1066
+ _a = __values(Object.entries(data)), _b = _a.next();
1067
+ _l.label = 2;
1068
+ case 2:
1069
+ if (!!_b.done) return [3 /*break*/, 5];
1070
+ _c = __read(_b.value, 2), field = _c[0], value = _c[1];
1071
+ return [5 /*yield**/, _loop_3(field, value)];
1072
+ case 3:
1073
+ _l.sent();
1074
+ _l.label = 4;
1075
+ case 4:
1076
+ _b = _a.next();
1077
+ return [3 /*break*/, 2];
1078
+ case 5: return [3 /*break*/, 8];
1079
+ case 6:
1080
+ e_8_1 = _l.sent();
1081
+ e_8 = { error: e_8_1 };
1082
+ return [3 /*break*/, 8];
1083
+ case 7:
1084
+ try {
1085
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
1086
+ }
1087
+ finally { if (e_8) throw e_8.error; }
1088
+ return [7 /*endfinally*/];
1089
+ case 8: return [2 /*return*/];
828
1090
  }
829
1091
  });
830
1092
  }); };
831
- exports.createRoles = createRoles;
1093
+ var Yates = /** @class */ (function () {
1094
+ function Yates(prisma) {
1095
+ var _this = this;
1096
+ this.prisma = prisma;
1097
+ this.inspectRunTimeDataModel = function () {
1098
+ var runtimeDataModel = _this.prisma
1099
+ ._runtimeDataModel;
1100
+ return runtimeDataModel;
1101
+ };
1102
+ this.getDefaultAbilities = function (models) {
1103
+ var e_17, _a;
1104
+ var abilities = {};
1105
+ try {
1106
+ for (var models_1 = __values(models), models_1_1 = models_1.next(); !models_1_1.done; models_1_1 = models_1.next()) {
1107
+ var model = models_1_1.value;
1108
+ abilities[model] = {
1109
+ create: {
1110
+ description: "Create ".concat(model),
1111
+ expression: {},
1112
+ operation: "INSERT",
1113
+ model: model,
1114
+ slug: "create",
1115
+ },
1116
+ read: {
1117
+ description: "Read ".concat(model),
1118
+ expression: {},
1119
+ operation: "SELECT",
1120
+ model: model,
1121
+ slug: "read",
1122
+ },
1123
+ update: {
1124
+ description: "Update ".concat(model),
1125
+ expression: {},
1126
+ operation: "UPDATE",
1127
+ model: model,
1128
+ slug: "update",
1129
+ },
1130
+ delete: {
1131
+ description: "Delete ".concat(model),
1132
+ expression: {},
1133
+ operation: "DELETE",
1134
+ model: model,
1135
+ slug: "delete",
1136
+ },
1137
+ };
1138
+ }
1139
+ }
1140
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
1141
+ finally {
1142
+ try {
1143
+ if (models_1_1 && !models_1_1.done && (_a = models_1.return)) _a.call(models_1);
1144
+ }
1145
+ finally { if (e_17) throw e_17.error; }
1146
+ }
1147
+ return abilities;
1148
+ };
1149
+ }
1150
+ return Yates;
1151
+ }());
1152
+ exports.Yates = Yates;
832
1153
  /**
833
- * Creates an extended client that sets contextual parameters and user role on every query
1154
+ * Creates an extended client that applies role abilities to Prisma queries.
834
1155
  **/
1156
+ exports.__private = {
1157
+ denyWhere: denyWhere,
1158
+ getIdField: getIdField,
1159
+ matchesScalarFilter: matchesScalarFilter,
1160
+ validateContext: validateContext,
1161
+ };
835
1162
  var setup = function (params) { return __awaiter(void 0, void 0, void 0, function () {
836
- var start, prisma, customAbilities, getRoles, getContext, client;
837
- return __generator(this, function (_a) {
838
- switch (_a.label) {
839
- case 0:
840
- start = performance.now();
841
- prisma = params.prisma, customAbilities = params.customAbilities, getRoles = params.getRoles, getContext = params.getContext;
842
- return [4 /*yield*/, (0, exports.createRoles)({
843
- prisma: prisma,
844
- customAbilities: customAbilities,
845
- getRoles: getRoles,
846
- })];
847
- case 1:
848
- _a.sent();
849
- client = (0, exports.createClient)(prisma, getContext, params.options);
850
- debug("Setup completed in", performance.now() - start, "ms");
851
- return [2 /*return*/, client];
1163
+ var start, prisma, customAbilities, getRoles, getContext, yates, runtimeDataModel, models, diff, defaultAbilities, abilities, models_2, models_2_1, model, modelCustomAbilities, modelAbilities, ability, operation, roles, allAbilities, roleAbilities, client;
1164
+ var e_18, _a;
1165
+ var _b;
1166
+ return __generator(this, function (_c) {
1167
+ start = performance.now();
1168
+ prisma = params.prisma, customAbilities = params.customAbilities, getRoles = params.getRoles, getContext = params.getContext;
1169
+ yates = new Yates(prisma);
1170
+ runtimeDataModel = yates.inspectRunTimeDataModel();
1171
+ models = Object.keys(runtimeDataModel.models).map(function (m) { return runtimeDataModel.models[m].dbName || m; });
1172
+ if (customAbilities) {
1173
+ diff = (0, difference_1.default)(Object.keys(customAbilities), models);
1174
+ if (diff.length) {
1175
+ throw new Error("Invalid models in custom abilities: ".concat(diff.join(", ")));
1176
+ }
852
1177
  }
1178
+ defaultAbilities = yates.getDefaultAbilities(models);
1179
+ abilities = (0, cloneDeep_1.default)(defaultAbilities);
1180
+ try {
1181
+ for (models_2 = __values(models), models_2_1 = models_2.next(); !models_2_1.done; models_2_1 = models_2.next()) {
1182
+ model = models_2_1.value;
1183
+ modelCustomAbilities = customAbilities === null || customAbilities === void 0 ? void 0 : customAbilities[model];
1184
+ if (modelCustomAbilities) {
1185
+ if (!abilities[model]) {
1186
+ abilities[model] = {};
1187
+ }
1188
+ modelAbilities = abilities[model];
1189
+ for (ability in modelCustomAbilities) {
1190
+ operation = (_b = modelCustomAbilities === null || modelCustomAbilities === void 0 ? void 0 : modelCustomAbilities[ability]) === null || _b === void 0 ? void 0 : _b.operation;
1191
+ if (!operation)
1192
+ continue;
1193
+ if (!VALID_OPERATIONS.includes(operation)) {
1194
+ throw new Error("Invalid operation: ".concat(operation));
1195
+ }
1196
+ modelAbilities[ability] = __assign(__assign({}, modelCustomAbilities[ability]), { operation: operation, model: model, slug: ability });
1197
+ }
1198
+ }
1199
+ }
1200
+ }
1201
+ catch (e_18_1) { e_18 = { error: e_18_1 }; }
1202
+ finally {
1203
+ try {
1204
+ if (models_2_1 && !models_2_1.done && (_a = models_2.return)) _a.call(models_2);
1205
+ }
1206
+ finally { if (e_18) throw e_18.error; }
1207
+ }
1208
+ roles = getRoles(abilities);
1209
+ allAbilities = Object.values(abilities).flatMap(function (modelAbilities) {
1210
+ return modelAbilities ? Object.values(modelAbilities) : [];
1211
+ });
1212
+ roleAbilities = buildRoleAbilities(roles, allAbilities);
1213
+ client = prisma.$extends({
1214
+ name: "Yates client",
1215
+ query: {
1216
+ $allModels: {
1217
+ $allOperations: function (params) {
1218
+ return __awaiter(this, void 0, void 0, function () {
1219
+ var model, args, query, operation, queryArgs, ctx, op, context, role, filters, abilityWhere, combinedWhere, deniedWhere, fluentField, delegate, result, _a, fluentField, delegate, result, _b, items, items_8, items_8_1, item, e_19_1, allowed, filters, abilityWhere, canUpdate, allowed, filters, abilityWhere;
1220
+ var e_19, _c;
1221
+ var _d, _e, _f, _g, _h, _j, _k, _l, _m;
1222
+ return __generator(this, function (_o) {
1223
+ switch (_o.label) {
1224
+ case 0:
1225
+ model = params.model, args = params.args, query = params.query, operation = params.operation;
1226
+ queryArgs = args;
1227
+ if (!model) {
1228
+ return [2 /*return*/, query(args)];
1229
+ }
1230
+ ctx = getContext();
1231
+ if (ctx === null) {
1232
+ return [2 /*return*/, query(args)];
1233
+ }
1234
+ validateContext(ctx === null || ctx === void 0 ? void 0 : ctx.context);
1235
+ op = OPERATION_MAP[operation];
1236
+ if (!op) {
1237
+ return [2 /*return*/, query(args)];
1238
+ }
1239
+ context = ctx === null || ctx === void 0 ? void 0 : ctx.context;
1240
+ role = ctx === null || ctx === void 0 ? void 0 : ctx.role;
1241
+ if (!SELECT_OPERATIONS.has(operation)) return [3 /*break*/, 17];
1242
+ return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, model, "SELECT", context)];
1243
+ case 1:
1244
+ filters = (_d = (_o.sent())) !== null && _d !== void 0 ? _d : [];
1245
+ abilityWhere = combineAbilityFilters(filters);
1246
+ combinedWhere = mergeWhere(queryArgs.where, abilityWhere);
1247
+ if (!!abilityWhere) return [3 /*break*/, 9];
1248
+ deniedWhere = denyWhere(runtimeDataModel, model);
1249
+ if (!(operation === "findUnique" ||
1250
+ operation === "findUniqueOrThrow")) return [3 /*break*/, 7];
1251
+ return [4 /*yield*/, applyReadSelections(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs, context)];
1252
+ case 2:
1253
+ _o.sent();
1254
+ fluentField = getFluentSelectionField(runtimeDataModel, model, queryArgs);
1255
+ delegate = prisma[lowerModelName(model)];
1256
+ if (!(operation === "findUnique")) return [3 /*break*/, 4];
1257
+ return [4 /*yield*/, delegate.findFirst(__assign(__assign({}, queryArgs), { where: deniedWhere }))];
1258
+ case 3:
1259
+ _a = _o.sent();
1260
+ return [3 /*break*/, 6];
1261
+ case 4: return [4 /*yield*/, delegate.findFirstOrThrow(__assign(__assign({}, queryArgs), { where: deniedWhere }))];
1262
+ case 5:
1263
+ _a = _o.sent();
1264
+ _o.label = 6;
1265
+ case 6:
1266
+ result = _a;
1267
+ if (fluentField && result) {
1268
+ return [2 /*return*/, result[fluentField]];
1269
+ }
1270
+ return [2 /*return*/, result];
1271
+ case 7:
1272
+ queryArgs.where =
1273
+ (_f = mergeWhere((_e = queryArgs.where) !== null && _e !== void 0 ? _e : {}, deniedWhere)) !== null && _f !== void 0 ? _f : queryArgs.where;
1274
+ return [4 /*yield*/, applyReadSelections(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs, context)];
1275
+ case 8:
1276
+ _o.sent();
1277
+ return [2 /*return*/, query(args)];
1278
+ case 9:
1279
+ if (!(operation === "findUnique" ||
1280
+ operation === "findUniqueOrThrow")) return [3 /*break*/, 15];
1281
+ return [4 /*yield*/, applyReadSelections(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs, context)];
1282
+ case 10:
1283
+ _o.sent();
1284
+ fluentField = getFluentSelectionField(runtimeDataModel, model, queryArgs);
1285
+ delegate = prisma[lowerModelName(model)];
1286
+ if (!(operation === "findUnique")) return [3 /*break*/, 12];
1287
+ return [4 /*yield*/, delegate.findFirst(__assign(__assign({}, queryArgs), { where: combinedWhere }))];
1288
+ case 11:
1289
+ _b = _o.sent();
1290
+ return [3 /*break*/, 14];
1291
+ case 12: return [4 /*yield*/, delegate.findFirstOrThrow(__assign(__assign({}, queryArgs), { where: combinedWhere }))];
1292
+ case 13:
1293
+ _b = _o.sent();
1294
+ _o.label = 14;
1295
+ case 14:
1296
+ result = _b;
1297
+ if (fluentField && result) {
1298
+ return [2 /*return*/, result[fluentField]];
1299
+ }
1300
+ return [2 /*return*/, result];
1301
+ case 15:
1302
+ queryArgs.where = combinedWhere !== null && combinedWhere !== void 0 ? combinedWhere : queryArgs.where;
1303
+ return [4 /*yield*/, applyReadSelections(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs, context)];
1304
+ case 16:
1305
+ _o.sent();
1306
+ return [2 /*return*/, query(args)];
1307
+ case 17:
1308
+ if (!(op === "INSERT")) return [3 /*break*/, 30];
1309
+ if (!(operation === "create")) return [3 /*break*/, 20];
1310
+ return [4 /*yield*/, assertCreateAllowed(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs.data, context)];
1311
+ case 18:
1312
+ _o.sent();
1313
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs.data, context)];
1314
+ case 19:
1315
+ _o.sent();
1316
+ return [2 /*return*/, query(args)];
1317
+ case 20:
1318
+ if (!(operation === "createMany")) return [3 /*break*/, 30];
1319
+ items = Array.isArray(queryArgs.data)
1320
+ ? queryArgs.data
1321
+ : [queryArgs.data];
1322
+ _o.label = 21;
1323
+ case 21:
1324
+ _o.trys.push([21, 27, 28, 29]);
1325
+ items_8 = __values(items), items_8_1 = items_8.next();
1326
+ _o.label = 22;
1327
+ case 22:
1328
+ if (!!items_8_1.done) return [3 /*break*/, 26];
1329
+ item = items_8_1.value;
1330
+ return [4 /*yield*/, assertCreateAllowed(prisma, runtimeDataModel, roleAbilities, role, model, item, context)];
1331
+ case 23:
1332
+ _o.sent();
1333
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, model, item, context)];
1334
+ case 24:
1335
+ _o.sent();
1336
+ _o.label = 25;
1337
+ case 25:
1338
+ items_8_1 = items_8.next();
1339
+ return [3 /*break*/, 22];
1340
+ case 26: return [3 /*break*/, 29];
1341
+ case 27:
1342
+ e_19_1 = _o.sent();
1343
+ e_19 = { error: e_19_1 };
1344
+ return [3 /*break*/, 29];
1345
+ case 28:
1346
+ try {
1347
+ if (items_8_1 && !items_8_1.done && (_c = items_8.return)) _c.call(items_8);
1348
+ }
1349
+ finally { if (e_19) throw e_19.error; }
1350
+ return [7 /*endfinally*/];
1351
+ case 29: return [2 /*return*/, query(args)];
1352
+ case 30:
1353
+ if (!(op === "UPDATE")) return [3 /*break*/, 47];
1354
+ if (!(operation === "update")) return [3 /*break*/, 34];
1355
+ return [4 /*yield*/, assertRecordAllowed(prisma, runtimeDataModel, roleAbilities, role, model, "UPDATE", queryArgs.where, context)];
1356
+ case 31:
1357
+ allowed = _o.sent();
1358
+ if (!allowed)
1359
+ throw updateNotFoundError();
1360
+ if (!queryArgs.data) return [3 /*break*/, 33];
1361
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs.data, context)];
1362
+ case 32:
1363
+ _o.sent();
1364
+ _o.label = 33;
1365
+ case 33: return [2 /*return*/, query(args)];
1366
+ case 34:
1367
+ if (!(operation === "updateMany")) return [3 /*break*/, 38];
1368
+ return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, model, "UPDATE", context)];
1369
+ case 35:
1370
+ filters = (_g = (_o.sent())) !== null && _g !== void 0 ? _g : [];
1371
+ abilityWhere = combineAbilityFilters(filters);
1372
+ if (!abilityWhere) {
1373
+ queryArgs.where = denyWhere(runtimeDataModel, model);
1374
+ }
1375
+ else {
1376
+ queryArgs.where =
1377
+ (_j = mergeWhere((_h = queryArgs.where) !== null && _h !== void 0 ? _h : {}, abilityWhere)) !== null && _j !== void 0 ? _j : queryArgs.where;
1378
+ }
1379
+ if (!queryArgs.data) return [3 /*break*/, 37];
1380
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, model, queryArgs.data, context)];
1381
+ case 36:
1382
+ _o.sent();
1383
+ _o.label = 37;
1384
+ case 37: return [2 /*return*/, query(args)];
1385
+ case 38:
1386
+ if (!(operation === "upsert")) return [3 /*break*/, 47];
1387
+ return [4 /*yield*/, assertRecordAllowed(prisma, runtimeDataModel, roleAbilities, role, model, "UPDATE", queryArgs.where, context)];
1388
+ case 39:
1389
+ canUpdate = _o.sent();
1390
+ if (!canUpdate) return [3 /*break*/, 42];
1391
+ if (!args.update) return [3 /*break*/, 41];
1392
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, model, args.update, context)];
1393
+ case 40:
1394
+ _o.sent();
1395
+ _o.label = 41;
1396
+ case 41: return [3 /*break*/, 46];
1397
+ case 42:
1398
+ if (!args.create) return [3 /*break*/, 45];
1399
+ return [4 /*yield*/, assertCreateAllowed(prisma, runtimeDataModel, roleAbilities, role, model, args.create, context)];
1400
+ case 43:
1401
+ _o.sent();
1402
+ return [4 /*yield*/, applyNestedWrites(prisma, runtimeDataModel, roleAbilities, role, model, args.create, context)];
1403
+ case 44:
1404
+ _o.sent();
1405
+ return [3 /*break*/, 46];
1406
+ case 45: throw updateNotFoundError();
1407
+ case 46: return [2 /*return*/, query(args)];
1408
+ case 47:
1409
+ if (!(op === "DELETE")) return [3 /*break*/, 51];
1410
+ if (!(operation === "delete")) return [3 /*break*/, 49];
1411
+ return [4 /*yield*/, assertRecordAllowed(prisma, runtimeDataModel, roleAbilities, role, model, "DELETE", queryArgs.where, context)];
1412
+ case 48:
1413
+ allowed = _o.sent();
1414
+ if (!allowed)
1415
+ throw deleteNotFoundError();
1416
+ return [2 /*return*/, query(args)];
1417
+ case 49:
1418
+ if (!(operation === "deleteMany")) return [3 /*break*/, 51];
1419
+ return [4 /*yield*/, getAbilityFilters(prisma, runtimeDataModel, roleAbilities, role, model, "DELETE", context)];
1420
+ case 50:
1421
+ filters = (_k = (_o.sent())) !== null && _k !== void 0 ? _k : [];
1422
+ abilityWhere = combineAbilityFilters(filters);
1423
+ if (!abilityWhere) {
1424
+ queryArgs.where = denyWhere(runtimeDataModel, model);
1425
+ }
1426
+ else {
1427
+ queryArgs.where =
1428
+ (_m = mergeWhere((_l = queryArgs.where) !== null && _l !== void 0 ? _l : {}, abilityWhere)) !== null && _m !== void 0 ? _m : queryArgs.where;
1429
+ }
1430
+ return [2 /*return*/, query(args)];
1431
+ case 51:
1432
+ if (!UNIQUE_OPERATIONS.has(operation)) {
1433
+ return [2 /*return*/, query(args)];
1434
+ }
1435
+ return [2 /*return*/, query(args)];
1436
+ }
1437
+ });
1438
+ });
1439
+ },
1440
+ },
1441
+ },
1442
+ });
1443
+ debug("Setup completed in", performance.now() - start, "ms");
1444
+ return [2 /*return*/, client];
853
1445
  });
854
1446
  }); };
855
1447
  exports.setup = setup;
856
- var templateObject_1, templateObject_2, templateObject_3;
857
1448
  //# sourceMappingURL=index.js.map