Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/runtime/src/cross/model-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string>;

Expand Down
25 changes: 9 additions & 16 deletions packages/runtime/src/enhancements/node/default-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,31 +126,24 @@ 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.:
//
// ```
// 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;
}
}

Expand Down
87 changes: 87 additions & 0 deletions tests/regression/tests/issue-2019.test.ts
Original file line number Diff line number Diff line change
@@ -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);
});
});
Loading