Skip to content

Commit c89012b

Browse files
authored
fix: incorrect relation owner analysis (#610)
2 parents ea7de9c + 86ecb4c commit c89012b

File tree

13 files changed

+83
-17
lines changed

13 files changed

+83
-17
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zenstack-monorepo",
3-
"version": "1.0.0-beta.12",
3+
"version": "1.0.0-beta.13",
44
"description": "",
55
"scripts": {
66
"build": "pnpm -r build",

packages/language/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/language",
3-
"version": "1.0.0-beta.12",
3+
"version": "1.0.0-beta.13",
44
"displayName": "ZenStack modeling language compiler",
55
"description": "ZenStack modeling language compiler",
66
"homepage": "https://zenstack.dev",

packages/plugins/openapi/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/openapi",
33
"displayName": "ZenStack Plugin and Runtime for OpenAPI",
4-
"version": "1.0.0-beta.12",
4+
"version": "1.0.0-beta.13",
55
"description": "ZenStack plugin and runtime supporting OpenAPI",
66
"main": "index.js",
77
"repository": {

packages/plugins/swr/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/swr",
33
"displayName": "ZenStack plugin for generating SWR hooks",
4-
"version": "1.0.0-beta.12",
4+
"version": "1.0.0-beta.13",
55
"description": "ZenStack plugin for generating SWR hooks",
66
"main": "index.js",
77
"repository": {

packages/plugins/tanstack-query/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/tanstack-query",
33
"displayName": "ZenStack plugin for generating tanstack-query hooks",
4-
"version": "1.0.0-beta.12",
4+
"version": "1.0.0-beta.13",
55
"description": "ZenStack plugin for generating tanstack-query hooks",
66
"main": "index.js",
77
"exports": {

packages/plugins/trpc/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/trpc",
33
"displayName": "ZenStack plugin for tRPC",
4-
"version": "1.0.0-beta.12",
4+
"version": "1.0.0-beta.13",
55
"description": "ZenStack plugin for tRPC",
66
"main": "index.js",
77
"repository": {

packages/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/runtime",
33
"displayName": "ZenStack Runtime Library",
4-
"version": "1.0.0-beta.12",
4+
"version": "1.0.0-beta.13",
55
"description": "Runtime of ZenStack for both client-side and server-side environments.",
66
"repository": {
77
"type": "git",

packages/schema/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"publisher": "zenstack",
44
"displayName": "ZenStack Language Tools",
55
"description": "A toolkit for building secure CRUD apps with Next.js + Typescript",
6-
"version": "1.0.0-beta.12",
6+
"version": "1.0.0-beta.13",
77
"author": {
88
"name": "ZenStack Team"
99
},

packages/schema/src/plugins/model-meta/index.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { RuntimeAttribute } from '@zenstackhq/runtime';
1111
import {
1212
createProject,
1313
emitProject,
14+
getAttributeArg,
1415
getAttributeArgs,
1516
getDataModels,
1617
getLiteral,
@@ -182,14 +183,25 @@ function isRelationOwner(field: DataModelField, backLink: DataModelField | undef
182183
return false;
183184
}
184185

185-
if (hasAttribute(field, '@relation')) {
186-
// this field has `@relation` attribute
186+
if (!backLink) {
187+
// CHECKME: can this really happen?
187188
return true;
188-
} else if (!backLink || !hasAttribute(backLink, '@relation')) {
189-
// if the opposite side field doesn't have `@relation` attribute either,
190-
// it's an implicit many-to-many relation, both sides are owners
189+
}
190+
191+
if (!hasAttribute(field, '@relation') && !hasAttribute(backLink, '@relation')) {
192+
// if neither side has `@relation` attribute, it's an implicit many-to-many relation,
193+
// both sides are owners
191194
return true;
192-
} else {
195+
}
196+
197+
return holdsForeignKey(field);
198+
}
199+
200+
function holdsForeignKey(field: DataModelField) {
201+
const relation = field.attributes.find((attr) => attr.decl.ref?.name === '@relation');
202+
if (!relation) {
193203
return false;
194204
}
205+
const fields = getAttributeArg(relation, 'fields');
206+
return !!fields;
195207
}

packages/sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/sdk",
3-
"version": "1.0.0-beta.12",
3+
"version": "1.0.0-beta.13",
44
"description": "ZenStack plugin development SDK",
55
"main": "index.js",
66
"scripts": {

packages/server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/server",
3-
"version": "1.0.0-beta.12",
3+
"version": "1.0.0-beta.13",
44
"displayName": "ZenStack Server-side Adapters",
55
"description": "ZenStack server-side adapters",
66
"homepage": "https://zenstack.dev",

packages/testtools/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/testtools",
3-
"version": "1.0.0-beta.12",
3+
"version": "1.0.0-beta.13",
44
"description": "ZenStack Test Tools",
55
"main": "index.js",
66
"publishConfig": {

tests/integration/tests/regression/issues.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,4 +300,58 @@ describe('GitHub issues regression', () => {
300300
},
301301
});
302302
});
303+
304+
it('issue 609', async () => {
305+
const { withPolicy, prisma } = await loadSchema(
306+
`
307+
model User {
308+
id String @id @default(cuid())
309+
comments Comment[]
310+
}
311+
312+
model Comment {
313+
id String @id @default(cuid())
314+
parentCommentId String?
315+
replies Comment[] @relation("CommentToComment")
316+
parent Comment? @relation("CommentToComment", fields: [parentCommentId], references: [id])
317+
comment String
318+
author User @relation(fields: [authorId], references: [id])
319+
authorId String
320+
321+
@@allow('read,create', true)
322+
@@allow('update,delete', auth() == author)
323+
}
324+
`
325+
);
326+
327+
await prisma.user.create({
328+
data: {
329+
id: '1',
330+
comments: {
331+
create: {
332+
id: '1',
333+
comment: 'Comment 1',
334+
},
335+
},
336+
},
337+
});
338+
339+
await prisma.user.create({
340+
data: {
341+
id: '2',
342+
},
343+
});
344+
345+
// connecting a child comment from a different user to a parent comment should succeed
346+
const db = withPolicy({ id: '2' });
347+
await expect(
348+
db.comment.create({
349+
data: {
350+
comment: 'Comment 2',
351+
author: { connect: { id: '2' } },
352+
parent: { connect: { id: '1' } },
353+
},
354+
})
355+
).toResolveTruthy();
356+
});
303357
});

0 commit comments

Comments
 (0)