From d2ad3a59f93a74189c29d3ee2960fc887b14851c Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Wed, 8 Nov 2023 11:07:14 -0800 Subject: [PATCH] fix: incorrect reverse query built for to-many relation --- .../src/enhancements/policy/policy-utils.ts | 3 +- .../tests/regression/issue-811.test.ts | 71 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 tests/integration/tests/regression/issue-811.test.ts diff --git a/packages/runtime/src/enhancements/policy/policy-utils.ts b/packages/runtime/src/enhancements/policy/policy-utils.ts index cfb6103f3..cc89942bc 100644 --- a/packages/runtime/src/enhancements/policy/policy-utils.ts +++ b/packages/runtime/src/enhancements/policy/policy-utils.ts @@ -525,6 +525,7 @@ export class PolicyUtil { if (backLinkField.isArray && !mutating) { // many-side of relationship, wrap with "some" query currQuery[currField.backLink] = { some: { ...visitWhere } }; + currQuery = currQuery[currField.backLink].some; } else { const fkMapping = where && backLinkField.isRelationOwner && backLinkField.foreignKeyMapping; @@ -553,8 +554,8 @@ export class PolicyUtil { // preserve the original structure currQuery[currField.backLink] = { ...visitWhere }; } + currQuery = currQuery[currField.backLink]; } - currQuery = currQuery[currField.backLink]; currField = field; } } diff --git a/tests/integration/tests/regression/issue-811.test.ts b/tests/integration/tests/regression/issue-811.test.ts new file mode 100644 index 000000000..af2268203 --- /dev/null +++ b/tests/integration/tests/regression/issue-811.test.ts @@ -0,0 +1,71 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('Regression: issue 811', () => { + it('regression', async () => { + const { prisma, enhance } = await loadSchema( + ` + model Membership { + id String @id @default(uuid()) + role String @default('STANDARD') + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + userId String @unique + + @@auth + @@allow('create,update,delete', auth().role == 'ADMIN') + @@allow('update', auth() == this) + @@allow('read', true) + } + model User { + id String @id @default(uuid()) + profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade) + profileId String @unique + memberships Membership[] + + @@allow('create,update,delete', auth().role == 'ADMIN') + @@allow('update', id == auth().userId) + @@allow('read', true) + } + model Profile { + id String @id @default(uuid()) + firstName String + users User[] + + @@allow('create,update,delete', auth().role == 'ADMIN') + @@allow('update', users?[id == auth().userId]) + @@allow('read', true) + } + ` + ); + + const r = await prisma.user.create({ + data: { + profile: { + create: { firstName: 'Tom' }, + }, + memberships: { + create: { role: 'STANDARD' }, + }, + }, + include: { + profile: true, + memberships: true, + }, + }); + + const membershipId = r.memberships[0].id; + const userId = r.id; + const db = enhance({ id: membershipId, role: 'ADMIN', userId }); + + const r1 = await db.membership.update({ + data: { + role: 'VIP', + user: { update: { data: { profile: { update: { data: { firstName: 'Jerry' } } } } } }, + }, + include: { user: { include: { profile: true } } }, + where: { id: membershipId }, + }); + + expect(r1.role).toBe('VIP'); + expect(r1.user.profile.firstName).toBe('Jerry'); + }); +});