@cerebruminc/yates 1.1.1 → 2.0.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.0](https://github.com/cerebruminc/yates/compare/v1.2.0...v2.0.0) (2023-02-22)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * Use client extensions instead of middleware
9
+
10
+ ### Features
11
+
12
+ * Use client extensions instead of middleware ([f3fa1a3](https://github.com/cerebruminc/yates/commit/f3fa1a3d187d62031e2124d023ba726e7b810e39))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * Explicity disconnect expression Prisma client ([ccceaa3](https://github.com/cerebruminc/yates/commit/ccceaa3f3baab26251b00b631962ae633deea714))
18
+ * Strongly type context values in expressions ([ec5e266](https://github.com/cerebruminc/yates/commit/ec5e2668a0ba776ed4319ade0940cd2f8dc9cbed))
19
+
20
+ ## [1.2.0](https://github.com/cerebruminc/yates/compare/v1.1.1...v1.2.0) (2023-02-20)
21
+
22
+
23
+ ### Features
24
+
25
+ * Add functionality for using Prisma as a query builder ([22d16a8](https://github.com/cerebruminc/yates/commit/22d16a8d21ea785256fe770747517e0a249e56c3))
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * Don't run integration tests when a PR is closed ([2b25093](https://github.com/cerebruminc/yates/commit/2b250937b0618d4ad7c7706286b74bca52603b22))
31
+
3
32
  ## [1.1.1](https://github.com/cerebruminc/yates/compare/v1.1.0...v1.1.1) (2023-01-30)
4
33
 
5
34
 
package/README.md CHANGED
@@ -18,15 +18,29 @@
18
18
  Yates is a module for implementing role based access control with Prisma. It is designed to be used with the [Prisma Client](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client) and [PostgreSQL](https://www.postgresql.org/).
19
19
  It uses the [Row Level Security](https://www.postgresql.org/docs/9.5/ddl-rowsecurity.html) feature of PostgreSQL to provide a simple and secure way to implement role based access control that allows you to define complex access control rules and have them apply to all of your Prisma queries automatically.
20
20
 
21
+ ## Prerequisites
22
+
23
+ Yates requires the `prisma` package ate version 4.9.0 or greater and the `@prisma/client` package at version 4.0.0 or greater. Additionally it makes use of the [Prisma Client extensions](https://www.prisma.io/docs/concepts/components/prisma-client/client-extensions) preview feature to generate rules and add RLS checking, so you will need to enable this feature in your Prisma schema.
24
+
25
+ ````prisma
26
+ generator client {
27
+ provider = "prisma-client-js"
28
+ previewFeatures = ["clientExtensions"]
29
+ }
30
+ ```
31
+
21
32
  ## Installation
22
33
 
23
34
  ```bash
24
35
  npm i @cerebruminc/yates
25
- ```
36
+ ````
26
37
 
27
38
  ## Usage
28
39
 
29
- Once you've installed Yates, you can use it in your Prisma project by importing it and calling the `setup` function. This function takes a Prisma Client instance and a configuration object as arguments. Yates uses prisma middleware to intercept all queries and apply the appropriate row level security policies to them, so it's important that it is setup _after_ all other middleware has been applied to the Prisma client.
40
+ Once you've installed Yates, you can use it in your Prisma project by importing it and calling the `setup` function. This function takes a Prisma Client instance and a configuration object as arguments and returns a client that can intercept all queries and apply the appropriate row level security policies to them.
41
+ Yates uses client extensions to generate the RLS rules and add the RLS checking to the Prisma Client queries. This means that you can use the Prisma Client as you normally would, and Yates will automatically apply the appropriate RLS policies to each query. It also means that you will need to apply your middleware _before_ creating the Yates client, as middleware cannot be applied to an extended client.
42
+ Client extensions share the same API as the Prisma Client, you can use the Yates client as a drop-in replacement for the Prisma Client in your application.
43
+ Client extensions also share the same connection pool as the base client, which means that you can freely create new Yates clients with minimal performance impact.
30
44
 
31
45
  The `setup` function will generate CRUD abilities for each model in your Prisma schema, as well as any additional abilities that you have defined in your configuration. It will then create a new PG role for each ability and apply the appropriate row level security policies to each role. Finally, it will create a new PG role for each user role you specify and grant them the appropriate abilities.
32
46
  For Yates to be able to set the correct user role for each request, you must pass a function called `getContext` in the `setup` configuration that will return the user role for the current request. This function will be called for each request and the user role returned will be used to set the `role` in the current session. If you want to bypass RLS completely for a specific role, you can return `null` from the `getContext` function for that role.
@@ -39,16 +53,44 @@ import { PrismaClient } from "@prisma/client";
39
53
 
40
54
  const prisma = new PrismaClient();
41
55
 
42
- await setup({
56
+ const client = await setup({
43
57
  prisma,
44
58
  // Define any custom abilities that you want to add to the system.
45
59
  customAbilities: () => ({
46
60
  USER: {
61
+ Post: {
62
+ insertOwnPost: {
63
+ description: "Insert own post",
64
+ // You can express the rule as a Prisma `where` clause.
65
+ expression: (client, row, context) => {
66
+ return {
67
+ // This expression uses a context setting returned by the getContext function
68
+ authorId: context('user.id')
69
+ }
70
+ },
71
+ operation: "INSERT",
72
+ },
73
+ },
74
+ Comment: {
75
+ deleteOnOwnPost: {
76
+ description: "Delete comment on own post",
77
+ // You can also express the rule as a conventional Prisma query.
78
+ expression: (client, row, context) => {
79
+ return client.post.findFirst({
80
+ where: {
81
+ id: row('postId'),
82
+ authorId: context('user.id')
83
+ }
84
+ })
85
+ },
86
+ operation: "DELETE",
87
+ },
88
+ }
47
89
  User: {
48
90
  updateOwnUser: {
49
91
  description: "Update own user",
50
- // This expression uses a context setting returned by the getContext function
51
- expression: `current_setting('context.user.id') = "id"`,
92
+ // For low-level control you can also write expressions as a raw SQL string.
93
+ expression: `current_setting('user.id') = "id"`,
52
94
  operation: "UPDATE",
53
95
  },
54
96
  }
@@ -82,11 +124,12 @@ await setup({
82
124
  return {
83
125
  role,
84
126
  context: {
85
- // This context setting will be available in ability expressions using `current_setting('context.user.id')`
86
- 'context.user.id': user.id,
127
+ // This context setting will be available in ability expressions using `current_setting('user.id')`
128
+ 'user.id': user.id,
87
129
  },
88
130
  };
89
131
  },
132
+ });
90
133
  ```
91
134
 
92
135
  ## Configuration
@@ -0,0 +1,2 @@
1
+ export declare const escapeIdentifier: (str: string) => string;
2
+ export declare const escapeLiteral: (str: string) => string;
package/dist/escape.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ // Source borrowed from node-postgrs (which borrows from PG itself)
3
+ // https://github.com/brianc/node-postgres/blob/3f6760c62ee2a901d374b5e50c2f025b7d550315/packages/pg/lib/client.js#L408-L437
4
+ // We need to manually escape strings because we're interpolating client values into SQL statements that don't support `PREPARE`, such as `CREATE POLICY`
5
+ exports.__esModule = true;
6
+ exports.escapeLiteral = exports.escapeIdentifier = void 0;
7
+ // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c
8
+ var escapeIdentifier = function (str) {
9
+ return "\"".concat(str.replace(/"/g, '""'), "\"");
10
+ };
11
+ exports.escapeIdentifier = escapeIdentifier;
12
+ // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c
13
+ var escapeLiteral = function (str) {
14
+ var hasBackslash = false;
15
+ var escaped = "'";
16
+ for (var i = 0; i < str.length; i++) {
17
+ var c = str[i];
18
+ if (c === "'") {
19
+ escaped += c + c;
20
+ }
21
+ else if (c === "\\") {
22
+ escaped += c + c;
23
+ hasBackslash = true;
24
+ }
25
+ else {
26
+ escaped += c;
27
+ }
28
+ }
29
+ escaped += "'";
30
+ if (hasBackslash === true) {
31
+ escaped = " E".concat(escaped);
32
+ }
33
+ return escaped;
34
+ };
35
+ exports.escapeLiteral = escapeLiteral;
36
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":";AAAA,mEAAmE;AACnE,4HAA4H;AAC5H,yJAAyJ;;;AAEzJ,6EAA6E;AACtE,IAAM,gBAAgB,GAAG,UAAU,GAAW;IACpD,OAAO,YAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAG,CAAC;AACvC,CAAC,CAAC;AAFW,QAAA,gBAAgB,oBAE3B;AAEF,6EAA6E;AACtE,IAAM,aAAa,GAAG,UAAU,GAAW;IACjD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,OAAO,GAAG,GAAG,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,EAAE;YACd,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;SACjB;aAAM,IAAI,CAAC,KAAK,IAAI,EAAE;YACtB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACjB,YAAY,GAAG,IAAI,CAAC;SACpB;aAAM;YACN,OAAO,IAAI,CAAC,CAAC;SACb;KACD;IAED,OAAO,IAAI,GAAG,CAAC;IAEf,IAAI,YAAY,KAAK,IAAI,EAAE;QAC1B,OAAO,GAAG,YAAK,OAAO,CAAE,CAAC;KACzB;IAED,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAvBW,QAAA,aAAa,iBAuBxB"}
@@ -0,0 +1,5 @@
1
+ import { PrismaClient } from "@prisma/client";
2
+ export type Expression<ContextKeys extends string = string> = string | ((client: PrismaClient, row: (col: string) => any, context: (key: ContextKeys) => string) => Promise<any> | {
3
+ [col: string]: any;
4
+ });
5
+ export declare const expressionToSQL: (getExpression: Expression, table: string) => Promise<string>;
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ exports.__esModule = true;
42
+ exports.expressionToSQL = void 0;
43
+ var client_1 = require("@prisma/client");
44
+ var random_1 = __importDefault(require("lodash/random"));
45
+ var matches_1 = __importDefault(require("lodash/matches"));
46
+ var node_sql_parser_1 = require("@lucianbuzzo/node-sql-parser");
47
+ var escape_1 = require("./escape");
48
+ var PRISMA_NUMERIC_TYPES = ["Int", "BigInt", "Float", "Decimal"];
49
+ var deepFind = function (obj, subObj) {
50
+ var matcher = (0, matches_1["default"])(subObj);
51
+ for (var key in obj) {
52
+ if (matcher(obj[key])) {
53
+ return obj[key];
54
+ }
55
+ else if (typeof obj[key] === "object") {
56
+ var result = deepFind(obj[key], subObj);
57
+ if (result) {
58
+ return result;
59
+ }
60
+ }
61
+ }
62
+ };
63
+ var expressionRowName = function (col) { return "___yates_row_".concat(col); };
64
+ var expressionContext = function (context) { return "___yates_context_".concat(context); };
65
+ // Generate a big 32bit signed integer to use as an ID
66
+ var getLargeRandomInt = function () { return (0, random_1["default"])(1000000000, 2147483647); };
67
+ var getDmmfMetaData = function (client, model, field) {
68
+ var modelData = client._baseDmmf.datamodel.models.find(function (m) { return m.name === model; });
69
+ if (!modelData) {
70
+ throw new Error("Could not retrieve model data from Prisma Client for model '".concat(model, "'"));
71
+ }
72
+ var fieldData = modelData.fields.find(function (f) { return f.name === field; });
73
+ return fieldData;
74
+ };
75
+ // Perform substitution of Ints so that Prisma doesn't throw an error due to mismatched type values
76
+ // After we've captured the SQL, we can replace the Ints with the original values
77
+ var tokenizeWhereExpression = function (
78
+ /** The Prisma client to use for metadata */
79
+ client,
80
+ /** The Prisma where expression to be tokenized */
81
+ where,
82
+ /** The base table we are generating an expression for */
83
+ table,
84
+ /** The model name being queried. e.g. 'User' */
85
+ model,
86
+ /** The tokens object to add the new tokens to */
87
+ tokens) {
88
+ if (tokens === void 0) { tokens = {}; }
89
+ for (var field in where) {
90
+ // Get field data from the prisma client for the model and field being queried
91
+ var fieldData = getDmmfMetaData(client, model, field);
92
+ var int = void 0;
93
+ // Small loop to make sure we get a unique int for the token key
94
+ do {
95
+ int = getLargeRandomInt();
96
+ } while (tokens[int]);
97
+ var astFragment = {};
98
+ var value = where[field];
99
+ var isNumeric = PRISMA_NUMERIC_TYPES.includes(fieldData.type);
100
+ var isColumnName = typeof value === "string" && !!value.match(/^___yates_row_/);
101
+ var isContext = typeof value === "string" && !!value.match(/^___yates_context_/);
102
+ switch (true) {
103
+ case isColumnName:
104
+ // Substiture the yates row placeholder for the actual column name
105
+ var column = value.replace(/^___yates_row_/, "");
106
+ if (!getDmmfMetaData(client, table, column)) {
107
+ throw new Error("Invalid field name \"".concat(column, "\""));
108
+ }
109
+ astFragment = {
110
+ type: "column_ref",
111
+ schema: "public",
112
+ table: table,
113
+ column: column
114
+ };
115
+ break;
116
+ case isContext && isNumeric:
117
+ astFragment = {
118
+ as: null,
119
+ type: "cast",
120
+ expr: {
121
+ type: "function",
122
+ name: "current_setting",
123
+ args: {
124
+ type: "expr_list",
125
+ value: [
126
+ {
127
+ type: "parameter",
128
+ value: (0, escape_1.escapeLiteral)(value.replace(/^___yates_context_/, ""))
129
+ },
130
+ ]
131
+ }
132
+ },
133
+ symbol: "::",
134
+ target: {
135
+ dataType: "float",
136
+ suffix: []
137
+ }
138
+ };
139
+ break;
140
+ case isContext && !isNumeric:
141
+ astFragment = {
142
+ type: "function",
143
+ name: "current_setting",
144
+ args: {
145
+ type: "expr_list",
146
+ value: [
147
+ {
148
+ type: "parameter",
149
+ value: (0, escape_1.escapeLiteral)(value.replace(/^___yates_context_/, ""))
150
+ },
151
+ ]
152
+ }
153
+ };
154
+ break;
155
+ case isNumeric:
156
+ if (typeof value !== "number") {
157
+ throw new Error("Numeric fields can only be queried with numbers: querying field '".concat(field, "' with value '").concat(value, "'"));
158
+ }
159
+ astFragment = {
160
+ type: "number",
161
+ value: value
162
+ };
163
+ break;
164
+ // All other types are treated as strings
165
+ default:
166
+ astFragment = {
167
+ type: "parameter",
168
+ value: (0, escape_1.escapeLiteral)(value)
169
+ };
170
+ break;
171
+ }
172
+ tokens[int] = {
173
+ astFragment: astFragment
174
+ };
175
+ where[field] = isNumeric ? int : "".concat(int);
176
+ }
177
+ return {
178
+ tokens: tokens,
179
+ where: where
180
+ };
181
+ };
182
+ var expressionToSQL = function (getExpression, table) { return __awaiter(void 0, void 0, void 0, function () {
183
+ var baseClient, tokens, expressionClient, sql;
184
+ return __generator(this, function (_a) {
185
+ switch (_a.label) {
186
+ case 0:
187
+ if (typeof getExpression === "string") {
188
+ return [2 /*return*/, getExpression];
189
+ }
190
+ baseClient = new client_1.PrismaClient({
191
+ log: [{ level: "query", emit: "event" }]
192
+ });
193
+ tokens = {};
194
+ expressionClient = baseClient.$extends({
195
+ name: "expressionClient",
196
+ query: {
197
+ $allModels: {
198
+ $allOperations: function (_a) {
199
+ var model = _a.model, operation = _a.operation, args = _a.args, query = _a.query;
200
+ // if not findFirst or findUnique
201
+ if (operation !== "findFirst" && operation !== "findUnique") {
202
+ throw new Error('Only "findFirst" and "findUnique" are supported in client expressions');
203
+ }
204
+ if ("where" in args && args.where) {
205
+ var where = tokenizeWhereExpression(baseClient, args.where, table, model, tokens).where;
206
+ args.where = where;
207
+ }
208
+ return query(args);
209
+ }
210
+ }
211
+ }
212
+ });
213
+ return [4 /*yield*/, new Promise(
214
+ // rome-ignore lint/suspicious/noAsyncPromiseExecutor: future cleanup
215
+ function (resolve, reject) { return __awaiter(void 0, void 0, void 0, function () {
216
+ var rawExpression, isSubselect, error_1;
217
+ return __generator(this, function (_a) {
218
+ switch (_a.label) {
219
+ case 0:
220
+ rawExpression = getExpression(expressionClient, expressionRowName, expressionContext);
221
+ isSubselect = typeof rawExpression === "object" && typeof rawExpression.then === "function";
222
+ expressionClient.$on("query", function (e) {
223
+ try {
224
+ var parser = new node_sql_parser_1.Parser();
225
+ // Parse the query into an AST
226
+ var ast = parser.astify(e.query, {
227
+ database: "postgresql"
228
+ });
229
+ var params = JSON.parse(e.params);
230
+ // By default Prisma will use a parameter for the limit, for Yates, the value is always "1"
231
+ ast.limit = { seperator: "", value: [{ type: "number", value: 1 }] };
232
+ // Now that the SQL has been generated, we can replace the tokens with the original values
233
+ for (var i = 0; i < params.length; i++) {
234
+ var param = params[i];
235
+ var token = tokens[param];
236
+ if (!token) {
237
+ continue;
238
+ }
239
+ var parameterizedStatement = deepFind(ast, {
240
+ right: {
241
+ type: "origin",
242
+ value: "$".concat(i + 1)
243
+ }
244
+ });
245
+ if (!parameterizedStatement) {
246
+ continue;
247
+ }
248
+ parameterizedStatement.right = token.astFragment;
249
+ }
250
+ if (isSubselect) {
251
+ // For subselects, we need to convert the entire query and wrap in EXISTS so it converts to a binary expression
252
+ var subSelect = parser.sqlify(ast, {
253
+ database: "postgresql"
254
+ });
255
+ resolve("EXISTS(".concat(subSelect, ")"));
256
+ }
257
+ else {
258
+ // For basic expressions, we're only interested in the WHERE clause and can convert just the WHERE clause into SQL
259
+ var where = parser.exprToSQL(ast.where, {
260
+ database: "postgresql"
261
+ });
262
+ resolve(where);
263
+ }
264
+ }
265
+ catch (error) {
266
+ reject(error);
267
+ }
268
+ });
269
+ _a.label = 1;
270
+ case 1:
271
+ _a.trys.push([1, 6, , 7]);
272
+ if (!isSubselect) return [3 /*break*/, 3];
273
+ return [4 /*yield*/, rawExpression];
274
+ case 2:
275
+ _a.sent();
276
+ return [3 /*break*/, 5];
277
+ case 3: return [4 /*yield*/, expressionClient[table].findFirst({
278
+ where: rawExpression
279
+ })];
280
+ case 4:
281
+ _a.sent();
282
+ _a.label = 5;
283
+ case 5: return [3 /*break*/, 7];
284
+ case 6:
285
+ error_1 = _a.sent();
286
+ reject(error_1);
287
+ return [3 /*break*/, 7];
288
+ case 7: return [2 /*return*/];
289
+ }
290
+ });
291
+ }); })];
292
+ case 1:
293
+ sql = _a.sent();
294
+ // Close the client
295
+ return [4 /*yield*/, expressionClient.$disconnect()];
296
+ case 2:
297
+ // Close the client
298
+ _a.sent();
299
+ return [4 /*yield*/, baseClient.$disconnect()];
300
+ case 3:
301
+ _a.sent();
302
+ return [2 /*return*/, sql];
303
+ }
304
+ });
305
+ }); };
306
+ exports.expressionToSQL = expressionToSQL;
307
+ //# sourceMappingURL=expressions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expressions.js","sourceRoot":"","sources":["../src/expressions.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { Prisma, PrismaClient } from "@prisma/client";
2
+ import { Expression } from "./expressions";
2
3
  declare const VALID_OPERATIONS: readonly ["SELECT", "UPDATE", "INSERT", "DELETE"];
3
4
  type Operation = typeof VALID_OPERATIONS[number];
4
5
  export type Models = Prisma.ModelName;
5
- export interface Ability {
6
+ export interface Ability<ContextKeys extends string = string> {
6
7
  description?: string;
7
- expression?: string;
8
+ expression?: Expression<ContextKeys>;
8
9
  operation: Operation;
9
10
  model?: Models;
10
11
  slug?: string;
@@ -15,28 +16,33 @@ export type DefaultAbilities = {
15
16
  [op in CRUDOperations]: Ability;
16
17
  };
17
18
  };
18
- export type CustomAbilities = {
19
+ export type CustomAbilities<ContextKeys extends string = string> = {
19
20
  [model in Models]?: {
20
- [op in string]?: Ability;
21
+ [op in string]?: Ability<ContextKeys>;
21
22
  };
22
23
  };
23
- export type GetContextFn = () => {
24
+ export type GetContextFn<ContextKeys extends string = string> = () => {
24
25
  role: string;
25
26
  context?: {
26
- [key: string]: string;
27
+ [key in ContextKeys]: string | number | string[];
27
28
  };
28
29
  } | null;
29
30
  export declare const createAbilityName: (model: string, ability: string) => string;
30
31
  export declare const createRoleName: (name: string) => string;
31
- export declare const setupMiddleware: (prisma: PrismaClient, getContext: GetContextFn) => void;
32
- export declare const createRoles: <K extends CustomAbilities = CustomAbilities, T = DefaultAbilities & K>({ prisma, customAbilities, getRoles, }: {
32
+ export declare const createClient: (prisma: PrismaClient, getContext: GetContextFn) => Omit<PrismaClient<Prisma.PrismaClientOptions, never, Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined, {
33
+ result: {} & Record<string, {}>;
34
+ model: {} & Record<string, {}>;
35
+ client: {};
36
+ query: {};
37
+ }>, "$use"> & {};
38
+ export declare const createRoles: <K extends CustomAbilities<string> = CustomAbilities<string>, T = DefaultAbilities & K>({ prisma, customAbilities, getRoles, }: {
33
39
  prisma: PrismaClient;
34
40
  customAbilities?: Partial<K> | undefined;
35
41
  getRoles: (abilities: T) => {
36
- [key: string]: Ability[] | "*";
42
+ [key: string]: "*" | Ability<string>[];
37
43
  };
38
44
  }) => Promise<void>;
39
- export interface SetupParams<K extends CustomAbilities = CustomAbilities> {
45
+ export interface SetupParams<ContextKeys extends string = string, K extends CustomAbilities<ContextKeys> = CustomAbilities<ContextKeys>> {
40
46
  /**
41
47
  * The Prisma client instance. Used for database queries and model introspection.
42
48
  */
@@ -58,7 +64,15 @@ export interface SetupParams<K extends CustomAbilities = CustomAbilities> {
58
64
  * You can also provide additional context here, which will be available in any RLS expressions you've defined.
59
65
  * Returning `null` will result in the permissions being skipped entirely.
60
66
  */
61
- getContext: GetContextFn;
67
+ getContext: GetContextFn<ContextKeys>;
62
68
  }
63
- export declare const setup: <K extends CustomAbilities = CustomAbilities>(params: SetupParams<K>) => Promise<void>;
69
+ /**
70
+ * Creates an extended client that sets contextual parameters and user role on every query
71
+ **/
72
+ export declare const setup: <ContextKeys extends string = string, K extends CustomAbilities<ContextKeys> = CustomAbilities<ContextKeys>>(params: SetupParams<ContextKeys, K>) => Promise<Omit<PrismaClient<Prisma.PrismaClientOptions, never, Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined, {
73
+ result: {} & Record<string, {}>;
74
+ model: {} & Record<string, {}>;
75
+ client: {};
76
+ query: {};
77
+ }>, "$use"> & {}>;
64
78
  export {};
package/dist/index.js CHANGED
@@ -50,6 +50,33 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
50
50
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
51
  }
52
52
  };
53
+ var __values = (this && this.__values) || function(o) {
54
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
55
+ if (m) return m.call(o);
56
+ if (o && typeof o.length === "number") return {
57
+ next: function () {
58
+ if (o && i >= o.length) o = void 0;
59
+ return { value: o && o[i++], done: !o };
60
+ }
61
+ };
62
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
63
+ };
64
+ var __read = (this && this.__read) || function (o, n) {
65
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
66
+ if (!m) return o;
67
+ var i = m.call(o), r, ar = [], e;
68
+ try {
69
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
70
+ }
71
+ catch (error) { e = { error: error }; }
72
+ finally {
73
+ try {
74
+ if (r && !r.done && (m = i["return"])) m.call(i);
75
+ }
76
+ finally { if (e) throw e.error; }
77
+ }
78
+ return ar;
79
+ };
53
80
  var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
54
81
  if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
55
82
  if (ar || !(i in from)) {
@@ -63,12 +90,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
63
90
  return (mod && mod.__esModule) ? mod : { "default": mod };
64
91
  };
65
92
  exports.__esModule = true;
66
- exports.setup = exports.createRoles = exports.setupMiddleware = exports.createRoleName = exports.createAbilityName = void 0;
67
- var client_1 = require("@prisma/client");
93
+ exports.setup = exports.createRoles = exports.createClient = exports.createRoleName = exports.createAbilityName = void 0;
68
94
  var difference_1 = __importDefault(require("lodash/difference"));
69
95
  var flatMap_1 = __importDefault(require("lodash/flatMap"));
70
96
  var map_1 = __importDefault(require("lodash/map"));
71
97
  var toPairs_1 = __importDefault(require("lodash/toPairs"));
98
+ var expressions_1 = require("./expressions");
72
99
  var VALID_OPERATIONS = ["SELECT", "UPDATE", "INSERT", "DELETE"];
73
100
  /**
74
101
  * This function is used to take a lock that is automatically released at the end of the current transaction.
@@ -89,127 +116,131 @@ var createRoleName = function (name) {
89
116
  return sanitizeSlug("yates_role_".concat(name));
90
117
  };
91
118
  exports.createRoleName = createRoleName;
92
- // This middleware is used to set the role and context for the current user so that RLS can be applied
93
- // It must be the *last* middleware in the chain, as it will call the original function itself and return the value.
94
- var setupMiddleware = function (prisma, getContext) {
95
- // Create a new admin client to use for unrestricted queries
96
- // This is required because the middleware is applied to the client, and so if we use the same client, we will
97
- // get an infinite loop and can trigger client middlewares multiple times
98
- var adminClient = new client_1.PrismaClient();
99
- prisma.$use(function (params, next) { return __awaiter(void 0, void 0, void 0, function () {
100
- var ctx, role, context, pgRole, modelName, _i, _a, k, txResults, queryResults, selectKeys, e_1;
101
- var _b;
102
- return __generator(this, function (_c) {
103
- switch (_c.label) {
104
- case 0:
105
- if (!params.model) {
106
- return [2 /*return*/, next(params)];
107
- }
108
- ctx = getContext();
109
- // If ctx is null, the middleware is explicitly skipped
110
- if (ctx === null) {
111
- return [2 /*return*/, next(params)];
112
- }
113
- role = ctx.role, context = ctx.context;
114
- pgRole = (0, exports.createRoleName)(role);
115
- modelName = params.model.charAt(0).toLowerCase() + params.model.slice(1);
116
- if (context) {
117
- for (_i = 0, _a = Object.keys(context); _i < _a.length; _i++) {
118
- k = _a[_i];
119
- if (!k.match(/^[a-z_\.]+$/)) {
120
- throw new Error("Context variable \"".concat(k, "\" contains invalid characters. Context variables must only contain lowercase letters, numbers, periods and underscores."));
121
- }
122
- if (typeof context[k] !== "number" && typeof context[k] !== "string") {
123
- throw new Error("Context variable \"".concat(k, "\" must be a string or number. Got ").concat(typeof context[k]));
119
+ // This uses client extensions to set the role and context for the current user so that RLS can be applied
120
+ var createClient = function (prisma, getContext) {
121
+ var client = prisma.$extends({
122
+ name: "Yates client",
123
+ query: {
124
+ $allModels: {
125
+ $allOperations: function (_a) {
126
+ var _b;
127
+ var model = _a.model, args = _a.args, query = _a.query;
128
+ return __awaiter(this, void 0, void 0, function () {
129
+ var ctx, role, context, pgRole, _c, _d, k, txResults, queryResults, e_1;
130
+ var e_2, _e;
131
+ return __generator(this, function (_f) {
132
+ switch (_f.label) {
133
+ case 0:
134
+ if (!model) {
135
+ return [2 /*return*/, query(args)];
136
+ }
137
+ ctx = getContext();
138
+ // If ctx is null, the middleware is explicitly skipped
139
+ if (ctx === null) {
140
+ return [2 /*return*/, query(args)];
141
+ }
142
+ role = ctx.role, context = ctx.context;
143
+ pgRole = (0, exports.createRoleName)(role);
144
+ if (context) {
145
+ try {
146
+ for (_c = __values(Object.keys(context)), _d = _c.next(); !_d.done; _d = _c.next()) {
147
+ k = _d.value;
148
+ if (!k.match(/^[a-z_\.]+$/)) {
149
+ throw new Error("Context variable \"".concat(k, "\" contains invalid characters. Context variables must only contain lowercase letters, numbers, periods and underscores."));
150
+ }
151
+ if (typeof context[k] !== "number" && typeof context[k] !== "string") {
152
+ throw new Error("Context variable \"".concat(k, "\" must be a string or number. Got ").concat(typeof context[k]));
153
+ }
154
+ }
155
+ }
156
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
157
+ finally {
158
+ try {
159
+ if (_d && !_d.done && (_e = _c["return"])) _e.call(_c);
160
+ }
161
+ finally { if (e_2) throw e_2.error; }
162
+ }
163
+ }
164
+ _f.label = 1;
165
+ case 1:
166
+ _f.trys.push([1, 3, , 4]);
167
+ return [4 /*yield*/, prisma.$transaction(__spreadArray(__spreadArray([
168
+ // 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 ROLE
169
+ prisma.$queryRawUnsafe("SET ROLE ".concat(pgRole))
170
+ ], __read((0, toPairs_1["default"])(context).map(function (_a) {
171
+ var _b = __read(_a, 2), key = _b[0], value = _b[1];
172
+ return prisma.$queryRaw(templateObject_1 || (templateObject_1 = __makeTemplateObject(["SELECT set_config(", ", ", ", true);"], ["SELECT set_config(", ", ", ", true);"])), key, value.toString());
173
+ })), false), [
174
+ // Now call original function
175
+ // Conveniently, the `query` function will happily run inside the transaction.
176
+ query(args),
177
+ // Switch role back to admin user
178
+ prisma.$queryRawUnsafe("SET ROLE none"),
179
+ ], false))];
180
+ case 2:
181
+ txResults = _f.sent();
182
+ queryResults = txResults[txResults.length - 2];
183
+ return [2 /*return*/, queryResults];
184
+ case 3:
185
+ e_1 = _f.sent();
186
+ // Normalize RLS errors to make them a bit more readable.
187
+ if ((_b = e_1.message) === null || _b === void 0 ? void 0 : _b.includes("new row violates row-level security policy for table")) {
188
+ throw new Error("You do not have permission to perform this action.");
189
+ }
190
+ throw e_1;
191
+ case 4: return [2 /*return*/];
124
192
  }
125
- }
126
- }
127
- _c.label = 1;
128
- case 1:
129
- _c.trys.push([1, 3, , 4]);
130
- return [4 /*yield*/, adminClient.$transaction(__spreadArray(__spreadArray([
131
- // 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 ROLE
132
- adminClient.$queryRawUnsafe("SET ROLE ".concat(pgRole))
133
- ], (0, toPairs_1["default"])(context).map(function (_a) {
134
- var key = _a[0], value = _a[1];
135
- return adminClient.$queryRaw(templateObject_1 || (templateObject_1 = __makeTemplateObject(["SELECT set_config(", ", ", ", true);"], ["SELECT set_config(", ", ", ", true);"])), key, value);
136
- }), true), [
137
- // Now call original function
138
- // Assumptions:
139
- // - prisma model class is params.model in camelCase
140
- // - prisma function name is params.action
141
- adminClient[modelName][params.action](params.args),
142
- // Switch role back to admin user
143
- adminClient.$queryRawUnsafe("SET ROLE none"),
144
- ], false))];
145
- case 2:
146
- txResults = _c.sent();
147
- queryResults = txResults[txResults.length - 2];
148
- // This heuristic is used to determine if this is a query for a related entity, and if so, unwraps the results.
149
- // This mimics the "native" prisma behaviour, where if you query for a related entity, it will return the related entity (or entities) directly, rather than an object with the related entity as a property.
150
- // See https://prisma.slack.com/archives/CA491RJH0/p1674126834205399
151
- if (params.args.select) {
152
- selectKeys = Object.keys(params.args.select);
153
- if (selectKeys.length === 1 &&
154
- params.dataPath.length > 0 &&
155
- selectKeys[0] === params.dataPath[params.dataPath.length - 1] &&
156
- selectKeys[0] === Object.keys(queryResults)[0]) {
157
- return [2 /*return*/, queryResults[selectKeys[0]]];
158
- }
159
- }
160
- return [2 /*return*/, queryResults];
161
- case 3:
162
- e_1 = _c.sent();
163
- // Normalize RLS errors to make them a bit more readable.
164
- if ((_b = e_1.message) === null || _b === void 0 ? void 0 : _b.includes("new row violates row-level security policy for table")) {
165
- throw new Error("You do not have permission to perform this action.");
166
- }
167
- throw e_1;
168
- case 4: return [2 /*return*/];
193
+ });
194
+ });
195
+ }
169
196
  }
170
- });
171
- }); });
197
+ }
198
+ });
199
+ return client;
172
200
  };
173
- exports.setupMiddleware = setupMiddleware;
174
- var setRLS = function (prisma, table, roleName, operation, expression) { return __awaiter(void 0, void 0, void 0, function () {
175
- var policyName, rows;
201
+ exports.createClient = createClient;
202
+ var setRLS = function (prisma, table, roleName, operation, rawExpression) { return __awaiter(void 0, void 0, void 0, function () {
203
+ var expression, policyName, rows;
176
204
  return __generator(this, function (_a) {
177
205
  switch (_a.label) {
178
- case 0:
206
+ case 0: return [4 /*yield*/, (0, expressions_1.expressionToSQL)(rawExpression, table)];
207
+ case 1:
208
+ expression = _a.sent();
179
209
  policyName = "".concat(roleName, "_policy");
180
210
  return [4 /*yield*/, prisma.$queryRawUnsafe("\n\t\tselect * from pg_catalog.pg_policies where tablename = '".concat(table, "' AND policyname = '").concat(policyName, "';\n\t"))];
181
- case 1:
211
+ case 2:
182
212
  rows = _a.sent();
183
- if (!(rows.length === 0)) return [3 /*break*/, 6];
184
- if (!(operation === "INSERT")) return [3 /*break*/, 3];
213
+ if (!(rows.length === 0)) return [3 /*break*/, 7];
214
+ if (!(operation === "INSERT")) return [3 /*break*/, 4];
185
215
  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 "))];
186
- case 2:
216
+ case 3:
187
217
  _a.sent();
188
- return [3 /*break*/, 5];
189
- 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 "))];
190
- case 4:
218
+ return [3 /*break*/, 6];
219
+ case 4: return [4 /*yield*/, prisma.$queryRawUnsafe("\n CREATE POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" FOR ").concat(operation, " TO ").concat(roleName, " USING (").concat(expression, ");\n "))];
220
+ case 5:
191
221
  _a.sent();
192
- _a.label = 5;
193
- case 5: return [3 /*break*/, 10];
194
- case 6:
195
- if (!(rows[0].qual !== expression)) return [3 /*break*/, 10];
196
- if (!(operation === "INSERT")) return [3 /*break*/, 8];
197
- return [4 /*yield*/, prisma.$queryRawUnsafe("\n ALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " WITH CHECK (").concat(expression, ");\n "))];
222
+ _a.label = 6;
223
+ case 6: return [3 /*break*/, 11];
198
224
  case 7:
225
+ if (!(rows[0].qual !== expression)) return [3 /*break*/, 11];
226
+ if (!(operation === "INSERT")) return [3 /*break*/, 9];
227
+ return [4 /*yield*/, prisma.$queryRawUnsafe("\n ALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " WITH CHECK (").concat(expression, ");\n "))];
228
+ case 8:
199
229
  _a.sent();
200
- return [3 /*break*/, 10];
201
- case 8: return [4 /*yield*/, prisma.$queryRawUnsafe("\n ALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " USING (").concat(expression, ");\n "))];
202
- case 9:
230
+ return [3 /*break*/, 11];
231
+ case 9: return [4 /*yield*/, prisma.$queryRawUnsafe("\n ALTER POLICY ".concat(policyName, " ON \"public\".\"").concat(table, "\" TO ").concat(roleName, " USING (").concat(expression, ");\n "))];
232
+ case 10:
203
233
  _a.sent();
204
- _a.label = 10;
205
- case 10: return [2 /*return*/];
234
+ _a.label = 11;
235
+ case 11: return [2 /*return*/];
206
236
  }
207
237
  });
208
238
  }); };
209
239
  var createRoles = function (_a) {
210
240
  var prisma = _a.prisma, customAbilities = _a.customAbilities, getRoles = _a.getRoles;
211
241
  return __awaiter(void 0, void 0, void 0, function () {
212
- var abilities, models, diff, _i, models_1, model, ability, operation, roles, _b, _c, _d, _e, model, table, _f, _g, _h, _j, slug, ability, roleName, _loop_1, _k, _l, _m, _o, key;
242
+ var abilities, models, diff, models_1, models_1_1, model, ability, operation, roles, _b, _c, _d, _i, model, table, _e, _f, _g, _h, slug, ability, roleName, _loop_1, _j, _k, _l, _m, key;
243
+ var e_3, _o;
213
244
  var _p;
214
245
  return __generator(this, function (_q) {
215
246
  switch (_q.label) {
@@ -222,57 +253,66 @@ var createRoles = function (_a) {
222
253
  throw new Error("Invalid models in custom abilities: ".concat(diff.join(", ")));
223
254
  }
224
255
  }
225
- for (_i = 0, models_1 = models; _i < models_1.length; _i++) {
226
- model = models_1[_i];
227
- abilities[model] = {
228
- create: {
229
- description: "Create ".concat(model),
230
- expression: "true",
231
- operation: "INSERT",
232
- model: model,
233
- slug: "create"
234
- },
235
- read: {
236
- description: "Read ".concat(model),
237
- expression: "true",
238
- operation: "SELECT",
239
- model: model,
240
- slug: "read"
241
- },
242
- update: {
243
- description: "Update ".concat(model),
244
- expression: "true",
245
- operation: "UPDATE",
246
- model: model,
247
- slug: "update"
248
- },
249
- "delete": {
250
- description: "Delete ".concat(model),
251
- expression: "true",
252
- operation: "DELETE",
253
- model: model,
254
- slug: "delete"
255
- }
256
- };
257
- if (customAbilities === null || customAbilities === void 0 ? void 0 : customAbilities[model]) {
258
- for (ability in customAbilities[model]) {
259
- operation = (_p = customAbilities[model][ability]) === null || _p === void 0 ? void 0 : _p.operation;
260
- if (!operation)
261
- continue;
262
- abilities[model][ability] = __assign(__assign({}, customAbilities[model][ability]), { operation: operation, model: model, slug: ability });
256
+ try {
257
+ for (models_1 = __values(models), models_1_1 = models_1.next(); !models_1_1.done; models_1_1 = models_1.next()) {
258
+ model = models_1_1.value;
259
+ abilities[model] = {
260
+ create: {
261
+ description: "Create ".concat(model),
262
+ expression: "true",
263
+ operation: "INSERT",
264
+ model: model,
265
+ slug: "create"
266
+ },
267
+ read: {
268
+ description: "Read ".concat(model),
269
+ expression: "true",
270
+ operation: "SELECT",
271
+ model: model,
272
+ slug: "read"
273
+ },
274
+ update: {
275
+ description: "Update ".concat(model),
276
+ expression: "true",
277
+ operation: "UPDATE",
278
+ model: model,
279
+ slug: "update"
280
+ },
281
+ "delete": {
282
+ description: "Delete ".concat(model),
283
+ expression: "true",
284
+ operation: "DELETE",
285
+ model: model,
286
+ slug: "delete"
287
+ }
288
+ };
289
+ if (customAbilities === null || customAbilities === void 0 ? void 0 : customAbilities[model]) {
290
+ for (ability in customAbilities[model]) {
291
+ operation = (_p = customAbilities[model][ability]) === null || _p === void 0 ? void 0 : _p.operation;
292
+ if (!operation)
293
+ continue;
294
+ abilities[model][ability] = __assign(__assign({}, customAbilities[model][ability]), { operation: operation, model: model, slug: ability });
295
+ }
263
296
  }
264
297
  }
265
298
  }
299
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
300
+ finally {
301
+ try {
302
+ if (models_1_1 && !models_1_1.done && (_o = models_1["return"])) _o.call(models_1);
303
+ }
304
+ finally { if (e_3) throw e_3.error; }
305
+ }
266
306
  roles = getRoles(abilities);
267
307
  _b = abilities;
268
308
  _c = [];
269
309
  for (_d in _b)
270
310
  _c.push(_d);
271
- _e = 0;
311
+ _i = 0;
272
312
  _q.label = 1;
273
313
  case 1:
274
- if (!(_e < _c.length)) return [3 /*break*/, 8];
275
- _d = _c[_e];
314
+ if (!(_i < _c.length)) return [3 /*break*/, 8];
315
+ _d = _c[_i];
276
316
  if (!(_d in _b)) return [3 /*break*/, 7];
277
317
  model = _d;
278
318
  table = model;
@@ -282,17 +322,17 @@ var createRoles = function (_a) {
282
322
  ])];
283
323
  case 2:
284
324
  _q.sent();
285
- _f = abilities[model];
286
- _g = [];
287
- for (_h in _f)
288
- _g.push(_h);
289
- _j = 0;
325
+ _e = abilities[model];
326
+ _f = [];
327
+ for (_g in _e)
328
+ _f.push(_g);
329
+ _h = 0;
290
330
  _q.label = 3;
291
331
  case 3:
292
- if (!(_j < _g.length)) return [3 /*break*/, 7];
293
- _h = _g[_j];
294
- if (!(_h in _f)) return [3 /*break*/, 6];
295
- slug = _h;
332
+ if (!(_h < _f.length)) return [3 /*break*/, 7];
333
+ _g = _f[_h];
334
+ if (!(_g in _e)) return [3 /*break*/, 6];
335
+ slug = _g;
296
336
  ability = abilities[model][slug];
297
337
  if (!VALID_OPERATIONS.includes(ability.operation)) {
298
338
  throw new Error("Invalid operation: ".concat(ability.operation));
@@ -313,10 +353,10 @@ var createRoles = function (_a) {
313
353
  _q.sent();
314
354
  _q.label = 6;
315
355
  case 6:
316
- _j++;
356
+ _h++;
317
357
  return [3 /*break*/, 3];
318
358
  case 7:
319
- _e++;
359
+ _i++;
320
360
  return [3 /*break*/, 1];
321
361
  case 8:
322
362
  _loop_1 = function (key) {
@@ -371,23 +411,23 @@ var createRoles = function (_a) {
371
411
  }
372
412
  });
373
413
  };
374
- _k = roles;
375
- _l = [];
376
- for (_m in _k)
377
- _l.push(_m);
378
- _o = 0;
414
+ _j = roles;
415
+ _k = [];
416
+ for (_l in _j)
417
+ _k.push(_l);
418
+ _m = 0;
379
419
  _q.label = 9;
380
420
  case 9:
381
- if (!(_o < _l.length)) return [3 /*break*/, 12];
382
- _m = _l[_o];
383
- if (!(_m in _k)) return [3 /*break*/, 11];
384
- key = _m;
421
+ if (!(_m < _k.length)) return [3 /*break*/, 12];
422
+ _l = _k[_m];
423
+ if (!(_l in _j)) return [3 /*break*/, 11];
424
+ key = _l;
385
425
  return [5 /*yield**/, _loop_1(key)];
386
426
  case 10:
387
427
  _q.sent();
388
428
  _q.label = 11;
389
429
  case 11:
390
- _o++;
430
+ _m++;
391
431
  return [3 /*break*/, 9];
392
432
  case 12: return [2 /*return*/];
393
433
  }
@@ -395,8 +435,11 @@ var createRoles = function (_a) {
395
435
  });
396
436
  };
397
437
  exports.createRoles = createRoles;
438
+ /**
439
+ * Creates an extended client that sets contextual parameters and user role on every query
440
+ **/
398
441
  var setup = function (params) { return __awaiter(void 0, void 0, void 0, function () {
399
- var prisma, customAbilities, getRoles, getContext;
442
+ var prisma, customAbilities, getRoles, getContext, client;
400
443
  return __generator(this, function (_a) {
401
444
  switch (_a.label) {
402
445
  case 0:
@@ -404,8 +447,8 @@ var setup = function (params) { return __awaiter(void 0, void 0, void 0, functio
404
447
  return [4 /*yield*/, (0, exports.createRoles)({ prisma: prisma, customAbilities: customAbilities, getRoles: getRoles })];
405
448
  case 1:
406
449
  _a.sent();
407
- (0, exports.setupMiddleware)(prisma, getContext);
408
- return [2 /*return*/];
450
+ client = (0, exports.createClient)(prisma, getContext);
451
+ return [2 /*return*/, client];
409
452
  }
410
453
  });
411
454
  }); };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cerebruminc/yates",
3
- "version": "1.1.1",
3
+ "version": "2.0.0",
4
4
  "description": "Role based access control for Prisma Apps",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -29,10 +29,11 @@
29
29
  "uuid": "^9.0.0"
30
30
  },
31
31
  "dependencies": {
32
+ "@lucianbuzzo/node-sql-parser": "^4.6.6",
32
33
  "lodash": "^4.17.21"
33
34
  },
34
35
  "peerDependencies": {
35
36
  "@prisma/client": "^4.0.0",
36
37
  "prisma": "^4.9.0"
37
38
  }
38
- }
39
+ }