diff --git a/packages/schema/src/plugins/access-policy/expression-writer.ts b/packages/schema/src/plugins/access-policy/expression-writer.ts index 46cad62dc..2ab3e2bdd 100644 --- a/packages/schema/src/plugins/access-policy/expression-writer.ts +++ b/packages/schema/src/plugins/access-policy/expression-writer.ts @@ -461,8 +461,9 @@ export class ExpressionWriter { this.writer.write(`db.${lowerCaseFirst(containingModel.name)}.fields.${expr.target.ref.name}`); } - private isAuthOrAuthMemberAccess(expr: Expression) { - return isAuthInvocation(expr) || (isMemberAccessExpr(expr) && isAuthInvocation(expr.operand)); + private isAuthOrAuthMemberAccess(expr: Expression): boolean { + // recursive check for auth().x.y.z + return isAuthInvocation(expr) || (isMemberAccessExpr(expr) && this.isAuthOrAuthMemberAccess(expr.operand)); } private writeOperator(operator: ComparisonOperator, fieldAccess: Expression, writeOperand: () => void) { diff --git a/tests/integration/tests/plugins/policy.test.ts b/tests/integration/tests/plugins/policy.test.ts index 4b67dae7c..5158584f4 100644 --- a/tests/integration/tests/plugins/policy.test.ts +++ b/tests/integration/tests/plugins/policy.test.ts @@ -73,4 +73,36 @@ model M { expect.objectContaining({ AND: [{ AND: [] }, { value: { gt: 0 } }] }) ); }); + it('auth() multiple level member access', async () => { + const model = ` + model User { + id Int @id @default(autoincrement()) + cart Cart? + } + + model Cart { + id Int @id @default(autoincrement()) + tasks Task[] + user User @relation(fields: [userId], references: [id]) + userId Int @unique + } + + model Task { + id Int @id @default(autoincrement()) + cart Cart @relation(fields: [cartId], references: [id]) + cartId Int + value Int + @@allow('read', auth().cart.tasks?[id == 123] && value >10) + } + `; + + const { policy } = await loadSchema(model); + expect(policy.guard.task.read({ user: { cart: { tasks: [{ id: 1 }] } } })).toEqual( + expect.objectContaining({ AND: [{ OR: [] }, { value: { gt: 10 } }] }) + ); + + expect(policy.guard.task.read({ user: { cart: { tasks: [{ id: 123 }] } } })).toEqual( + expect.objectContaining({ AND: [{ AND: [] }, { value: { gt: 10 } }] }) + ); + }); });