From d90d7c83e95d33c85e9c3b4b650e014ee76136c3 Mon Sep 17 00:00:00 2001 From: Yiming Date: Sun, 7 May 2023 15:18:17 -0700 Subject: [PATCH] fix: undefined field access when selecting with _count (#403) --- package.json | 2 +- packages/language/package.json | 2 +- packages/next/package.json | 2 +- packages/plugins/openapi/package.json | 2 +- packages/plugins/react/package.json | 2 +- packages/plugins/trpc/package.json | 2 +- packages/runtime/package.json | 2 +- .../src/enhancements/policy/policy-utils.ts | 26 +++++++------- packages/schema/package.json | 2 +- packages/sdk/package.json | 2 +- packages/server/package.json | 2 +- packages/server/src/openapi/index.ts | 5 +-- packages/testtools/package.json | 2 +- tests/integration/test-run/package-lock.json | 4 +-- .../tests/regression/issues.test.ts | 35 +++++++++++++++++++ 15 files changed, 65 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 1f7e764ab..7d04946c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zenstack-monorepo", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "description": "", "scripts": { "build": "pnpm -r build", diff --git a/packages/language/package.json b/packages/language/package.json index d9da11eff..f90bf0dc0 100644 --- a/packages/language/package.json +++ b/packages/language/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/language", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "displayName": "ZenStack modeling language compiler", "description": "ZenStack modeling language compiler", "homepage": "https://zenstack.dev", diff --git a/packages/next/package.json b/packages/next/package.json index 039f9eb66..8008ac997 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/next", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "displayName": "ZenStack Next.js integration", "description": "ZenStack Next.js integration", "homepage": "https://zenstack.dev", diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index aab3ab3b2..49e062720 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": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "description": "ZenStack plugin and runtime supporting OpenAPI", "main": "index.js", "repository": { diff --git a/packages/plugins/react/package.json b/packages/plugins/react/package.json index 1172841d7..0b03abc31 100644 --- a/packages/plugins/react/package.json +++ b/packages/plugins/react/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/react", "displayName": "ZenStack plugin and runtime for ReactJS", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "description": "ZenStack plugin and runtime for ReactJS", "main": "index.js", "repository": { diff --git a/packages/plugins/trpc/package.json b/packages/plugins/trpc/package.json index 101eaa877..e6b1c4df6 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": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "description": "ZenStack plugin for tRPC", "main": "index.js", "repository": { diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 998506c9e..1d512bb11 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,7 +1,7 @@ { "name": "@zenstackhq/runtime", "displayName": "ZenStack Runtime Library", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "description": "Runtime of ZenStack for both client-side and server-side environments.", "repository": { "type": "git", diff --git a/packages/runtime/src/enhancements/policy/policy-utils.ts b/packages/runtime/src/enhancements/policy/policy-utils.ts index e5472de8d..6f944b530 100644 --- a/packages/runtime/src/enhancements/policy/policy-utils.ts +++ b/packages/runtime/src/enhancements/policy/policy-utils.ts @@ -345,20 +345,22 @@ export class PolicyUtil { } const fieldInfo = resolveField(this.modelMeta, model, field); - if (fieldInfo && fieldInfo.isDataModel && !fieldInfo.isArray) { - // to-one relation data cannot be trimmed by injected guards, we have to - // post-check them - const ids = this.getEntityIds(fieldInfo.type, fieldData); - - if (Object.keys(ids).length !== 0) { - // DEBUG - // this.logger.info(`Validating read of to-one relation: ${fieldInfo.type}#${formatObject(ids)}`); - await this.checkPolicyForFilter(fieldInfo.type, ids, operation, this.db); + if (fieldInfo) { + if (fieldInfo.isDataModel && !fieldInfo.isArray) { + // to-one relation data cannot be trimmed by injected guards, we have to + // post-check them + const ids = this.getEntityIds(fieldInfo.type, fieldData); + + if (Object.keys(ids).length !== 0) { + // DEBUG + // this.logger.info(`Validating read of to-one relation: ${fieldInfo.type}#${formatObject(ids)}`); + await this.checkPolicyForFilter(fieldInfo.type, ids, operation, this.db); + } } - } - // recurse - await this.postProcessForRead(fieldData, fieldInfo.type, injectTarget[field], operation); + // recurse + await this.postProcessForRead(fieldData, fieldInfo.type, injectTarget[field], operation); + } } } } diff --git a/packages/schema/package.json b/packages/schema/package.json index 9596f3692..42f5f8eab 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -3,7 +3,7 @@ "publisher": "zenstack", "displayName": "ZenStack Language Tools", "description": "A toolkit for building secure CRUD apps with Next.js + Typescript", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "author": { "name": "ZenStack Team" }, diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 6abf52700..e7ff6db38 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/sdk", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "description": "ZenStack plugin development SDK", "main": "index.js", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index 51a340a1a..67524d532 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/server", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "displayName": "ZenStack Server-side Adapters", "description": "ZenStack server-side adapters", "homepage": "https://zenstack.dev", diff --git a/packages/server/src/openapi/index.ts b/packages/server/src/openapi/index.ts index 684257dfd..c4636f88b 100644 --- a/packages/server/src/openapi/index.ts +++ b/packages/server/src/openapi/index.ts @@ -221,7 +221,8 @@ export async function handleRequest({ }, }; } else { - logError(logger, (err as Error).message); + const _err = err as Error; + logError(logger, _err.message + (_err.stack ? '\n' + _err.stack : '')); return { status: 400, body: { @@ -238,7 +239,7 @@ function unmarshal(value: string) { function logError(logger: LoggerConfig | undefined | null, message: string, code?: string) { if (logger === undefined) { - console.error(`@zenstackhq/openapi: error ${code ? '[' + code + ']' : ''}, ${message}`); + console.error(`@zenstackhq/server: error ${code ? '[' + code + ']' : ''}, ${message}`); } else if (logger?.error) { logger.error(message, code); } diff --git a/packages/testtools/package.json b/packages/testtools/package.json index 741f418f4..d72044474 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/testtools", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "description": "ZenStack Test Tools", "main": "index.js", "publishConfig": { diff --git a/tests/integration/test-run/package-lock.json b/tests/integration/test-run/package-lock.json index dfaffcab0..d4b00e702 100644 --- a/tests/integration/test-run/package-lock.json +++ b/tests/integration/test-run/package-lock.json @@ -126,7 +126,7 @@ }, "../../../packages/runtime/dist": { "name": "@zenstackhq/runtime", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "license": "MIT", "dependencies": { "@paralleldrive/cuid2": "^2.2.0", @@ -160,7 +160,7 @@ }, "../../../packages/schema/dist": { "name": "zenstack", - "version": "1.0.0-alpha.114", + "version": "1.0.0-alpha.115", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/tests/integration/tests/regression/issues.test.ts b/tests/integration/tests/regression/issues.test.ts index 1324bf5d1..03363583b 100644 --- a/tests/integration/tests/regression/issues.test.ts +++ b/tests/integration/tests/regression/issues.test.ts @@ -129,4 +129,39 @@ describe('GitHub issues regression', () => { ` ); }); + + it('select with _count', async () => { + const { prisma, withPolicy } = await loadSchema( + ` + model User { + id String @id @unique @default(uuid()) + posts Post[] + + @@allow('all', true) + } + + model Post { + id String @id @default(uuid()) + title String + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId String + + @@allow('all', true) + } + ` + ); + + await prisma.user.create({ + data: { + posts: { + create: [{ title: 'Post 1' }, { title: 'Post 2' }], + }, + }, + }); + + const db = withPolicy(); + const r = await db.user.findFirst({ select: { _count: { select: { posts: true } } } }); + expect(r).toMatchObject({ _count: { posts: 2 } }); + }); });