@zenstackhq/plugin-policy 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/functions.ts","../src/policy-handler.ts","../src/column-collector.ts","../src/expression-transformer.ts","../src/expression-evaluator.ts","../src/types.ts","../src/utils.ts","../src/plugin.ts"],"sourcesContent":["export * from './plugin';\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { ZModelFunction, ZModelFunctionContext } from '@zenstackhq/orm';\nimport { CRUD, QueryUtils } from '@zenstackhq/orm';\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/orm';\nimport { getCrudDialect, QueryUtils, RejectedByPolicyReason, SchemaUtils, type CRUD_EXT } from '@zenstackhq/orm';\nimport {\n ExpressionUtils,\n type BuiltinType,\n type Expression,\n type MemberExpression,\n type SchemaDef,\n} from '@zenstackhq/orm/schema';\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 {\n buildIsFalse,\n conjunction,\n createRejectedByPolicyError,\n createUnsupportedError,\n disjunction,\n falseNode,\n getTableName,\n isBeforeInvocation,\n trueNode,\n} 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 createRejectedByPolicyError(\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 this.tryRejectNonexistentModel(mutationModel);\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 createRejectedByPolicyError(mutationModel, RejectedByPolicyReason.NO_ACCESS);\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 createRejectedByPolicyError(\n mutationModel,\n RejectedByPolicyReason.OTHER,\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 createRejectedByPolicyError(\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 createRejectedByPolicyError(\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: string) {\n const policies = this.getModelPolicies(model, 'post-update');\n return policies.length > 0;\n }\n\n private async loadBeforeUpdateEntities(\n model: string,\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: string) {\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 SchemaUtils.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 this.tryRejectNonexistentModel(table.model);\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: string,\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: string,\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, 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, 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 createRejectedByPolicyError(\n m2m.firstModel,\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 createRejectedByPolicyError(\n m2m.secondModel,\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: string,\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 createRejectedByPolicyError(model, RejectedByPolicyReason.NO_ACCESS);\n }\n }\n\n private unwrapCreateValueRows(\n node: OperationNode,\n model: string,\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 invariant(false, `Unexpected node kind: ${node.kind} for unwrapping create values`);\n }\n }\n\n private unwrapCreateValueRow(\n data: readonly unknown[],\n model: string,\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: string, 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)!,\n alias: undefined,\n }))\n .when(UpdateQueryNode.is, (node) => {\n if (!node.table) {\n invariant(false, '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 createUnsupportedError('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 invariant(false, `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: string, 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: string; alias?: string } | undefined {\n if (TableNode.is(node)) {\n return { model: node.table.identifier.name };\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 this.tryRejectNonexistentModel(model);\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(model: string, alias: string | undefined, operation: CRUD_EXT, policy: Policy) {\n return new ExpressionTransformer(this.client).transform(policy.condition, {\n modelOrType: model,\n thisType: model, // type name for `this`, never changed during the entire transformation\n thisAlias: alias, // alias for `this`, never changed during the entire transformation\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(this.buildPolicyFilter(m2m.firstModel, undefined, checkForOperation)).as(\n '$conditionA',\n ),\n );\n\n const bQuery = eb\n .selectFrom(m2m.secondModel)\n .whereRef(`${m2m.secondModel}.${m2m.secondIdField}`, '=', `${joinTable}.B`)\n .select(() =>\n new ExpressionWrapper(this.buildPolicyFilter(m2m.secondModel, undefined, checkForOperation)).as(\n '$conditionB',\n ),\n );\n\n return eb.and([aQuery, bQuery]).toOperationNode();\n }\n\n private tryRejectNonexistentModel(model: string) {\n if (!QueryUtils.hasModel(this.client.$schema, model) && !this.isManyToManyJoinTable(model)) {\n throw createRejectedByPolicyError(model, RejectedByPolicyReason.NO_ACCESS);\n }\n }\n\n // #endregion\n}\n","import { KyselyUtils } from '@zenstackhq/orm';\nimport type { ColumnNode, OperationNode } from 'kysely';\n\n/**\n * Collects all column names from a query.\n */\nexport class ColumnCollector extends KyselyUtils.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 QueryUtils,\n SchemaUtils,\n type BaseCrudDialect,\n type ClientContract,\n type CRUD_EXT,\n} from '@zenstackhq/orm';\nimport type {\n BinaryExpression,\n BinaryOperator,\n BuiltinType,\n FieldDef,\n GetModels,\n LiteralExpression,\n MemberExpression,\n UnaryExpression,\n} from '@zenstackhq/orm/schema';\nimport {\n ExpressionUtils,\n type ArrayExpression,\n type CallExpression,\n type Expression,\n type FieldExpression,\n type SchemaDef,\n} from '@zenstackhq/orm/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 { CollectionPredicateOperator } from './types';\nimport {\n conjunction,\n createUnsupportedError,\n disjunction,\n falseNode,\n isBeforeInvocation,\n logicalNot,\n trueNode,\n} from './utils';\n\n/**\n * Context for transforming a policy expression\n */\nexport type ExpressionTransformerContext = {\n /**\n * The current model or type name fields should be resolved against\n */\n modelOrType: string;\n\n /**\n * The alias name that should be used to address a model\n */\n alias?: string;\n\n /**\n * The CRUD operation\n */\n operation: CRUD_EXT;\n\n /**\n * In case of transforming a collection predicate's LHS, the compiled RHS filter expression\n */\n memberFilter?: OperationNode;\n\n /**\n * In case of transforming a collection predicate's LHS, the field name to select as the predicate result\n */\n memberSelect?: SelectionNode;\n\n /**\n * The value object that fields should be evaluated against\n */\n contextValue?: Record<string, any>;\n\n /**\n * The model or type name that `this` keyword refers to\n */\n thisType: string;\n\n /**\n * The table alias name used to compile `this` keyword\n */\n thisAlias?: string;\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 invariant(false, 'Schema does not have an \"authType\" specified');\n }\n return this.schema.authType!;\n }\n\n transform(expression: Expression, context: ExpressionTransformerContext): 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) {\n return ValueListNode.create(expr.items.map((item) => this.transform(item, context)));\n }\n\n @expr('field')\n private _field(expr: FieldExpression, context: ExpressionTransformerContext) {\n if (context.contextValue) {\n // if we're transforming against a value object, fields should be evaluated directly\n const fieldDef = QueryUtils.requireField(this.schema, context.modelOrType, expr.field);\n return this.transformValue(context.contextValue[expr.field], fieldDef.type as BuiltinType);\n }\n\n const fieldDef = QueryUtils.requireField(this.schema, context.modelOrType, 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) {\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 if (operator === '==' || operator === '!=') {\n // equality checks against null\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 } else {\n // otherwise any comparison with null is null\n return ValueNode.createImmediate(null);\n }\n }\n\n private normalizeBinaryOperationOperands(expr: BinaryExpression, context: ExpressionTransformerContext) {\n if (context.contextValue) {\n // no normalization needed if evaluating against a value object\n return { normalizedLeft: expr.left, normalizedRight: expr.right };\n }\n\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.modelOrType)) {\n invariant(ExpressionUtils.isNull(expr.right), 'only null comparison is supported for relation field');\n const leftRelDef = this.getFieldDefFromFieldRef(expr.left, context.modelOrType);\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.modelOrType)) {\n invariant(ExpressionUtils.isNull(expr.left), 'only null comparison is supported for relation field');\n const rightRelDef = this.getFieldDefFromFieldRef(expr.right, context.modelOrType);\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) {\n this.ensureCollectionPredicateOperator(expr.op);\n\n if (this.isAuthMember(expr.left) || context.contextValue) {\n invariant(\n ExpressionUtils.isMember(expr.left) || ExpressionUtils.isField(expr.left),\n 'expected member or field expression',\n );\n\n // LHS of the expression is evaluated as a value\n const evaluator = new ExpressionEvaluator();\n const receiver = evaluator.evaluate(expr.left, { thisValue: context.contextValue, auth: this.auth });\n\n // get LHS's type\n const baseType = this.isAuthMember(expr.left) ? this.authType : context.modelOrType;\n const memberType = this.getMemberType(baseType, expr.left);\n\n // transform the entire expression with a value LHS and the correct context type\n return this.transformValueCollectionPredicate(receiver, expr, { ...context, modelOrType: memberType });\n }\n\n // otherwise, transform the expression with relation joins\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.modelOrType);\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.modelOrType, 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 modelOrType: newContextModel,\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 ensureCollectionPredicateOperator(op: BinaryOperator): asserts op is CollectionPredicateOperator {\n invariant(CollectionPredicateOperator.includes(op as any), 'expected \"?\" or \"!\" or \"^\" operator');\n }\n\n private transformValueCollectionPredicate(\n receiver: any,\n expr: BinaryExpression,\n context: ExpressionTransformerContext,\n ) {\n if (!receiver) {\n return ValueNode.createImmediate(null);\n }\n\n this.ensureCollectionPredicateOperator(expr.op);\n\n const visitor = new SchemaUtils.MatchingExpressionVisitor((e) => ExpressionUtils.isThis(e));\n if (!visitor.find(expr.right)) {\n // right side only refers to the value tree, evaluate directly as an optimization\n const value = new ExpressionEvaluator().evaluate(expr, {\n auth: this.auth,\n thisValue: context.contextValue,\n });\n return this.transformValue(value, 'Boolean');\n } else {\n // right side refers to `this`, need expand into a real filter\n // e.g.: `auth().profiles?[age == this.age], where `this` refer to the containing model\n invariant(Array.isArray(receiver), 'array value is expected');\n\n // for each LHS element, transform RHS\n // e.g.: `auth().profiles[age == this.age]`, each `auth().profiles` element (which is a value)\n // is used to build an expression for the RHS `age == this.age`\n // the transformation happens recursively for nested collection predicates\n const components = receiver.map((item) =>\n this.transform(expr.right, {\n operation: context.operation,\n thisType: context.thisType,\n thisAlias: context.thisAlias,\n modelOrType: context.modelOrType,\n contextValue: item,\n }),\n );\n\n // compose the components based on the operator\n return (\n match(expr.op)\n // some\n .with('?', () => disjunction(this.dialect, components))\n // every\n .with('!', () => conjunction(this.dialect, components))\n // none\n .with('^', () => logicalNot(this.dialect, disjunction(this.dialect, components)))\n .exhaustive()\n );\n }\n }\n\n private getMemberType(receiverType: string, expr: MemberExpression | FieldExpression) {\n if (ExpressionUtils.isField(expr)) {\n const fieldDef = QueryUtils.requireField(this.schema, receiverType, expr.field);\n return fieldDef.type;\n } else {\n let currType = receiverType;\n for (const member of expr.members) {\n const fieldDef = QueryUtils.requireField(this.schema, currType, member);\n currType = fieldDef.type;\n }\n return currType;\n }\n }\n\n private transformAuthBinary(expr: BinaryExpression, context: ExpressionTransformerContext) {\n if (expr.op !== '==' && expr.op !== '!=') {\n throw createUnsupportedError(\n `Unsupported operator for \\`auth()\\` in policy of model \"${context.modelOrType}\": ${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 createUnsupportedError(\n `Unsupported use of \\`auth()\\` in policy of model \"${context.modelOrType}\", 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 const transformed = this.dialect.transformPrimitive(value, type, false) ?? null;\n if (!Array.isArray(transformed)) {\n // simple primitives can be immediate values\n return ValueNode.createImmediate(transformed);\n } else {\n return ValueNode.create(transformed);\n }\n }\n }\n\n @expr('unary')\n // @ts-ignore\n private _unary(expr: UnaryExpression, context: ExpressionTransformerContext) {\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) {\n const result = this.transformCall(expr, context);\n return result.toOperationNode();\n }\n\n private transformCall(expr: CallExpression, context: ExpressionTransformerContext) {\n const func = this.getFunctionImpl(expr.function);\n if (!func) {\n throw createUnsupportedError(`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.modelOrType as GetModels<Schema>,\n modelAlias: context.alias ?? context.modelOrType,\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,\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 createUnsupportedError(`Unsupported argument expression: ${arg.kind}`);\n }\n\n @expr('member')\n // @ts-ignore\n private _member(expr: MemberExpression, context: ExpressionTransformerContext) {\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]!), {\n ...context,\n alias: context.thisAlias,\n modelOrType: context.thisType,\n thisType: context.thisType,\n contextValue: undefined,\n });\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.thisType, 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.modelOrType, expr.receiver.field);\n startType = receiverField.type;\n } else {\n // \"this.\" case\n startType = context.thisType;\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 modelOrType: fromModel,\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 invariant(expr.members.length > 0, 'member expression must have at least one member');\n\n let curr: any = receiver;\n let currType = receiverType;\n for (let i = 0; i < expr.members.length; i++) {\n const field = expr.members[i]!;\n curr = curr?.[field];\n if (curr === undefined) {\n curr = ValueNode.createImmediate(null);\n break;\n }\n currType = QueryUtils.requireField(this.schema, currType, field).type;\n if (i === expr.members.length - 1) {\n // last segment (which is the value), make sure it's transformed\n curr = this.transformValue(curr, currType as BuiltinType);\n }\n }\n return curr;\n }\n\n private transformRelationAccess(\n field: string,\n relationModel: string,\n context: ExpressionTransformerContext,\n ): SelectQueryNode {\n const m2m = QueryUtils.getManyToManyRelation(this.schema, context.modelOrType, field);\n if (m2m) {\n return this.transformManyToManyRelationAccess(m2m, context);\n }\n\n const fromModel = context.modelOrType;\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,\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.modelOrType}.${m2m.parentPKName}`,\n ),\n );\n return relationQuery.toOperationNode();\n }\n\n private createColumnRef(column: string, context: ExpressionTransformerContext) {\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.modelOrType;\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.modelOrType, column);\n if (!fieldDef.originModel || fieldDef.originModel === context.modelOrType) {\n return ReferenceNode.create(ColumnNode.create(column), TableNode.create(tableName));\n }\n\n return this.buildDelegateBaseFieldSelect(context.modelOrType, 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: string) {\n const fieldDef = this.getFieldDefFromFieldRef(expr, model);\n return !!fieldDef?.relation;\n }\n\n private getFieldDefFromFieldRef(expr: Expression, model: string): FieldDef | undefined {\n if (ExpressionUtils.isField(expr)) {\n return QueryUtils.getField(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.getField(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/orm/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 if (!['==', '!='].includes(expr.op) && (left === null || right === null)) {\n // non-equality comparison with null always yields null (follow SQL logic)\n return null;\n }\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 === null || left === undefined) {\n return null;\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 { CRUD_EXT } from '@zenstackhq/orm';\nimport type { Expression } from '@zenstackhq/orm/schema';\n\n/**\n * Access policy kind.\n */\nexport type PolicyKind = 'allow' | 'deny';\n\n/**\n * Access policy operation.\n */\nexport type PolicyOperation = CRUD_EXT | 'all';\n\n/**\n * Access policy definition.\n */\nexport type Policy = {\n kind: PolicyKind;\n operations: readonly PolicyOperation[];\n condition: Expression;\n};\n\n/**\n * Operators allowed for collection predicate expressions.\n */\nexport const CollectionPredicateOperator = ['?', '!', '^'] as const;\n\n/**\n * Operators allowed for collection predicate expressions.\n */\nexport type CollectionPredicateOperator = (typeof CollectionPredicateOperator)[number];\n","import { ORMError, ORMErrorReason, RejectedByPolicyReason, type BaseCrudDialect } from '@zenstackhq/orm';\nimport { ExpressionUtils, type Expression, type SchemaDef } from '@zenstackhq/orm/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\nexport function createRejectedByPolicyError(\n model: string | undefined,\n reason: RejectedByPolicyReason,\n message?: string,\n) {\n const err = new ORMError(ORMErrorReason.REJECTED_BY_POLICY, message ?? 'operation is rejected by access policies');\n err.rejectedByPolicyReason = reason;\n err.model = model;\n return err;\n}\n\nexport function createUnsupportedError(message: string) {\n return new ORMError(ORMErrorReason.NOT_SUPPORTED, message);\n}\n","import { type OnKyselyQueryArgs, type RuntimePlugin } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/orm/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":["import_common_helpers","import_orm","import_kysely","import_common_helpers","import_orm","import_schema","import_kysely","import_ts_pattern","ColumnCollector","KyselyUtils","DefaultOperationNodeVisitor","columns","collect","node","visitNode","visitColumn","includes","column","name","push","import_common_helpers","import_orm","import_schema","import_kysely","import_ts_pattern","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","includes","_right","invariant","Array","undefined","some","every","CollectionPredicateOperator","import_orm","import_schema","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","createRejectedByPolicyError","model","reason","message","err","ORMError","ORMErrorReason","REJECTED_BY_POLICY","rejectedByPolicyReason","createUnsupportedError","NOT_SUPPORTED","expressionHandlers","Map","expr","kind","_target","_propertyKey","descriptor","get","set","ExpressionTransformer","dialect","client","getCrudDialect","schema","clientOptions","$schema","$options","auth","$auth","authType","invariant","transform","expression","context","handler","Error","value","call","_literal","transformValue","_array","ValueListNode","create","items","map","item","_field","contextValue","fieldDef","QueryUtils","requireField","modelOrType","field","type","relation","createColumnRef","memberFilter","memberSelect","restContext","transformRelationAccess","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","falseNode","isRelationField","ExpressionUtils","isNull","leftRelDef","getFieldDefFromFieldRef","idFields","requireIdFields","makeOrAppendMember","rightRelDef","ensureCollectionPredicateOperator","isAuthMember","isMember","isField","evaluator","ExpressionEvaluator","receiver","evaluate","thisValue","baseType","memberType","getMemberType","transformValueCollectionPredicate","newContextModel","JSON","stringify","member","members","memberDef","predicateFilter","alias","undefined","logicalNot","count","predicateResult","match","with","exhaustive","SelectionNode","AliasNode","IdentifierNode","CollectionPredicateOperator","includes","visitor","SchemaUtils","MatchingExpressionVisitor","e","isThis","find","Array","isArray","components","operation","thisType","thisAlias","receiverType","currType","createUnsupportedError","authExpr","other","authModel","getModel","Object","values","fields","filter","f","id","name","length","conditions","fieldName","binary","result","buildAnd","buildLogicalNot","transformed","transformPrimitive","_unary","operand","mappedOp","otherwise","_call","transformCall","toOperationNode","func","getFunctionImpl","function","eb","expressionBuilder","args","arg","transformCallArg","model","modelAlias","functionName","functions","plugin","plugins","isLiteral","val","ref","isCall","valNode","valueMemberAccess","_member","isBeforeInvocation","ReferenceNode","ColumnNode","TableNode","firstMemberFieldDef","slice","SelectQueryNode","startType","receiverField","memberFields","push","fromModel","currNode","i","curr","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","getField","PolicyHandler","OperationNodeTransformer","dialect","client","getCrudDialect","$schema","$options","kysely","$qb","handle","node","proceed","isCrudQueryNode","createRejectedByPolicyError","undefined","RejectedByPolicyReason","OTHER","isMutationQueryNode","transformNode","mutationModel","getMutationModel","tryRejectNonexistentModel","InsertQueryNode","is","isManyToManyJoinTable","needCheckPreCreate","constCondition","tryGetConstantPolicy","NO_ACCESS","enforcePreCreatePolicy","hasPostUpdatePolicies","UpdateQueryNode","beforeUpdateInfo","loadBeforeUpdateEntities","where","result","rows","length","invariant","idFields","QueryUtils","requireIdFields","postRow","beforeRow","find","r","every","f","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","returning","onlyReturningId","postProcessMutationResult","readBackResult","processReadBack","CANNOT_READ_BACK","numAffectedRows","BigInt","model","policies","getModelPolicies","beforeUpdateAccessFields","getFieldsAccessForBeforeUpdatePolicies","policyFilter","combinedFilter","query","TableNode","WhereNode","ColumnNode","Set","fieldCollector","SchemaUtils","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","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","createUnsupportedError","exhaustive","SelectQueryNode","m2mFilter","getModelPolicyFilterForManyToManyJoinTable","allows","compilePolicyCondition","denies","combinedPolicy","trueNode","falseNode","combinedDenies","d","buildIsFalse","identifier","inner","extractResult","ExpressionTransformer","transform","modelOrType","thisType","thisAlias","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","hasModel","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"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/functions.ts","../src/policy-handler.ts","../src/column-collector.ts","../src/expression-transformer.ts","../src/expression-evaluator.ts","../src/types.ts","../src/utils.ts","../src/plugin.ts"],"sourcesContent":["export * from './plugin';\n","import { invariant } from '@zenstackhq/common-helpers';\nimport type { ZModelFunction, ZModelFunctionContext } from '@zenstackhq/orm';\nimport { CRUD, QueryUtils } from '@zenstackhq/orm';\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, CRUD_EXT, ProceedKyselyQueryFunction } from '@zenstackhq/orm';\nimport { getCrudDialect, QueryUtils, RejectedByPolicyReason, SchemaUtils } from '@zenstackhq/orm';\nimport {\n ExpressionUtils,\n type BuiltinType,\n type Expression,\n type MemberExpression,\n type SchemaDef,\n} from '@zenstackhq/orm/schema';\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 {\n buildIsFalse,\n conjunction,\n createRejectedByPolicyError,\n createUnsupportedError,\n disjunction,\n falseNode,\n getTableName,\n isBeforeInvocation,\n isTrueNode,\n logicalNot,\n trueNode,\n} from './utils';\n\nexport type CrudQueryNode = SelectQueryNode | InsertQueryNode | UpdateQueryNode | DeleteQueryNode;\n\nexport type MutationQueryNode = InsertQueryNode | UpdateQueryNode | DeleteQueryNode;\n\ntype FieldLevelPolicyOperations = Exclude<CRUD_EXT, 'create' | 'delete'>;\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 // #region main entry point\n\n async handle(node: RootOperationNode, proceed: ProceedKyselyQueryFunction) {\n if (!this.isCrudQueryNode(node)) {\n // non-CRUD queries are not allowed\n throw createRejectedByPolicyError(\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 // reject non-existing model\n this.tryRejectNonexistentModel(mutationModel);\n\n // #region Pre mutation work\n\n // create\n if (InsertQueryNode.is(node)) {\n await this.preCreateCheck(mutationModel, node, proceed);\n }\n\n // update\n if (UpdateQueryNode.is(node)) {\n await this.preUpdateCheck(mutationModel, node, proceed);\n }\n\n // post-update: load before-update entities if needed\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 // #endregion\n\n // #region mutation execution\n\n const result = await proceed(this.transformNode(node));\n\n // #endregion\n\n // #region 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 createRejectedByPolicyError(\n mutationModel,\n RejectedByPolicyReason.OTHER,\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 createRejectedByPolicyError(\n mutationModel,\n RejectedByPolicyReason.NO_ACCESS,\n 'some or all updated rows failed to pass post-update policy check',\n );\n }\n\n // #endregion\n }\n\n // #region 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 createRejectedByPolicyError(\n mutationModel,\n RejectedByPolicyReason.CANNOT_READ_BACK,\n 'result is not allowed to be read back',\n );\n }\n return readBackResult;\n }\n\n // #endregion\n }\n\n private async preCreateCheck(mutationModel: string, node: InsertQueryNode, proceed: ProceedKyselyQueryFunction) {\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 createRejectedByPolicyError(mutationModel, RejectedByPolicyReason.NO_ACCESS);\n }\n }\n\n if (needCheckPreCreate) {\n await this.enforcePreCreatePolicy(node, mutationModel, isManyToManyJoinTable, proceed);\n }\n }\n\n private async preUpdateCheck(mutationModel: string, node: UpdateQueryNode, proceed: ProceedKyselyQueryFunction) {\n // check if any rows will be filtered out by field-level update policies, and reject the whole update if so\n\n const fieldsToUpdate =\n node.updates\n ?.map((u) => (ColumnNode.is(u.column) ? u.column.column.name : undefined))\n .filter((f): f is string => !!f) ?? [];\n const fieldUpdatePolicies = fieldsToUpdate.map((f) => this.buildFieldPolicyFilter(mutationModel, f, 'update'));\n\n // filter combining field-level update policies\n const fieldLevelFilter = conjunction(this.dialect, fieldUpdatePolicies);\n if (isTrueNode(fieldLevelFilter)) {\n return;\n }\n\n // model-level update policy filter\n const modelLevelFilter = this.buildPolicyFilter(mutationModel, undefined, 'update');\n\n // filter combining model-level update policy and update where\n const updateFilter = conjunction(this.dialect, [modelLevelFilter, node.where?.where ?? trueNode(this.dialect)]);\n\n // build a query to count rows that will be rejected by field-level policies\n // `SELECT COALESCE(SUM((not <fieldsFilter>) as integer), 0) AS $filteredCount WHERE <updateFilter> AND <rowFilter>`\n const preUpdateCheckQuery = expressionBuilder<any, any>()\n .selectFrom(mutationModel)\n .select((eb) =>\n eb.fn\n .coalesce(\n eb.fn.sum(\n eb.cast(new ExpressionWrapper(logicalNot(this.dialect, fieldLevelFilter)), 'integer'),\n ),\n eb.lit(0),\n )\n .as('$filteredCount'),\n )\n .where(() => new ExpressionWrapper(updateFilter));\n\n const preUpdateResult = await proceed(preUpdateCheckQuery.toOperationNode());\n if (preUpdateResult.rows[0].$filteredCount > 0) {\n throw createRejectedByPolicyError(\n mutationModel,\n RejectedByPolicyReason.NO_ACCESS,\n 'some rows cannot be updated due to field policies',\n );\n }\n }\n\n // #endregion\n\n // #region Transformations\n\n protected override transformSelectQuery(node: SelectQueryNode) {\n if (!node.from) {\n return super.transformSelectQuery(node);\n }\n\n // reject non-existing tables\n this.tryRejectNonexistingTables(node.from.froms);\n\n let result = super.transformSelectQuery(node);\n\n const hasFieldLevelPolicies = node.from.froms.some((table) => {\n const extractedTable = this.extractTableName(table);\n if (extractedTable) {\n return this.hasFieldLevelPolicies(extractedTable.model, 'read');\n } else {\n return false;\n }\n });\n\n if (hasFieldLevelPolicies) {\n // when a select query involves field-level policies, we build a nested query selecting all fields guarded with:\n // CASE WHEN <field policy> THEN <field> ELSE NULL END\n // model-level policies are also applied at this nested query level\n\n const updatedFroms: OperationNode[] = [];\n for (const table of result.from!.froms) {\n const extractedTable = this.extractTableName(table);\n if (extractedTable?.model && QueryUtils.getModel(this.client.$schema, extractedTable.model)) {\n const { query } = this.createSelectAllFieldsWithPolicies(\n extractedTable.model,\n extractedTable.alias,\n 'read',\n );\n updatedFroms.push(query);\n } else {\n // keep the original from\n updatedFroms.push(table);\n }\n }\n result = { ...result, from: FromNode.create(updatedFroms) };\n } else {\n // when there's no field-level policies, we merge model-level policy filters into where clause directly\n // for generating simpler SQL\n\n let whereNode = result.where;\n const policyFilter = this.createPolicyFilterForFrom(result.from);\n if (policyFilter && !isTrueNode(policyFilter)) {\n whereNode = WhereNode.create(\n whereNode?.where ? conjunction(this.dialect, [whereNode.where, policyFilter]) : policyFilter,\n );\n }\n result = { ...result, where: whereNode };\n }\n\n return result;\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 // reject non-existing model\n this.tryRejectNonexistentModel(table.model);\n\n if (!QueryUtils.getModel(this.client.$schema, table.model)) {\n // not a defined model, could be m2m join table, keep as is\n return super.transformJoin(node);\n }\n\n const result = super.transformJoin(node);\n\n const { hasPolicies, query: nestedQuery } = this.createSelectAllFieldsWithPolicies(\n table.model,\n table.alias,\n 'read',\n );\n\n // join table has no policies, keep it as is\n if (!hasPolicies) {\n return result;\n }\n\n // otherwise replace it with the nested query guarded with policies\n return {\n ...result,\n table: nestedQuery,\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 // reject non-existing tables\n this.tryRejectNonexistingTables(node.from.froms);\n\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 // reject non-existing tables\n this.tryRejectNonexistingTables(node.using.tables);\n\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 post-update\n\n private async loadBeforeUpdateEntities(\n model: string,\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: string) {\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 SchemaUtils.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 private hasPostUpdatePolicies(model: string) {\n const policies = this.getModelPolicies(model, 'post-update');\n return policies.length > 0;\n }\n\n // #endregion\n\n // #region field-level policies\n\n private createSelectAllFieldsWithPolicies(\n model: string,\n alias: string | undefined,\n operation: FieldLevelPolicyOperations,\n ) {\n let hasPolicies = false;\n const modelDef = QueryUtils.requireModel(this.client.$schema, model);\n\n let selections: SelectionNode[] = [];\n for (const fieldDef of Object.values(modelDef.fields).filter(\n // exclude relation/computed/inherited fields\n (f) => !f.relation && !f.computed && !f.originModel,\n )) {\n const { hasPolicies: fieldHasPolicies, selection } = this.createFieldSelectionWithPolicy(\n model,\n fieldDef.name,\n operation,\n );\n hasPolicies = hasPolicies || fieldHasPolicies;\n selections.push(selection);\n }\n\n if (!hasPolicies) {\n // if there're no field-level policies, simplify to select all\n selections = [SelectionNode.create(SelectAllNode.create())];\n }\n\n const modelPolicyFilter = this.buildPolicyFilter(model, alias, operation);\n if (!isTrueNode(modelPolicyFilter)) {\n hasPolicies = true;\n }\n\n const nestedQuery: SelectQueryNode = {\n kind: 'SelectQueryNode',\n from: FromNode.create([TableNode.create(model)]),\n where: isTrueNode(modelPolicyFilter) ? undefined : WhereNode.create(modelPolicyFilter),\n selections,\n };\n\n return {\n hasPolicies,\n query: AliasNode.create(ParensNode.create(nestedQuery), IdentifierNode.create(alias ?? model)),\n };\n }\n\n private createFieldSelectionWithPolicy(model: string, field: string, operation: FieldLevelPolicyOperations) {\n const filter = this.buildFieldPolicyFilter(model, field, operation);\n if (isTrueNode(filter)) {\n return { hasPolicies: false, selection: SelectionNode.create(ColumnNode.create(field)) };\n }\n const eb = expressionBuilder<any, any>();\n // CASE WHEN <filter> THEN <field> ELSE NULL END\n const selection = eb\n .case()\n .when(new ExpressionWrapper(filter))\n .then(eb.ref(field))\n .else(null)\n .end()\n .as(field)\n .toOperationNode();\n return { hasPolicies: true, selection: SelectionNode.create(selection) };\n }\n\n private hasFieldLevelPolicies(model: string, operation: FieldLevelPolicyOperations) {\n const modelDef = QueryUtils.getModel(this.client.$schema, model);\n if (!modelDef) {\n return false;\n }\n return Object.keys(modelDef.fields).some((field) => this.getFieldPolicies(model, field, operation).length > 0);\n }\n\n private buildFieldPolicyFilter(model: string, field: string, operation: FieldLevelPolicyOperations) {\n const policies = this.getFieldPolicies(model, field, operation);\n\n const allows = policies\n .filter((policy) => policy.kind === 'allow')\n .map((policy) => this.compilePolicyCondition(model, model, operation, policy));\n\n const denies = policies\n .filter((policy) => policy.kind === 'deny')\n .map((policy) => this.compilePolicyCondition(model, model, 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 // field access is allowed by default\n combinedPolicy = trueNode(this.dialect);\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 // #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: string,\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: string,\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, 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, 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 createRejectedByPolicyError(\n m2m.firstModel,\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 createRejectedByPolicyError(\n m2m.secondModel,\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: string,\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 createRejectedByPolicyError(model, RejectedByPolicyReason.NO_ACCESS);\n }\n }\n\n private unwrapCreateValueRows(\n node: OperationNode,\n model: string,\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 invariant(false, `Unexpected node kind: ${node.kind} for unwrapping create values`);\n }\n }\n\n private unwrapCreateValueRow(\n data: readonly unknown[],\n model: string,\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: string, 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)!,\n alias: undefined,\n }))\n .when(UpdateQueryNode.is, (node) => {\n if (!node.table) {\n invariant(false, '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 createUnsupportedError('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 invariant(false, `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: string, 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: string; alias?: string } | undefined {\n if (TableNode.is(node)) {\n return { model: node.table.identifier.name };\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(model: string, alias: string | undefined, operation: CRUD_EXT, policy: Policy) {\n return new ExpressionTransformer(this.client).transform(policy.condition, {\n modelOrType: model,\n thisType: model, // type name for `this`, never changed during the entire transformation\n thisAlias: alias, // alias for `this`, never changed during the entire transformation\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 getFieldPolicies(model: string, field: string, operation: FieldLevelPolicyOperations) {\n const fieldDef = QueryUtils.requireField(this.client.$schema, model, field);\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 (fieldDef.attributes) {\n result.push(\n ...fieldDef.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((policy) => policy.operations.includes('all') || policy.operations.includes(operation)),\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(this.buildPolicyFilter(m2m.firstModel, undefined, checkForOperation)).as(\n '$conditionA',\n ),\n );\n\n const bQuery = eb\n .selectFrom(m2m.secondModel)\n .whereRef(`${m2m.secondModel}.${m2m.secondIdField}`, '=', `${joinTable}.B`)\n .select(() =>\n new ExpressionWrapper(this.buildPolicyFilter(m2m.secondModel, undefined, checkForOperation)).as(\n '$conditionB',\n ),\n );\n\n return eb.and([aQuery, bQuery]).toOperationNode();\n }\n\n private tryRejectNonexistentModel(model: string) {\n if (!QueryUtils.hasModel(this.client.$schema, model) && !this.isManyToManyJoinTable(model)) {\n throw createRejectedByPolicyError(model, RejectedByPolicyReason.NO_ACCESS);\n }\n }\n\n private tryRejectNonexistingTables(tables: readonly OperationNode[]) {\n for (const table of tables) {\n const extractResult = this.extractTableName(table);\n if (extractResult) {\n this.tryRejectNonexistentModel(extractResult.model);\n }\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 // #endregion\n}\n","import { KyselyUtils } from '@zenstackhq/orm';\nimport type { ColumnNode, OperationNode } from 'kysely';\n\n/**\n * Collects all column names from a query.\n */\nexport class ColumnCollector extends KyselyUtils.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 QueryUtils,\n SchemaUtils,\n type BaseCrudDialect,\n type ClientContract,\n type CRUD_EXT,\n} from '@zenstackhq/orm';\nimport type {\n BinaryExpression,\n BinaryOperator,\n BuiltinType,\n FieldDef,\n GetModels,\n LiteralExpression,\n MemberExpression,\n UnaryExpression,\n} from '@zenstackhq/orm/schema';\nimport {\n ExpressionUtils,\n type ArrayExpression,\n type CallExpression,\n type Expression,\n type FieldExpression,\n type SchemaDef,\n} from '@zenstackhq/orm/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 { CollectionPredicateOperator } from './types';\nimport {\n conjunction,\n createUnsupportedError,\n disjunction,\n falseNode,\n isBeforeInvocation,\n logicalNot,\n trueNode,\n} from './utils';\n\n/**\n * Context for transforming a policy expression\n */\nexport type ExpressionTransformerContext = {\n /**\n * The current model or type name fields should be resolved against\n */\n modelOrType: string;\n\n /**\n * The alias name that should be used to address a model\n */\n alias?: string;\n\n /**\n * The CRUD operation\n */\n operation: CRUD_EXT;\n\n /**\n * In case of transforming a collection predicate's LHS, the compiled RHS filter expression\n */\n memberFilter?: OperationNode;\n\n /**\n * In case of transforming a collection predicate's LHS, the field name to select as the predicate result\n */\n memberSelect?: SelectionNode;\n\n /**\n * The value object that fields should be evaluated against\n */\n contextValue?: Record<string, any>;\n\n /**\n * The model or type name that `this` keyword refers to\n */\n thisType: string;\n\n /**\n * The table alias name used to compile `this` keyword\n */\n thisAlias?: string;\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 invariant(false, 'Schema does not have an \"authType\" specified');\n }\n return this.schema.authType!;\n }\n\n transform(expression: Expression, context: ExpressionTransformerContext): 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) {\n return ValueListNode.create(expr.items.map((item) => this.transform(item, context)));\n }\n\n @expr('field')\n private _field(expr: FieldExpression, context: ExpressionTransformerContext) {\n if (context.contextValue) {\n // if we're transforming against a value object, fields should be evaluated directly\n const fieldDef = QueryUtils.requireField(this.schema, context.modelOrType, expr.field);\n return this.transformValue(context.contextValue[expr.field], fieldDef.type as BuiltinType);\n }\n\n const fieldDef = QueryUtils.requireField(this.schema, context.modelOrType, 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) {\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 if (operator === '==' || operator === '!=') {\n // equality checks against null\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 } else {\n // otherwise any comparison with null is null\n return ValueNode.createImmediate(null);\n }\n }\n\n private normalizeBinaryOperationOperands(expr: BinaryExpression, context: ExpressionTransformerContext) {\n if (context.contextValue) {\n // no normalization needed if evaluating against a value object\n return { normalizedLeft: expr.left, normalizedRight: expr.right };\n }\n\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.modelOrType)) {\n invariant(ExpressionUtils.isNull(expr.right), 'only null comparison is supported for relation field');\n const leftRelDef = this.getFieldDefFromFieldRef(expr.left, context.modelOrType);\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.modelOrType)) {\n invariant(ExpressionUtils.isNull(expr.left), 'only null comparison is supported for relation field');\n const rightRelDef = this.getFieldDefFromFieldRef(expr.right, context.modelOrType);\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) {\n this.ensureCollectionPredicateOperator(expr.op);\n\n if (this.isAuthMember(expr.left) || context.contextValue) {\n invariant(\n ExpressionUtils.isMember(expr.left) || ExpressionUtils.isField(expr.left),\n 'expected member or field expression',\n );\n\n // LHS of the expression is evaluated as a value\n const evaluator = new ExpressionEvaluator();\n const receiver = evaluator.evaluate(expr.left, { thisValue: context.contextValue, auth: this.auth });\n\n // get LHS's type\n const baseType = this.isAuthMember(expr.left) ? this.authType : context.modelOrType;\n const memberType = this.getMemberType(baseType, expr.left);\n\n // transform the entire expression with a value LHS and the correct context type\n return this.transformValueCollectionPredicate(receiver, expr, { ...context, modelOrType: memberType });\n }\n\n // otherwise, transform the expression with relation joins\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.modelOrType);\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.modelOrType, 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 modelOrType: newContextModel,\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 ensureCollectionPredicateOperator(op: BinaryOperator): asserts op is CollectionPredicateOperator {\n invariant(CollectionPredicateOperator.includes(op as any), 'expected \"?\" or \"!\" or \"^\" operator');\n }\n\n private transformValueCollectionPredicate(\n receiver: any,\n expr: BinaryExpression,\n context: ExpressionTransformerContext,\n ) {\n if (!receiver) {\n return ValueNode.createImmediate(null);\n }\n\n this.ensureCollectionPredicateOperator(expr.op);\n\n const visitor = new SchemaUtils.MatchingExpressionVisitor((e) => ExpressionUtils.isThis(e));\n if (!visitor.find(expr.right)) {\n // right side only refers to the value tree, evaluate directly as an optimization\n const value = new ExpressionEvaluator().evaluate(expr, {\n auth: this.auth,\n thisValue: context.contextValue,\n });\n return this.transformValue(value, 'Boolean');\n } else {\n // right side refers to `this`, need expand into a real filter\n // e.g.: `auth().profiles?[age == this.age], where `this` refer to the containing model\n invariant(Array.isArray(receiver), 'array value is expected');\n\n // for each LHS element, transform RHS\n // e.g.: `auth().profiles[age == this.age]`, each `auth().profiles` element (which is a value)\n // is used to build an expression for the RHS `age == this.age`\n // the transformation happens recursively for nested collection predicates\n const components = receiver.map((item) =>\n this.transform(expr.right, {\n operation: context.operation,\n thisType: context.thisType,\n thisAlias: context.thisAlias,\n modelOrType: context.modelOrType,\n contextValue: item,\n }),\n );\n\n // compose the components based on the operator\n return (\n match(expr.op)\n // some\n .with('?', () => disjunction(this.dialect, components))\n // every\n .with('!', () => conjunction(this.dialect, components))\n // none\n .with('^', () => logicalNot(this.dialect, disjunction(this.dialect, components)))\n .exhaustive()\n );\n }\n }\n\n private getMemberType(receiverType: string, expr: MemberExpression | FieldExpression) {\n if (ExpressionUtils.isField(expr)) {\n const fieldDef = QueryUtils.requireField(this.schema, receiverType, expr.field);\n return fieldDef.type;\n } else {\n let currType = receiverType;\n for (const member of expr.members) {\n const fieldDef = QueryUtils.requireField(this.schema, currType, member);\n currType = fieldDef.type;\n }\n return currType;\n }\n }\n\n private transformAuthBinary(expr: BinaryExpression, context: ExpressionTransformerContext) {\n if (expr.op !== '==' && expr.op !== '!=') {\n throw createUnsupportedError(\n `Unsupported operator for \\`auth()\\` in policy of model \"${context.modelOrType}\": ${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 createUnsupportedError(\n `Unsupported use of \\`auth()\\` in policy of model \"${context.modelOrType}\", 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 const transformed = this.dialect.transformPrimitive(value, type, false) ?? null;\n if (!Array.isArray(transformed)) {\n // simple primitives can be immediate values\n return ValueNode.createImmediate(transformed);\n } else {\n return ValueNode.create(transformed);\n }\n }\n }\n\n @expr('unary')\n // @ts-ignore\n private _unary(expr: UnaryExpression, context: ExpressionTransformerContext) {\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) {\n const result = this.transformCall(expr, context);\n return result.toOperationNode();\n }\n\n private transformCall(expr: CallExpression, context: ExpressionTransformerContext) {\n const func = this.getFunctionImpl(expr.function);\n if (!func) {\n throw createUnsupportedError(`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.modelOrType as GetModels<Schema>,\n modelAlias: context.alias ?? context.modelOrType,\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,\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 createUnsupportedError(`Unsupported argument expression: ${arg.kind}`);\n }\n\n @expr('member')\n // @ts-ignore\n private _member(expr: MemberExpression, context: ExpressionTransformerContext) {\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]!), {\n ...context,\n alias: context.thisAlias,\n modelOrType: context.thisType,\n thisType: context.thisType,\n contextValue: undefined,\n });\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.thisType, 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.modelOrType, expr.receiver.field);\n startType = receiverField.type;\n } else {\n // \"this.\" case\n startType = context.thisType;\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 modelOrType: fromModel,\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 invariant(expr.members.length > 0, 'member expression must have at least one member');\n\n let curr: any = receiver;\n let currType = receiverType;\n for (let i = 0; i < expr.members.length; i++) {\n const field = expr.members[i]!;\n curr = curr?.[field];\n if (curr === undefined) {\n curr = ValueNode.createImmediate(null);\n break;\n }\n currType = QueryUtils.requireField(this.schema, currType, field).type;\n if (i === expr.members.length - 1) {\n // last segment (which is the value), make sure it's transformed\n curr = this.transformValue(curr, currType as BuiltinType);\n }\n }\n return curr;\n }\n\n private transformRelationAccess(\n field: string,\n relationModel: string,\n context: ExpressionTransformerContext,\n ): SelectQueryNode {\n const m2m = QueryUtils.getManyToManyRelation(this.schema, context.modelOrType, field);\n if (m2m) {\n return this.transformManyToManyRelationAccess(m2m, context);\n }\n\n const fromModel = context.modelOrType;\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,\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.modelOrType}.${m2m.parentPKName}`,\n ),\n );\n return relationQuery.toOperationNode();\n }\n\n private createColumnRef(column: string, context: ExpressionTransformerContext) {\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.modelOrType;\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.modelOrType, column);\n if (!fieldDef.originModel || fieldDef.originModel === context.modelOrType) {\n return ReferenceNode.create(ColumnNode.create(column), TableNode.create(tableName));\n }\n\n return this.buildDelegateBaseFieldSelect(context.modelOrType, 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: string) {\n const fieldDef = this.getFieldDefFromFieldRef(expr, model);\n return !!fieldDef?.relation;\n }\n\n private getFieldDefFromFieldRef(expr: Expression, model: string): FieldDef | undefined {\n if (ExpressionUtils.isField(expr)) {\n return QueryUtils.getField(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.getField(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/orm/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 if (!['==', '!='].includes(expr.op) && (left === null || right === null)) {\n // non-equality comparison with null always yields null (follow SQL logic)\n return null;\n }\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 === null || left === undefined) {\n return null;\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 { CRUD_EXT } from '@zenstackhq/orm';\nimport type { Expression } from '@zenstackhq/orm/schema';\n\n/**\n * Access policy kind.\n */\nexport type PolicyKind = 'allow' | 'deny';\n\n/**\n * Access policy operation.\n */\nexport type PolicyOperation = CRUD_EXT | 'all';\n\n/**\n * Access policy definition.\n */\nexport type Policy = {\n kind: PolicyKind;\n operations: readonly PolicyOperation[];\n condition: Expression;\n};\n\n/**\n * Operators allowed for collection predicate expressions.\n */\nexport const CollectionPredicateOperator = ['?', '!', '^'] as const;\n\n/**\n * Operators allowed for collection predicate expressions.\n */\nexport type CollectionPredicateOperator = (typeof CollectionPredicateOperator)[number];\n","import { ORMError, ORMErrorReason, RejectedByPolicyReason, type BaseCrudDialect } from '@zenstackhq/orm';\nimport { ExpressionUtils, type Expression, type SchemaDef } from '@zenstackhq/orm/schema';\nimport type { OperationNode } from 'kysely';\nimport {\n AliasNode,\n AndNode,\n BinaryOperationNode,\n ColumnNode,\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\n/**\n * Gets the column name from a node.\n */\nexport function getColumnName(node: OperationNode | undefined) {\n if (!node) {\n return node;\n }\n if (AliasNode.is(node)) {\n return getColumnName(node.node);\n } else if (ReferenceNode.is(node)) {\n return getColumnName(node.column);\n } else if (ColumnNode.is(node)) {\n return node.column.name;\n }\n return undefined;\n}\n\nexport function isBeforeInvocation(expr: Expression) {\n return ExpressionUtils.isCall(expr) && expr.function === 'before';\n}\n\nexport function createRejectedByPolicyError(\n model: string | undefined,\n reason: RejectedByPolicyReason,\n message?: string,\n) {\n const err = new ORMError(ORMErrorReason.REJECTED_BY_POLICY, message ?? 'operation is rejected by access policies');\n err.rejectedByPolicyReason = reason;\n err.model = model;\n return err;\n}\n\nexport function createUnsupportedError(message: string) {\n return new ORMError(ORMErrorReason.NOT_SUPPORTED, message);\n}\n","import { type OnKyselyQueryArgs, type RuntimePlugin } from '@zenstackhq/orm';\nimport type { SchemaDef } from '@zenstackhq/orm/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":["import_common_helpers","import_orm","import_kysely","import_common_helpers","import_orm","import_schema","import_kysely","import_ts_pattern","ColumnCollector","KyselyUtils","DefaultOperationNodeVisitor","columns","collect","node","visitNode","visitColumn","includes","column","name","push","import_common_helpers","import_orm","import_schema","import_kysely","import_ts_pattern","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","includes","_right","invariant","Array","undefined","some","every","CollectionPredicateOperator","import_orm","import_schema","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","createRejectedByPolicyError","model","reason","message","err","ORMError","ORMErrorReason","REJECTED_BY_POLICY","rejectedByPolicyReason","createUnsupportedError","NOT_SUPPORTED","expressionHandlers","Map","expr","kind","_target","_propertyKey","descriptor","get","set","ExpressionTransformer","dialect","client","getCrudDialect","schema","clientOptions","$schema","$options","auth","$auth","authType","invariant","transform","expression","context","handler","Error","value","call","_literal","transformValue","_array","ValueListNode","create","items","map","item","_field","contextValue","fieldDef","QueryUtils","requireField","modelOrType","field","type","relation","createColumnRef","memberFilter","memberSelect","restContext","transformRelationAccess","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","falseNode","isRelationField","ExpressionUtils","isNull","leftRelDef","getFieldDefFromFieldRef","idFields","requireIdFields","makeOrAppendMember","rightRelDef","ensureCollectionPredicateOperator","isAuthMember","isMember","isField","evaluator","ExpressionEvaluator","receiver","evaluate","thisValue","baseType","memberType","getMemberType","transformValueCollectionPredicate","newContextModel","JSON","stringify","member","members","memberDef","predicateFilter","alias","undefined","logicalNot","count","predicateResult","match","with","exhaustive","SelectionNode","AliasNode","IdentifierNode","CollectionPredicateOperator","includes","visitor","SchemaUtils","MatchingExpressionVisitor","e","isThis","find","Array","isArray","components","operation","thisType","thisAlias","receiverType","currType","createUnsupportedError","authExpr","other","authModel","getModel","Object","values","fields","filter","f","id","name","length","conditions","fieldName","binary","result","buildAnd","buildLogicalNot","transformed","transformPrimitive","_unary","operand","mappedOp","otherwise","_call","transformCall","toOperationNode","func","getFunctionImpl","function","eb","expressionBuilder","args","arg","transformCallArg","model","modelAlias","functionName","functions","plugin","plugins","isLiteral","val","ref","isCall","valNode","valueMemberAccess","_member","isBeforeInvocation","ReferenceNode","ColumnNode","TableNode","firstMemberFieldDef","slice","SelectQueryNode","startType","receiverField","memberFields","push","fromModel","currNode","i","curr","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","getField","PolicyHandler","OperationNodeTransformer","dialect","client","getCrudDialect","$schema","$options","kysely","$qb","handle","node","proceed","isCrudQueryNode","createRejectedByPolicyError","undefined","RejectedByPolicyReason","OTHER","isMutationQueryNode","transformNode","mutationModel","getMutationModel","tryRejectNonexistentModel","InsertQueryNode","is","preCreateCheck","UpdateQueryNode","preUpdateCheck","hasPostUpdatePolicies","beforeUpdateInfo","loadBeforeUpdateEntities","where","result","rows","length","invariant","idFields","QueryUtils","requireIdFields","postRow","beforeRow","find","r","every","f","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","isManyToManyJoinTable","needCheckPreCreate","constCondition","tryGetConstantPolicy","enforcePreCreatePolicy","fieldsToUpdate","updates","u","ColumnNode","column","filter","fieldUpdatePolicies","buildFieldPolicyFilter","fieldLevelFilter","isTrueNode","modelLevelFilter","updateFilter","trueNode","preUpdateCheckQuery","coalesce","sum","cast","logicalNot","preUpdateResult","$filteredCount","transformSelectQuery","tryRejectNonexistingTables","froms","hasFieldLevelPolicies","some","table","extractedTable","extractTableName","model","updatedFroms","getModel","query","createSelectAllFieldsWithPolicies","alias","push","whereNode","policyFilter","createPolicyFilterForFrom","WhereNode","transformJoin","hasPolicies","nestedQuery","transformInsertQuery","onConflict","updateWhere","processedNode","ReturningNode","transformUpdateQuery","joinFilter","transformDeleteQuery","using","tables","createPolicyFilterForTables","beforeUpdateAccessFields","getFieldsAccessForBeforeUpdatePolicies","combinedFilter","TableNode","policies","getModelPolicies","Set","fieldCollector","SchemaUtils","ExpressionVisitor","visitMember","e","isBeforeInvocation","receiver","members","add","policy","visit","condition","size","forEach","Array","sort","operation","modelDef","requireModel","fieldDef","Object","values","relation","computed","originModel","fieldHasPolicies","selection","createFieldSelectionWithPolicy","SelectAllNode","modelPolicyFilter","AliasNode","IdentifierNode","field","case","when","then","else","end","keys","getFieldPolicies","allows","compilePolicyCondition","denies","combinedPolicy","disjunction","combinedDenies","d","buildIsFalse","s","includes","collector","ColumnCollector","selectedColumns","collect","c","columns","valueRows","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","allValues","_def","createImmediate","constTable","ValueListNode","BinaryOperationNode","FunctionNode","OperatorNode","unwrapCreateValueRow","data","isImplicitManyToManyJoinTable","i","item","transformPrimitive","type","array","isArray","RawNode","createWithSql","buildArrayLiteralSQL","p","isTrueExpr","expr","ExpressionUtils","isLiteral","selectResult","row","ReferenceNode","match","getTableName","into","DeleteQueryNode","createUnsupportedError","exhaustive","SelectQueryNode","m2mFilter","getModelPolicyFilterForManyToManyJoinTable","falseNode","identifier","inner","extractResult","ExpressionTransformer","transform","modelOrType","thisType","thisAlias","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","hasModel","numAffectedRows","BigInt","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"]}