diff --git a/src/collections/operations/find.ts b/src/collections/operations/find.ts index a8a9a3beb..7867d7e71 100644 --- a/src/collections/operations/find.ts +++ b/src/collections/operations/find.ts @@ -171,6 +171,7 @@ async function find(incomingArgs: Arguments): Promis accessResult, payload, entity: collectionConfig, + entityType: 'collection', doc, locale, }))), diff --git a/src/collections/operations/findByID.ts b/src/collections/operations/findByID.ts index 2b3f888d7..471369b34 100644 --- a/src/collections/operations/findByID.ts +++ b/src/collections/operations/findByID.ts @@ -127,6 +127,7 @@ async function findByID(incomingArgs: Arguments): Pr result = await replaceWithDraftIfAvailable({ payload, entity: collectionConfig, + entityType: 'collection', doc: result, accessResult, locale, diff --git a/src/globals/operations/findOne.ts b/src/globals/operations/findOne.ts index 1a04613e5..e04ec672c 100644 --- a/src/globals/operations/findOne.ts +++ b/src/globals/operations/findOne.ts @@ -40,7 +40,7 @@ async function findOne(args: Args): Promise { // Retrieve and execute access // ///////////////////////////////////// - const queryToBuild: { where?: Where} = { + const queryToBuild: { where?: Where } = { where: { and: [ { @@ -89,6 +89,7 @@ async function findOne(args: Args): Promise { doc = await replaceWithDraftIfAvailable({ payload, entity: globalConfig, + entityType: 'global', doc, locale, accessResult, diff --git a/src/versions/drafts/replaceWithDraftIfAvailable.ts b/src/versions/drafts/replaceWithDraftIfAvailable.ts index c82276078..30b3cb04f 100644 --- a/src/versions/drafts/replaceWithDraftIfAvailable.ts +++ b/src/versions/drafts/replaceWithDraftIfAvailable.ts @@ -11,6 +11,7 @@ import { SanitizedGlobalConfig } from '../../globals/config/types'; type Arguments = { payload: Payload entity: SanitizedCollectionConfig | SanitizedGlobalConfig + entityType: 'collection' | 'global' doc: T locale: string accessResult: AccessResult @@ -19,70 +20,74 @@ type Arguments = { const replaceWithDraftIfAvailable = async ({ payload, entity, + entityType, doc, locale, accessResult, }: Arguments): Promise => { - if (docHasTimestamps(doc)) { - const VersionModel = payload.versions[entity.slug] as CollectionModel; + const VersionModel = payload.versions[entity.slug] as CollectionModel; - let useEstimatedCount = false; - const queryToBuild: { where: Where } = { - where: { - and: [ - { - parent: { - equals: doc.id, - }, + let useEstimatedCount = false; + + const queryToBuild: { where: Where } = { + where: { + and: [ + { + 'version._status': { + equals: 'draft', }, - { - 'version._status': { - equals: 'draft', - }, - }, - { - updatedAt: { - greater_than: doc.updatedAt, - }, - }, - ], + }, + ], + }, + }; + + if (entityType === 'collection') { + queryToBuild.where.and.push({ + parent: { + equals: doc.id, }, - }; - - if (hasWhereAccessResult(accessResult)) { - const versionAccessResult = appendVersionToQueryKey(accessResult); - queryToBuild.where.and.push(versionAccessResult); - } - - const constraints = flattenWhereConstraints(queryToBuild); - useEstimatedCount = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near')); - const query = await VersionModel.buildQuery(queryToBuild, locale); - - let draft = await VersionModel.findOne(query, {}, { - lean: true, - useEstimatedCount, - sort: { updatedAt: 'desc' }, }); - - if (!draft) { - return doc; - } - - draft = JSON.parse(JSON.stringify(draft)); - draft = sanitizeInternalFields(draft); - - // Disregard all other draft content at this point, - // Only interested in the version itself. - // Operations will handle firing hooks, etc. - return { - id: doc.id, - ...draft.version, - createdAt: draft.createdAt, - updatedAt: draft.updatedAt, - }; } - return doc; + if (docHasTimestamps(doc)) { + queryToBuild.where.and.push({ + updatedAt: { + greater_than: doc.updatedAt, + }, + }); + } + + if (hasWhereAccessResult(accessResult)) { + const versionAccessResult = appendVersionToQueryKey(accessResult); + queryToBuild.where.and.push(versionAccessResult); + } + + const constraints = flattenWhereConstraints(queryToBuild); + useEstimatedCount = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near')); + const query = await VersionModel.buildQuery(queryToBuild, locale); + + let draft = await VersionModel.findOne(query, {}, { + lean: true, + useEstimatedCount, + sort: { updatedAt: 'desc' }, + }); + + if (!draft) { + return doc; + } + + draft = JSON.parse(JSON.stringify(draft)); + draft = sanitizeInternalFields(draft); + + // Disregard all other draft content at this point, + // Only interested in the version itself. + // Operations will handle firing hooks, etc. + return { + id: doc.id, + ...draft.version, + createdAt: draft.createdAt, + updatedAt: draft.updatedAt, + }; }; export default replaceWithDraftIfAvailable; diff --git a/test/versions/config.ts b/test/versions/config.ts index f12260bcf..7711c9e2b 100644 --- a/test/versions/config.ts +++ b/test/versions/config.ts @@ -3,6 +3,7 @@ import AutosavePosts from './collections/Autosave'; import DraftPosts from './collections/Drafts'; import AutosaveGlobal from './globals/Autosave'; import { devUser } from '../credentials'; +import DraftGlobal from './globals/Draft'; export default buildConfig({ collections: [ @@ -11,6 +12,7 @@ export default buildConfig({ ], globals: [ AutosaveGlobal, + DraftGlobal, ], localization: { locales: ['en', 'es'], diff --git a/test/versions/globals/Draft.ts b/test/versions/globals/Draft.ts new file mode 100644 index 000000000..251333c54 --- /dev/null +++ b/test/versions/globals/Draft.ts @@ -0,0 +1,30 @@ +import { GlobalConfig } from '../../../src/globals/config/types'; + +const DraftGlobal: GlobalConfig = { + slug: 'draft-global', + label: 'Draft Global', + versions: { + max: 20, + drafts: true, + }, + access: { + read: ({ draft, req: { user } }) => { + // To read a draft of this global, you need to be authenticated + if (draft) { + return Boolean(user); + } + + return true; + }, + }, + fields: [ + { + name: 'title', + type: 'text', + required: true, + localized: true, + }, + ], +}; + +export default DraftGlobal;