diff --git a/packages/payload/src/fields/hooks/afterRead/promise.ts b/packages/payload/src/fields/hooks/afterRead/promise.ts index 0406c400e9d..2edcf24ca7f 100644 --- a/packages/payload/src/fields/hooks/afterRead/promise.ts +++ b/packages/payload/src/fields/hooks/afterRead/promise.ts @@ -373,12 +373,19 @@ export const promise = async ({ } // Set defaultValue on the field for globals being returned without being first created - // or collection documents created prior to having a default + // or collection documents created prior to having a default. + + // Skip setting defaults when: global has no ID (never created or filtered by access) + // AND access control is active (not overriding). This prevents default values like + // `_status: 'draft'` from appearing when access control filters out the document. + const shouldSkipDefaults = global && !doc.id && !overrideAccess + if ( !removedFieldValue && allowDefaultValue && typeof siblingDoc[field.name!] === 'undefined' && - typeof field.defaultValue !== 'undefined' + typeof field.defaultValue !== 'undefined' && + !shouldSkipDefaults ) { siblingDoc[field.name!] = await getDefaultValue({ defaultValue: field.defaultValue, diff --git a/test/versions/globals/DraftWithMax.ts b/test/versions/globals/DraftWithMax.ts index dab8ec339fb..2e7bf612ef6 100644 --- a/test/versions/globals/DraftWithMax.ts +++ b/test/versions/globals/DraftWithMax.ts @@ -4,7 +4,7 @@ import { draftWithMaxGlobalSlug } from '../slugs.js' const DraftWithMaxGlobal: GlobalConfig = { slug: draftWithMaxGlobalSlug, - label: 'Draft Global', + label: 'Draft with Max Global', admin: { components: { views: { diff --git a/test/versions/int.spec.ts b/test/versions/int.spec.ts index 34c86b67524..61858807e01 100644 --- a/test/versions/int.spec.ts +++ b/test/versions/int.spec.ts @@ -2554,6 +2554,36 @@ describe('Versions', () => { expect(retrieved.title).toStrictEqual('i will be a draft') }) + it('should not return _status field when access control denies read', async () => { + // Create a draft global + const draft = await payload.updateGlobal({ + slug: draftGlobalSlug, + data: { + _status: 'draft', + title: 'draft only', + }, + draft: true, + }) + + expect(draft._status).toStrictEqual('draft') + + // Create a request without a user (simulating unauthenticated request) + // Access control on draftGlobalSlug requires published status when no user + const req = await createLocalReq({}, payload) + req.user = null + + const result = await payload.findGlobal({ + slug: draftGlobalSlug, + overrideAccess: false, + req, + }) + + // Should return empty object, not {_status: 'draft'} + // The _status field should not be populated with its default value + expect(Object.keys(result)).toHaveLength(0) + expect(result._status).toBeUndefined() + }) + describe('server functions', () => { let draftDoc let event diff --git a/test/versions/payload-types.ts b/test/versions/payload-types.ts index f492524df89..28b6b667424 100644 --- a/test/versions/payload-types.ts +++ b/test/versions/payload-types.ts @@ -209,7 +209,7 @@ export interface AutosavePost { root: { type: string; children: { - type: string; + type: any; version: number; [k: string]: unknown; }[]; @@ -514,7 +514,7 @@ export interface Diff { root: { type: string; children: { - type: string; + type: any; version: number; [k: string]: unknown; }[]; @@ -529,7 +529,7 @@ export interface Diff { root: { type: string; children: { - type: string; + type: any; version: number; [k: string]: unknown; }[];