@cerebruminc/yates 3.3.2-beta.dangerous.6e79492 → 3.3.2-beta.dangerous.8bebbaf
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 +297 -245
- package/dist/index.js.map +1 -1
- package/dist/startup.d.ts +1 -0
- package/dist/startup.js +1116 -0
- package/dist/startup.js.map +1 -0
- package/package.json +48 -47
package/dist/index.js
CHANGED
|
@@ -177,11 +177,11 @@ var createClient = function (prisma, getContext, options) {
|
|
|
177
177
|
query: {
|
|
178
178
|
$allModels: {
|
|
179
179
|
$allOperations: function (params) {
|
|
180
|
+
var _a;
|
|
180
181
|
return __awaiter(this, void 0, void 0, function () {
|
|
181
|
-
var model, args, query, operation, ctx, role, context, pgRole,
|
|
182
|
-
var e_2,
|
|
182
|
+
var model, args, query, operation, ctx, role, context, pgRole, _b, _c, k, _d, _e, v, queryResults, e_1;
|
|
183
|
+
var e_2, _f, e_3, _g;
|
|
183
184
|
var _this = this;
|
|
184
|
-
var _g;
|
|
185
185
|
return __generator(this, function (_h) {
|
|
186
186
|
switch (_h.label) {
|
|
187
187
|
case 0:
|
|
@@ -201,8 +201,8 @@ var createClient = function (prisma, getContext, options) {
|
|
|
201
201
|
pgRole = (0, exports.createRoleName)(role);
|
|
202
202
|
if (context) {
|
|
203
203
|
try {
|
|
204
|
-
for (
|
|
205
|
-
k =
|
|
204
|
+
for (_b = __values(Object.keys(context)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
205
|
+
k = _c.value;
|
|
206
206
|
if (!k.match(/^[a-z_\.]+$/)) {
|
|
207
207
|
throw new Error("Context variable \"".concat(k, "\" contains invalid characters. Context variables must only contain lowercase letters, numbers, periods and underscores."));
|
|
208
208
|
}
|
|
@@ -213,8 +213,8 @@ var createClient = function (prisma, getContext, options) {
|
|
|
213
213
|
}
|
|
214
214
|
if (Array.isArray(context[k])) {
|
|
215
215
|
try {
|
|
216
|
-
for (
|
|
217
|
-
v =
|
|
216
|
+
for (_d = (e_3 = void 0, __values(context[k])), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
217
|
+
v = _e.value;
|
|
218
218
|
if (typeof v !== "string") {
|
|
219
219
|
throw new Error("Context variable \"".concat(k, "\" must be an array of strings. Got ").concat(typeof v));
|
|
220
220
|
}
|
|
@@ -223,7 +223,7 @@ var createClient = function (prisma, getContext, options) {
|
|
|
223
223
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
224
224
|
finally {
|
|
225
225
|
try {
|
|
226
|
-
if (
|
|
226
|
+
if (_e && !_e.done && (_g = _d.return)) _g.call(_d);
|
|
227
227
|
}
|
|
228
228
|
finally { if (e_3) throw e_3.error; }
|
|
229
229
|
}
|
|
@@ -235,7 +235,7 @@ var createClient = function (prisma, getContext, options) {
|
|
|
235
235
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
236
236
|
finally {
|
|
237
237
|
try {
|
|
238
|
-
if (
|
|
238
|
+
if (_c && !_c.done && (_f = _b.return)) _f.call(_b);
|
|
239
239
|
}
|
|
240
240
|
finally { if (e_2) throw e_2.error; }
|
|
241
241
|
}
|
|
@@ -307,7 +307,7 @@ var createClient = function (prisma, getContext, options) {
|
|
|
307
307
|
case 3:
|
|
308
308
|
e_1 = _h.sent();
|
|
309
309
|
// Normalize RLS errors to make them a bit more readable.
|
|
310
|
-
if ((
|
|
310
|
+
if ((_a = e_1.message) === null || _a === void 0 ? void 0 : _a.includes("new row violates row-level security policy for table")) {
|
|
311
311
|
throw new Error("You do not have permission to perform this action: ".concat(model, ".").concat(operation, "(...)"));
|
|
312
312
|
}
|
|
313
313
|
throw e_1;
|
|
@@ -322,266 +322,315 @@ var createClient = function (prisma, getContext, options) {
|
|
|
322
322
|
return client;
|
|
323
323
|
};
|
|
324
324
|
exports.createClient = createClient;
|
|
325
|
-
var setRLS = function (prisma,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
325
|
+
var setRLS = function (prisma,
|
|
326
|
+
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this, by providing the correct type for the catalog
|
|
327
|
+
policies, table, roleName, operation, rawExpression) { return __awaiter(void 0, void 0, void 0, function () {
|
|
328
|
+
var expression, policyName, rows, normalizedExpression, normalizedQual;
|
|
329
|
+
var _a, _b, _c, _d;
|
|
330
|
+
return __generator(this, function (_e) {
|
|
331
|
+
switch (_e.label) {
|
|
329
332
|
case 0:
|
|
330
333
|
debug("Calculating RLS expression from", rawExpression);
|
|
331
334
|
return [4 /*yield*/, (0, expressions_1.expressionToSQL)(rawExpression, table)];
|
|
332
335
|
case 1:
|
|
333
|
-
expression =
|
|
336
|
+
expression = _e.sent();
|
|
334
337
|
policyName = roleName;
|
|
335
|
-
|
|
336
|
-
case 2:
|
|
337
|
-
rows = _a.sent();
|
|
338
|
+
rows = policies.filter(function (row) { return row.tablename === table && row.policyname === policyName; });
|
|
338
339
|
debug("Creating RLS policy", policyName);
|
|
339
340
|
debug("On table", table);
|
|
340
341
|
debug("For operation", operation);
|
|
341
342
|
debug("To role", roleName);
|
|
342
343
|
debug("With expression", expression);
|
|
343
|
-
|
|
344
|
-
|
|
344
|
+
console.log(expression);
|
|
345
|
+
normalizedExpression = expression === "true"
|
|
346
|
+
? expression
|
|
347
|
+
: "(".concat(expression.replace(/(\r\n|\n|\r)/gm, ""), ")");
|
|
348
|
+
normalizedQual = operation === "INSERT"
|
|
349
|
+
? (_b = (_a = rows === null || rows === void 0 ? void 0 : rows[0]) === null || _a === void 0 ? void 0 : _a.with_check) === null || _b === void 0 ? void 0 : _b.replace(/(\r\n|\n|\r)/gm, "")
|
|
350
|
+
: (_d = (_c = rows === null || rows === void 0 ? void 0 : rows[0]) === null || _c === void 0 ? void 0 : _c.qual) === null || _d === void 0 ? void 0 : _d.replace(/(\r\n|\n|\r)/gm, "");
|
|
351
|
+
if (!(rows.length === 0)) return [3 /*break*/, 6];
|
|
352
|
+
if (!(operation === "INSERT")) return [3 /*break*/, 3];
|
|
345
353
|
return [4 /*yield*/, prisma.$queryRawUnsafe("\n CREATE POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" FOR ").concat(operation, " TO ").concat(roleName, " WITH CHECK (").concat(expression, ");\n "))];
|
|
346
|
-
case
|
|
347
|
-
|
|
348
|
-
return [3 /*break*/,
|
|
349
|
-
case
|
|
350
|
-
case
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
case
|
|
354
|
-
case
|
|
355
|
-
if (!(
|
|
356
|
-
|
|
354
|
+
case 2:
|
|
355
|
+
_e.sent();
|
|
356
|
+
return [3 /*break*/, 5];
|
|
357
|
+
case 3: return [4 /*yield*/, prisma.$queryRawUnsafe("\n CREATE POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" FOR ").concat(operation, " TO ").concat(roleName, " USING (").concat(expression, ");\n "))];
|
|
358
|
+
case 4:
|
|
359
|
+
_e.sent();
|
|
360
|
+
_e.label = 5;
|
|
361
|
+
case 5: return [3 /*break*/, 10];
|
|
362
|
+
case 6:
|
|
363
|
+
if (!(normalizedQual !== normalizedExpression)) return [3 /*break*/, 10];
|
|
364
|
+
console.count("ALTERING RLS POLICY");
|
|
365
|
+
console.log({ operation: operation });
|
|
366
|
+
console.log("ROW QUAL", normalizedQual);
|
|
367
|
+
console.log("NORMALIZED", normalizedExpression);
|
|
368
|
+
console.log("\n\n");
|
|
369
|
+
if (!(operation === "INSERT")) return [3 /*break*/, 8];
|
|
357
370
|
return [4 /*yield*/, prisma.$queryRawUnsafe("\n ALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " WITH CHECK (").concat(expression, ");\n "))];
|
|
358
|
-
case
|
|
359
|
-
|
|
360
|
-
return [3 /*break*/,
|
|
361
|
-
case
|
|
362
|
-
case
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
case
|
|
371
|
+
case 7:
|
|
372
|
+
_e.sent();
|
|
373
|
+
return [3 /*break*/, 10];
|
|
374
|
+
case 8: return [4 /*yield*/, prisma.$queryRawUnsafe("\n ALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " USING (").concat(expression, ");\n "))];
|
|
375
|
+
case 9:
|
|
376
|
+
_e.sent();
|
|
377
|
+
_e.label = 10;
|
|
378
|
+
case 10: return [2 /*return*/];
|
|
366
379
|
}
|
|
367
380
|
});
|
|
368
381
|
}); };
|
|
369
|
-
var createRoles = function (_a) {
|
|
370
|
-
var
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
382
|
+
var createRoles = function (_a) {
|
|
383
|
+
var prisma = _a.prisma, customAbilities = _a.customAbilities, getRoles = _a.getRoles;
|
|
384
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
385
|
+
var abilities, runtimeDataModel, models, diff, models_1, models_1_1, model, ability, operation, roles, pgRoles, pgPolicies, _b, _c, _d, _i, model, table, _loop_1, _e, _f, _g, _h, slug, _loop_2, _j, _k, _l, _m, key;
|
|
386
|
+
var e_5, _o;
|
|
387
|
+
var _p;
|
|
388
|
+
return __generator(this, function (_q) {
|
|
389
|
+
switch (_q.label) {
|
|
390
|
+
case 0:
|
|
391
|
+
abilities = {};
|
|
392
|
+
runtimeDataModel = prisma
|
|
393
|
+
._runtimeDataModel;
|
|
394
|
+
models = Object.keys(runtimeDataModel.models).map(function (m) { return runtimeDataModel.models[m].dbName || m; });
|
|
395
|
+
if (customAbilities) {
|
|
396
|
+
diff = (0, difference_1.default)(Object.keys(customAbilities), models);
|
|
397
|
+
if (diff.length) {
|
|
398
|
+
throw new Error("Invalid models in custom abilities: ".concat(diff.join(", ")));
|
|
399
|
+
}
|
|
385
400
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
412
|
-
model: model,
|
|
413
|
-
slug: "update",
|
|
414
|
-
},
|
|
415
|
-
delete: {
|
|
416
|
-
description: "Delete ".concat(model),
|
|
417
|
-
expression: "true",
|
|
418
|
-
operation: "DELETE",
|
|
419
|
-
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
420
|
-
model: model,
|
|
421
|
-
slug: "delete",
|
|
422
|
-
},
|
|
423
|
-
};
|
|
424
|
-
if (customAbilities === null || customAbilities === void 0 ? void 0 : customAbilities[model]) {
|
|
425
|
-
for (ability in customAbilities[model]) {
|
|
426
|
-
operation =
|
|
427
|
-
// biome-ignore lint/style/noNonNullAssertion: TODO fix this
|
|
428
|
-
(_q = customAbilities[model][ability]) === null || _q === void 0 ? void 0 : _q.operation;
|
|
429
|
-
if (!operation)
|
|
430
|
-
continue;
|
|
431
|
-
// biome-ignore lint/style/noNonNullAssertion: TODO fix this
|
|
432
|
-
abilities[model][ability] = __assign(__assign({}, customAbilities[model][ability]), { operation: operation,
|
|
401
|
+
try {
|
|
402
|
+
for (models_1 = __values(models), models_1_1 = models_1.next(); !models_1_1.done; models_1_1 = models_1.next()) {
|
|
403
|
+
model = models_1_1.value;
|
|
404
|
+
abilities[model] = {
|
|
405
|
+
// @ts-ignore
|
|
406
|
+
create: {
|
|
407
|
+
description: "Create ".concat(model),
|
|
408
|
+
expression: "true",
|
|
409
|
+
operation: "INSERT",
|
|
410
|
+
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
411
|
+
model: model,
|
|
412
|
+
slug: "create",
|
|
413
|
+
},
|
|
414
|
+
read: {
|
|
415
|
+
description: "Read ".concat(model),
|
|
416
|
+
expression: "true",
|
|
417
|
+
operation: "SELECT",
|
|
418
|
+
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
419
|
+
model: model,
|
|
420
|
+
slug: "read",
|
|
421
|
+
},
|
|
422
|
+
update: {
|
|
423
|
+
description: "Update ".concat(model),
|
|
424
|
+
expression: "true",
|
|
425
|
+
operation: "UPDATE",
|
|
433
426
|
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
434
|
-
model: model,
|
|
427
|
+
model: model,
|
|
428
|
+
slug: "update",
|
|
429
|
+
},
|
|
430
|
+
delete: {
|
|
431
|
+
description: "Delete ".concat(model),
|
|
432
|
+
expression: "true",
|
|
433
|
+
operation: "DELETE",
|
|
434
|
+
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
435
|
+
model: model,
|
|
436
|
+
slug: "delete",
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
if (customAbilities === null || customAbilities === void 0 ? void 0 : customAbilities[model]) {
|
|
440
|
+
for (ability in customAbilities[model]) {
|
|
441
|
+
operation =
|
|
442
|
+
// biome-ignore lint/style/noNonNullAssertion: TODO fix this
|
|
443
|
+
(_p = customAbilities[model][ability]) === null || _p === void 0 ? void 0 : _p.operation;
|
|
444
|
+
if (!operation)
|
|
445
|
+
continue;
|
|
446
|
+
// biome-ignore lint/style/noNonNullAssertion: TODO fix this
|
|
447
|
+
abilities[model][ability] = __assign(__assign({}, customAbilities[model][ability]), { operation: operation,
|
|
448
|
+
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
449
|
+
model: model, slug: ability });
|
|
450
|
+
}
|
|
435
451
|
}
|
|
436
452
|
}
|
|
437
453
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
454
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
455
|
+
finally {
|
|
456
|
+
try {
|
|
457
|
+
if (models_1_1 && !models_1_1.done && (_o = models_1.return)) _o.call(models_1);
|
|
458
|
+
}
|
|
459
|
+
finally { if (e_5) throw e_5.error; }
|
|
443
460
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
461
|
+
roles = getRoles(abilities);
|
|
462
|
+
debug("Setting row level security on tables");
|
|
463
|
+
return [4 /*yield*/, prisma.$transaction(__spreadArray([
|
|
464
|
+
takeLock(prisma)
|
|
465
|
+
], __read(Object.keys(abilities).map(function (table) {
|
|
466
|
+
return prisma.$queryRawUnsafe("ALTER table \"".concat(table, "\" enable row level security;"));
|
|
467
|
+
})), false))];
|
|
468
|
+
case 1:
|
|
469
|
+
_q.sent();
|
|
470
|
+
return [4 /*yield*/, prisma.$queryRawUnsafe("\n\t\t\tselect * from pg_catalog.pg_roles\n\t\t")];
|
|
471
|
+
case 2:
|
|
472
|
+
pgRoles = _q.sent();
|
|
473
|
+
return [4 /*yield*/, prisma.$queryRawUnsafe("\n\t\tselect * from pg_catalog.pg_policies;\n\t")];
|
|
474
|
+
case 3:
|
|
475
|
+
pgPolicies = _q.sent();
|
|
476
|
+
_b = abilities;
|
|
477
|
+
_c = [];
|
|
478
|
+
for (_d in _b)
|
|
479
|
+
_c.push(_d);
|
|
480
|
+
_i = 0;
|
|
481
|
+
_q.label = 4;
|
|
482
|
+
case 4:
|
|
483
|
+
if (!(_i < _c.length)) return [3 /*break*/, 9];
|
|
484
|
+
_d = _c[_i];
|
|
485
|
+
if (!(_d in _b)) return [3 /*break*/, 8];
|
|
486
|
+
model = _d;
|
|
487
|
+
table = model;
|
|
488
|
+
_loop_1 = function (slug) {
|
|
489
|
+
var ability, roleName;
|
|
490
|
+
return __generator(this, function (_r) {
|
|
491
|
+
switch (_r.label) {
|
|
492
|
+
case 0:
|
|
493
|
+
ability =
|
|
494
|
+
// biome-ignore lint/style/noNonNullAssertion: TODO fix this
|
|
495
|
+
abilities[model][slug];
|
|
496
|
+
if (!VALID_OPERATIONS.includes(ability.operation)) {
|
|
497
|
+
throw new Error("Invalid operation: ".concat(ability.operation));
|
|
498
|
+
}
|
|
499
|
+
roleName = (0, exports.createAbilityName)(model, slug);
|
|
500
|
+
// Check if role already exists
|
|
501
|
+
debug("Checking if role exists", roleName);
|
|
502
|
+
if (!pgRoles.find(function (role) { return role.rolname === roleName; })) return [3 /*break*/, 1];
|
|
503
|
+
debug("Role already exists", roleName);
|
|
504
|
+
return [3 /*break*/, 3];
|
|
505
|
+
case 1: return [4 /*yield*/, prisma.$transaction([
|
|
506
|
+
takeLock(prisma),
|
|
507
|
+
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\tGRANT ").concat(ability.operation, " ON \"").concat(table, "\" TO ").concat(roleName, ";\n\t\t\t\t\tend\n\t\t\t\t\t$$\n\t\t\t\t\t;\n\t\t\t\t")),
|
|
508
|
+
])];
|
|
509
|
+
case 2:
|
|
510
|
+
_r.sent();
|
|
511
|
+
_r.label = 3;
|
|
512
|
+
case 3:
|
|
513
|
+
if (!ability.expression) return [3 /*break*/, 5];
|
|
514
|
+
return [4 /*yield*/, setRLS(prisma, pgPolicies, table, roleName, ability.operation,
|
|
515
|
+
// biome-ignore lint/suspicious/noExplicitAny: TODO fix this
|
|
516
|
+
ability.expression)];
|
|
517
|
+
case 4:
|
|
518
|
+
_r.sent();
|
|
519
|
+
_r.label = 5;
|
|
520
|
+
case 5:
|
|
521
|
+
debug("Finished setting RLS for model", model);
|
|
522
|
+
return [2 /*return*/];
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
};
|
|
526
|
+
_e = abilities[model];
|
|
527
|
+
_f = [];
|
|
528
|
+
for (_g in _e)
|
|
529
|
+
_f.push(_g);
|
|
530
|
+
_h = 0;
|
|
531
|
+
_q.label = 5;
|
|
532
|
+
case 5:
|
|
533
|
+
if (!(_h < _f.length)) return [3 /*break*/, 8];
|
|
534
|
+
_g = _f[_h];
|
|
535
|
+
if (!(_g in _e)) return [3 /*break*/, 7];
|
|
536
|
+
slug = _g;
|
|
537
|
+
return [5 /*yield**/, _loop_1(slug)];
|
|
538
|
+
case 6:
|
|
539
|
+
_q.sent();
|
|
540
|
+
_q.label = 7;
|
|
541
|
+
case 7:
|
|
542
|
+
_h++;
|
|
543
|
+
return [3 /*break*/, 5];
|
|
544
|
+
case 8:
|
|
545
|
+
_i++;
|
|
546
|
+
return [3 /*break*/, 4];
|
|
547
|
+
case 9:
|
|
548
|
+
_loop_2 = function (key) {
|
|
549
|
+
var role, wildCardAbilities, roleAbilities, rlsRoles, userRoles, oldRoles;
|
|
550
|
+
return __generator(this, function (_s) {
|
|
551
|
+
switch (_s.label) {
|
|
552
|
+
case 0:
|
|
553
|
+
role = (0, exports.createRoleName)(key);
|
|
554
|
+
debug("Creating role", role);
|
|
555
|
+
wildCardAbilities = (0, flatMap_1.default)(abilities, function (model, modelName) {
|
|
556
|
+
return (0, map_1.default)(model, function (_params, slug) {
|
|
557
|
+
return (0, exports.createAbilityName)(modelName, slug);
|
|
558
|
+
});
|
|
526
559
|
});
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
560
|
+
roleAbilities = roles[key];
|
|
561
|
+
rlsRoles = roleAbilities === "*"
|
|
562
|
+
? wildCardAbilities
|
|
563
|
+
: roleAbilities.map(function (ability) {
|
|
564
|
+
// biome-ignore lint/style/noNonNullAssertion: TODO fix this
|
|
565
|
+
return (0, exports.createAbilityName)(ability.model, ability.slug);
|
|
566
|
+
});
|
|
567
|
+
// 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.
|
|
568
|
+
// 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.
|
|
569
|
+
debug("Granting role access");
|
|
570
|
+
// Check if role already exists
|
|
571
|
+
debug("Checking if role exists", role);
|
|
572
|
+
if (!pgRoles.find(function (row) { return row.rolname === role; })) return [3 /*break*/, 1];
|
|
573
|
+
debug("Role already exists", role);
|
|
574
|
+
return [3 /*break*/, 3];
|
|
575
|
+
case 1: return [4 /*yield*/, prisma.$transaction([
|
|
530
576
|
takeLock(prisma),
|
|
531
|
-
prisma.$executeRawUnsafe("
|
|
532
|
-
prisma.$executeRawUnsafe("\n\t\t\t\tGRANT ALL ON ALL SEQUENCES IN SCHEMA public TO ".concat(role, ";\n\t\t\t")),
|
|
533
|
-
prisma.$executeRawUnsafe("\n\t\t\t\tGRANT ALL ON SCHEMA public TO ".concat(role, ";\n\t\t\t")),
|
|
534
|
-
prisma.$queryRawUnsafe("GRANT ".concat(rlsRoles.join(", "), " TO ").concat(role)),
|
|
577
|
+
prisma.$executeRawUnsafe("\n\t\t\t\tdo\n\t\t\t\t$$\n\t\t\t\tbegin\n\t\t\t\tif not exists (select * from pg_catalog.pg_roles where rolname = '".concat(role, "') then \n\t\t\t\t\tcreate role ").concat(role, ";\n\t\t\t\tend if;\n\t\t\t\tGRANT ALL ON ALL TABLES IN SCHEMA public TO ").concat(role, ";\n\t\t\t\tGRANT ALL ON ALL SEQUENCES IN SCHEMA public TO ").concat(role, ";\n\t\t\t\tGRANT ALL ON SCHEMA public TO ").concat(role, ";\n\t\t\t\tend\n\t\t\t\t$$\n\t\t\t\t;\n\t\t\t")),
|
|
535
578
|
])];
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
.
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
579
|
+
case 2:
|
|
580
|
+
_s.sent();
|
|
581
|
+
_s.label = 3;
|
|
582
|
+
case 3: return [4 /*yield*/, prisma.$executeRawUnsafe("GRANT ".concat(rlsRoles.join(", "), " TO ").concat(role, ";"))];
|
|
583
|
+
case 4:
|
|
584
|
+
_s.sent();
|
|
585
|
+
// Cleanup any old roles that aren't included in the new roles
|
|
586
|
+
debug("Cleaning up old roles");
|
|
587
|
+
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 "))];
|
|
588
|
+
case 5:
|
|
589
|
+
userRoles = _s.sent();
|
|
590
|
+
oldRoles = userRoles
|
|
591
|
+
.filter(function (_a) {
|
|
592
|
+
var rolename = _a.rolename;
|
|
593
|
+
return !rlsRoles.includes(rolename);
|
|
594
|
+
})
|
|
595
|
+
.map(function (_a) {
|
|
596
|
+
var rolename = _a.rolename;
|
|
597
|
+
return rolename;
|
|
598
|
+
});
|
|
599
|
+
if (!oldRoles.length) return [3 /*break*/, 7];
|
|
600
|
+
debug("Revoking ".concat(oldRoles.length, " old roles from ").concat(role));
|
|
601
|
+
// Now revoke old roles from the user role
|
|
602
|
+
return [4 /*yield*/, prisma.$executeRawUnsafe("REVOKE ".concat(oldRoles.join(", "), " FROM ").concat(role))];
|
|
603
|
+
case 6:
|
|
604
|
+
// Now revoke old roles from the user role
|
|
605
|
+
_s.sent();
|
|
606
|
+
_s.label = 7;
|
|
607
|
+
case 7: return [2 /*return*/];
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
};
|
|
611
|
+
_j = roles;
|
|
612
|
+
_k = [];
|
|
613
|
+
for (_l in _j)
|
|
614
|
+
_k.push(_l);
|
|
615
|
+
_m = 0;
|
|
616
|
+
_q.label = 10;
|
|
617
|
+
case 10:
|
|
618
|
+
if (!(_m < _k.length)) return [3 /*break*/, 13];
|
|
619
|
+
_l = _k[_m];
|
|
620
|
+
if (!(_l in _j)) return [3 /*break*/, 12];
|
|
621
|
+
key = _l;
|
|
622
|
+
return [5 /*yield**/, _loop_2(key)];
|
|
623
|
+
case 11:
|
|
624
|
+
_q.sent();
|
|
625
|
+
_q.label = 12;
|
|
626
|
+
case 12:
|
|
627
|
+
_m++;
|
|
628
|
+
return [3 /*break*/, 10];
|
|
629
|
+
case 13: return [2 /*return*/];
|
|
630
|
+
}
|
|
631
|
+
});
|
|
583
632
|
});
|
|
584
|
-
}
|
|
633
|
+
};
|
|
585
634
|
exports.createRoles = createRoles;
|
|
586
635
|
/**
|
|
587
636
|
* Creates an extended client that sets contextual parameters and user role on every query
|
|
@@ -592,6 +641,7 @@ var setup = function (params) { return __awaiter(void 0, void 0, void 0, functio
|
|
|
592
641
|
switch (_a.label) {
|
|
593
642
|
case 0:
|
|
594
643
|
prisma = params.prisma, customAbilities = params.customAbilities, getRoles = params.getRoles, getContext = params.getContext;
|
|
644
|
+
debug("Creating roles");
|
|
595
645
|
return [4 /*yield*/, (0, exports.createRoles)({
|
|
596
646
|
prisma: prisma,
|
|
597
647
|
customAbilities: customAbilities,
|
|
@@ -599,7 +649,9 @@ var setup = function (params) { return __awaiter(void 0, void 0, void 0, functio
|
|
|
599
649
|
})];
|
|
600
650
|
case 1:
|
|
601
651
|
_a.sent();
|
|
652
|
+
debug("Creating client");
|
|
602
653
|
client = (0, exports.createClient)(prisma, getContext, params.options);
|
|
654
|
+
debug("Client ready");
|
|
603
655
|
return [2 /*return*/, client];
|
|
604
656
|
}
|
|
605
657
|
});
|