Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit 9a62051

Browse files
authored
fix(orm): use id-only filter for update read-back (#585)
1 parent c4ee20a commit 9a62051

3 files changed

Lines changed: 90 additions & 2 deletions

File tree

packages/orm/src/client/crud/operations/update.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ export class UpdateOperationHandler<Schema extends SchemaDef> extends BaseOperat
4343
if (needReadBack) {
4444
// updated can be undefined if there's nothing to update, in that case we'll use the original
4545
// filter to read back the entity
46-
const readFilter = updateResult ?? args.where;
46+
// note that we trim filter to id fields only, just in case underlying executor returns more fields
47+
const readFilter = updateResult ? getIdValues(this.schema, this.model, updateResult) : args.where;
4748
let readBackResult: any = undefined;
4849
readBackResult = await this.readUnique(tx, this.model, {
4950
select: args.select,

tests/e2e/orm/policy/crud/update.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { describe, expect, it } from 'vitest';
21
import { createPolicyTestClient } from '@zenstackhq/testtools';
2+
import { describe, expect, it } from 'vitest';
33

44
describe('Update policy tests', () => {
55
describe('Scalar condition tests', () => {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { createPolicyTestClient } from '@zenstackhq/testtools';
2+
import { describe, expect, it } from 'vitest';
3+
4+
describe('Regression for issue #586', () => {
5+
it('does not throw cannot-read-back for json array update with extra mutation plugin', async () => {
6+
const schema = `
7+
8+
type AuthInfo {
9+
aProperty Boolean
10+
11+
@@auth
12+
}
13+
14+
type Foo {
15+
bar String
16+
baz Int
17+
18+
@@allow("all", auth().aProperty)
19+
}
20+
21+
model JsonArrayRoot {
22+
id String @id @default(cuid())
23+
24+
fields JsonArrayField[]
25+
26+
@@allow("all", auth().aProperty)
27+
}
28+
29+
model JsonArrayField {
30+
id String @id @default(cuid())
31+
data Foo[] @json
32+
rootId String
33+
34+
root JsonArrayRoot @relation(fields: [rootId], references: [id])
35+
36+
@@allow("all", auth().aProperty)
37+
}
38+
`;
39+
40+
const db = await createPolicyTestClient(schema, {
41+
provider: 'postgresql',
42+
usePrismaPush: true,
43+
plugins: [
44+
{
45+
id: 'foo',
46+
name: 'foo',
47+
description: 'foo',
48+
onEntityMutation: {
49+
afterEntityMutation: async () => Promise.resolve(),
50+
beforeEntityMutation: async () => Promise.resolve(),
51+
runAfterMutationWithinTransaction: true,
52+
},
53+
},
54+
],
55+
});
56+
57+
try {
58+
const authed = db.$setAuth({ aProperty: true });
59+
60+
const root = await authed.jsonArrayRoot.create({ data: {} });
61+
62+
const created = await authed.jsonArrayField.create({
63+
data: {
64+
data: [],
65+
rootId: root.id,
66+
},
67+
});
68+
69+
const updateData = [
70+
{ bar: 'hello', baz: 1 },
71+
{ bar: 'world', baz: 2 },
72+
];
73+
74+
await expect(
75+
authed.jsonArrayField.update({
76+
where: { id: created.id },
77+
data: {
78+
data: updateData,
79+
rootId: root.id,
80+
},
81+
}),
82+
).resolves.toMatchObject({ data: updateData });
83+
} finally {
84+
await db.$disconnect?.();
85+
}
86+
});
87+
});

0 commit comments

Comments
 (0)