From 20bd5056dc56e95be7891de1b08583f015bc602a Mon Sep 17 00:00:00 2001 From: Josh Calder Date: Tue, 3 Jan 2023 14:18:12 +1100 Subject: [PATCH] Fixes Dataloader error when resolving relationships when access is `false` on related to-one item (#8216) --- .changeset/shy-falcons-think.md | 5 +++ .../core/src/lib/core/queries/output-field.ts | 4 +- .../relationships/crud/one-to-many.test.ts | 39 ++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 .changeset/shy-falcons-think.md diff --git a/.changeset/shy-falcons-think.md b/.changeset/shy-falcons-think.md new file mode 100644 index 00000000000..49e2164cb68 --- /dev/null +++ b/.changeset/shy-falcons-think.md @@ -0,0 +1,5 @@ +--- +'@keystone-6/core': patch +--- + +Fixes Dataloader error when resolving relationships when access is `false` on related to-one item diff --git a/packages/core/src/lib/core/queries/output-field.ts b/packages/core/src/lib/core/queries/output-field.ts index 997a3dae1cd..0a6ca89a4a1 100644 --- a/packages/core/src/lib/core/queries/output-field.ts +++ b/packages/core/src/lib/core/queries/output-field.ts @@ -102,12 +102,12 @@ async function fetchRelatedItems( ) { const operationAccess = await getOperationAccess(foreignList, context, 'query'); if (!operationAccess) { - return []; + return toFetch.map(() => undefined); } const accessFilters = await getAccessFilters(foreignList, context, 'query'); if (accessFilters === false) { - return []; + return toFetch.map(() => undefined); } const resolvedWhere = await accessControlledFilter( diff --git a/tests/api-tests/relationships/crud/one-to-many.test.ts b/tests/api-tests/relationships/crud/one-to-many.test.ts index 0846c0e7d03..78711cd2f40 100644 --- a/tests/api-tests/relationships/crud/one-to-many.test.ts +++ b/tests/api-tests/relationships/crud/one-to-many.test.ts @@ -3,7 +3,7 @@ import { text, relationship } from '@keystone-6/core/fields'; import { list } from '@keystone-6/core'; import { setupTestRunner } from '@keystone-6/api-tests/test-runner'; import type { KeystoneContext } from '@keystone-6/core/types'; -import { allowAll } from '@keystone-6/core/access'; +import { allowAll, denyAll } from '@keystone-6/core/access'; import { apiTestConfig, ContextFromRunner } from '../../utils'; type IdType = any; @@ -107,6 +107,27 @@ const runner = setupTestRunner({ }), }); +const runnerWithDeny = setupTestRunner({ + config: apiTestConfig({ + lists: { + Company: list({ + access: denyAll, + fields: { + name: text(), + locations: relationship({ ref: 'Location.company', many: true }), + }, + }), + Location: list({ + access: allowAll, + fields: { + name: text(), + company: relationship({ ref: 'Company.locations' }), + }, + }), + }, + }), +}); + describe(`One-to-many relationships`, () => { describe('Read', () => { test( @@ -205,6 +226,22 @@ describe(`One-to-many relationships`, () => { ); }) ); + + test( + 'Deny access to related items returns null', + runnerWithDeny(async ({ context }) => { + await createReadData(context.sudo()); + const companies = await context.query.Company.findMany({ + query: 'id name', + }); + expect(companies.toString()).toBe(''); + + const locations = await context.query.Location.findMany({ + query: 'id name company { id name }', + }); + expect(locations[0].company).toBeNull(); + }) + ); }); describe('Count', () => {