From 91bedcd43bee86fe1b578d2f10790a4a9ac4f891 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Fri, 28 Feb 2025 14:09:39 -0800 Subject: [PATCH] fix(auth): refix issue #1997 fixes #2019 --- packages/runtime/src/cross/model-meta.ts | 3 +- .../src/enhancements/node/default-auth.ts | 25 ++---- tests/regression/tests/issue-2019.test.ts | 87 +++++++++++++++++++ 3 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 tests/regression/tests/issue-2019.test.ts diff --git a/packages/runtime/src/cross/model-meta.ts b/packages/runtime/src/cross/model-meta.ts index 3b27f1686..727038fd4 100644 --- a/packages/runtime/src/cross/model-meta.ts +++ b/packages/runtime/src/cross/model-meta.ts @@ -86,8 +86,7 @@ export type FieldInfo = { relationField?: string; /** - * Mapping from foreign key field names to relation field names. - * Only available on relation fields. + * Mapping from relation's pk to fk. Only available on relation fields. */ foreignKeyMapping?: Record; diff --git a/packages/runtime/src/enhancements/node/default-auth.ts b/packages/runtime/src/enhancements/node/default-auth.ts index f151d014f..8bdd76490 100644 --- a/packages/runtime/src/enhancements/node/default-auth.ts +++ b/packages/runtime/src/enhancements/node/default-auth.ts @@ -126,7 +126,7 @@ class DefaultAuthHandler extends DefaultPrismaProxyHandler { return; } - if (context.field?.backLink && context.nestingPath.length > 1) { + if (context.field?.backLink) { // if the fk field is in a creation context where its implied by the parent, // we should not set the default value, e.g.: // @@ -134,23 +134,16 @@ class DefaultAuthHandler extends DefaultPrismaProxyHandler { // parent.create({ data: { child: { create: {} } } }) // ``` // - // event if child's fk to parent has a default value, we should not set default + // even if child's fk to parent has a default value, we should not set default // value here - // fetch parent model from the parent context - const parentModel = getModelInfo( - this.options.modelMeta, - context.nestingPath[context.nestingPath.length - 2].model - ); - - if (parentModel) { - // get the opposite side of the relation for the current create context - const oppositeRelationField = requireField(this.options.modelMeta, model, context.field.backLink); - if (parentModel.name === oppositeRelationField.type) { - // if the opposite side matches the parent model, it means we currently in a creation context - // that implicitly sets this fk field - return; - } + // get the opposite side of the relation for the current create context + const oppositeRelationField = requireField(this.options.modelMeta, model, context.field.backLink); + if ( + oppositeRelationField.foreignKeyMapping && + Object.values(oppositeRelationField.foreignKeyMapping).includes(fieldInfo.name) + ) { + return; } } diff --git a/tests/regression/tests/issue-2019.test.ts b/tests/regression/tests/issue-2019.test.ts new file mode 100644 index 000000000..e5eea9254 --- /dev/null +++ b/tests/regression/tests/issue-2019.test.ts @@ -0,0 +1,87 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('issue 2019', () => { + it('regression', async () => { + const { prisma, enhance } = await loadSchema( + ` + model Tenant { + id String @id @default(uuid()) + + users User[] + content Content[] + } + + model User { + id String @id @default(uuid()) + tenantId String @default(auth().tenantId) + tenant Tenant @relation(fields: [tenantId], references: [id]) + posts Post[] + likes PostUserLikes[] + + @@allow('all', true) + } + + model Content { + tenantId String @default(auth().tenantId) + tenant Tenant @relation(fields: [tenantId], references: [id]) + id String @id @default(uuid()) + contentType String + + @@delegate(contentType) + @@allow('all', true) + } + + model Post extends Content { + author User @relation(fields: [authorId], references: [id]) + authorId String @default(auth().id) + + comments Comment[] + likes PostUserLikes[] + + @@allow('all', true) + } + + model PostUserLikes extends Content { + userId String + user User @relation(fields: [userId], references: [id]) + + postId String + post Post @relation(fields: [postId], references: [id]) + + @@unique([userId, postId]) + + @@allow('all', true) + } + + model Comment extends Content { + postId String + post Post @relation(fields: [postId], references: [id]) + + @@allow('all', true) + } + `, + { logPrismaQuery: true } + ); + + const tenant = await prisma.tenant.create({ data: {} }); + const user = await prisma.user.create({ data: { tenantId: tenant.id } }); + const db = enhance({ id: user.id, tenantId: tenant.id }); + const result = await db.post.create({ + data: { + likes: { + createMany: { + data: [ + { + userId: user.id, + }, + ], + }, + }, + }, + include: { + likes: true, + }, + }); + expect(result.likes[0].tenantId).toBe(tenant.id); + }); +});