diff --git a/packages/api-headless-cms/__tests__/contentAPI/contentModel.crud.test.ts b/packages/api-headless-cms/__tests__/contentAPI/contentModel.crud.test.ts index 919a4151845..2c6868a803a 100644 --- a/packages/api-headless-cms/__tests__/contentAPI/contentModel.crud.test.ts +++ b/packages/api-headless-cms/__tests__/contentAPI/contentModel.crud.test.ts @@ -293,7 +293,7 @@ describe("content model test", () => { updateContentModelMutation, deleteContentModelMutation } = useGraphQLHandler(manageHandlerOpts); - const { createCategory } = useCategoryManageHandler(manageHandlerOpts); + const { createCategory, deleteCategory } = useCategoryManageHandler(manageHandlerOpts); const category = models.find(m => m.modelId === "category"); if (!category) { throw new Error("Could not find model `category`."); @@ -359,22 +359,70 @@ describe("content model test", () => { } }); - const [response] = await deleteContentModelMutation({ + // Let's try to delete the content model: it should fail because we still have entries for the selected content model. + const [deleteWithEntriesResponse] = await deleteContentModelMutation({ modelId: model.modelId }); - - expect(response).toEqual({ + expect(deleteWithEntriesResponse).toEqual({ data: { deleteContentModel: { data: null, error: { message: `Cannot delete content model "${model.modelId}" because there are existing entries.`, code: "CONTENT_MODEL_BEFORE_DELETE_HOOK_FAILED", - data: null + data: { + model: expect.any(Object) + } + } + } + } + }); + + // Let's move the entry to the trash bin and try to delete the content model: it should fail. + await deleteCategory({ + revision: createCategoryResponse.data.createCategory.data.entryId, + options: { + permanently: false + } + }); + const [deleteWithEntriesInTrashResponse] = await deleteContentModelMutation({ + modelId: model.modelId + }); + expect(deleteWithEntriesInTrashResponse).toEqual({ + data: { + deleteContentModel: { + data: null, + error: { + message: `Cannot delete content model "${model.modelId}" because there are existing entries in the trash.`, + code: "CONTENT_MODEL_BEFORE_DELETE_HOOK_FAILED", + data: { + model: expect.any(Object) + } } } } }); + + // Let's permanently delete the entry: it should be able to delete the content model. + await deleteCategory({ + revision: createCategoryResponse.data.createCategory.data.entryId, + options: { + permanently: true + } + }); + + const [deleteWithoutEntriesResponse] = await deleteContentModelMutation({ + modelId: model.modelId + }); + + expect(deleteWithoutEntriesResponse).toEqual({ + data: { + deleteContentModel: { + data: true, + error: null + } + } + }); }); test("get existing content model", async () => { diff --git a/packages/api-headless-cms/__tests__/contentAPI/model.delete.test.ts b/packages/api-headless-cms/__tests__/contentAPI/model.delete.test.ts index 16585f8cf78..a7a16844367 100644 --- a/packages/api-headless-cms/__tests__/contentAPI/model.delete.test.ts +++ b/packages/api-headless-cms/__tests__/contentAPI/model.delete.test.ts @@ -102,7 +102,9 @@ describe("model delete", () => { data: null, error: { code: "CONTENT_MODEL_BEFORE_DELETE_HOOK_FAILED", - data: null, + data: { + model: expect.any(Object) + }, message: `Cannot delete content model "category" because there are existing entries.` } } diff --git a/packages/api-headless-cms/src/crud/contentModel.crud.ts b/packages/api-headless-cms/src/crud/contentModel.crud.ts index eb6ac857168..276158caae5 100644 --- a/packages/api-headless-cms/src/crud/contentModel.crud.ts +++ b/packages/api-headless-cms/src/crud/contentModel.crud.ts @@ -269,8 +269,7 @@ export const createModelsCrud = (params: CreateModelsCrudParams): CmsModelContex }); assignModelBeforeDelete({ onModelBeforeDelete, - plugins: context.plugins, - storageOperations + context }); /** diff --git a/packages/api-headless-cms/src/crud/contentModel/beforeDelete.ts b/packages/api-headless-cms/src/crud/contentModel/beforeDelete.ts index b68973f87a0..5a1574f8d55 100644 --- a/packages/api-headless-cms/src/crud/contentModel/beforeDelete.ts +++ b/packages/api-headless-cms/src/crud/contentModel/beforeDelete.ts @@ -1,21 +1,19 @@ import { Topic } from "@webiny/pubsub/types"; -import { HeadlessCmsStorageOperations, OnModelBeforeDeleteTopicParams } from "~/types"; -import { PluginsContainer } from "@webiny/plugins"; +import { CmsContext, OnModelBeforeDeleteTopicParams } from "~/types"; import WebinyError from "@webiny/error"; import { CmsModelPlugin } from "~/plugins/CmsModelPlugin"; interface AssignBeforeModelDeleteParams { onModelBeforeDelete: Topic; - storageOperations: HeadlessCmsStorageOperations; - plugins: PluginsContainer; + context: CmsContext; } export const assignModelBeforeDelete = (params: AssignBeforeModelDeleteParams) => { - const { onModelBeforeDelete, storageOperations, plugins } = params; + const { onModelBeforeDelete, context } = params; onModelBeforeDelete.subscribe(async params => { const { model } = params; - const modelPlugin = plugins + const modelPlugin = context.plugins .byType(CmsModelPlugin.type) .find(item => item.contentModel.modelId === model.modelId); @@ -29,30 +27,32 @@ export const assignModelBeforeDelete = (params: AssignBeforeModelDeleteParams) = ); } - let entries = []; try { - const result = await storageOperations.entries.list(model, { - where: { - latest: true - }, - limit: 1 - }); - entries = result.items; + const [latestEntries] = await context.cms.listLatestEntries(model, { limit: 1 }); + + if (latestEntries.length > 0) { + throw new WebinyError( + `Cannot delete content model "${model.modelId}" because there are existing entries.`, + "CONTENT_MODEL_BEFORE_DELETE_HOOK_FAILED" + ); + } + + const [deletedEntries] = await context.cms.listDeletedEntries(model, { limit: 1 }); + + if (deletedEntries.length > 0) { + throw new WebinyError( + `Cannot delete content model "${model.modelId}" because there are existing entries in the trash.`, + "CONTENT_MODEL_BEFORE_DELETE_HOOK_FAILED" + ); + } } catch (ex) { - throw new WebinyError( - "Could not retrieve a list of content entries from the model.", - "ENTRIES_ERROR", - { - error: ex, + throw WebinyError.from(ex, { + message: "Could not retrieve a list of content entries from the model.", + code: "ENTRIES_ERROR", + data: { model } - ); - } - if (entries.length > 0) { - throw new WebinyError( - `Cannot delete content model "${model.modelId}" because there are existing entries.`, - "CONTENT_MODEL_BEFORE_DELETE_HOOK_FAILED" - ); + }); } }); };