diff --git a/package.json b/package.json index 2c3f83c87..cd08cf7ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zenstack-monorepo", - "version": "2.11.5", + "version": "2.11.6", "description": "", "scripts": { "build": "pnpm -r --filter=\"!./packages/ide/*\" build", diff --git a/packages/ide/jetbrains/build.gradle.kts b/packages/ide/jetbrains/build.gradle.kts index 9b796a2de..b6dedac5b 100644 --- a/packages/ide/jetbrains/build.gradle.kts +++ b/packages/ide/jetbrains/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } group = "dev.zenstack" -version = "2.11.5" +version = "2.11.6" repositories { mavenCentral() diff --git a/packages/ide/jetbrains/package.json b/packages/ide/jetbrains/package.json index 56f8db3b0..b8c745cb0 100644 --- a/packages/ide/jetbrains/package.json +++ b/packages/ide/jetbrains/package.json @@ -1,6 +1,6 @@ { "name": "jetbrains", - "version": "2.11.5", + "version": "2.11.6", "displayName": "ZenStack JetBrains IDE Plugin", "description": "ZenStack JetBrains IDE plugin", "homepage": "https://zenstack.dev", diff --git a/packages/language/package.json b/packages/language/package.json index 66d4ae151..5ca53d403 100644 --- a/packages/language/package.json +++ b/packages/language/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/language", - "version": "2.11.5", + "version": "2.11.6", "displayName": "ZenStack modeling language compiler", "description": "ZenStack modeling language compiler", "homepage": "https://zenstack.dev", diff --git a/packages/misc/redwood/package.json b/packages/misc/redwood/package.json index f3d8574b9..91f1120b9 100644 --- a/packages/misc/redwood/package.json +++ b/packages/misc/redwood/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/redwood", "displayName": "ZenStack RedwoodJS Integration", - "version": "2.11.5", + "version": "2.11.6", "description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.", "repository": { "type": "git", diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index 279dcc05c..eab38e311 100644 --- a/packages/plugins/openapi/package.json +++ b/packages/plugins/openapi/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/openapi", "displayName": "ZenStack Plugin and Runtime for OpenAPI", - "version": "2.11.5", + "version": "2.11.6", "description": "ZenStack plugin and runtime supporting OpenAPI", "main": "index.js", "repository": { diff --git a/packages/plugins/swr/package.json b/packages/plugins/swr/package.json index 733c5345a..d26596d20 100644 --- a/packages/plugins/swr/package.json +++ b/packages/plugins/swr/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/swr", "displayName": "ZenStack plugin for generating SWR hooks", - "version": "2.11.5", + "version": "2.11.6", "description": "ZenStack plugin for generating SWR hooks", "main": "index.js", "repository": { diff --git a/packages/plugins/tanstack-query/package.json b/packages/plugins/tanstack-query/package.json index afd14fa49..d23dc40ff 100644 --- a/packages/plugins/tanstack-query/package.json +++ b/packages/plugins/tanstack-query/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/tanstack-query", "displayName": "ZenStack plugin for generating tanstack-query hooks", - "version": "2.11.5", + "version": "2.11.6", "description": "ZenStack plugin for generating tanstack-query hooks", "main": "index.js", "exports": { diff --git a/packages/plugins/trpc/package.json b/packages/plugins/trpc/package.json index ae25e8fba..cd581c42a 100644 --- a/packages/plugins/trpc/package.json +++ b/packages/plugins/trpc/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/trpc", "displayName": "ZenStack plugin for tRPC", - "version": "2.11.5", + "version": "2.11.6", "description": "ZenStack plugin for tRPC", "main": "index.js", "repository": { diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 1f8883876..545e972da 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/runtime", "displayName": "ZenStack Runtime Library", - "version": "2.11.5", + "version": "2.11.6", "description": "Runtime of ZenStack for both client-side and server-side environments.", "repository": { "type": "git", diff --git a/packages/runtime/src/enhancements/node/policy/policy-utils.ts b/packages/runtime/src/enhancements/node/policy/policy-utils.ts index b39ac5b00..82a5bc88e 100644 --- a/packages/runtime/src/enhancements/node/policy/policy-utils.ts +++ b/packages/runtime/src/enhancements/node/policy/policy-utils.ts @@ -1183,7 +1183,7 @@ export class PolicyUtil extends QueryUtils { if (this.hasFieldLevelPolicy(model)) { // recursively inject selection for fields needed for field-level read checks - const readFieldSelect = this.getFieldReadCheckSelector(model); + const readFieldSelect = this.getFieldReadCheckSelector(model, args.select); if (readFieldSelect) { this.doInjectReadCheckSelect(model, args, { select: readFieldSelect }); } @@ -1311,17 +1311,20 @@ export class PolicyUtil extends QueryUtils { } // get a merged selector object for all field-level read policies - private getFieldReadCheckSelector(model: string) { + private getFieldReadCheckSelector(model: string, fieldSelection: Record | undefined) { const def = this.getModelPolicyDef(model); let result: any = {}; const fieldLevel = def.fieldLevel?.read; if (fieldLevel) { - for (const def of Object.values(fieldLevel)) { - if (def.entityChecker?.selector) { - result = deepmerge(result, def.entityChecker.selector); - } - if (def.overrideEntityChecker?.selector) { - result = deepmerge(result, def.overrideEntityChecker.selector); + for (const [field, def] of Object.entries(fieldLevel)) { + if (!fieldSelection || fieldSelection[field]) { + // field is selected, merge the field-level selector + if (def.entityChecker?.selector) { + result = deepmerge(result, def.entityChecker.selector); + } + if (def.overrideEntityChecker?.selector) { + result = deepmerge(result, def.overrideEntityChecker.selector); + } } } } diff --git a/packages/schema/package.json b/packages/schema/package.json index 924c984c8..2c72d93e6 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -3,7 +3,7 @@ "publisher": "zenstack", "displayName": "ZenStack Language Tools", "description": "FullStack enhancement for Prisma ORM: seamless integration from database to UI", - "version": "2.11.5", + "version": "2.11.6", "author": { "name": "ZenStack Team" }, diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 36c88b8ea..a374bfafd 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/sdk", - "version": "2.11.5", + "version": "2.11.6", "description": "ZenStack plugin development SDK", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index f0d0404b0..f3b5db083 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/server", - "version": "2.11.5", + "version": "2.11.6", "displayName": "ZenStack Server-side Adapters", "description": "ZenStack server-side adapters", "homepage": "https://zenstack.dev", diff --git a/packages/testtools/package.json b/packages/testtools/package.json index a3b44c096..9456abb9c 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/testtools", - "version": "2.11.5", + "version": "2.11.6", "description": "ZenStack Test Tools", "main": "index.js", "private": true, diff --git a/tests/regression/tests/issue-1978.test.ts b/tests/regression/tests/issue-1978.test.ts new file mode 100644 index 000000000..63c91a6e5 --- /dev/null +++ b/tests/regression/tests/issue-1978.test.ts @@ -0,0 +1,41 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('issue 1978', () => { + it('regression', async () => { + const { prisma, enhance } = await loadSchema( + ` + model User { + id Int @id + posts Post[] + secret String @allow('read', posts?[published]) + @@allow('all', true) + } + + model Post { + id Int @id + author User @relation(fields: [authorId], references: [id]) + authorId Int + published Boolean @default(false) + @@allow('all', true) + } + `, + { logPrismaQuery: true } + ); + + const user1 = await prisma.user.create({ + data: { id: 1, secret: 'secret', posts: { create: { id: 1, published: true } } }, + }); + const user2 = await prisma.user.create({ + data: { id: 2, secret: 'secret' }, + }); + + const db = enhance(); + await expect(db.user.findFirst({ where: { id: 1 } })).resolves.toMatchObject({ secret: 'secret' }); + await expect(db.user.findFirst({ where: { id: 1 }, select: { id: true } })).resolves.toEqual({ id: 1 }); + + let r = await db.user.findFirst({ where: { id: 2 } }); + expect(r.secret).toBeUndefined(); + r = await db.user.findFirst({ where: { id: 2 }, select: { id: true } }); + expect(r.secret).toBeUndefined(); + }); +});