zenstack 0.6.0-pre.9 → 1.0.0-alpha.19

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.
Files changed (133) hide show
  1. package/cli/cli-error.d.ts +5 -0
  2. package/cli/cli-error.js +12 -0
  3. package/cli/cli-error.js.map +1 -0
  4. package/cli/cli-util.d.ts +18 -0
  5. package/cli/cli-util.js +122 -0
  6. package/cli/cli-util.js.map +1 -0
  7. package/cli/index.d.ts +14 -0
  8. package/cli/index.js +72 -6529
  9. package/cli/index.js.map +1 -0
  10. package/cli/plugin-runner.d.ts +14 -0
  11. package/cli/plugin-runner.js +133 -0
  12. package/cli/plugin-runner.js.map +1 -0
  13. package/global.d.js +1 -0
  14. package/global.d.js.map +1 -0
  15. package/language-server/constants.d.ts +12 -0
  16. package/language-server/constants.js +24 -0
  17. package/language-server/constants.js.map +1 -0
  18. package/language-server/main.d.ts +1 -0
  19. package/language-server/main.js +20 -6436
  20. package/language-server/main.js.map +1 -0
  21. package/language-server/types.d.ts +10 -0
  22. package/language-server/types.js +1 -0
  23. package/language-server/types.js.map +1 -0
  24. package/language-server/utils.d.ts +10 -0
  25. package/language-server/utils.js +28 -0
  26. package/language-server/utils.js.map +1 -0
  27. package/language-server/validator/attribute-validator.d.ts +9 -0
  28. package/language-server/validator/attribute-validator.js +15 -0
  29. package/language-server/validator/attribute-validator.js.map +1 -0
  30. package/language-server/validator/datamodel-validator.d.ts +16 -0
  31. package/language-server/validator/datamodel-validator.js +365 -0
  32. package/language-server/validator/datamodel-validator.js.map +1 -0
  33. package/language-server/validator/datasource-validator.d.ts +13 -0
  34. package/language-server/validator/datasource-validator.js +85 -0
  35. package/language-server/validator/datasource-validator.js.map +1 -0
  36. package/language-server/validator/enum-validator.d.ts +9 -0
  37. package/language-server/validator/enum-validator.js +18 -0
  38. package/language-server/validator/enum-validator.js.map +1 -0
  39. package/language-server/validator/expression-validator.d.ts +11 -0
  40. package/language-server/validator/expression-validator.js +40 -0
  41. package/language-server/validator/expression-validator.js.map +1 -0
  42. package/language-server/validator/schema-validator.d.ts +10 -0
  43. package/language-server/validator/schema-validator.js +35 -0
  44. package/language-server/validator/schema-validator.js.map +1 -0
  45. package/language-server/validator/utils.d.ts +24 -0
  46. package/language-server/validator/utils.js +116 -0
  47. package/language-server/validator/utils.js.map +1 -0
  48. package/language-server/validator/zmodel-validator.d.ts +21 -0
  49. package/language-server/validator/zmodel-validator.js +72 -0
  50. package/language-server/validator/zmodel-validator.js.map +1 -0
  51. package/language-server/zmodel-linker.d.ts +29 -0
  52. package/language-server/zmodel-linker.js +364 -0
  53. package/language-server/zmodel-linker.js.map +1 -0
  54. package/language-server/zmodel-module.d.ts +41 -0
  55. package/language-server/zmodel-module.js +83 -0
  56. package/language-server/zmodel-module.js.map +1 -0
  57. package/language-server/zmodel-scope.d.ts +10 -0
  58. package/language-server/zmodel-scope.js +34 -0
  59. package/language-server/zmodel-scope.js.map +1 -0
  60. package/language-server/zmodel-workspace-manager.d.ts +8 -0
  61. package/language-server/zmodel-workspace-manager.js +25 -0
  62. package/language-server/zmodel-workspace-manager.js.map +1 -0
  63. package/package.json +23 -18
  64. package/plugins/access-policy/expression-writer.d.ts +38 -0
  65. package/plugins/access-policy/expression-writer.js +323 -0
  66. package/plugins/access-policy/expression-writer.js.map +1 -0
  67. package/plugins/access-policy/index.d.ts +4 -0
  68. package/plugins/access-policy/index.js +15 -0
  69. package/plugins/access-policy/index.js.map +1 -0
  70. package/plugins/access-policy/policy-guard-generator.d.ts +15 -0
  71. package/plugins/access-policy/policy-guard-generator.js +345 -0
  72. package/plugins/access-policy/policy-guard-generator.js.map +1 -0
  73. package/plugins/access-policy/typescript-expression-transformer.d.ts +26 -0
  74. package/plugins/access-policy/typescript-expression-transformer.js +110 -0
  75. package/plugins/access-policy/typescript-expression-transformer.js.map +1 -0
  76. package/plugins/access-policy/utils.d.ts +5 -0
  77. package/plugins/access-policy/utils.js +16 -0
  78. package/plugins/access-policy/utils.js.map +1 -0
  79. package/plugins/access-policy/zod-schema-generator.d.ts +12 -0
  80. package/plugins/access-policy/zod-schema-generator.js +174 -0
  81. package/plugins/access-policy/zod-schema-generator.js.map +1 -0
  82. package/plugins/model-meta/index.d.ts +4 -0
  83. package/plugins/model-meta/index.js +130 -0
  84. package/plugins/model-meta/index.js.map +1 -0
  85. package/plugins/plugin-utils.d.ts +16 -0
  86. package/plugins/plugin-utils.js +58 -0
  87. package/plugins/plugin-utils.js.map +1 -0
  88. package/plugins/prisma/indent-string.d.ts +4 -0
  89. package/plugins/prisma/indent-string.js +16 -0
  90. package/plugins/prisma/indent-string.js.map +1 -0
  91. package/plugins/prisma/index.d.ts +4 -0
  92. package/plugins/prisma/index.js +15 -3740
  93. package/plugins/prisma/index.js.map +1 -0
  94. package/plugins/prisma/prisma-builder.d.ts +130 -0
  95. package/plugins/prisma/prisma-builder.js +271 -0
  96. package/plugins/prisma/prisma-builder.js.map +1 -0
  97. package/plugins/prisma/schema-generator.d.ts +24 -0
  98. package/plugins/prisma/schema-generator.js +212 -0
  99. package/plugins/prisma/schema-generator.js.map +1 -0
  100. package/plugins/prisma/zmodel-code-generator.d.ts +27 -0
  101. package/plugins/prisma/zmodel-code-generator.js +110 -0
  102. package/plugins/prisma/zmodel-code-generator.js.map +1 -0
  103. package/res/prism-zmodel.js +2 -4
  104. package/res/starter.zmodel +47 -0
  105. package/res/stdlib.zmodel +12 -1
  106. package/telemetry.d.ts +21 -0
  107. package/telemetry.js +102 -0
  108. package/telemetry.js.map +1 -0
  109. package/types.d.ts +11 -0
  110. package/types.js +1 -0
  111. package/types.js.map +1 -0
  112. package/utils/ast-utils.d.ts +15 -0
  113. package/utils/ast-utils.js +79 -0
  114. package/utils/ast-utils.js.map +1 -0
  115. package/utils/exec-utils.d.ts +6 -0
  116. package/utils/exec-utils.js +22 -0
  117. package/utils/exec-utils.js.map +1 -0
  118. package/utils/pkg-utils.d.ts +3 -0
  119. package/utils/pkg-utils.js +43 -0
  120. package/utils/pkg-utils.js.map +1 -0
  121. package/utils/version-utils.d.ts +1 -0
  122. package/utils/version-utils.js +15 -0
  123. package/utils/version-utils.js.map +1 -0
  124. package/asset/logo-256-bg.png +0 -0
  125. package/asset/logo-dark-256.png +0 -0
  126. package/asset/logo-light-256.png +0 -0
  127. package/extension.js +0 -39
  128. package/plugins/policy-guard/index.js +0 -4289
  129. package/plugins/react-hooks/index.js +0 -4318
  130. package/plugins/trpc/index.js +0 -5386
  131. package/plugins/zod/index.js +0 -4808
  132. package/res/package.template.json +0 -9
  133. package/res/tsconfig.template.json +0 -17
@@ -0,0 +1,345 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _ast = require("@zenstackhq/language/ast");
8
+ var _sdk = require("@zenstackhq/sdk");
9
+ var _changeCase = require("change-case");
10
+ var _langium = require("langium");
11
+ var _path = _interopRequireDefault(require("path"));
12
+ var _tsMorph = require("ts-morph");
13
+ var _ = require(".");
14
+ var _utils = require("../../language-server/utils");
15
+ var _astUtils = require("../../utils/ast-utils");
16
+ var _pluginUtils = require("../plugin-utils");
17
+ var _expressionWriter = require("./expression-writer");
18
+ var _utils2 = require("./utils");
19
+ var _zodSchemaGenerator = require("./zod-schema-generator");
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+ const UNKNOWN_USER_ID = 'zenstack_unknown_user';
22
+
23
+ /**
24
+ * Generates source file that contains Prisma query guard objects used for injecting database queries
25
+ */
26
+ class PolicyGenerator {
27
+ async generate(model, options) {
28
+ const output = options.output ? options.output : (0, _pluginUtils.getDefaultOutputFolder)();
29
+ if (!output) {
30
+ console.error(`Unable to determine output path, not running plugin ${_.name}`);
31
+ return;
32
+ }
33
+ const project = new _tsMorph.Project();
34
+ const sf = project.createSourceFile(_path.default.join(output, 'policy.ts'), undefined, {
35
+ overwrite: true
36
+ });
37
+ sf.addImportDeclaration({
38
+ namedImports: [{
39
+ name: 'QueryContext'
40
+ }],
41
+ moduleSpecifier: `${_pluginUtils.RUNTIME_PACKAGE}`,
42
+ isTypeOnly: true
43
+ });
44
+ sf.addImportDeclaration({
45
+ namedImports: [{
46
+ name: 'z'
47
+ }],
48
+ moduleSpecifier: 'zod'
49
+ });
50
+
51
+ // import enums
52
+ for (const e of model.declarations.filter(d => (0, _ast.isEnum)(d))) {
53
+ sf.addImportDeclaration({
54
+ namedImports: [{
55
+ name: e.name
56
+ }],
57
+ moduleSpecifier: '@prisma/client'
58
+ });
59
+ }
60
+ const models = model.declarations.filter(d => (0, _ast.isDataModel)(d));
61
+ const policyMap = {};
62
+ for (const model of models) {
63
+ policyMap[model.name] = await this.generateQueryGuardForModel(model, sf);
64
+ }
65
+ const zodGenerator = new _zodSchemaGenerator.ZodSchemaGenerator();
66
+ sf.addVariableStatement({
67
+ declarationKind: _tsMorph.VariableDeclarationKind.Const,
68
+ declarations: [{
69
+ name: 'policy',
70
+ initializer: writer => {
71
+ writer.block(() => {
72
+ writer.write('guard:');
73
+ writer.inlineBlock(() => {
74
+ for (const [model, map] of Object.entries(policyMap)) {
75
+ writer.write(`${(0, _changeCase.camelCase)(model)}:`);
76
+ writer.inlineBlock(() => {
77
+ for (const [op, func] of Object.entries(map)) {
78
+ if (typeof func === 'object') {
79
+ writer.write(`${op}: ${JSON.stringify(func)},`);
80
+ } else {
81
+ writer.write(`${op}: ${func},`);
82
+ }
83
+ }
84
+ });
85
+ writer.write(',');
86
+ }
87
+ });
88
+ writer.writeLine(',');
89
+ writer.write('schema:');
90
+ zodGenerator.generate(writer, models);
91
+ });
92
+ }
93
+ }]
94
+ });
95
+ sf.addStatements('export default policy');
96
+ sf.formatText();
97
+ await project.save();
98
+ await project.emit();
99
+ }
100
+ getPolicyExpressions(model, kind, operation) {
101
+ const attrs = model.attributes.filter(attr => {
102
+ var _attr$decl$ref;
103
+ return ((_attr$decl$ref = attr.decl.ref) === null || _attr$decl$ref === void 0 ? void 0 : _attr$decl$ref.name) === `@@${kind}`;
104
+ });
105
+ const checkOperation = operation === 'postUpdate' ? 'update' : operation;
106
+ let result = attrs.filter(attr => {
107
+ const opsValue = (0, _sdk.getLiteral)(attr.args[0].value);
108
+ if (!opsValue) {
109
+ return false;
110
+ }
111
+ const ops = opsValue.split(',').map(s => s.trim());
112
+ return ops.includes(checkOperation) || ops.includes('all');
113
+ }).map(attr => attr.args[1].value);
114
+ if (operation === 'update') {
115
+ result = this.processUpdatePolicies(result, false);
116
+ } else if (operation === 'postUpdate') {
117
+ result = this.processUpdatePolicies(result, true);
118
+ }
119
+ return result;
120
+ }
121
+ processUpdatePolicies(expressions, postUpdate) {
122
+ return expressions.map(expr => this.visitPolicyExpression(expr, postUpdate)).filter(e => !!e);
123
+ }
124
+ visitPolicyExpression(expr, postUpdate) {
125
+ if ((0, _ast.isBinaryExpr)(expr) && (expr.operator === '&&' || expr.operator === '||')) {
126
+ const left = this.visitPolicyExpression(expr.left, postUpdate);
127
+ const right = this.visitPolicyExpression(expr.right, postUpdate);
128
+ if (!left) return right;
129
+ if (!right) return left;
130
+ return {
131
+ ...expr,
132
+ left,
133
+ right
134
+ };
135
+ }
136
+ if ((0, _ast.isUnaryExpr)(expr) && expr.operator === '!') {
137
+ const operand = this.visitPolicyExpression(expr.operand, postUpdate);
138
+ if (!operand) return undefined;
139
+ return {
140
+ ...expr,
141
+ operand
142
+ };
143
+ }
144
+ if (postUpdate && !this.hasFutureReference(expr)) {
145
+ return undefined;
146
+ } else if (!postUpdate && this.hasFutureReference(expr)) {
147
+ return undefined;
148
+ }
149
+ return expr;
150
+ }
151
+ hasFutureReference(expr) {
152
+ for (const node of (0, _langium.streamAllContents)(expr)) {
153
+ var _node$function$ref;
154
+ if ((0, _ast.isInvocationExpr)(node) && ((_node$function$ref = node.function.ref) === null || _node$function$ref === void 0 ? void 0 : _node$function$ref.name) === 'future' && (0, _utils.isFromStdlib)(node.function.ref)) {
155
+ return true;
156
+ }
157
+ }
158
+ return false;
159
+ }
160
+ async generateQueryGuardForModel(model, sourceFile) {
161
+ const result = {};
162
+
163
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
164
+ const policies = (0, _astUtils.analyzePolicies)(model);
165
+ for (const kind of _pluginUtils.ALL_OPERATION_KINDS) {
166
+ if (policies[kind] === true || policies[kind] === false) {
167
+ result[kind] = policies[kind];
168
+ continue;
169
+ }
170
+ const denies = this.getPolicyExpressions(model, 'deny', kind);
171
+ const allows = this.getPolicyExpressions(model, 'allow', kind);
172
+ if (kind === 'update' && allows.length === 0) {
173
+ // no allow rule for 'update', policy is constant based on if there's
174
+ // post-update counterpart
175
+ if (this.getPolicyExpressions(model, 'allow', 'postUpdate').length === 0) {
176
+ result[kind] = false;
177
+ continue;
178
+ } else {
179
+ result[kind] = true;
180
+ continue;
181
+ }
182
+ }
183
+ if (kind === 'postUpdate' && allows.length === 0 && denies.length === 0) {
184
+ // no rule 'postUpdate', always allow
185
+ result[kind] = true;
186
+ continue;
187
+ }
188
+ const func = this.generateQueryGuardFunction(sourceFile, model, kind, allows, denies);
189
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
190
+ result[kind] = func.getName();
191
+ if (kind === 'postUpdate') {
192
+ const preValueSelect = this.generatePreValueSelect(model, allows, denies);
193
+ if (preValueSelect) {
194
+ result['preValueSelect'] = preValueSelect;
195
+ }
196
+ }
197
+ }
198
+ return result;
199
+ }
200
+
201
+ // generates an object that can be used as the 'select' argument when fetching pre-update
202
+ // entity value
203
+ generatePreValueSelect(model, allows, denies) {
204
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
205
+ const result = {};
206
+ const addPath = path => {
207
+ let curr = result;
208
+ path.forEach((seg, i) => {
209
+ if (i === path.length - 1) {
210
+ curr[seg] = true;
211
+ } else {
212
+ if (!curr[seg]) {
213
+ curr[seg] = {
214
+ select: {}
215
+ };
216
+ }
217
+ curr = curr[seg].select;
218
+ }
219
+ });
220
+ };
221
+ const visit = node => {
222
+ if ((0, _ast.isReferenceExpr)(node)) {
223
+ const target = (0, _sdk.resolved)(node.target);
224
+ if ((0, _ast.isDataModelField)(target)) {
225
+ // a field selection, it's a terminal
226
+ return [target.name];
227
+ }
228
+ } else if ((0, _ast.isMemberAccessExpr)(node)) {
229
+ if ((0, _utils2.isFutureExpr)(node.operand)) {
230
+ // future().field is not subject to pre-update select
231
+ return undefined;
232
+ }
233
+
234
+ // build a selection path inside-out for chained member access
235
+ const inner = visit(node.operand);
236
+ if (inner) {
237
+ return [...inner, node.member.$refText];
238
+ }
239
+ }
240
+ return undefined;
241
+ };
242
+ for (const rule of [...allows, ...denies]) {
243
+ for (const expr of (0, _langium.streamAllContents)(rule).filter(node => (0, _ast.isExpression)(node))) {
244
+ // only care about member access and reference expressions
245
+ if (!(0, _ast.isMemberAccessExpr)(expr) && !(0, _ast.isReferenceExpr)(expr)) {
246
+ continue;
247
+ }
248
+ if (expr.$container.$type === _ast.MemberAccessExpr) {
249
+ // only visit top-level member access
250
+ continue;
251
+ }
252
+ const path = visit(expr);
253
+ if (path) {
254
+ var _expr$$resolvedType;
255
+ if ((0, _ast.isDataModel)((_expr$$resolvedType = expr.$resolvedType) === null || _expr$$resolvedType === void 0 ? void 0 : _expr$$resolvedType.decl)) {
256
+ // member selection ended at a data model field, include its 'id'
257
+ path.push('id');
258
+ }
259
+ addPath(path);
260
+ }
261
+ }
262
+ }
263
+ return Object.keys(result).length === 0 ? null : result;
264
+ }
265
+ generateQueryGuardFunction(sourceFile, model, kind, allows, denies) {
266
+ const func = sourceFile.addFunction({
267
+ name: model.name + '_' + kind,
268
+ returnType: 'any',
269
+ parameters: [{
270
+ name: 'context',
271
+ type: 'QueryContext'
272
+ }]
273
+ }).addBody();
274
+
275
+ // check if any allow or deny rule contains 'auth()' invocation
276
+ let hasAuthRef = false;
277
+ for (const node of [...denies, ...allows]) {
278
+ for (const child of (0, _langium.streamAllContents)(node)) {
279
+ if ((0, _ast.isInvocationExpr)(child) && (0, _sdk.resolved)(child.function).name === 'auth') {
280
+ hasAuthRef = true;
281
+ break;
282
+ }
283
+ }
284
+ if (hasAuthRef) {
285
+ break;
286
+ }
287
+ }
288
+ if (hasAuthRef) {
289
+ const userModel = model.$container.declarations.find(decl => (0, _ast.isDataModel)(decl) && decl.name === 'User');
290
+ if (!userModel) {
291
+ throw new _sdk.PluginError('User model not found');
292
+ }
293
+ const userIdField = (0, _astUtils.getIdField)(userModel);
294
+ if (!userIdField) {
295
+ throw new _sdk.PluginError('User model does not have an id field');
296
+ }
297
+ func.addStatements(
298
+ // make sure user id is always available
299
+ `const user = context.user?.${userIdField.name} ? context.user : { ...context.user, ${userIdField.name}: '${UNKNOWN_USER_ID}' };`);
300
+ }
301
+
302
+ // r = <guard object>;
303
+ func.addStatements(writer => {
304
+ writer.write('return ');
305
+ const exprWriter = new _expressionWriter.ExpressionWriter(writer, kind === 'postUpdate');
306
+ const writeDenies = () => {
307
+ writer.conditionalWrite(denies.length > 1, '{ AND: [');
308
+ denies.forEach((expr, i) => {
309
+ writer.inlineBlock(() => {
310
+ writer.write('NOT: ');
311
+ exprWriter.write(expr);
312
+ });
313
+ writer.conditionalWrite(i !== denies.length - 1, ',');
314
+ });
315
+ writer.conditionalWrite(denies.length > 1, ']}');
316
+ };
317
+ const writeAllows = () => {
318
+ writer.conditionalWrite(allows.length > 1, '{ OR: [');
319
+ allows.forEach((expr, i) => {
320
+ exprWriter.write(expr);
321
+ writer.conditionalWrite(i !== allows.length - 1, ',');
322
+ });
323
+ writer.conditionalWrite(allows.length > 1, ']}');
324
+ };
325
+ if (allows.length > 0 && denies.length > 0) {
326
+ writer.write('{ AND: [');
327
+ writeDenies();
328
+ writer.write(',');
329
+ writeAllows();
330
+ writer.write(']}');
331
+ } else if (denies.length > 0) {
332
+ writeDenies();
333
+ } else if (allows.length > 0) {
334
+ writeAllows();
335
+ } else {
336
+ // disallow any operation
337
+ writer.write(`{ ${_sdk.GUARD_FIELD_NAME}: false }`);
338
+ }
339
+ writer.write(';');
340
+ });
341
+ return func;
342
+ }
343
+ }
344
+ exports.default = PolicyGenerator;
345
+ //# sourceMappingURL=policy-guard-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-guard-generator.js","names":["UNKNOWN_USER_ID","PolicyGenerator","generate","model","options","output","getDefaultOutputFolder","console","error","name","project","Project","sf","createSourceFile","path","join","undefined","overwrite","addImportDeclaration","namedImports","moduleSpecifier","RUNTIME_PACKAGE","isTypeOnly","e","declarations","filter","d","isEnum","models","isDataModel","policyMap","generateQueryGuardForModel","zodGenerator","ZodSchemaGenerator","addVariableStatement","declarationKind","VariableDeclarationKind","Const","initializer","writer","block","write","inlineBlock","map","Object","entries","camelCase","op","func","JSON","stringify","writeLine","addStatements","formatText","save","emit","getPolicyExpressions","kind","operation","attrs","attributes","attr","decl","ref","checkOperation","result","opsValue","getLiteral","args","value","ops","split","s","trim","includes","processUpdatePolicies","expressions","postUpdate","expr","visitPolicyExpression","isBinaryExpr","operator","left","right","isUnaryExpr","operand","hasFutureReference","node","streamAllContents","isInvocationExpr","function","isFromStdlib","sourceFile","policies","analyzePolicies","ALL_OPERATION_KINDS","denies","allows","length","generateQueryGuardFunction","getName","preValueSelect","generatePreValueSelect","addPath","curr","forEach","seg","i","select","visit","isReferenceExpr","target","resolved","isDataModelField","isMemberAccessExpr","isFutureExpr","inner","member","$refText","rule","isExpression","$container","$type","MemberAccessExpr","$resolvedType","push","keys","addFunction","returnType","parameters","type","addBody","hasAuthRef","child","userModel","find","PluginError","userIdField","getIdField","exprWriter","ExpressionWriter","writeDenies","conditionalWrite","writeAllows","GUARD_FIELD_NAME"],"sources":["../../../src/plugins/access-policy/policy-guard-generator.ts"],"sourcesContent":["import {\n DataModel,\n Expression,\n MemberAccessExpr,\n Model,\n isBinaryExpr,\n isDataModel,\n isDataModelField,\n isEnum,\n isExpression,\n isInvocationExpr,\n isMemberAccessExpr,\n isReferenceExpr,\n isUnaryExpr,\n} from '@zenstackhq/language/ast';\nimport { PolicyKind, PolicyOperationKind } from '@zenstackhq/runtime';\nimport { GUARD_FIELD_NAME, PluginError, PluginOptions, getLiteral, resolved } from '@zenstackhq/sdk';\nimport { camelCase } from 'change-case';\nimport { streamAllContents } from 'langium';\nimport path from 'path';\nimport { FunctionDeclaration, Project, SourceFile, VariableDeclarationKind } from 'ts-morph';\nimport { name } from '.';\nimport { isFromStdlib } from '../../language-server/utils';\nimport { analyzePolicies, getIdField } from '../../utils/ast-utils';\nimport { ALL_OPERATION_KINDS, RUNTIME_PACKAGE, getDefaultOutputFolder } from '../plugin-utils';\nimport { ExpressionWriter } from './expression-writer';\nimport { isFutureExpr } from './utils';\nimport { ZodSchemaGenerator } from './zod-schema-generator';\n\nconst UNKNOWN_USER_ID = 'zenstack_unknown_user';\n\n/**\n * Generates source file that contains Prisma query guard objects used for injecting database queries\n */\nexport default class PolicyGenerator {\n async generate(model: Model, options: PluginOptions) {\n const output = options.output ? (options.output as string) : getDefaultOutputFolder();\n if (!output) {\n console.error(`Unable to determine output path, not running plugin ${name}`);\n return;\n }\n\n const project = new Project();\n const sf = project.createSourceFile(path.join(output, 'policy.ts'), undefined, { overwrite: true });\n\n sf.addImportDeclaration({\n namedImports: [{ name: 'QueryContext' }],\n moduleSpecifier: `${RUNTIME_PACKAGE}`,\n isTypeOnly: true,\n });\n\n sf.addImportDeclaration({\n namedImports: [{ name: 'z' }],\n moduleSpecifier: 'zod',\n });\n\n // import enums\n for (const e of model.declarations.filter((d) => isEnum(d))) {\n sf.addImportDeclaration({\n namedImports: [{ name: e.name }],\n moduleSpecifier: '@prisma/client',\n });\n }\n\n const models = model.declarations.filter((d) => isDataModel(d)) as DataModel[];\n\n const policyMap: Record<string, Record<string, string | boolean | object>> = {};\n for (const model of models) {\n policyMap[model.name] = await this.generateQueryGuardForModel(model, sf);\n }\n\n const zodGenerator = new ZodSchemaGenerator();\n\n sf.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'policy',\n initializer: (writer) => {\n writer.block(() => {\n writer.write('guard:');\n writer.inlineBlock(() => {\n for (const [model, map] of Object.entries(policyMap)) {\n writer.write(`${camelCase(model)}:`);\n writer.inlineBlock(() => {\n for (const [op, func] of Object.entries(map)) {\n if (typeof func === 'object') {\n writer.write(`${op}: ${JSON.stringify(func)},`);\n } else {\n writer.write(`${op}: ${func},`);\n }\n }\n });\n writer.write(',');\n }\n });\n\n writer.writeLine(',');\n\n writer.write('schema:');\n zodGenerator.generate(writer, models);\n });\n },\n },\n ],\n });\n\n sf.addStatements('export default policy');\n\n sf.formatText();\n await project.save();\n await project.emit();\n }\n\n private getPolicyExpressions(model: DataModel, kind: PolicyKind, operation: PolicyOperationKind) {\n const attrs = model.attributes.filter((attr) => attr.decl.ref?.name === `@@${kind}`);\n\n const checkOperation = operation === 'postUpdate' ? 'update' : operation;\n\n let result = attrs\n .filter((attr) => {\n const opsValue = getLiteral<string>(attr.args[0].value);\n if (!opsValue) {\n return false;\n }\n const ops = opsValue.split(',').map((s) => s.trim());\n return ops.includes(checkOperation) || ops.includes('all');\n })\n .map((attr) => attr.args[1].value);\n\n if (operation === 'update') {\n result = this.processUpdatePolicies(result, false);\n } else if (operation === 'postUpdate') {\n result = this.processUpdatePolicies(result, true);\n }\n\n return result;\n }\n\n private processUpdatePolicies(expressions: Expression[], postUpdate: boolean) {\n return expressions\n .map((expr) => this.visitPolicyExpression(expr, postUpdate))\n .filter((e): e is Expression => !!e);\n }\n\n private visitPolicyExpression(expr: Expression, postUpdate: boolean): Expression | undefined {\n if (isBinaryExpr(expr) && (expr.operator === '&&' || expr.operator === '||')) {\n const left = this.visitPolicyExpression(expr.left, postUpdate);\n const right = this.visitPolicyExpression(expr.right, postUpdate);\n if (!left) return right;\n if (!right) return left;\n return { ...expr, left, right };\n }\n\n if (isUnaryExpr(expr) && expr.operator === '!') {\n const operand = this.visitPolicyExpression(expr.operand, postUpdate);\n if (!operand) return undefined;\n return { ...expr, operand };\n }\n\n if (postUpdate && !this.hasFutureReference(expr)) {\n return undefined;\n } else if (!postUpdate && this.hasFutureReference(expr)) {\n return undefined;\n }\n\n return expr;\n }\n\n private hasFutureReference(expr: Expression) {\n for (const node of streamAllContents(expr)) {\n if (isInvocationExpr(node) && node.function.ref?.name === 'future' && isFromStdlib(node.function.ref)) {\n return true;\n }\n }\n return false;\n }\n\n private async generateQueryGuardForModel(model: DataModel, sourceFile: SourceFile) {\n const result: Record<string, string | boolean | object> = {};\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const policies: any = analyzePolicies(model);\n\n for (const kind of ALL_OPERATION_KINDS) {\n if (policies[kind] === true || policies[kind] === false) {\n result[kind] = policies[kind];\n continue;\n }\n\n const denies = this.getPolicyExpressions(model, 'deny', kind);\n const allows = this.getPolicyExpressions(model, 'allow', kind);\n\n if (kind === 'update' && allows.length === 0) {\n // no allow rule for 'update', policy is constant based on if there's\n // post-update counterpart\n if (this.getPolicyExpressions(model, 'allow', 'postUpdate').length === 0) {\n result[kind] = false;\n continue;\n } else {\n result[kind] = true;\n continue;\n }\n }\n\n if (kind === 'postUpdate' && allows.length === 0 && denies.length === 0) {\n // no rule 'postUpdate', always allow\n result[kind] = true;\n continue;\n }\n\n const func = this.generateQueryGuardFunction(sourceFile, model, kind, allows, denies);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n result[kind] = func.getName()!;\n\n if (kind === 'postUpdate') {\n const preValueSelect = this.generatePreValueSelect(model, allows, denies);\n if (preValueSelect) {\n result['preValueSelect'] = preValueSelect;\n }\n }\n }\n return result;\n }\n\n // generates an object that can be used as the 'select' argument when fetching pre-update\n // entity value\n private generatePreValueSelect(model: DataModel, allows: Expression[], denies: Expression[]): object {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = {};\n const addPath = (path: string[]) => {\n let curr = result;\n path.forEach((seg, i) => {\n if (i === path.length - 1) {\n curr[seg] = true;\n } else {\n if (!curr[seg]) {\n curr[seg] = { select: {} };\n }\n curr = curr[seg].select;\n }\n });\n };\n\n const visit = (node: Expression): string[] | undefined => {\n if (isReferenceExpr(node)) {\n const target = resolved(node.target);\n if (isDataModelField(target)) {\n // a field selection, it's a terminal\n return [target.name];\n }\n } else if (isMemberAccessExpr(node)) {\n if (isFutureExpr(node.operand)) {\n // future().field is not subject to pre-update select\n return undefined;\n }\n\n // build a selection path inside-out for chained member access\n const inner = visit(node.operand);\n if (inner) {\n return [...inner, node.member.$refText];\n }\n }\n return undefined;\n };\n\n for (const rule of [...allows, ...denies]) {\n for (const expr of streamAllContents(rule).filter((node): node is Expression => isExpression(node))) {\n // only care about member access and reference expressions\n if (!isMemberAccessExpr(expr) && !isReferenceExpr(expr)) {\n continue;\n }\n\n if (expr.$container.$type === MemberAccessExpr) {\n // only visit top-level member access\n continue;\n }\n\n const path = visit(expr);\n if (path) {\n if (isDataModel(expr.$resolvedType?.decl)) {\n // member selection ended at a data model field, include its 'id'\n path.push('id');\n }\n addPath(path);\n }\n }\n }\n\n return Object.keys(result).length === 0 ? null : result;\n }\n\n private generateQueryGuardFunction(\n sourceFile: SourceFile,\n model: DataModel,\n kind: PolicyOperationKind,\n allows: Expression[],\n denies: Expression[]\n ): FunctionDeclaration {\n const func = sourceFile\n .addFunction({\n name: model.name + '_' + kind,\n returnType: 'any',\n parameters: [\n {\n name: 'context',\n type: 'QueryContext',\n },\n ],\n })\n .addBody();\n\n // check if any allow or deny rule contains 'auth()' invocation\n let hasAuthRef = false;\n for (const node of [...denies, ...allows]) {\n for (const child of streamAllContents(node)) {\n if (isInvocationExpr(child) && resolved(child.function).name === 'auth') {\n hasAuthRef = true;\n break;\n }\n }\n if (hasAuthRef) {\n break;\n }\n }\n\n if (hasAuthRef) {\n const userModel = model.$container.declarations.find(\n (decl): decl is DataModel => isDataModel(decl) && decl.name === 'User'\n );\n if (!userModel) {\n throw new PluginError('User model not found');\n }\n const userIdField = getIdField(userModel);\n if (!userIdField) {\n throw new PluginError('User model does not have an id field');\n }\n func.addStatements(\n // make sure user id is always available\n `const user = context.user?.${userIdField.name} ? context.user : { ...context.user, ${userIdField.name}: '${UNKNOWN_USER_ID}' };`\n );\n }\n\n // r = <guard object>;\n func.addStatements((writer) => {\n writer.write('return ');\n const exprWriter = new ExpressionWriter(writer, kind === 'postUpdate');\n const writeDenies = () => {\n writer.conditionalWrite(denies.length > 1, '{ AND: [');\n denies.forEach((expr, i) => {\n writer.inlineBlock(() => {\n writer.write('NOT: ');\n exprWriter.write(expr);\n });\n writer.conditionalWrite(i !== denies.length - 1, ',');\n });\n writer.conditionalWrite(denies.length > 1, ']}');\n };\n\n const writeAllows = () => {\n writer.conditionalWrite(allows.length > 1, '{ OR: [');\n allows.forEach((expr, i) => {\n exprWriter.write(expr);\n writer.conditionalWrite(i !== allows.length - 1, ',');\n });\n writer.conditionalWrite(allows.length > 1, ']}');\n };\n\n if (allows.length > 0 && denies.length > 0) {\n writer.write('{ AND: [');\n writeDenies();\n writer.write(',');\n writeAllows();\n writer.write(']}');\n } else if (denies.length > 0) {\n writeDenies();\n } else if (allows.length > 0) {\n writeAllows();\n } else {\n // disallow any operation\n writer.write(`{ ${GUARD_FIELD_NAME}: false }`);\n }\n writer.write(';');\n });\n return func;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Expression } from '@zenstackhq/language/ast';
2
+ /**
3
+ * Transforms ZModel expression to plain TypeScript expression.
4
+ */
5
+ export default class TypeScriptExpressionTransformer {
6
+ private readonly isPostGuard;
7
+ /**
8
+ * Constructs a new TypeScriptExpressionTransformer.
9
+ *
10
+ * @param isPostGuard indicates if we're writing for post-update conditions
11
+ */
12
+ constructor(isPostGuard?: boolean);
13
+ /**
14
+ *
15
+ * @param expr
16
+ * @returns
17
+ */
18
+ transform(expr: Expression): string;
19
+ private this;
20
+ private memberAccess;
21
+ private invocation;
22
+ private reference;
23
+ private null;
24
+ private array;
25
+ private literal;
26
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _ast = require("@zenstackhq/language/ast");
8
+ var _sdk = require("@zenstackhq/sdk");
9
+ var _utils = require("./utils");
10
+ /**
11
+ * Transforms ZModel expression to plain TypeScript expression.
12
+ */
13
+ class TypeScriptExpressionTransformer {
14
+ /**
15
+ * Constructs a new TypeScriptExpressionTransformer.
16
+ *
17
+ * @param isPostGuard indicates if we're writing for post-update conditions
18
+ */
19
+ constructor(isPostGuard = false) {
20
+ this.isPostGuard = isPostGuard;
21
+ }
22
+
23
+ /**
24
+ *
25
+ * @param expr
26
+ * @returns
27
+ */
28
+ transform(expr) {
29
+ switch (expr.$type) {
30
+ case _ast.LiteralExpr:
31
+ return this.literal(expr);
32
+ case _ast.ArrayExpr:
33
+ return this.array(expr);
34
+ case _ast.NullExpr:
35
+ return this.null();
36
+ case _ast.ThisExpr:
37
+ return this.this(expr);
38
+ case _ast.ReferenceExpr:
39
+ return this.reference(expr);
40
+ case _ast.InvocationExpr:
41
+ return this.invocation(expr);
42
+ case _ast.MemberAccessExpr:
43
+ return this.memberAccess(expr);
44
+ default:
45
+ throw new _sdk.PluginError(`Unsupported expression type: ${expr.$type}`);
46
+ }
47
+ }
48
+
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
+ this(expr) {
51
+ // "this" is mapped to id comparison
52
+ return 'id';
53
+ }
54
+ memberAccess(expr) {
55
+ if (!expr.member.ref) {
56
+ throw new _sdk.PluginError(`Unresolved MemberAccessExpr`);
57
+ }
58
+ if ((0, _ast.isThisExpr)(expr.operand)) {
59
+ return expr.member.ref.name;
60
+ } else if ((0, _utils.isFutureExpr)(expr.operand)) {
61
+ if (!this.isPostGuard) {
62
+ throw new _sdk.PluginError(`future() is only supported in postUpdate rules`);
63
+ }
64
+ return expr.member.ref.name;
65
+ } else {
66
+ return `${this.transform(expr.operand)}?.${expr.member.ref.name}`;
67
+ }
68
+ }
69
+ invocation(expr) {
70
+ var _expr$function$ref;
71
+ if (((_expr$function$ref = expr.function.ref) === null || _expr$function$ref === void 0 ? void 0 : _expr$function$ref.name) === 'auth') {
72
+ return 'user';
73
+ } else {
74
+ var _expr$function$ref2;
75
+ throw new _sdk.PluginError(`Function invocation is not supported: ${(_expr$function$ref2 = expr.function.ref) === null || _expr$function$ref2 === void 0 ? void 0 : _expr$function$ref2.name}`);
76
+ }
77
+ }
78
+ reference(expr) {
79
+ if (!expr.target.ref) {
80
+ throw new _sdk.PluginError(`Unresolved ReferenceExpr`);
81
+ }
82
+ if ((0, _ast.isEnumField)(expr.target.ref)) {
83
+ return `${expr.target.ref.$container.name}.${expr.target.ref.name}`;
84
+ } else {
85
+ if (this.isPostGuard) {
86
+ // if we're processing post-update, any direct field access should be
87
+ // treated as access to context.preValue, which is entity's value before
88
+ // the update
89
+ return `context.preValue?.${expr.target.ref.name}`;
90
+ } else {
91
+ return expr.target.ref.name;
92
+ }
93
+ }
94
+ }
95
+ null() {
96
+ return 'null';
97
+ }
98
+ array(expr) {
99
+ return `[${expr.items.map(item => this.transform(item)).join(', ')}]`;
100
+ }
101
+ literal(expr) {
102
+ if (typeof expr.value === 'string') {
103
+ return `'${expr.value}'`;
104
+ } else {
105
+ return expr.value.toString();
106
+ }
107
+ }
108
+ }
109
+ exports.default = TypeScriptExpressionTransformer;
110
+ //# sourceMappingURL=typescript-expression-transformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-expression-transformer.js","names":["TypeScriptExpressionTransformer","constructor","isPostGuard","transform","expr","$type","LiteralExpr","literal","ArrayExpr","array","NullExpr","null","ThisExpr","this","ReferenceExpr","reference","InvocationExpr","invocation","MemberAccessExpr","memberAccess","PluginError","member","ref","isThisExpr","operand","name","isFutureExpr","function","target","isEnumField","$container","items","map","item","join","value","toString"],"sources":["../../../src/plugins/access-policy/typescript-expression-transformer.ts"],"sourcesContent":["import {\n ArrayExpr,\n Expression,\n InvocationExpr,\n LiteralExpr,\n MemberAccessExpr,\n NullExpr,\n ReferenceExpr,\n ThisExpr,\n isEnumField,\n isThisExpr,\n} from '@zenstackhq/language/ast';\nimport { PluginError } from '@zenstackhq/sdk';\nimport { isFutureExpr } from './utils';\n\n/**\n * Transforms ZModel expression to plain TypeScript expression.\n */\nexport default class TypeScriptExpressionTransformer {\n /**\n * Constructs a new TypeScriptExpressionTransformer.\n *\n * @param isPostGuard indicates if we're writing for post-update conditions\n */\n constructor(private readonly isPostGuard = false) {}\n\n /**\n *\n * @param expr\n * @returns\n */\n transform(expr: Expression): string {\n switch (expr.$type) {\n case LiteralExpr:\n return this.literal(expr as LiteralExpr);\n\n case ArrayExpr:\n return this.array(expr as ArrayExpr);\n\n case NullExpr:\n return this.null();\n\n case ThisExpr:\n return this.this(expr as ThisExpr);\n\n case ReferenceExpr:\n return this.reference(expr as ReferenceExpr);\n\n case InvocationExpr:\n return this.invocation(expr as InvocationExpr);\n\n case MemberAccessExpr:\n return this.memberAccess(expr as MemberAccessExpr);\n\n default:\n throw new PluginError(`Unsupported expression type: ${expr.$type}`);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n private this(expr: ThisExpr) {\n // \"this\" is mapped to id comparison\n return 'id';\n }\n\n private memberAccess(expr: MemberAccessExpr) {\n if (!expr.member.ref) {\n throw new PluginError(`Unresolved MemberAccessExpr`);\n }\n\n if (isThisExpr(expr.operand)) {\n return expr.member.ref.name;\n } else if (isFutureExpr(expr.operand)) {\n if (!this.isPostGuard) {\n throw new PluginError(`future() is only supported in postUpdate rules`);\n }\n return expr.member.ref.name;\n } else {\n return `${this.transform(expr.operand)}?.${expr.member.ref.name}`;\n }\n }\n\n private invocation(expr: InvocationExpr) {\n if (expr.function.ref?.name === 'auth') {\n return 'user';\n } else {\n throw new PluginError(`Function invocation is not supported: ${expr.function.ref?.name}`);\n }\n }\n\n private reference(expr: ReferenceExpr) {\n if (!expr.target.ref) {\n throw new PluginError(`Unresolved ReferenceExpr`);\n }\n\n if (isEnumField(expr.target.ref)) {\n return `${expr.target.ref.$container.name}.${expr.target.ref.name}`;\n } else {\n if (this.isPostGuard) {\n // if we're processing post-update, any direct field access should be\n // treated as access to context.preValue, which is entity's value before\n // the update\n return `context.preValue?.${expr.target.ref.name}`;\n } else {\n return expr.target.ref.name;\n }\n }\n }\n\n private null() {\n return 'null';\n }\n\n private array(expr: ArrayExpr) {\n return `[${expr.items.map((item) => this.transform(item)).join(', ')}]`;\n }\n\n private literal(expr: LiteralExpr) {\n if (typeof expr.value === 'string') {\n return `'${expr.value}'`;\n } else {\n return expr.value.toString();\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Expression } from '@zenstackhq/language/ast';
2
+ /**
3
+ * Returns if the given expression is a "future()" method call.
4
+ */
5
+ export declare function isFutureExpr(expr: Expression): boolean;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isFutureExpr = isFutureExpr;
7
+ var _ast = require("@zenstackhq/language/ast");
8
+ var _utils = require("../../language-server/utils");
9
+ /**
10
+ * Returns if the given expression is a "future()" method call.
11
+ */
12
+ function isFutureExpr(expr) {
13
+ var _expr$function$ref;
14
+ return !!((0, _ast.isInvocationExpr)(expr) && ((_expr$function$ref = expr.function.ref) === null || _expr$function$ref === void 0 ? void 0 : _expr$function$ref.name) === 'future' && (0, _utils.isFromStdlib)(expr.function.ref));
15
+ }
16
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","names":["isFutureExpr","expr","isInvocationExpr","function","ref","name","isFromStdlib"],"sources":["../../../src/plugins/access-policy/utils.ts"],"sourcesContent":["import { Expression, isInvocationExpr } from '@zenstackhq/language/ast';\nimport { isFromStdlib } from '../../language-server/utils';\n\n/**\n * Returns if the given expression is a \"future()\" method call.\n */\nexport function isFutureExpr(expr: Expression) {\n return !!(isInvocationExpr(expr) && expr.function.ref?.name === 'future' && isFromStdlib(expr.function.ref));\n}\n"],"mappings":";;;;;;AAAA;AACA;AAEA;AACA;AACA;AACO,SAASA,YAAY,CAACC,IAAgB,EAAE;EAAA;EAC3C,OAAO,CAAC,EAAE,IAAAC,qBAAgB,EAACD,IAAI,CAAC,IAAI,uBAAAA,IAAI,CAACE,QAAQ,CAACC,GAAG,uDAAjB,mBAAmBC,IAAI,MAAK,QAAQ,IAAI,IAAAC,mBAAY,EAACL,IAAI,CAACE,QAAQ,CAACC,GAAG,CAAC,CAAC;AAChH"}
@@ -0,0 +1,12 @@
1
+ import { DataModel } from '@zenstackhq/language/ast';
2
+ import { CodeBlockWriter } from 'ts-morph';
3
+ /**
4
+ * Writes Zod schema for data models.
5
+ */
6
+ export declare class ZodSchemaGenerator {
7
+ generate(writer: CodeBlockWriter, models: DataModel[]): void;
8
+ private hasValidationAttributes;
9
+ private makeFieldValidator;
10
+ private makeZodSchema;
11
+ private getAttrLiteralArg;
12
+ }