@zenstackhq/plugin-policy 3.0.0-beta.9
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/LICENSE +21 -0
- package/dist/index.cjs +1556 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +1531 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/functions.ts","../src/policy-handler.ts","../src/column-collector.ts","../src/expression-transformer.ts","../src/expression-evaluator.ts","../src/utils.ts","../src/plugin.ts"],"sourcesContent":["import { invariant } from '@zenstackhq/common-helpers';\nimport type { ZModelFunction, ZModelFunctionContext } from '@zenstackhq/runtime';\nimport { CRUD, QueryUtils } from '@zenstackhq/runtime';\nimport { ExpressionWrapper, ValueNode, type Expression, type ExpressionBuilder } from 'kysely';\nimport { PolicyHandler } from './policy-handler';\n\n/**\n * Relation checker implementation.\n */\nexport const check: ZModelFunction<any> = (\n eb: ExpressionBuilder<any, any>,\n args: Expression<any>[],\n { client, model, modelAlias, operation }: ZModelFunctionContext<any>,\n) => {\n invariant(args.length === 1 || args.length === 2, '\"check\" function requires 1 or 2 arguments');\n\n const arg1Node = args[0]!.toOperationNode();\n\n const arg2Node = args.length === 2 ? args[1]!.toOperationNode() : undefined;\n if (arg2Node) {\n invariant(\n ValueNode.is(arg2Node) && typeof arg2Node.value === 'string',\n '\"operation\" parameter must be a string literal when provided',\n );\n invariant(\n CRUD.includes(arg2Node.value as CRUD),\n '\"operation\" parameter must be one of \"create\", \"read\", \"update\", \"delete\"',\n );\n }\n\n // first argument must be a field reference\n const fieldName = QueryUtils.extractFieldName(arg1Node);\n invariant(fieldName, 'Failed to extract field name from the first argument of \"check\" function');\n const fieldDef = QueryUtils.requireField(client.$schema, model, fieldName);\n invariant(fieldDef.relation, `Field \"${fieldName}\" is not a relation field in model \"${model}\"`);\n invariant(!fieldDef.array, `Field \"${fieldName}\" is a to-many relation, which is not supported by \"check\"`);\n const relationModel = fieldDef.type;\n\n // build the join condition between the current model and the related model\n const joinConditions: Expression<any>[] = [];\n const fkInfo = QueryUtils.getRelationForeignKeyFieldPairs(client.$schema, model, fieldName);\n const idFields = QueryUtils.requireIdFields(client.$schema, model);\n\n // helper to build a base model select for delegate models\n const buildBaseSelect = (baseModel: string, field: string): Expression<any> => {\n return eb\n .selectFrom(baseModel)\n .select(field)\n .where(\n eb.and(\n idFields.map((idField) =>\n eb(eb.ref(`${fieldDef.originModel}.${idField}`), '=', eb.ref(`${modelAlias}.${idField}`)),\n ),\n ),\n );\n };\n\n if (fkInfo.ownedByModel) {\n // model owns the relation\n joinConditions.push(\n ...fkInfo.keyPairs.map(({ fk, pk }) => {\n let fkRef: Expression<any>;\n if (fieldDef.originModel && fieldDef.originModel !== model) {\n // relation is actually defined in a delegate base model, select from there\n fkRef = buildBaseSelect(fieldDef.originModel, fk);\n } else {\n fkRef = eb.ref(`${modelAlias}.${fk}`);\n }\n return eb(fkRef, '=', eb.ref(`${relationModel}.${pk}`));\n }),\n );\n } else {\n // related model owns the relation\n joinConditions.push(\n ...fkInfo.keyPairs.map(({ fk, pk }) => {\n let pkRef: Expression<any>;\n if (fieldDef.originModel && fieldDef.originModel !== model) {\n // relation is actually defined in a delegate base model, select from there\n pkRef = buildBaseSelect(fieldDef.originModel, pk);\n } else {\n pkRef = eb.ref(`${modelAlias}.${pk}`);\n }\n return eb(pkRef, '=', eb.ref(`${relationModel}.${fk}`));\n }),\n );\n }\n\n const joinCondition = joinConditions.length === 1 ? joinConditions[0]! : eb.and(joinConditions);\n\n // policy condition of the related model\n const policyHandler = new PolicyHandler(client);\n const op = arg2Node ? (arg2Node.value as CRUD) : operation;\n const policyCondition = policyHandler.buildPolicyFilter(relationModel, undefined, op);\n\n // build the final nested select that evaluates the policy condition\n const result = eb\n .selectFrom(relationModel)\n .where(joinCondition)\n .select(new ExpressionWrapper(policyCondition).as('$condition'));\n\n return result;\n};\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { BaseCrudDialect, ClientContract, ProceedKyselyQueryFunction } from '@zenstackhq/runtime';\nimport {\n getCrudDialect,\n InternalError,\n QueryError,\n QueryUtils,\n RejectedByPolicyError,\n RejectedByPolicyReason,\n type CRUD_EXT,\n} from '@zenstackhq/runtime';\nimport {\n ExpressionUtils,\n type BuiltinType,\n type Expression,\n type GetModels,\n type MemberExpression,\n type SchemaDef,\n} from '@zenstackhq/runtime/schema';\nimport { ExpressionVisitor } from '@zenstackhq/sdk';\nimport {\n AliasNode,\n BinaryOperationNode,\n ColumnNode,\n DeleteQueryNode,\n expressionBuilder,\n ExpressionWrapper,\n FromNode,\n FunctionNode,\n IdentifierNode,\n InsertQueryNode,\n JoinNode,\n OperationNodeTransformer,\n OperatorNode,\n ParensNode,\n PrimitiveValueListNode,\n RawNode,\n ReferenceNode,\n ReturningNode,\n SelectAllNode,\n SelectionNode,\n SelectQueryNode,\n sql,\n TableNode,\n UpdateQueryNode,\n ValueListNode,\n ValueNode,\n ValuesNode,\n WhereNode,\n type OperationNode,\n type QueryResult,\n type RootOperationNode,\n} from 'kysely';\nimport { match } from 'ts-pattern';\nimport { ColumnCollector } from './column-collector';\nimport { ExpressionTransformer } from './expression-transformer';\nimport type { Policy, PolicyOperation } from './types';\nimport { buildIsFalse, conjunction, disjunction, falseNode, getTableName, isBeforeInvocation, trueNode } from './utils';\n\nexport type CrudQueryNode = SelectQueryNode | InsertQueryNode | UpdateQueryNode | DeleteQueryNode;\n\nexport type MutationQueryNode = InsertQueryNode | UpdateQueryNode | DeleteQueryNode;\n\nexport class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransformer {\n private readonly dialect: BaseCrudDialect<Schema>;\n\n constructor(private readonly client: ClientContract<Schema>) {\n super();\n this.dialect = getCrudDialect(this.client.$schema, this.client.$options);\n }\n\n get kysely() {\n return this.client.$qb;\n }\n\n async handle(node: RootOperationNode, proceed: ProceedKyselyQueryFunction) {\n if (!this.isCrudQueryNode(node)) {\n // non-CRUD queries are not allowed\n throw new RejectedByPolicyError(\n undefined,\n RejectedByPolicyReason.OTHER,\n 'non-CRUD queries are not allowed',\n );\n }\n\n if (!this.isMutationQueryNode(node)) {\n // transform and proceed with read directly\n return proceed(this.transformNode(node));\n }\n\n const { mutationModel } = this.getMutationModel(node);\n\n // --- Pre mutation work ---\n\n if (InsertQueryNode.is(node)) {\n // pre-create policy evaluation happens before execution of the query\n const isManyToManyJoinTable = this.isManyToManyJoinTable(mutationModel);\n let needCheckPreCreate = true;\n\n // many-to-many join table is not a model so can't have policies on it\n if (!isManyToManyJoinTable) {\n // check constant policies\n const constCondition = this.tryGetConstantPolicy(mutationModel, 'create');\n if (constCondition === true) {\n needCheckPreCreate = false;\n } else if (constCondition === false) {\n throw new RejectedByPolicyError(mutationModel);\n }\n }\n\n if (needCheckPreCreate) {\n await this.enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed);\n }\n }\n\n const hasPostUpdatePolicies = UpdateQueryNode.is(node) && this.hasPostUpdatePolicies(mutationModel);\n\n let beforeUpdateInfo: Awaited<ReturnType<typeof this.loadBeforeUpdateEntities>> | undefined;\n if (hasPostUpdatePolicies) {\n beforeUpdateInfo = await this.loadBeforeUpdateEntities(mutationModel, node.where, proceed);\n }\n\n // proceed with query\n\n const result = await proceed(this.transformNode(node));\n\n // --- Post mutation work ---\n\n if (hasPostUpdatePolicies && result.rows.length > 0) {\n // verify if before-update rows and post-update rows still id-match\n if (beforeUpdateInfo) {\n invariant(beforeUpdateInfo.rows.length === result.rows.length);\n const idFields = QueryUtils.requireIdFields(this.client.$schema, mutationModel);\n for (const postRow of result.rows) {\n const beforeRow = beforeUpdateInfo.rows.find((r) => idFields.every((f) => r[f] === postRow[f]));\n if (!beforeRow) {\n throw new QueryError(\n 'Before-update and after-update rows do not match by id. If you have post-update policies on a model, updating id fields is not supported.',\n );\n }\n }\n }\n\n // entities updated filter\n const idConditions = this.buildIdConditions(mutationModel, result.rows);\n\n // post-update policy filter\n const postUpdateFilter = this.buildPolicyFilter(mutationModel, undefined, 'post-update');\n\n // read the post-update row with filter applied\n\n const eb = expressionBuilder<any, any>();\n\n // create a `SELECT column1 as field1, column2 as field2, ... FROM (VALUES (...))` table for before-update rows\n const beforeUpdateTable: SelectQueryNode | undefined = beforeUpdateInfo\n ? {\n kind: 'SelectQueryNode',\n from: FromNode.create([\n ParensNode.create(\n ValuesNode.create(\n beforeUpdateInfo!.rows.map((r) =>\n PrimitiveValueListNode.create(beforeUpdateInfo!.fields.map((f) => r[f])),\n ),\n ),\n ),\n ]),\n selections: beforeUpdateInfo.fields.map((name, index) => {\n const def = QueryUtils.requireField(this.client.$schema, mutationModel, name);\n const castedColumnRef =\n sql`CAST(${eb.ref(`column${index + 1}`)} as ${sql.raw(this.dialect.getFieldSqlType(def))})`.as(\n name,\n );\n return SelectionNode.create(castedColumnRef.toOperationNode());\n }),\n }\n : undefined;\n\n const postUpdateQuery = eb\n .selectFrom(mutationModel)\n .select(() => [eb(eb.fn('COUNT', [eb.lit(1)]), '=', result.rows.length).as('$condition')])\n .where(() => new ExpressionWrapper(conjunction(this.dialect, [idConditions, postUpdateFilter])))\n .$if(!!beforeUpdateInfo, (qb) =>\n qb.leftJoin(\n () => new ExpressionWrapper(beforeUpdateTable!).as('$before'),\n (join) => {\n const idFields = QueryUtils.requireIdFields(this.client.$schema, mutationModel);\n return idFields.reduce(\n (acc, f) => acc.onRef(`${mutationModel}.${f}`, '=', `$before.${f}`),\n join,\n );\n },\n ),\n );\n\n const postUpdateResult = await proceed(postUpdateQuery.toOperationNode());\n if (!postUpdateResult.rows[0]?.$condition) {\n throw new RejectedByPolicyError(\n mutationModel,\n RejectedByPolicyReason.NO_ACCESS,\n 'some or all updated rows failed to pass post-update policy check',\n );\n }\n }\n\n // --- Read back ---\n\n if (!node.returning || this.onlyReturningId(node)) {\n // no need to check read back\n return this.postProcessMutationResult(result, node);\n } else {\n const readBackResult = await this.processReadBack(node, result, proceed);\n if (readBackResult.rows.length !== result.rows.length) {\n throw new RejectedByPolicyError(\n mutationModel,\n RejectedByPolicyReason.CANNOT_READ_BACK,\n 'result is not allowed to be read back',\n );\n }\n return readBackResult;\n }\n }\n\n // correction to kysely mutation result may be needed because we might have added\n // returning clause to the query and caused changes to the result shape\n private postProcessMutationResult(result: QueryResult<any>, node: MutationQueryNode) {\n if (node.returning) {\n return result;\n } else {\n return {\n ...result,\n rows: [],\n numAffectedRows: result.numAffectedRows ?? BigInt(result.rows.length),\n };\n }\n }\n\n hasPostUpdatePolicies(model: GetModels<Schema>) {\n const policies = this.getModelPolicies(model, 'post-update');\n return policies.length > 0;\n }\n\n private async loadBeforeUpdateEntities(\n model: GetModels<Schema>,\n where: WhereNode | undefined,\n proceed: ProceedKyselyQueryFunction,\n ) {\n const beforeUpdateAccessFields = this.getFieldsAccessForBeforeUpdatePolicies(model);\n if (!beforeUpdateAccessFields || beforeUpdateAccessFields.length === 0) {\n return undefined;\n }\n\n // combine update's where with policy filter\n const policyFilter = this.buildPolicyFilter(model, model, 'update');\n const combinedFilter = where ? conjunction(this.dialect, [where.where, policyFilter]) : policyFilter;\n\n const query: SelectQueryNode = {\n kind: 'SelectQueryNode',\n from: FromNode.create([TableNode.create(model)]),\n where: WhereNode.create(combinedFilter),\n selections: [...beforeUpdateAccessFields.map((f) => SelectionNode.create(ColumnNode.create(f)))],\n };\n const result = await proceed(query);\n return { fields: beforeUpdateAccessFields, rows: result.rows };\n }\n\n private getFieldsAccessForBeforeUpdatePolicies(model: GetModels<Schema>) {\n const policies = this.getModelPolicies(model, 'post-update');\n if (policies.length === 0) {\n return undefined;\n }\n\n const fields = new Set<string>();\n const fieldCollector = new (class extends ExpressionVisitor {\n protected override visitMember(e: MemberExpression): void {\n if (isBeforeInvocation(e.receiver)) {\n invariant(e.members.length === 1, 'before() can only be followed by a scalar field access');\n fields.add(e.members[0]!);\n }\n super.visitMember(e);\n }\n })();\n\n for (const policy of policies) {\n fieldCollector.visit(policy.condition);\n }\n\n if (fields.size === 0) {\n return undefined;\n }\n\n // make sure id fields are included\n QueryUtils.requireIdFields(this.client.$schema, model).forEach((f) => fields.add(f));\n\n return Array.from(fields).sort();\n }\n\n // #region overrides\n\n protected override transformSelectQuery(node: SelectQueryNode) {\n if (!node.from) {\n return super.transformSelectQuery(node);\n }\n\n let whereNode = this.transformNode(node.where);\n\n // get combined policy filter for all froms, and merge into where clause\n const policyFilter = this.createPolicyFilterForFrom(node.from);\n if (policyFilter) {\n whereNode = WhereNode.create(\n whereNode?.where ? conjunction(this.dialect, [whereNode.where, policyFilter]) : policyFilter,\n );\n }\n\n const baseResult = super.transformSelectQuery({\n ...node,\n where: undefined,\n });\n\n return {\n ...baseResult,\n where: whereNode,\n };\n }\n\n protected override transformJoin(node: JoinNode) {\n const table = this.extractTableName(node.table);\n if (!table) {\n // unable to extract table name, can be a subquery, which will be handled when nested transformation happens\n return super.transformJoin(node);\n }\n\n // build a nested query with policy filter applied\n const filter = this.buildPolicyFilter(table.model, table.alias, 'read');\n\n const nestedSelect: SelectQueryNode = {\n kind: 'SelectQueryNode',\n from: FromNode.create([node.table]),\n selections: [SelectionNode.createSelectAll()],\n where: WhereNode.create(filter),\n };\n return {\n ...node,\n table: AliasNode.create(ParensNode.create(nestedSelect), IdentifierNode.create(table.alias ?? table.model)),\n };\n }\n\n protected override transformInsertQuery(node: InsertQueryNode) {\n // pre-insert check is done in `handle()`\n\n let onConflict = node.onConflict;\n\n if (onConflict?.updates) {\n // for \"on conflict do update\", we need to apply policy filter to the \"where\" clause\n const { mutationModel, alias } = this.getMutationModel(node);\n const filter = this.buildPolicyFilter(mutationModel, alias, 'update');\n if (onConflict.updateWhere) {\n onConflict = {\n ...onConflict,\n updateWhere: WhereNode.create(conjunction(this.dialect, [onConflict.updateWhere.where, filter])),\n };\n } else {\n onConflict = {\n ...onConflict,\n updateWhere: WhereNode.create(filter),\n };\n }\n }\n\n // merge updated onConflict\n const processedNode = onConflict ? { ...node, onConflict } : node;\n\n const result = super.transformInsertQuery(processedNode);\n\n // if any field is to be returned, we select ID fields here which will be used\n // for reading back post-insert\n let returning = result.returning;\n if (returning) {\n const { mutationModel } = this.getMutationModel(node);\n const idFields = QueryUtils.requireIdFields(this.client.$schema, mutationModel);\n returning = ReturningNode.create(idFields.map((f) => SelectionNode.create(ColumnNode.create(f))));\n }\n\n return {\n ...result,\n returning,\n };\n }\n\n protected override transformUpdateQuery(node: UpdateQueryNode) {\n const result = super.transformUpdateQuery(node);\n const { mutationModel, alias } = this.getMutationModel(node);\n let filter = this.buildPolicyFilter(mutationModel, alias, 'update');\n\n if (node.from) {\n // for update with from (join), we need to merge join tables' policy filters to the \"where\" clause\n const joinFilter = this.createPolicyFilterForFrom(node.from);\n if (joinFilter) {\n filter = conjunction(this.dialect, [filter, joinFilter]);\n }\n }\n\n let returning = result.returning;\n\n // regarding returning:\n // 1. if fields are to be returned, we only select id fields here which will be used for reading back\n // post-update\n // 2. if there are post-update policies, we need to make sure id fields are selected for joining with\n // before-update rows\n\n if (returning || this.hasPostUpdatePolicies(mutationModel)) {\n const idFields = QueryUtils.requireIdFields(this.client.$schema, mutationModel);\n returning = ReturningNode.create(idFields.map((f) => SelectionNode.create(ColumnNode.create(f))));\n }\n\n return {\n ...result,\n where: WhereNode.create(result.where ? conjunction(this.dialect, [result.where.where, filter]) : filter),\n returning,\n };\n }\n\n protected override transformDeleteQuery(node: DeleteQueryNode) {\n const result = super.transformDeleteQuery(node);\n const { mutationModel, alias } = this.getMutationModel(node);\n let filter = this.buildPolicyFilter(mutationModel, alias, 'delete');\n\n if (node.using) {\n // for delete with using (join), we need to merge join tables' policy filters to the \"where\" clause\n const joinFilter = this.createPolicyFilterForTables(node.using.tables);\n if (joinFilter) {\n filter = conjunction(this.dialect, [filter, joinFilter]);\n }\n }\n\n return {\n ...result,\n where: WhereNode.create(result.where ? conjunction(this.dialect, [result.where.where, filter]) : filter),\n };\n }\n\n // #endregion\n\n // #region helpers\n\n private onlyReturningId(node: MutationQueryNode) {\n if (!node.returning) {\n return true;\n }\n const { mutationModel } = this.getMutationModel(node);\n const idFields = QueryUtils.requireIdFields(this.client.$schema, mutationModel);\n\n if (node.returning.selections.some((s) => SelectAllNode.is(s.selection))) {\n const modelDef = QueryUtils.requireModel(this.client.$schema, mutationModel);\n if (Object.keys(modelDef.fields).some((f) => !idFields.includes(f))) {\n // there are fields other than ID fields\n return false;\n } else {\n // select all but model only has ID fields\n return true;\n }\n }\n\n // analyze selected columns\n const collector = new ColumnCollector();\n const selectedColumns = collector.collect(node.returning);\n return selectedColumns.every((c) => idFields.includes(c));\n }\n\n private async enforcePreCreatePolicy(\n node: InsertQueryNode,\n mutationModel: GetModels<Schema>,\n isManyToManyJoinTable: boolean,\n proceed: ProceedKyselyQueryFunction,\n ) {\n const fields = node.columns?.map((c) => c.column.name) ?? [];\n const valueRows = node.values\n ? this.unwrapCreateValueRows(node.values, mutationModel, fields, isManyToManyJoinTable)\n : [[]];\n for (const values of valueRows) {\n if (isManyToManyJoinTable) {\n await this.enforcePreCreatePolicyForManyToManyJoinTable(\n mutationModel,\n fields,\n values.map((v) => v.node),\n proceed,\n );\n } else {\n await this.enforcePreCreatePolicyForOne(\n mutationModel,\n fields,\n values.map((v) => v.node),\n proceed,\n );\n }\n }\n }\n\n private async enforcePreCreatePolicyForManyToManyJoinTable(\n tableName: GetModels<Schema>,\n fields: string[],\n values: OperationNode[],\n proceed: ProceedKyselyQueryFunction,\n ) {\n const m2m = this.resolveManyToManyJoinTable(tableName);\n invariant(m2m);\n\n // m2m create requires both sides to be updatable\n invariant(fields.includes('A') && fields.includes('B'), 'many-to-many join table must have A and B fk fields');\n\n const aIndex = fields.indexOf('A');\n const aNode = values[aIndex]!;\n const bIndex = fields.indexOf('B');\n const bNode = values[bIndex]!;\n invariant(ValueNode.is(aNode) && ValueNode.is(bNode), 'A and B values must be ValueNode');\n\n const aValue = aNode.value;\n const bValue = bNode.value;\n invariant(aValue !== null && aValue !== undefined, 'A value cannot be null or undefined');\n invariant(bValue !== null && bValue !== undefined, 'B value cannot be null or undefined');\n\n const eb = expressionBuilder<any, any>();\n\n const filterA = this.buildPolicyFilter(m2m.firstModel as GetModels<Schema>, undefined, 'update');\n const queryA = eb\n .selectFrom(m2m.firstModel)\n .where(eb(eb.ref(`${m2m.firstModel}.${m2m.firstIdField}`), '=', aValue))\n .select(() => new ExpressionWrapper(filterA).as('$t'));\n\n const filterB = this.buildPolicyFilter(m2m.secondModel as GetModels<Schema>, undefined, 'update');\n const queryB = eb\n .selectFrom(m2m.secondModel)\n .where(eb(eb.ref(`${m2m.secondModel}.${m2m.secondIdField}`), '=', bValue))\n .select(() => new ExpressionWrapper(filterB).as('$t'));\n\n // select both conditions in one query\n const queryNode: SelectQueryNode = {\n kind: 'SelectQueryNode',\n selections: [\n SelectionNode.create(AliasNode.create(queryA.toOperationNode(), IdentifierNode.create('$conditionA'))),\n SelectionNode.create(AliasNode.create(queryB.toOperationNode(), IdentifierNode.create('$conditionB'))),\n ],\n };\n\n const result = await proceed(queryNode);\n if (!result.rows[0]?.$conditionA) {\n throw new RejectedByPolicyError(\n m2m.firstModel as GetModels<Schema>,\n RejectedByPolicyReason.CANNOT_READ_BACK,\n `many-to-many relation participant model \"${m2m.firstModel}\" not updatable`,\n );\n }\n if (!result.rows[0]?.$conditionB) {\n throw new RejectedByPolicyError(\n m2m.secondModel as GetModels<Schema>,\n RejectedByPolicyReason.NO_ACCESS,\n `many-to-many relation participant model \"${m2m.secondModel}\" not updatable`,\n );\n }\n }\n\n private async enforcePreCreatePolicyForOne(\n model: GetModels<Schema>,\n fields: string[],\n values: OperationNode[],\n proceed: ProceedKyselyQueryFunction,\n ) {\n const allFields = Object.entries(QueryUtils.requireModel(this.client.$schema, model).fields).filter(\n ([, def]) => !def.relation,\n );\n const allValues: OperationNode[] = [];\n\n for (const [name, _def] of allFields) {\n const index = fields.indexOf(name);\n if (index >= 0) {\n allValues.push(values[index]!);\n } else {\n // set non-provided fields to null\n allValues.push(ValueNode.createImmediate(null));\n }\n }\n\n // create a `SELECT column1 as field1, column2 as field2, ... FROM (VALUES (...))` table for policy evaluation\n const eb = expressionBuilder<any, any>();\n\n const constTable: SelectQueryNode = {\n kind: 'SelectQueryNode',\n from: FromNode.create([\n AliasNode.create(\n ParensNode.create(ValuesNode.create([ValueListNode.create(allValues)])),\n IdentifierNode.create('$t'),\n ),\n ]),\n selections: allFields.map(([name, def], index) => {\n const castedColumnRef =\n sql`CAST(${eb.ref(`column${index + 1}`)} as ${sql.raw(this.dialect.getFieldSqlType(def))})`.as(\n name,\n );\n return SelectionNode.create(castedColumnRef.toOperationNode());\n }),\n };\n\n const filter = this.buildPolicyFilter(model, undefined, 'create');\n\n const preCreateCheck: SelectQueryNode = {\n kind: 'SelectQueryNode',\n from: FromNode.create([AliasNode.create(constTable, IdentifierNode.create(model))]),\n selections: [\n SelectionNode.create(\n AliasNode.create(\n BinaryOperationNode.create(\n FunctionNode.create('COUNT', [ValueNode.createImmediate(1)]),\n OperatorNode.create('>'),\n ValueNode.createImmediate(0),\n ),\n IdentifierNode.create('$condition'),\n ),\n ),\n ],\n where: WhereNode.create(filter),\n };\n\n const result = await proceed(preCreateCheck);\n if (!result.rows[0]?.$condition) {\n throw new RejectedByPolicyError(model);\n }\n }\n\n private unwrapCreateValueRows(\n node: OperationNode,\n model: GetModels<Schema>,\n fields: string[],\n isManyToManyJoinTable: boolean,\n ) {\n if (ValuesNode.is(node)) {\n return node.values.map((v) => this.unwrapCreateValueRow(v.values, model, fields, isManyToManyJoinTable));\n } else if (PrimitiveValueListNode.is(node)) {\n return [this.unwrapCreateValueRow(node.values, model, fields, isManyToManyJoinTable)];\n } else {\n throw new InternalError(`Unexpected node kind: ${node.kind} for unwrapping create values`);\n }\n }\n\n private unwrapCreateValueRow(\n data: readonly unknown[],\n model: GetModels<Schema>,\n fields: string[],\n isImplicitManyToManyJoinTable: boolean,\n ) {\n invariant(data.length === fields.length, 'data length must match fields length');\n const result: { node: OperationNode; raw: unknown }[] = [];\n for (let i = 0; i < data.length; i++) {\n const item = data[i]!;\n if (typeof item === 'object' && item && 'kind' in item) {\n const fieldDef = QueryUtils.requireField(this.client.$schema, model, fields[i]!);\n invariant(item.kind === 'ValueNode', 'expecting a ValueNode');\n result.push({\n node: ValueNode.create(\n this.dialect.transformPrimitive(\n (item as ValueNode).value,\n fieldDef.type as BuiltinType,\n !!fieldDef.array,\n ),\n ),\n raw: (item as ValueNode).value,\n });\n } else {\n let value: unknown = item;\n\n // many-to-many join table is not a model so we don't have field definitions,\n // but there's no need to transform values anyway because they're the fields\n // are all foreign keys\n if (!isImplicitManyToManyJoinTable) {\n const fieldDef = QueryUtils.requireField(this.client.$schema, model, fields[i]!);\n value = this.dialect.transformPrimitive(item, fieldDef.type as BuiltinType, !!fieldDef.array);\n }\n if (Array.isArray(value)) {\n result.push({\n node: RawNode.createWithSql(this.dialect.buildArrayLiteralSQL(value)),\n raw: value,\n });\n } else {\n result.push({ node: ValueNode.create(value), raw: value });\n }\n }\n }\n return result;\n }\n\n private tryGetConstantPolicy(model: GetModels<Schema>, operation: PolicyOperation) {\n const policies = this.getModelPolicies(model, operation);\n if (!policies.some((p) => p.kind === 'allow')) {\n // no allow -> unconditional deny\n return false;\n } else if (\n // unconditional deny\n policies.some((p) => p.kind === 'deny' && this.isTrueExpr(p.condition))\n ) {\n return false;\n } else if (\n // unconditional allow\n !policies.some((p) => p.kind === 'deny') &&\n policies.some((p) => p.kind === 'allow' && this.isTrueExpr(p.condition))\n ) {\n return true;\n } else {\n return undefined;\n }\n }\n\n private isTrueExpr(expr: Expression) {\n return ExpressionUtils.isLiteral(expr) && expr.value === true;\n }\n\n private async processReadBack(node: CrudQueryNode, result: QueryResult<any>, proceed: ProceedKyselyQueryFunction) {\n if (result.rows.length === 0) {\n return result;\n }\n\n if (!this.isMutationQueryNode(node) || !node.returning) {\n return result;\n }\n\n // do a select (with policy) in place of returning\n const { mutationModel } = this.getMutationModel(node);\n const idConditions = this.buildIdConditions(mutationModel, result.rows);\n const policyFilter = this.buildPolicyFilter(mutationModel, undefined, 'read');\n\n const select: SelectQueryNode = {\n kind: 'SelectQueryNode',\n from: FromNode.create([TableNode.create(mutationModel)]),\n where: WhereNode.create(conjunction(this.dialect, [idConditions, policyFilter])),\n selections: node.returning.selections,\n };\n const selectResult = await proceed(select);\n return selectResult;\n }\n\n private buildIdConditions(table: string, rows: any[]): OperationNode {\n const idFields = QueryUtils.requireIdFields(this.client.$schema, table);\n return disjunction(\n this.dialect,\n rows.map((row) =>\n conjunction(\n this.dialect,\n idFields.map((field) =>\n BinaryOperationNode.create(\n ReferenceNode.create(ColumnNode.create(field), TableNode.create(table)),\n OperatorNode.create('='),\n ValueNode.create(row[field]),\n ),\n ),\n ),\n ),\n );\n }\n\n private getMutationModel(node: InsertQueryNode | UpdateQueryNode | DeleteQueryNode) {\n const r = match(node)\n .when(InsertQueryNode.is, (node) => ({\n mutationModel: getTableName(node.into) as GetModels<Schema>,\n alias: undefined,\n }))\n .when(UpdateQueryNode.is, (node) => {\n if (!node.table) {\n throw new QueryError('Update query must have a table');\n }\n const r = this.extractTableName(node.table);\n return r ? { mutationModel: r.model, alias: r.alias } : undefined;\n })\n .when(DeleteQueryNode.is, (node) => {\n if (node.from.froms.length !== 1) {\n throw new QueryError('Only one from table is supported for delete');\n }\n const r = this.extractTableName(node.from.froms[0]!);\n return r ? { mutationModel: r.model, alias: r.alias } : undefined;\n })\n .exhaustive();\n if (!r) {\n throw new InternalError(`Unable to get table name for query node: ${node}`);\n }\n return r;\n }\n\n private isCrudQueryNode(node: RootOperationNode): node is CrudQueryNode {\n return (\n SelectQueryNode.is(node) || InsertQueryNode.is(node) || UpdateQueryNode.is(node) || DeleteQueryNode.is(node)\n );\n }\n\n private isMutationQueryNode(node: RootOperationNode): node is MutationQueryNode {\n return InsertQueryNode.is(node) || UpdateQueryNode.is(node) || DeleteQueryNode.is(node);\n }\n\n buildPolicyFilter(model: GetModels<Schema>, alias: string | undefined, operation: CRUD_EXT): OperationNode {\n // first check if it's a many-to-many join table, and if so, handle specially\n const m2mFilter = this.getModelPolicyFilterForManyToManyJoinTable(model, alias, operation);\n if (m2mFilter) {\n return m2mFilter;\n }\n\n const policies = this.getModelPolicies(model, operation);\n\n const allows = policies\n .filter((policy) => policy.kind === 'allow')\n .map((policy) => this.compilePolicyCondition(model, alias, operation, policy));\n\n const denies = policies\n .filter((policy) => policy.kind === 'deny')\n .map((policy) => this.compilePolicyCondition(model, alias, operation, policy));\n\n // 'post-update' is by default allowed, other operations are by default denied\n let combinedPolicy: OperationNode;\n\n if (allows.length === 0) {\n // no allow rules\n if (operation === 'post-update') {\n // post-update is allowed if no allow rules are defined\n combinedPolicy = trueNode(this.dialect);\n } else {\n // other operations are denied by default\n combinedPolicy = falseNode(this.dialect);\n }\n } else {\n // or(...allows)\n combinedPolicy = disjunction(this.dialect, allows);\n }\n\n // and(...!denies)\n if (denies.length !== 0) {\n const combinedDenies = conjunction(\n this.dialect,\n denies.map((d) => buildIsFalse(d, this.dialect)),\n );\n // or(...allows) && and(...!denies)\n combinedPolicy = conjunction(this.dialect, [combinedPolicy, combinedDenies]);\n }\n\n return combinedPolicy;\n }\n\n private extractTableName(node: OperationNode): { model: GetModels<Schema>; alias?: string } | undefined {\n if (TableNode.is(node)) {\n return { model: node.table.identifier.name as GetModels<Schema> };\n }\n if (AliasNode.is(node)) {\n const inner = this.extractTableName(node.node);\n if (!inner) {\n return undefined;\n }\n return {\n model: inner.model,\n alias: IdentifierNode.is(node.alias) ? node.alias.name : undefined,\n };\n } else {\n // this can happen for subqueries, which will be handled when nested\n // transformation happens\n return undefined;\n }\n }\n\n private createPolicyFilterForFrom(node: FromNode | undefined) {\n if (!node) {\n return undefined;\n }\n return this.createPolicyFilterForTables(node.froms);\n }\n\n private createPolicyFilterForTables(tables: readonly OperationNode[]) {\n return tables.reduce<OperationNode | undefined>((acc, table) => {\n const extractResult = this.extractTableName(table);\n if (extractResult) {\n const { model, alias } = extractResult;\n const filter = this.buildPolicyFilter(model, alias, 'read');\n return acc ? conjunction(this.dialect, [acc, filter]) : filter;\n }\n return acc;\n }, undefined);\n }\n\n private compilePolicyCondition(\n model: GetModels<Schema>,\n alias: string | undefined,\n operation: CRUD_EXT,\n policy: Policy,\n ) {\n return new ExpressionTransformer(this.client).transform(policy.condition, {\n model,\n alias,\n operation,\n });\n }\n\n private getModelPolicies(model: string, operation: PolicyOperation) {\n const modelDef = QueryUtils.requireModel(this.client.$schema, model);\n const result: Policy[] = [];\n\n const extractOperations = (expr: Expression) => {\n invariant(ExpressionUtils.isLiteral(expr), 'expecting a literal');\n invariant(typeof expr.value === 'string', 'expecting a string literal');\n return expr.value\n .split(',')\n .filter((v) => !!v)\n .map((v) => v.trim()) as PolicyOperation[];\n };\n\n if (modelDef.attributes) {\n result.push(\n ...modelDef.attributes\n .filter((attr) => attr.name === '@@allow' || attr.name === '@@deny')\n .map(\n (attr) =>\n ({\n kind: attr.name === '@@allow' ? 'allow' : 'deny',\n operations: extractOperations(attr.args![0]!.value),\n condition: attr.args![1]!.value,\n }) as const,\n )\n .filter(\n (policy) =>\n (operation !== 'post-update' && policy.operations.includes('all')) ||\n policy.operations.includes(operation),\n ),\n );\n }\n return result;\n }\n\n private resolveManyToManyJoinTable(tableName: string) {\n for (const model of Object.values(this.client.$schema.models)) {\n for (const field of Object.values(model.fields)) {\n const m2m = QueryUtils.getManyToManyRelation(this.client.$schema, model.name, field.name);\n if (m2m?.joinTable === tableName) {\n const sortedRecord = [\n {\n model: model.name,\n field: field.name,\n },\n {\n model: m2m.otherModel,\n field: m2m.otherField,\n },\n ].sort(this.manyToManySorter);\n\n const firstIdFields = QueryUtils.requireIdFields(this.client.$schema, sortedRecord[0]!.model);\n const secondIdFields = QueryUtils.requireIdFields(this.client.$schema, sortedRecord[1]!.model);\n invariant(\n firstIdFields.length === 1 && secondIdFields.length === 1,\n 'only single-field id is supported for implicit many-to-many join table',\n );\n\n return {\n firstModel: sortedRecord[0]!.model,\n firstField: sortedRecord[0]!.field,\n firstIdField: firstIdFields[0]!,\n secondModel: sortedRecord[1]!.model,\n secondField: sortedRecord[1]!.field,\n secondIdField: secondIdFields[0]!,\n };\n }\n }\n }\n return undefined;\n }\n\n private manyToManySorter(a: { model: string; field: string }, b: { model: string; field: string }): number {\n // the implicit m2m join table's \"A\", \"B\" fk fields' order is determined\n // by model name's sort order, and when identical (for self-relations),\n // field name's sort order\n return a.model !== b.model ? a.model.localeCompare(b.model) : a.field.localeCompare(b.field);\n }\n\n private isManyToManyJoinTable(tableName: string) {\n return !!this.resolveManyToManyJoinTable(tableName);\n }\n\n private getModelPolicyFilterForManyToManyJoinTable(\n tableName: string,\n alias: string | undefined,\n operation: PolicyOperation,\n ): OperationNode | undefined {\n const m2m = this.resolveManyToManyJoinTable(tableName);\n if (!m2m) {\n return undefined;\n }\n\n // join table's permission:\n // - read: requires both sides to be readable\n // - mutation: requires both sides to be updatable\n\n const checkForOperation = operation === 'read' ? 'read' : 'update';\n const eb = expressionBuilder<any, any>();\n const joinTable = alias ?? tableName;\n\n const aQuery = eb\n .selectFrom(m2m.firstModel)\n .whereRef(`${m2m.firstModel}.${m2m.firstIdField}`, '=', `${joinTable}.A`)\n .select(() =>\n new ExpressionWrapper(\n this.buildPolicyFilter(m2m.firstModel as GetModels<Schema>, undefined, checkForOperation),\n ).as('$conditionA'),\n );\n\n const bQuery = eb\n .selectFrom(m2m.secondModel)\n .whereRef(`${m2m.secondModel}.${m2m.secondIdField}`, '=', `${joinTable}.B`)\n .select(() =>\n new ExpressionWrapper(\n this.buildPolicyFilter(m2m.secondModel as GetModels<Schema>, undefined, checkForOperation),\n ).as('$conditionB'),\n );\n\n return eb.and([aQuery, bQuery]).toOperationNode();\n }\n\n // #endregion\n}\n","import type { ColumnNode, OperationNode } from 'kysely';\nimport { DefaultOperationNodeVisitor } from '@zenstackhq/sdk';\n\n/**\n * Collects all column names from a query.\n */\nexport class ColumnCollector extends DefaultOperationNodeVisitor {\n private columns: string[] = [];\n\n collect(node: OperationNode) {\n this.columns = [];\n this.visitNode(node);\n return this.columns;\n }\n\n protected override visitColumn(node: ColumnNode): void {\n if (!this.columns.includes(node.column.name)) {\n this.columns.push(node.column.name);\n }\n }\n}\n","import { invariant } from '@zenstackhq/common-helpers';\nimport {\n getCrudDialect,\n InternalError,\n QueryError,\n QueryUtils,\n type BaseCrudDialect,\n type ClientContract,\n type CRUD_EXT,\n} from '@zenstackhq/runtime';\nimport type {\n BinaryExpression,\n BinaryOperator,\n BuiltinType,\n FieldDef,\n GetModels,\n LiteralExpression,\n MemberExpression,\n UnaryExpression,\n} from '@zenstackhq/runtime/schema';\nimport {\n ExpressionUtils,\n type ArrayExpression,\n type CallExpression,\n type Expression,\n type FieldExpression,\n type SchemaDef,\n} from '@zenstackhq/runtime/schema';\nimport {\n AliasNode,\n BinaryOperationNode,\n ColumnNode,\n expressionBuilder,\n FromNode,\n FunctionNode,\n IdentifierNode,\n OperatorNode,\n ReferenceNode,\n SelectionNode,\n SelectQueryNode,\n TableNode,\n ValueListNode,\n ValueNode,\n WhereNode,\n type ExpressionBuilder,\n type OperandExpression,\n type OperationNode,\n} from 'kysely';\nimport { match } from 'ts-pattern';\nimport { ExpressionEvaluator } from './expression-evaluator';\nimport { conjunction, disjunction, falseNode, isBeforeInvocation, logicalNot, trueNode } from './utils';\n\nexport type ExpressionTransformerContext<Schema extends SchemaDef> = {\n model: GetModels<Schema>;\n alias?: string;\n operation: CRUD_EXT;\n memberFilter?: OperationNode;\n memberSelect?: SelectionNode;\n};\n\n// a registry of expression handlers marked with @expr\nconst expressionHandlers = new Map<string, PropertyDescriptor>();\n\n// expression handler decorator\nfunction expr(kind: Expression['kind']) {\n return function (_target: unknown, _propertyKey: string, descriptor: PropertyDescriptor) {\n if (!expressionHandlers.get(kind)) {\n expressionHandlers.set(kind, descriptor);\n }\n return descriptor;\n };\n}\n\nexport class ExpressionTransformer<Schema extends SchemaDef> {\n private readonly dialect: BaseCrudDialect<Schema>;\n\n constructor(private readonly client: ClientContract<Schema>) {\n this.dialect = getCrudDialect(this.schema, this.clientOptions);\n }\n\n get schema() {\n return this.client.$schema;\n }\n\n get clientOptions() {\n return this.client.$options;\n }\n\n get auth() {\n return this.client.$auth;\n }\n\n get authType() {\n if (!this.schema.authType) {\n throw new InternalError('Schema does not have an \"authType\" specified');\n }\n return this.schema.authType!;\n }\n\n transform(expression: Expression, context: ExpressionTransformerContext<Schema>): OperationNode {\n const handler = expressionHandlers.get(expression.kind);\n if (!handler) {\n throw new Error(`Unsupported expression kind: ${expression.kind}`);\n }\n return handler.value.call(this, expression, context);\n }\n\n @expr('literal')\n // @ts-expect-error\n private _literal(expr: LiteralExpression) {\n return this.transformValue(\n expr.value,\n typeof expr.value === 'string' ? 'String' : typeof expr.value === 'boolean' ? 'Boolean' : 'Int',\n );\n }\n\n @expr('array')\n // @ts-expect-error\n private _array(expr: ArrayExpression, context: ExpressionTransformerContext<Schema>) {\n return ValueListNode.create(expr.items.map((item) => this.transform(item, context)));\n }\n\n @expr('field')\n private _field(expr: FieldExpression, context: ExpressionTransformerContext<Schema>) {\n const fieldDef = QueryUtils.requireField(this.schema, context.model, expr.field);\n if (!fieldDef.relation) {\n return this.createColumnRef(expr.field, context);\n } else {\n const { memberFilter, memberSelect, ...restContext } = context;\n const relation = this.transformRelationAccess(expr.field, fieldDef.type, restContext);\n return {\n ...relation,\n where: this.mergeWhere(relation.where, memberFilter),\n selections: memberSelect ? [memberSelect] : relation.selections,\n };\n }\n }\n\n private mergeWhere(where: WhereNode | undefined, memberFilter: OperationNode | undefined) {\n if (!where) {\n return WhereNode.create(memberFilter ?? trueNode(this.dialect));\n }\n if (!memberFilter) {\n return where;\n }\n return WhereNode.create(conjunction(this.dialect, [where.where, memberFilter]));\n }\n\n @expr('null')\n // @ts-ignore\n private _null() {\n return ValueNode.createImmediate(null);\n }\n\n @expr('binary')\n // @ts-ignore\n private _binary(expr: BinaryExpression, context: ExpressionTransformerContext<Schema>) {\n if (expr.op === '&&') {\n return conjunction(this.dialect, [this.transform(expr.left, context), this.transform(expr.right, context)]);\n } else if (expr.op === '||') {\n return disjunction(this.dialect, [this.transform(expr.left, context), this.transform(expr.right, context)]);\n }\n\n if (this.isAuthCall(expr.left) || this.isAuthCall(expr.right)) {\n return this.transformAuthBinary(expr, context);\n }\n\n const op = expr.op;\n\n if (op === '?' || op === '!' || op === '^') {\n return this.transformCollectionPredicate(expr, context);\n }\n\n const { normalizedLeft, normalizedRight } = this.normalizeBinaryOperationOperands(expr, context);\n const left = this.transform(normalizedLeft, context);\n const right = this.transform(normalizedRight, context);\n\n if (op === 'in') {\n if (this.isNullNode(left)) {\n return this.transformValue(false, 'Boolean');\n } else {\n if (ValueListNode.is(right)) {\n return BinaryOperationNode.create(left, OperatorNode.create('in'), right);\n } else {\n // array contains\n return BinaryOperationNode.create(\n left,\n OperatorNode.create('='),\n FunctionNode.create('any', [right]),\n );\n }\n }\n }\n\n if (this.isNullNode(right)) {\n return this.transformNullCheck(left, expr.op);\n } else if (this.isNullNode(left)) {\n return this.transformNullCheck(right, expr.op);\n } else {\n return BinaryOperationNode.create(left, this.transformOperator(op), right);\n }\n }\n\n private transformNullCheck(expr: OperationNode, operator: BinaryOperator) {\n invariant(operator === '==' || operator === '!=', 'operator must be \"==\" or \"!=\" for null comparison');\n if (ValueNode.is(expr)) {\n if (expr.value === null) {\n return operator === '==' ? trueNode(this.dialect) : falseNode(this.dialect);\n } else {\n return operator === '==' ? falseNode(this.dialect) : trueNode(this.dialect);\n }\n } else {\n return operator === '=='\n ? BinaryOperationNode.create(expr, OperatorNode.create('is'), ValueNode.createImmediate(null))\n : BinaryOperationNode.create(expr, OperatorNode.create('is not'), ValueNode.createImmediate(null));\n }\n }\n\n private normalizeBinaryOperationOperands(expr: BinaryExpression, context: ExpressionTransformerContext<Schema>) {\n // if relation fields are used directly in comparison, it can only be compared with null,\n // so we normalize the args with the id field (use the first id field if multiple)\n let normalizedLeft: Expression = expr.left;\n if (this.isRelationField(expr.left, context.model)) {\n invariant(ExpressionUtils.isNull(expr.right), 'only null comparison is supported for relation field');\n const leftRelDef = this.getFieldDefFromFieldRef(expr.left, context.model);\n invariant(leftRelDef, 'failed to get relation field definition');\n const idFields = QueryUtils.requireIdFields(this.schema, leftRelDef.type);\n normalizedLeft = this.makeOrAppendMember(normalizedLeft, idFields[0]!);\n }\n let normalizedRight: Expression = expr.right;\n if (this.isRelationField(expr.right, context.model)) {\n invariant(ExpressionUtils.isNull(expr.left), 'only null comparison is supported for relation field');\n const rightRelDef = this.getFieldDefFromFieldRef(expr.right, context.model);\n invariant(rightRelDef, 'failed to get relation field definition');\n const idFields = QueryUtils.requireIdFields(this.schema, rightRelDef.type);\n normalizedRight = this.makeOrAppendMember(normalizedRight, idFields[0]!);\n }\n return { normalizedLeft, normalizedRight };\n }\n\n private transformCollectionPredicate(expr: BinaryExpression, context: ExpressionTransformerContext<Schema>) {\n invariant(expr.op === '?' || expr.op === '!' || expr.op === '^', 'expected \"?\" or \"!\" or \"^\" operator');\n\n if (this.isAuthCall(expr.left) || this.isAuthMember(expr.left)) {\n const value = new ExpressionEvaluator().evaluate(expr, {\n auth: this.auth,\n });\n return this.transformValue(value, 'Boolean');\n }\n\n invariant(\n ExpressionUtils.isField(expr.left) || ExpressionUtils.isMember(expr.left),\n 'left operand must be field or member access',\n );\n\n let newContextModel: string;\n const fieldDef = this.getFieldDefFromFieldRef(expr.left, context.model);\n if (fieldDef) {\n invariant(fieldDef.relation, `field is not a relation: ${JSON.stringify(expr.left)}`);\n newContextModel = fieldDef.type;\n } else {\n invariant(\n ExpressionUtils.isMember(expr.left) && ExpressionUtils.isField(expr.left.receiver),\n 'left operand must be member access with field receiver',\n );\n const fieldDef = QueryUtils.requireField(this.schema, context.model, expr.left.receiver.field);\n newContextModel = fieldDef.type;\n for (const member of expr.left.members) {\n const memberDef = QueryUtils.requireField(this.schema, newContextModel, member);\n newContextModel = memberDef.type;\n }\n }\n\n let predicateFilter = this.transform(expr.right, {\n ...context,\n model: newContextModel as GetModels<Schema>,\n alias: undefined,\n });\n\n if (expr.op === '!') {\n predicateFilter = logicalNot(this.dialect, predicateFilter);\n }\n\n const count = FunctionNode.create('count', [ValueNode.createImmediate(1)]);\n\n const predicateResult = match(expr.op)\n .with('?', () => BinaryOperationNode.create(count, OperatorNode.create('>'), ValueNode.createImmediate(0)))\n .with('!', () => BinaryOperationNode.create(count, OperatorNode.create('='), ValueNode.createImmediate(0)))\n .with('^', () => BinaryOperationNode.create(count, OperatorNode.create('='), ValueNode.createImmediate(0)))\n .exhaustive();\n\n return this.transform(expr.left, {\n ...context,\n memberSelect: SelectionNode.create(AliasNode.create(predicateResult, IdentifierNode.create('$t'))),\n memberFilter: predicateFilter,\n });\n }\n\n private transformAuthBinary(expr: BinaryExpression, context: ExpressionTransformerContext<Schema>) {\n if (expr.op !== '==' && expr.op !== '!=') {\n throw new QueryError(\n `Unsupported operator for \\`auth()\\` in policy of model \"${context.model}\": ${expr.op}`,\n );\n }\n\n let authExpr: Expression;\n let other: Expression;\n if (this.isAuthCall(expr.left)) {\n authExpr = expr.left;\n other = expr.right;\n } else {\n authExpr = expr.right;\n other = expr.left;\n }\n\n if (ExpressionUtils.isNull(other)) {\n return this.transformValue(expr.op === '==' ? !this.auth : !!this.auth, 'Boolean');\n } else {\n const authModel = QueryUtils.getModel(this.schema, this.authType);\n if (!authModel) {\n throw new QueryError(\n `Unsupported use of \\`auth()\\` in policy of model \"${context.model}\", comparing with \\`auth()\\` is only possible when auth type is a model`,\n );\n }\n\n const idFields = Object.values(authModel.fields)\n .filter((f) => f.id)\n .map((f) => f.name);\n invariant(idFields.length > 0, 'auth type model must have at least one id field');\n\n // convert `auth() == other` into `auth().id == other.id`\n const conditions = idFields.map((fieldName) =>\n ExpressionUtils.binary(\n ExpressionUtils.member(authExpr, [fieldName]),\n '==',\n this.makeOrAppendMember(other, fieldName),\n ),\n );\n let result = this.buildAnd(conditions);\n if (expr.op === '!=') {\n result = this.buildLogicalNot(result);\n }\n return this.transform(result, context);\n }\n }\n\n private makeOrAppendMember(other: Expression, fieldName: string): Expression {\n if (ExpressionUtils.isMember(other)) {\n return ExpressionUtils.member(other.receiver, [...other.members, fieldName]);\n } else {\n return ExpressionUtils.member(other, [fieldName]);\n }\n }\n\n private transformValue(value: unknown, type: BuiltinType) {\n if (value === true) {\n return trueNode(this.dialect);\n } else if (value === false) {\n return falseNode(this.dialect);\n } else {\n return ValueNode.create(this.dialect.transformPrimitive(value, type, false) ?? null);\n }\n }\n\n @expr('unary')\n // @ts-ignore\n private _unary(expr: UnaryExpression, context: ExpressionTransformerContext<Schema>) {\n // only '!' operator for now\n invariant(expr.op === '!', 'only \"!\" operator is supported');\n return logicalNot(this.dialect, this.transform(expr.operand, context));\n }\n\n private transformOperator(op: Exclude<BinaryOperator, '?' | '!' | '^'>) {\n const mappedOp = match(op)\n .with('==', () => '=' as const)\n .otherwise(() => op);\n return OperatorNode.create(mappedOp);\n }\n\n @expr('call')\n // @ts-ignore\n private _call(expr: CallExpression, context: ExpressionTransformerContext<Schema>) {\n const result = this.transformCall(expr, context);\n return result.toOperationNode();\n }\n\n private transformCall(expr: CallExpression, context: ExpressionTransformerContext<Schema>) {\n const func = this.getFunctionImpl(expr.function);\n if (!func) {\n throw new QueryError(`Function not implemented: ${expr.function}`);\n }\n const eb = expressionBuilder<any, any>();\n return func(\n eb,\n (expr.args ?? []).map((arg) => this.transformCallArg(eb, arg, context)),\n {\n client: this.client,\n dialect: this.dialect,\n model: context.model,\n modelAlias: context.alias ?? context.model,\n operation: context.operation,\n },\n );\n }\n\n private getFunctionImpl(functionName: string) {\n // check built-in functions\n let func = this.clientOptions.functions?.[functionName];\n if (!func) {\n // check plugins\n for (const plugin of this.clientOptions.plugins ?? []) {\n if (plugin.functions?.[functionName]) {\n func = plugin.functions[functionName];\n break;\n }\n }\n }\n return func;\n }\n\n private transformCallArg(\n eb: ExpressionBuilder<any, any>,\n arg: Expression,\n context: ExpressionTransformerContext<Schema>,\n ): OperandExpression<any> {\n if (ExpressionUtils.isLiteral(arg)) {\n return eb.val(arg.value);\n }\n\n if (ExpressionUtils.isField(arg)) {\n return eb.ref(arg.field);\n }\n\n if (ExpressionUtils.isCall(arg)) {\n return this.transformCall(arg, context);\n }\n\n if (this.isAuthMember(arg)) {\n const valNode = this.valueMemberAccess(this.auth, arg as MemberExpression, this.authType);\n return valNode ? eb.val(valNode.value) : eb.val(null);\n }\n\n // TODO\n // if (Expression.isMember(arg)) {\n // }\n\n throw new InternalError(`Unsupported argument expression: ${arg.kind}`);\n }\n\n @expr('member')\n // @ts-ignore\n private _member(expr: MemberExpression, context: ExpressionTransformerContext<Schema>) {\n // `auth()` member access\n if (this.isAuthCall(expr.receiver)) {\n return this.valueMemberAccess(this.auth, expr, this.authType);\n }\n\n // `before()` member access\n if (isBeforeInvocation(expr.receiver)) {\n // policy handler creates a join table named `$before` using entity value before update,\n // we can directly reference the column from there\n invariant(context.operation === 'post-update', 'before() can only be used in post-update policy');\n invariant(expr.members.length === 1, 'before() can only be followed by a scalar field access');\n return ReferenceNode.create(ColumnNode.create(expr.members[0]!), TableNode.create('$before'));\n }\n\n invariant(\n ExpressionUtils.isField(expr.receiver) || ExpressionUtils.isThis(expr.receiver),\n 'expect receiver to be field expression or \"this\"',\n );\n\n let members = expr.members;\n let receiver: OperationNode;\n const { memberFilter, memberSelect, ...restContext } = context;\n\n if (ExpressionUtils.isThis(expr.receiver)) {\n if (expr.members.length === 1) {\n // `this.relation` case, equivalent to field access\n return this._field(ExpressionUtils.field(expr.members[0]!), context);\n } else {\n // transform the first segment into a relation access, then continue with the rest of the members\n const firstMemberFieldDef = QueryUtils.requireField(this.schema, context.model, expr.members[0]!);\n receiver = this.transformRelationAccess(expr.members[0]!, firstMemberFieldDef.type, restContext);\n members = expr.members.slice(1);\n }\n } else {\n receiver = this.transform(expr.receiver, restContext);\n }\n\n invariant(SelectQueryNode.is(receiver), 'expected receiver to be select query');\n\n let startType: string;\n if (ExpressionUtils.isField(expr.receiver)) {\n const receiverField = QueryUtils.requireField(this.schema, context.model, expr.receiver.field);\n startType = receiverField.type;\n } else {\n // \"this.\" case, start type is the model of the context\n startType = context.model;\n }\n\n // traverse forward to collect member types\n const memberFields: { fromModel: string; fieldDef: FieldDef }[] = [];\n let currType = startType;\n for (const member of members) {\n const fieldDef = QueryUtils.requireField(this.schema, currType, member);\n memberFields.push({ fieldDef, fromModel: currType });\n currType = fieldDef.type;\n }\n\n let currNode: SelectQueryNode | ColumnNode | ReferenceNode | undefined = undefined;\n\n for (let i = members.length - 1; i >= 0; i--) {\n const member = members[i]!;\n const { fieldDef, fromModel } = memberFields[i]!;\n\n if (fieldDef.relation) {\n const relation = this.transformRelationAccess(member, fieldDef.type, {\n ...restContext,\n model: fromModel as GetModels<Schema>,\n alias: undefined,\n });\n\n if (currNode) {\n currNode = {\n ...relation,\n selections: [\n SelectionNode.create(AliasNode.create(currNode, IdentifierNode.create(members[i + 1]!))),\n ],\n };\n } else {\n // inner most member, merge with member filter from the context\n currNode = {\n ...relation,\n where: this.mergeWhere(relation.where, memberFilter),\n selections: memberSelect ? [memberSelect] : relation.selections,\n };\n }\n } else {\n invariant(i === members.length - 1, 'plain field access must be the last segment');\n invariant(!currNode, 'plain field access must be the last segment');\n\n currNode = ColumnNode.create(member);\n }\n }\n\n return {\n ...receiver,\n selections: [SelectionNode.create(AliasNode.create(currNode!, IdentifierNode.create('$t')))],\n };\n }\n\n private valueMemberAccess(receiver: any, expr: MemberExpression, receiverType: string) {\n if (!receiver) {\n return ValueNode.createImmediate(null);\n }\n\n if (expr.members.length !== 1) {\n throw new Error(`Only single member access is supported`);\n }\n\n const field = expr.members[0]!;\n const fieldDef = QueryUtils.requireField(this.schema, receiverType, field);\n const fieldValue = receiver[field] ?? null;\n return this.transformValue(fieldValue, fieldDef.type as BuiltinType);\n }\n\n private transformRelationAccess(\n field: string,\n relationModel: string,\n context: ExpressionTransformerContext<Schema>,\n ): SelectQueryNode {\n const m2m = QueryUtils.getManyToManyRelation(this.schema, context.model, field);\n if (m2m) {\n return this.transformManyToManyRelationAccess(m2m, context);\n }\n\n const fromModel = context.model;\n const relationFieldDef = QueryUtils.requireField(this.schema, fromModel, field);\n const { keyPairs, ownedByModel } = QueryUtils.getRelationForeignKeyFieldPairs(this.schema, fromModel, field);\n\n let condition: OperationNode;\n if (ownedByModel) {\n // `fromModel` owns the fk\n\n condition = conjunction(\n this.dialect,\n keyPairs.map(({ fk, pk }) => {\n let fkRef: OperationNode = ReferenceNode.create(\n ColumnNode.create(fk),\n TableNode.create(context.alias ?? fromModel),\n );\n if (relationFieldDef.originModel && relationFieldDef.originModel !== fromModel) {\n fkRef = this.buildDelegateBaseFieldSelect(\n fromModel,\n context.alias ?? fromModel,\n fk,\n relationFieldDef.originModel,\n );\n }\n return BinaryOperationNode.create(\n fkRef,\n OperatorNode.create('='),\n ReferenceNode.create(ColumnNode.create(pk), TableNode.create(relationModel)),\n );\n }),\n );\n } else {\n // `relationModel` owns the fk\n condition = conjunction(\n this.dialect,\n keyPairs.map(({ fk, pk }) =>\n BinaryOperationNode.create(\n ReferenceNode.create(ColumnNode.create(pk), TableNode.create(context.alias ?? fromModel)),\n OperatorNode.create('='),\n ReferenceNode.create(ColumnNode.create(fk), TableNode.create(relationModel)),\n ),\n ),\n );\n }\n\n return {\n kind: 'SelectQueryNode',\n from: FromNode.create([TableNode.create(relationModel)]),\n where: WhereNode.create(condition),\n };\n }\n\n private transformManyToManyRelationAccess(\n m2m: NonNullable<ReturnType<typeof QueryUtils.getManyToManyRelation>>,\n context: ExpressionTransformerContext<Schema>,\n ) {\n const eb = expressionBuilder<any, any>();\n const relationQuery = eb\n .selectFrom(m2m.otherModel)\n // inner join with join table and additionally filter by the parent model\n .innerJoin(m2m.joinTable, (join) =>\n join\n // relation model pk to join table fk\n .onRef(`${m2m.otherModel}.${m2m.otherPKName}`, '=', `${m2m.joinTable}.${m2m.otherFkName}`)\n // parent model pk to join table fk\n .onRef(\n `${m2m.joinTable}.${m2m.parentFkName}`,\n '=',\n `${context.alias ?? context.model}.${m2m.parentPKName}`,\n ),\n );\n return relationQuery.toOperationNode();\n }\n\n private createColumnRef(column: string, context: ExpressionTransformerContext<Schema>) {\n // if field comes from a delegate base model, we need to use the join alias\n // of that base model\n\n const tableName = context.alias ?? context.model;\n\n // \"create\" policies evaluate table from \"VALUES\" node so no join from delegate bases are\n // created and thus we should directly use the model table name\n if (context.operation === 'create') {\n return ReferenceNode.create(ColumnNode.create(column), TableNode.create(tableName));\n }\n\n const fieldDef = QueryUtils.requireField(this.schema, context.model, column);\n if (!fieldDef.originModel || fieldDef.originModel === context.model) {\n return ReferenceNode.create(ColumnNode.create(column), TableNode.create(tableName));\n }\n\n return this.buildDelegateBaseFieldSelect(context.model, tableName, column, fieldDef.originModel);\n }\n\n private buildDelegateBaseFieldSelect(model: string, modelAlias: string, field: string, baseModel: string) {\n const idFields = QueryUtils.requireIdFields(this.client.$schema, model);\n return {\n kind: 'SelectQueryNode',\n from: FromNode.create([TableNode.create(baseModel)]),\n selections: [\n SelectionNode.create(ReferenceNode.create(ColumnNode.create(field), TableNode.create(baseModel))),\n ],\n where: WhereNode.create(\n conjunction(\n this.dialect,\n idFields.map((idField) =>\n BinaryOperationNode.create(\n ReferenceNode.create(ColumnNode.create(idField), TableNode.create(baseModel)),\n OperatorNode.create('='),\n ReferenceNode.create(ColumnNode.create(idField), TableNode.create(modelAlias)),\n ),\n ),\n ),\n ),\n } satisfies SelectQueryNode;\n }\n\n private isAuthCall(value: unknown): value is CallExpression {\n return ExpressionUtils.isCall(value) && value.function === 'auth';\n }\n\n private isAuthMember(expr: Expression) {\n return ExpressionUtils.isMember(expr) && this.isAuthCall(expr.receiver);\n }\n\n private isNullNode(node: OperationNode) {\n return ValueNode.is(node) && node.value === null;\n }\n\n private buildLogicalNot(result: Expression): Expression {\n return ExpressionUtils.unary('!', result);\n }\n\n private buildAnd(conditions: BinaryExpression[]): Expression {\n if (conditions.length === 0) {\n return ExpressionUtils.literal(true);\n } else if (conditions.length === 1) {\n return conditions[0]!;\n } else {\n return conditions.reduce((acc, condition) => ExpressionUtils.binary(acc, '&&', condition));\n }\n }\n\n private isRelationField(expr: Expression, model: GetModels<Schema>) {\n const fieldDef = this.getFieldDefFromFieldRef(expr, model);\n return !!fieldDef?.relation;\n }\n\n private getFieldDefFromFieldRef(expr: Expression, model: GetModels<Schema>): FieldDef | undefined {\n if (ExpressionUtils.isField(expr)) {\n return QueryUtils.requireField(this.schema, model, expr.field);\n } else if (\n ExpressionUtils.isMember(expr) &&\n expr.members.length === 1 &&\n ExpressionUtils.isThis(expr.receiver)\n ) {\n return QueryUtils.requireField(this.schema, model, expr.members[0]!);\n } else {\n return undefined;\n }\n }\n}\n","import { invariant } from '@zenstackhq/common-helpers';\nimport { match } from 'ts-pattern';\nimport {\n ExpressionUtils,\n type ArrayExpression,\n type BinaryExpression,\n type CallExpression,\n type Expression,\n type FieldExpression,\n type LiteralExpression,\n type MemberExpression,\n type UnaryExpression,\n} from '@zenstackhq/runtime/schema';\n\ntype ExpressionEvaluatorContext = {\n auth?: any;\n thisValue?: any;\n};\n\n/**\n * Evaluate a schema expression into a JavaScript value.\n */\nexport class ExpressionEvaluator {\n evaluate(expression: Expression, context: ExpressionEvaluatorContext): any {\n const result = match(expression)\n .when(ExpressionUtils.isArray, (expr) => this.evaluateArray(expr, context))\n .when(ExpressionUtils.isBinary, (expr) => this.evaluateBinary(expr, context))\n .when(ExpressionUtils.isField, (expr) => this.evaluateField(expr, context))\n .when(ExpressionUtils.isLiteral, (expr) => this.evaluateLiteral(expr))\n .when(ExpressionUtils.isMember, (expr) => this.evaluateMember(expr, context))\n .when(ExpressionUtils.isUnary, (expr) => this.evaluateUnary(expr, context))\n .when(ExpressionUtils.isCall, (expr) => this.evaluateCall(expr, context))\n .when(ExpressionUtils.isThis, () => context.thisValue)\n .when(ExpressionUtils.isNull, () => null)\n .exhaustive();\n\n return result ?? null;\n }\n\n private evaluateCall(expr: CallExpression, context: ExpressionEvaluatorContext): any {\n if (expr.function === 'auth') {\n return context.auth;\n } else {\n throw new Error(`Unsupported call expression function: ${expr.function}`);\n }\n }\n\n private evaluateUnary(expr: UnaryExpression, context: ExpressionEvaluatorContext) {\n return match(expr.op)\n .with('!', () => !this.evaluate(expr.operand, context))\n .exhaustive();\n }\n\n private evaluateMember(expr: MemberExpression, context: ExpressionEvaluatorContext) {\n let val = this.evaluate(expr.receiver, context);\n for (const member of expr.members) {\n val = val?.[member];\n }\n return val;\n }\n\n private evaluateLiteral(expr: LiteralExpression): any {\n return expr.value;\n }\n\n private evaluateField(expr: FieldExpression, context: ExpressionEvaluatorContext): any {\n return context.thisValue?.[expr.field];\n }\n\n private evaluateArray(expr: ArrayExpression, context: ExpressionEvaluatorContext) {\n return expr.items.map((item) => this.evaluate(item, context));\n }\n\n private evaluateBinary(expr: BinaryExpression, context: ExpressionEvaluatorContext) {\n if (expr.op === '?' || expr.op === '!' || expr.op === '^') {\n return this.evaluateCollectionPredicate(expr, context);\n }\n\n const left = this.evaluate(expr.left, context);\n const right = this.evaluate(expr.right, context);\n\n return match(expr.op)\n .with('==', () => left === right)\n .with('!=', () => left !== right)\n .with('>', () => left > right)\n .with('>=', () => left >= right)\n .with('<', () => left < right)\n .with('<=', () => left <= right)\n .with('&&', () => left && right)\n .with('||', () => left || right)\n .with('in', () => {\n const _right = right ?? [];\n invariant(Array.isArray(_right), 'expected array for \"in\" operator');\n return _right.includes(left);\n })\n .exhaustive();\n }\n\n private evaluateCollectionPredicate(expr: BinaryExpression, context: ExpressionEvaluatorContext) {\n const op = expr.op;\n invariant(op === '?' || op === '!' || op === '^', 'expected \"?\" or \"!\" or \"^\" operator');\n\n const left = this.evaluate(expr.left, context);\n if (!left) {\n return false;\n }\n\n invariant(Array.isArray(left), 'expected array');\n\n return match(op)\n .with('?', () => left.some((item: any) => this.evaluate(expr.right, { ...context, thisValue: item })))\n .with('!', () => left.every((item: any) => this.evaluate(expr.right, { ...context, thisValue: item })))\n .with(\n '^',\n () =>\n !left.some((item: any) =>\n this.evaluate(expr.right, {\n ...context,\n thisValue: item,\n }),\n ),\n )\n .exhaustive();\n }\n}\n","import type { BaseCrudDialect } from '@zenstackhq/runtime';\nimport { ExpressionUtils, type Expression, type SchemaDef } from '@zenstackhq/runtime/schema';\nimport type { OperationNode } from 'kysely';\nimport {\n AliasNode,\n AndNode,\n BinaryOperationNode,\n FunctionNode,\n OperatorNode,\n OrNode,\n ParensNode,\n ReferenceNode,\n TableNode,\n UnaryOperationNode,\n ValueNode,\n} from 'kysely';\n\n/**\n * Creates a `true` value node.\n */\nexport function trueNode<Schema extends SchemaDef>(dialect: BaseCrudDialect<Schema>) {\n return ValueNode.createImmediate(dialect.transformPrimitive(true, 'Boolean', false));\n}\n\n/**\n * Creates a `false` value node.\n */\nexport function falseNode<Schema extends SchemaDef>(dialect: BaseCrudDialect<Schema>) {\n return ValueNode.createImmediate(dialect.transformPrimitive(false, 'Boolean', false));\n}\n\n/**\n * Checks if a node is a truthy value node.\n */\nexport function isTrueNode(node: OperationNode): boolean {\n return ValueNode.is(node) && (node.value === true || node.value === 1);\n}\n\n/**\n * Checks if a node is a falsy value node.\n */\nexport function isFalseNode(node: OperationNode): boolean {\n return ValueNode.is(node) && (node.value === false || node.value === 0);\n}\n\n/**\n * Builds a logical conjunction of a list of nodes.\n */\nexport function conjunction<Schema extends SchemaDef>(\n dialect: BaseCrudDialect<Schema>,\n nodes: OperationNode[],\n): OperationNode {\n if (nodes.length === 0) {\n return trueNode(dialect);\n }\n if (nodes.length === 1) {\n return nodes[0]!;\n }\n if (nodes.some(isFalseNode)) {\n return falseNode(dialect);\n }\n const items = nodes.filter((n) => !isTrueNode(n));\n if (items.length === 0) {\n return trueNode(dialect);\n }\n return items.reduce((acc, node) => AndNode.create(wrapParensIf(acc, OrNode.is), wrapParensIf(node, OrNode.is)));\n}\n\nexport function disjunction<Schema extends SchemaDef>(\n dialect: BaseCrudDialect<Schema>,\n nodes: OperationNode[],\n): OperationNode {\n if (nodes.length === 0) {\n return falseNode(dialect);\n }\n if (nodes.length === 1) {\n return nodes[0]!;\n }\n if (nodes.some(isTrueNode)) {\n return trueNode(dialect);\n }\n const items = nodes.filter((n) => !isFalseNode(n));\n if (items.length === 0) {\n return falseNode(dialect);\n }\n return items.reduce((acc, node) => OrNode.create(wrapParensIf(acc, AndNode.is), wrapParensIf(node, AndNode.is)));\n}\n\n/**\n * Negates a logical expression.\n */\nexport function logicalNot<Schema extends SchemaDef>(\n dialect: BaseCrudDialect<Schema>,\n node: OperationNode,\n): OperationNode {\n if (isTrueNode(node)) {\n return falseNode(dialect);\n }\n if (isFalseNode(node)) {\n return trueNode(dialect);\n }\n return UnaryOperationNode.create(\n OperatorNode.create('not'),\n wrapParensIf(node, (n) => AndNode.is(n) || OrNode.is(n)),\n );\n}\n\nfunction wrapParensIf(node: OperationNode, predicate: (node: OperationNode) => boolean): OperationNode {\n return predicate(node) ? ParensNode.create(node) : node;\n}\n\n/**\n * Builds an expression node that checks if a node is true.\n */\nexport function buildIsTrue<Schema extends SchemaDef>(node: OperationNode, dialect: BaseCrudDialect<Schema>) {\n if (isTrueNode(node)) {\n return trueNode(dialect);\n } else if (isFalseNode(node)) {\n return falseNode(dialect);\n }\n return BinaryOperationNode.create(node, OperatorNode.create('='), trueNode(dialect));\n}\n\n/**\n * Builds an expression node that checks if a node is false.\n */\nexport function buildIsFalse<Schema extends SchemaDef>(node: OperationNode, dialect: BaseCrudDialect<Schema>) {\n if (isFalseNode(node)) {\n return trueNode(dialect);\n } else if (isTrueNode(node)) {\n return falseNode(dialect);\n }\n return BinaryOperationNode.create(\n // coalesce so null is treated as false\n FunctionNode.create('coalesce', [node, falseNode(dialect)]),\n OperatorNode.create('='),\n falseNode(dialect),\n );\n}\n\n/**\n * Gets the table name from a node.\n */\nexport function getTableName(node: OperationNode | undefined) {\n if (!node) {\n return node;\n }\n if (TableNode.is(node)) {\n return node.table.identifier.name;\n } else if (AliasNode.is(node)) {\n return getTableName(node.node);\n } else if (ReferenceNode.is(node) && node.table) {\n return getTableName(node.table);\n }\n return undefined;\n}\n\nexport function isBeforeInvocation(expr: Expression) {\n return ExpressionUtils.isCall(expr) && expr.function === 'before';\n}\n","import { type OnKyselyQueryArgs, type RuntimePlugin } from '@zenstackhq/runtime';\nimport type { SchemaDef } from '@zenstackhq/runtime/schema';\nimport { check } from './functions';\nimport { PolicyHandler } from './policy-handler';\n\nexport class PolicyPlugin<Schema extends SchemaDef> implements RuntimePlugin<Schema> {\n get id() {\n return 'policy';\n }\n\n get name() {\n return 'Access Policy';\n }\n\n get description() {\n return 'Enforces access policies defined in the schema.';\n }\n\n get functions() {\n return {\n check,\n };\n }\n\n onKyselyQuery({ query, client, proceed }: OnKyselyQueryArgs<Schema>) {\n const handler = new PolicyHandler<Schema>(client);\n return handler.handle(query, proceed);\n }\n}\n"],"mappings":"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","names":["invariant","CRUD","QueryUtils","ExpressionWrapper","ValueNode","invariant","getCrudDialect","InternalError","QueryError","QueryUtils","RejectedByPolicyError","RejectedByPolicyReason","ExpressionUtils","ExpressionVisitor","AliasNode","BinaryOperationNode","ColumnNode","DeleteQueryNode","expressionBuilder","ExpressionWrapper","FromNode","FunctionNode","IdentifierNode","InsertQueryNode","OperationNodeTransformer","OperatorNode","ParensNode","PrimitiveValueListNode","RawNode","ReferenceNode","ReturningNode","SelectAllNode","SelectionNode","SelectQueryNode","sql","TableNode","UpdateQueryNode","ValueListNode","ValueNode","ValuesNode","WhereNode","match","DefaultOperationNodeVisitor","ColumnCollector","DefaultOperationNodeVisitor","columns","collect","node","visitNode","visitColumn","includes","column","name","push","invariant","getCrudDialect","InternalError","QueryError","QueryUtils","ExpressionUtils","AliasNode","BinaryOperationNode","ColumnNode","expressionBuilder","FromNode","FunctionNode","IdentifierNode","OperatorNode","ReferenceNode","SelectionNode","SelectQueryNode","TableNode","ValueListNode","ValueNode","WhereNode","match","invariant","match","ExpressionUtils","ExpressionEvaluator","evaluate","expression","context","result","match","when","ExpressionUtils","isArray","expr","evaluateArray","isBinary","evaluateBinary","isField","evaluateField","isLiteral","evaluateLiteral","isMember","evaluateMember","isUnary","evaluateUnary","isCall","evaluateCall","isThis","thisValue","isNull","exhaustive","function","auth","Error","op","with","operand","val","receiver","member","members","value","field","items","map","item","evaluateCollectionPredicate","left","right","_right","invariant","Array","includes","some","every","ExpressionUtils","AliasNode","AndNode","BinaryOperationNode","FunctionNode","OperatorNode","OrNode","ParensNode","ReferenceNode","TableNode","UnaryOperationNode","ValueNode","trueNode","dialect","ValueNode","createImmediate","transformPrimitive","falseNode","isTrueNode","node","is","value","isFalseNode","conjunction","nodes","length","some","items","filter","n","reduce","acc","AndNode","create","wrapParensIf","OrNode","disjunction","logicalNot","UnaryOperationNode","OperatorNode","predicate","ParensNode","buildIsFalse","node","dialect","isFalseNode","trueNode","isTrueNode","falseNode","BinaryOperationNode","create","FunctionNode","OperatorNode","getTableName","TableNode","is","table","identifier","name","AliasNode","ReferenceNode","undefined","isBeforeInvocation","expr","ExpressionUtils","isCall","function","expressionHandlers","Map","expr","kind","_target","_propertyKey","descriptor","get","set","ExpressionTransformer","dialect","client","getCrudDialect","schema","clientOptions","$schema","$options","auth","$auth","authType","InternalError","transform","expression","context","handler","Error","value","call","_literal","transformValue","_array","ValueListNode","create","items","map","item","_field","fieldDef","QueryUtils","requireField","model","field","relation","createColumnRef","memberFilter","memberSelect","restContext","transformRelationAccess","type","where","mergeWhere","selections","WhereNode","trueNode","conjunction","_null","ValueNode","createImmediate","_binary","op","left","right","disjunction","isAuthCall","transformAuthBinary","transformCollectionPredicate","normalizedLeft","normalizedRight","normalizeBinaryOperationOperands","isNullNode","is","BinaryOperationNode","OperatorNode","FunctionNode","transformNullCheck","transformOperator","operator","invariant","falseNode","isRelationField","ExpressionUtils","isNull","leftRelDef","getFieldDefFromFieldRef","idFields","requireIdFields","makeOrAppendMember","rightRelDef","isAuthMember","ExpressionEvaluator","evaluate","isField","isMember","newContextModel","JSON","stringify","receiver","member","members","memberDef","predicateFilter","alias","undefined","logicalNot","count","predicateResult","match","with","exhaustive","SelectionNode","AliasNode","IdentifierNode","QueryError","authExpr","other","authModel","getModel","Object","values","fields","filter","f","id","name","length","conditions","fieldName","binary","result","buildAnd","buildLogicalNot","transformPrimitive","_unary","operand","mappedOp","otherwise","_call","transformCall","toOperationNode","func","getFunctionImpl","function","eb","expressionBuilder","args","arg","transformCallArg","modelAlias","operation","functionName","functions","plugin","plugins","isLiteral","val","ref","isCall","valNode","valueMemberAccess","_member","isBeforeInvocation","ReferenceNode","ColumnNode","TableNode","isThis","firstMemberFieldDef","slice","SelectQueryNode","startType","receiverField","memberFields","currType","push","fromModel","currNode","i","receiverType","fieldValue","relationModel","m2m","getManyToManyRelation","transformManyToManyRelationAccess","relationFieldDef","keyPairs","ownedByModel","getRelationForeignKeyFieldPairs","condition","fk","pk","fkRef","originModel","buildDelegateBaseFieldSelect","from","FromNode","relationQuery","selectFrom","otherModel","innerJoin","joinTable","join","onRef","otherPKName","otherFkName","parentFkName","parentPKName","column","tableName","baseModel","idField","node","unary","literal","reduce","acc","PolicyHandler","OperationNodeTransformer","dialect","client","getCrudDialect","$schema","$options","kysely","$qb","handle","node","proceed","isCrudQueryNode","RejectedByPolicyError","undefined","RejectedByPolicyReason","OTHER","isMutationQueryNode","transformNode","mutationModel","getMutationModel","InsertQueryNode","is","isManyToManyJoinTable","needCheckPreCreate","constCondition","tryGetConstantPolicy","enforcePreCreatePolicy","hasPostUpdatePolicies","UpdateQueryNode","beforeUpdateInfo","loadBeforeUpdateEntities","where","result","rows","length","invariant","idFields","QueryUtils","requireIdFields","postRow","beforeRow","find","r","every","f","QueryError","idConditions","buildIdConditions","postUpdateFilter","buildPolicyFilter","eb","expressionBuilder","beforeUpdateTable","kind","from","FromNode","create","ParensNode","ValuesNode","map","PrimitiveValueListNode","fields","selections","name","index","def","requireField","castedColumnRef","sql","ref","raw","getFieldSqlType","as","SelectionNode","toOperationNode","postUpdateQuery","selectFrom","select","fn","lit","ExpressionWrapper","conjunction","$if","qb","leftJoin","join","reduce","acc","onRef","postUpdateResult","$condition","NO_ACCESS","returning","onlyReturningId","postProcessMutationResult","readBackResult","processReadBack","CANNOT_READ_BACK","numAffectedRows","BigInt","model","policies","getModelPolicies","beforeUpdateAccessFields","getFieldsAccessForBeforeUpdatePolicies","policyFilter","combinedFilter","query","TableNode","WhereNode","ColumnNode","Set","fieldCollector","ExpressionVisitor","visitMember","e","isBeforeInvocation","receiver","members","add","policy","visit","condition","size","forEach","Array","sort","transformSelectQuery","whereNode","createPolicyFilterForFrom","baseResult","transformJoin","table","extractTableName","filter","alias","nestedSelect","createSelectAll","AliasNode","IdentifierNode","transformInsertQuery","onConflict","updates","updateWhere","processedNode","ReturningNode","transformUpdateQuery","joinFilter","transformDeleteQuery","using","createPolicyFilterForTables","tables","some","s","SelectAllNode","selection","modelDef","requireModel","Object","keys","includes","collector","ColumnCollector","selectedColumns","collect","c","columns","column","valueRows","values","unwrapCreateValueRows","enforcePreCreatePolicyForManyToManyJoinTable","v","enforcePreCreatePolicyForOne","tableName","m2m","resolveManyToManyJoinTable","aIndex","indexOf","aNode","bIndex","bNode","ValueNode","aValue","value","bValue","filterA","firstModel","queryA","firstIdField","filterB","secondModel","queryB","secondIdField","queryNode","$conditionA","$conditionB","allFields","entries","relation","allValues","_def","push","createImmediate","constTable","ValueListNode","preCreateCheck","BinaryOperationNode","FunctionNode","OperatorNode","unwrapCreateValueRow","InternalError","data","isImplicitManyToManyJoinTable","i","item","fieldDef","transformPrimitive","type","array","isArray","RawNode","createWithSql","buildArrayLiteralSQL","operation","p","isTrueExpr","expr","ExpressionUtils","isLiteral","selectResult","disjunction","row","field","ReferenceNode","match","when","getTableName","into","DeleteQueryNode","froms","exhaustive","SelectQueryNode","m2mFilter","getModelPolicyFilterForManyToManyJoinTable","allows","compilePolicyCondition","denies","combinedPolicy","trueNode","falseNode","combinedDenies","d","buildIsFalse","identifier","inner","extractResult","ExpressionTransformer","transform","extractOperations","split","trim","attributes","attr","operations","args","models","getManyToManyRelation","joinTable","sortedRecord","otherModel","otherField","manyToManySorter","firstIdFields","secondIdFields","firstField","secondField","a","b","localeCompare","checkForOperation","aQuery","whereRef","bQuery","and","check","eb","args","client","model","modelAlias","operation","invariant","length","arg1Node","toOperationNode","arg2Node","undefined","ValueNode","is","value","CRUD","includes","fieldName","QueryUtils","extractFieldName","fieldDef","requireField","$schema","relation","array","relationModel","type","joinConditions","fkInfo","getRelationForeignKeyFieldPairs","idFields","requireIdFields","buildBaseSelect","baseModel","field","selectFrom","select","where","and","map","idField","ref","originModel","ownedByModel","push","keyPairs","fk","pk","fkRef","pkRef","joinCondition","policyHandler","PolicyHandler","op","policyCondition","buildPolicyFilter","result","ExpressionWrapper","as","PolicyPlugin","id","name","description","functions","check","onKyselyQuery","query","client","proceed","handler","PolicyHandler","handle"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zenstackhq/plugin-policy",
|
|
3
|
+
"version": "3.0.0-beta.9",
|
|
4
|
+
"description": "ZenStack Policy Plugin",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [],
|
|
7
|
+
"author": "ZenStack Team",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"require": {
|
|
19
|
+
"types": "./dist/index.d.cts",
|
|
20
|
+
"default": "./dist/index.cjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"./package.json": {
|
|
24
|
+
"import": "./package.json",
|
|
25
|
+
"require": "./package.json"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"ts-pattern": "^5.7.1",
|
|
30
|
+
"@zenstackhq/common-helpers": "3.0.0-beta.9",
|
|
31
|
+
"@zenstackhq/sdk": "3.0.0-beta.9",
|
|
32
|
+
"@zenstackhq/runtime": "3.0.0-beta.9"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"kysely": "^0.27.6"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
39
|
+
"@types/pg": "^8.0.0",
|
|
40
|
+
"@zenstackhq/typescript-config": "3.0.0-beta.9",
|
|
41
|
+
"@zenstackhq/eslint-config": "3.0.0-beta.9",
|
|
42
|
+
"@zenstackhq/vitest-config": "3.0.0-beta.9"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc --noEmit && tsup-node",
|
|
46
|
+
"watch": "tsup-node --watch",
|
|
47
|
+
"lint": "eslint src --ext ts",
|
|
48
|
+
"pack": "pnpm pack"
|
|
49
|
+
}
|
|
50
|
+
}
|