@strapi/content-manager 5.0.0-rc.1 → 5.0.0-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-D8RyVgJC.js → ComponentConfigurationPage-D_M8iBw5.js} +3 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-D8RyVgJC.js.map → ComponentConfigurationPage-D_M8iBw5.js.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-DLuACgva.mjs → ComponentConfigurationPage-qemkOlnj.mjs} +3 -3
  4. package/dist/_chunks/{ComponentConfigurationPage-DLuACgva.mjs.map → ComponentConfigurationPage-qemkOlnj.mjs.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-fOm5AebB.js → EditConfigurationPage-BePwPuHy.js} +3 -3
  6. package/dist/_chunks/{EditConfigurationPage-fOm5AebB.js.map → EditConfigurationPage-BePwPuHy.js.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-CuCAsHWR.mjs → EditConfigurationPage-CjUrEewK.mjs} +3 -3
  8. package/dist/_chunks/{EditConfigurationPage-CuCAsHWR.mjs.map → EditConfigurationPage-CjUrEewK.mjs.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-Or0fpTwh.js → EditViewPage-B-RJeiJD.js} +19 -8
  10. package/dist/_chunks/EditViewPage-B-RJeiJD.js.map +1 -0
  11. package/dist/_chunks/{EditViewPage-BqDlT9w0.mjs → EditViewPage-De8GyU8P.mjs} +19 -8
  12. package/dist/_chunks/EditViewPage-De8GyU8P.mjs.map +1 -0
  13. package/dist/_chunks/{Field-Bix2HU_O.js → Field-dq8Tg1M_.js} +99 -33
  14. package/dist/_chunks/Field-dq8Tg1M_.js.map +1 -0
  15. package/dist/_chunks/{Field-OfBJ6x59.mjs → Field-pb2o8uBe.mjs} +101 -35
  16. package/dist/_chunks/Field-pb2o8uBe.mjs.map +1 -0
  17. package/dist/_chunks/{Form-Bv5ABnqE.js → Form-DGIf4jQU.js} +22 -11
  18. package/dist/_chunks/Form-DGIf4jQU.js.map +1 -0
  19. package/dist/_chunks/{Form-DyMXqj_v.mjs → Form-DJn0Dxha.mjs} +22 -11
  20. package/dist/_chunks/Form-DJn0Dxha.mjs.map +1 -0
  21. package/dist/_chunks/{History-rvLnluF0.mjs → History-BowL3JKP.mjs} +4 -4
  22. package/dist/_chunks/{History-rvLnluF0.mjs.map → History-BowL3JKP.mjs.map} +1 -1
  23. package/dist/_chunks/{History-fnln26gA.js → History-Dh2NEHnR.js} +4 -4
  24. package/dist/_chunks/{History-fnln26gA.js.map → History-Dh2NEHnR.js.map} +1 -1
  25. package/dist/_chunks/{ListConfigurationPage-DdKfJRdq.mjs → ListConfigurationPage-BpVOB-hn.mjs} +14 -4
  26. package/dist/_chunks/ListConfigurationPage-BpVOB-hn.mjs.map +1 -0
  27. package/dist/_chunks/{ListConfigurationPage-BtCBP_L_.js → ListConfigurationPage-BxYCWz9e.js} +14 -4
  28. package/dist/_chunks/ListConfigurationPage-BxYCWz9e.js.map +1 -0
  29. package/dist/_chunks/{ListViewPage-CGZWD2qn.js → ListViewPage-4XsciqHZ.js} +9 -4
  30. package/dist/_chunks/ListViewPage-4XsciqHZ.js.map +1 -0
  31. package/dist/_chunks/{ListViewPage-B8cPO1bK.mjs → ListViewPage-CXFUjZQC.mjs} +10 -5
  32. package/dist/_chunks/ListViewPage-CXFUjZQC.mjs.map +1 -0
  33. package/dist/_chunks/{NoContentTypePage-oJxX0WCQ.js → NoContentTypePage-C8OpoHeU.js} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-oJxX0WCQ.js.map → NoContentTypePage-C8OpoHeU.js.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-CVqYTeML.mjs → NoContentTypePage-DuhOTp3x.mjs} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-CVqYTeML.mjs.map → NoContentTypePage-DuhOTp3x.mjs.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-mlXqh8p6.mjs → NoPermissionsPage-DVz3mzDz.mjs} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-mlXqh8p6.mjs.map → NoPermissionsPage-DVz3mzDz.mjs.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-BB11jqM_.js → NoPermissionsPage-y_r7DVA2.js} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-BB11jqM_.js.map → NoPermissionsPage-y_r7DVA2.js.map} +1 -1
  41. package/dist/_chunks/{Relations-DWscdjKO.mjs → Relations-CVNLrn1Y.mjs} +4 -4
  42. package/dist/_chunks/{Relations-DWscdjKO.mjs.map → Relations-CVNLrn1Y.mjs.map} +1 -1
  43. package/dist/_chunks/{Relations-6xIumgbN.js → Relations-DPFCAa7b.js} +4 -4
  44. package/dist/_chunks/{Relations-6xIumgbN.js.map → Relations-DPFCAa7b.js.map} +1 -1
  45. package/dist/_chunks/{index-BzUwgKUj.js → index-C3fJE-1-.js} +140 -71
  46. package/dist/_chunks/index-C3fJE-1-.js.map +1 -0
  47. package/dist/_chunks/{index-JSJrqmB9.mjs → index-DiMrfcfy.mjs} +158 -89
  48. package/dist/_chunks/index-DiMrfcfy.mjs.map +1 -0
  49. package/dist/_chunks/{layout-U4xJd8Oi.js → layout-C788OmNr.js} +19 -7
  50. package/dist/_chunks/layout-C788OmNr.js.map +1 -0
  51. package/dist/_chunks/{layout-Dewoec1b.mjs → layout-ls3gxfpH.mjs} +20 -8
  52. package/dist/_chunks/layout-ls3gxfpH.mjs.map +1 -0
  53. package/dist/_chunks/{relations-DMxeUp5V.mjs → relations-CLcOmGO0.mjs} +2 -2
  54. package/dist/_chunks/{relations-DMxeUp5V.mjs.map → relations-CLcOmGO0.mjs.map} +1 -1
  55. package/dist/_chunks/{relations-BifGhhuo.js → relations-DYeotliT.js} +2 -2
  56. package/dist/_chunks/{relations-BifGhhuo.js.map → relations-DYeotliT.js.map} +1 -1
  57. package/dist/admin/index.js +1 -1
  58. package/dist/admin/index.mjs +4 -4
  59. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  60. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  61. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  62. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +10 -22
  63. package/dist/admin/src/services/api.d.ts +1 -1
  64. package/dist/admin/src/services/components.d.ts +2 -2
  65. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  66. package/dist/admin/src/services/documents.d.ts +16 -16
  67. package/dist/admin/src/services/init.d.ts +1 -1
  68. package/dist/admin/src/services/relations.d.ts +2 -2
  69. package/dist/admin/src/services/uid.d.ts +3 -3
  70. package/dist/admin/src/utils/validation.d.ts +4 -1
  71. package/dist/server/index.js +155 -103
  72. package/dist/server/index.js.map +1 -1
  73. package/dist/server/index.mjs +156 -104
  74. package/dist/server/index.mjs.map +1 -1
  75. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  76. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  77. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  78. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  79. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  80. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  81. package/dist/server/src/history/services/utils.d.ts +1 -1
  82. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  83. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  84. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  85. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  86. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  87. package/package.json +8 -8
  88. package/dist/_chunks/EditViewPage-BqDlT9w0.mjs.map +0 -1
  89. package/dist/_chunks/EditViewPage-Or0fpTwh.js.map +0 -1
  90. package/dist/_chunks/Field-Bix2HU_O.js.map +0 -1
  91. package/dist/_chunks/Field-OfBJ6x59.mjs.map +0 -1
  92. package/dist/_chunks/Form-Bv5ABnqE.js.map +0 -1
  93. package/dist/_chunks/Form-DyMXqj_v.mjs.map +0 -1
  94. package/dist/_chunks/ListConfigurationPage-BtCBP_L_.js.map +0 -1
  95. package/dist/_chunks/ListConfigurationPage-DdKfJRdq.mjs.map +0 -1
  96. package/dist/_chunks/ListViewPage-B8cPO1bK.mjs.map +0 -1
  97. package/dist/_chunks/ListViewPage-CGZWD2qn.js.map +0 -1
  98. package/dist/_chunks/index-BzUwgKUj.js.map +0 -1
  99. package/dist/_chunks/index-JSJrqmB9.mjs.map +0 -1
  100. package/dist/_chunks/layout-Dewoec1b.mjs.map +0 -1
  101. package/dist/_chunks/layout-U4xJd8Oi.js.map +0 -1
@@ -226,9 +226,10 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
226
226
  const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
227
227
  return documentMetadataService.getStatus(document, meta.availableStatus);
228
228
  };
229
- const getDeepPopulate2 = (uid2) => {
229
+ const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
230
230
  const model = strapi2.getModel(uid2);
231
231
  const attributes = Object.entries(model.attributes);
232
+ const fieldSelector = useDatabaseSyntax ? "select" : "fields";
232
233
  return attributes.reduce((acc, [attributeName, attribute]) => {
233
234
  switch (attribute.type) {
234
235
  case "relation": {
@@ -238,12 +239,12 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
238
239
  }
239
240
  const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
240
241
  if (isVisible2) {
241
- acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
242
+ acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
242
243
  }
243
244
  break;
244
245
  }
245
246
  case "media": {
246
- acc[attributeName] = { fields: ["id"] };
247
+ acc[attributeName] = { [fieldSelector]: ["id"] };
247
248
  break;
248
249
  }
249
250
  case "component": {
@@ -494,6 +495,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
494
495
  }
495
496
  };
496
497
  };
498
+ const shouldCreateHistoryVersion = (context) => {
499
+ if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
500
+ return false;
501
+ }
502
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
503
+ return false;
504
+ }
505
+ if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
506
+ return false;
507
+ }
508
+ if (!context.contentType.uid.startsWith("api::")) {
509
+ return false;
510
+ }
511
+ return true;
512
+ };
513
+ const getSchemas = (uid2) => {
514
+ const attributesSchema = strapi.getModel(uid2).attributes;
515
+ const componentsSchemas = Object.keys(attributesSchema).reduce(
516
+ (currentComponentSchemas, key) => {
517
+ const fieldSchema = attributesSchema[key];
518
+ if (fieldSchema.type === "component") {
519
+ const componentSchema = strapi.getModel(fieldSchema.component).attributes;
520
+ return {
521
+ ...currentComponentSchemas,
522
+ [fieldSchema.component]: componentSchema
523
+ };
524
+ }
525
+ return currentComponentSchemas;
526
+ },
527
+ {}
528
+ );
529
+ return {
530
+ schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
531
+ componentsSchemas
532
+ };
533
+ };
497
534
  const createLifecyclesService = ({ strapi: strapi2 }) => {
498
535
  const state = {
499
536
  deleteExpiredJob: null,
@@ -506,63 +543,43 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
506
543
  return;
507
544
  }
508
545
  strapi2.documents.use(async (context, next) => {
509
- if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
510
- return next();
511
- }
512
- if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
513
- return next();
514
- }
515
- if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
516
- return next();
517
- }
518
- const contentTypeUid = context.contentType.uid;
519
- if (!contentTypeUid.startsWith("api::")) {
520
- return next();
521
- }
522
546
  const result = await next();
523
- const documentContext = {
524
- documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
525
- locale: context.params?.locale
526
- };
547
+ if (!shouldCreateHistoryVersion(context)) {
548
+ return result;
549
+ }
550
+ const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
527
551
  const defaultLocale = await serviceUtils.getDefaultLocale();
528
- const locale = documentContext.locale || defaultLocale;
529
- if (Array.isArray(locale)) {
530
- strapi2.log.warn(
531
- "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
532
- );
533
- return next();
552
+ const locales = fp.castArray(context.params?.locale || defaultLocale);
553
+ if (!locales.length) {
554
+ return result;
534
555
  }
535
- const document = await strapi2.documents(contentTypeUid).findOne({
536
- documentId: documentContext.documentId,
537
- locale,
538
- populate: serviceUtils.getDeepPopulate(contentTypeUid)
556
+ const uid2 = context.contentType.uid;
557
+ const schemas = getSchemas(uid2);
558
+ const localeEntries = await strapi2.db.query(uid2).findMany({
559
+ where: {
560
+ documentId,
561
+ locale: { $in: locales },
562
+ publishedAt: null
563
+ },
564
+ populate: serviceUtils.getDeepPopulate(
565
+ uid2,
566
+ true
567
+ /* use database syntax */
568
+ )
539
569
  });
540
- const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
541
- const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
542
- const componentsSchemas = Object.keys(
543
- attributesSchema
544
- ).reduce((currentComponentSchemas, key) => {
545
- const fieldSchema = attributesSchema[key];
546
- if (fieldSchema.type === "component") {
547
- const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
548
- return {
549
- ...currentComponentSchemas,
550
- [fieldSchema.component]: componentSchema
551
- };
552
- }
553
- return currentComponentSchemas;
554
- }, {});
555
570
  await strapi2.db.transaction(async ({ onCommit }) => {
556
- onCommit(() => {
557
- getService(strapi2, "history").createVersion({
558
- contentType: contentTypeUid,
559
- data: fp.omit(FIELDS_TO_IGNORE, document),
560
- schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
561
- componentsSchemas,
562
- relatedDocumentId: documentContext.documentId,
563
- locale,
564
- status
565
- });
571
+ onCommit(async () => {
572
+ for (const entry of localeEntries) {
573
+ const status = await serviceUtils.getVersionStatus(uid2, entry);
574
+ await getService(strapi2, "history").createVersion({
575
+ contentType: uid2,
576
+ data: fp.omit(FIELDS_TO_IGNORE, entry),
577
+ relatedDocumentId: documentId,
578
+ locale: entry.locale,
579
+ status,
580
+ ...schemas
581
+ });
582
+ }
566
583
  });
567
584
  });
568
585
  return result;
@@ -1202,6 +1219,11 @@ const { createPolicy } = strapiUtils.policy;
1202
1219
  const hasPermissions = createPolicy({
1203
1220
  name: "plugin::content-manager.hasPermissions",
1204
1221
  validator: validateHasPermissionsInput,
1222
+ /**
1223
+ * NOTE: Action aliases are currently not checked at this level (policy).
1224
+ * This is currently the intended behavior to avoid changing the behavior of API related permissions.
1225
+ * If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
1226
+ */
1205
1227
  handler(ctx, config = {}) {
1206
1228
  const { actions = [], hasAtLeastOne = false } = config;
1207
1229
  const { userAbility } = ctx.state;
@@ -1595,9 +1617,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
1595
1617
  (value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1596
1618
  );
1597
1619
  const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
1598
- const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1620
+ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
1599
1621
  const { allowMultipleLocales } = opts;
1600
- const { locale, status, ...rest } = request || {};
1622
+ const { locale, status: providedStatus, ...rest } = request || {};
1623
+ const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
1624
+ const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
1601
1625
  const schema = strapiUtils.yup.object().shape({
1602
1626
  locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1603
1627
  status: statusSchema
@@ -1645,7 +1669,7 @@ const createDocument = async (ctx, opts) => {
1645
1669
  const setCreator = strapiUtils.setCreatorFields({ user });
1646
1670
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1647
1671
  const sanitizedBody = await sanitizeFn(body);
1648
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1672
+ const { locale, status } = await getDocumentLocaleAndStatus(body, model);
1649
1673
  return documentManager2.create(model, {
1650
1674
  data: sanitizedBody,
1651
1675
  locale,
@@ -1664,7 +1688,7 @@ const updateDocument = async (ctx, opts) => {
1664
1688
  }
1665
1689
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1666
1690
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1667
- const { locale } = await getDocumentLocaleAndStatus(body);
1691
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1668
1692
  const [documentVersion, documentExists] = await Promise.all([
1669
1693
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1670
1694
  documentManager2.exists(model, id)
@@ -1702,7 +1726,7 @@ const collectionTypes = {
1702
1726
  }
1703
1727
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1704
1728
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1705
- const { locale, status } = await getDocumentLocaleAndStatus(query);
1729
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
1706
1730
  const { results: documents, pagination } = await documentManager2.findPage(
1707
1731
  { ...permissionQuery, populate, locale, status },
1708
1732
  model
@@ -1737,7 +1761,7 @@ const collectionTypes = {
1737
1761
  }
1738
1762
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1739
1763
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1740
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1764
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1741
1765
  const version = await documentManager2.findOne(id, model, {
1742
1766
  populate,
1743
1767
  locale,
@@ -1804,7 +1828,7 @@ const collectionTypes = {
1804
1828
  }
1805
1829
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1806
1830
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1807
- const { locale } = await getDocumentLocaleAndStatus(body);
1831
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1808
1832
  const document = await documentManager2.findOne(id, model, {
1809
1833
  populate,
1810
1834
  locale,
@@ -1849,7 +1873,7 @@ const collectionTypes = {
1849
1873
  }
1850
1874
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1851
1875
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1852
- const { locale } = await getDocumentLocaleAndStatus(ctx.query);
1876
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
1853
1877
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1854
1878
  if (documentLocales.length === 0) {
1855
1879
  return ctx.notFound();
@@ -1878,11 +1902,28 @@ const collectionTypes = {
1878
1902
  const publishedDocument = await strapi.db.transaction(async () => {
1879
1903
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1880
1904
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1881
- const document = id ? await updateDocument(ctx, { populate }) : await createDocument(ctx, { populate });
1905
+ let document;
1906
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1907
+ const isCreate = fp.isNil(id);
1908
+ if (isCreate) {
1909
+ if (permissionChecker2.cannot.create()) {
1910
+ throw new strapiUtils.errors.ForbiddenError();
1911
+ }
1912
+ document = await createDocument(ctx, { populate });
1913
+ }
1914
+ const isUpdate = !isCreate;
1915
+ if (isUpdate) {
1916
+ document = await documentManager2.findOne(id, model, { populate, locale });
1917
+ if (!document) {
1918
+ throw new strapiUtils.errors.NotFoundError("Document not found");
1919
+ }
1920
+ if (permissionChecker2.can.update(document)) {
1921
+ await updateDocument(ctx);
1922
+ }
1923
+ }
1882
1924
  if (permissionChecker2.cannot.publish(document)) {
1883
1925
  throw new strapiUtils.errors.ForbiddenError();
1884
1926
  }
1885
- const { locale } = await getDocumentLocaleAndStatus(body);
1886
1927
  const publishResult = await documentManager2.publish(document.documentId, model, {
1887
1928
  locale
1888
1929
  // TODO: Allow setting creator fields on publish
@@ -1909,7 +1950,9 @@ const collectionTypes = {
1909
1950
  }
1910
1951
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1911
1952
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1912
- const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
1953
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
1954
+ allowMultipleLocales: true
1955
+ });
1913
1956
  const entityPromises = documentIds.map(
1914
1957
  (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1915
1958
  );
@@ -1936,7 +1979,7 @@ const collectionTypes = {
1936
1979
  if (permissionChecker2.cannot.unpublish()) {
1937
1980
  return ctx.forbidden();
1938
1981
  }
1939
- const { locale } = await getDocumentLocaleAndStatus(body);
1982
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1940
1983
  const entityPromises = documentIds.map(
1941
1984
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1942
1985
  );
@@ -1969,7 +2012,7 @@ const collectionTypes = {
1969
2012
  }
1970
2013
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1971
2014
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1972
- const { locale } = await getDocumentLocaleAndStatus(body);
2015
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1973
2016
  const document = await documentManager2.findOne(id, model, {
1974
2017
  populate,
1975
2018
  locale,
@@ -2006,7 +2049,7 @@ const collectionTypes = {
2006
2049
  }
2007
2050
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
2008
2051
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2009
- const { locale } = await getDocumentLocaleAndStatus(body);
2052
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2010
2053
  const document = await documentManager2.findOne(id, model, {
2011
2054
  populate,
2012
2055
  locale,
@@ -2037,7 +2080,7 @@ const collectionTypes = {
2037
2080
  }
2038
2081
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
2039
2082
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2040
- const { locale } = await getDocumentLocaleAndStatus(body);
2083
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2041
2084
  const documentLocales = await documentManager2.findLocales(documentIds, model, {
2042
2085
  populate,
2043
2086
  locale
@@ -2064,7 +2107,7 @@ const collectionTypes = {
2064
2107
  }
2065
2108
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2066
2109
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2067
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
2110
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
2068
2111
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2069
2112
  if (!entity) {
2070
2113
  return ctx.notFound();
@@ -2287,20 +2330,13 @@ const sanitizeMainField = (model, mainField, userAbility) => {
2287
2330
  userAbility,
2288
2331
  model: model.uid
2289
2332
  });
2290
- if (!isListable(model, mainField)) {
2333
+ const isMainFieldListable = isListable(model, mainField);
2334
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2335
+ if (!isMainFieldListable || !canReadMainField) {
2291
2336
  return "id";
2292
2337
  }
2293
- if (permissionChecker2.cannot.read(null, mainField)) {
2294
- if (model.uid === "plugin::users-permissions.role") {
2295
- const userPermissionChecker = getService$1("permission-checker").create({
2296
- userAbility,
2297
- model: "plugin::users-permissions.user"
2298
- });
2299
- if (userPermissionChecker.can.read()) {
2300
- return "name";
2301
- }
2302
- }
2303
- return "id";
2338
+ if (model.uid === "plugin::users-permissions.role") {
2339
+ return "name";
2304
2340
  }
2305
2341
  return mainField;
2306
2342
  };
@@ -2558,9 +2594,7 @@ const relations = {
2558
2594
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2559
2595
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2560
2596
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2561
- ordering: "desc",
2562
- page: ctx.request.query.page,
2563
- pageSize: ctx.request.query.pageSize
2597
+ ordering: "desc"
2564
2598
  });
2565
2599
  const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
2566
2600
  ctx.body = {
@@ -2592,7 +2626,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
2592
2626
  throw new strapiUtils.errors.ForbiddenError();
2593
2627
  }
2594
2628
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2595
- const { locale } = await getDocumentLocaleAndStatus(body);
2629
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2596
2630
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2597
2631
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2598
2632
  // Find the first document to check if it exists
@@ -2633,7 +2667,7 @@ const singleTypes = {
2633
2667
  return ctx.forbidden();
2634
2668
  }
2635
2669
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2636
- const { locale, status } = await getDocumentLocaleAndStatus(query);
2670
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
2637
2671
  const version = await findDocument(permissionQuery, model, { locale, status });
2638
2672
  if (!version) {
2639
2673
  if (permissionChecker2.cannot.create()) {
@@ -2678,7 +2712,7 @@ const singleTypes = {
2678
2712
  }
2679
2713
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2680
2714
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2681
- const { locale } = await getDocumentLocaleAndStatus(query);
2715
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2682
2716
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2683
2717
  populate,
2684
2718
  locale
@@ -2715,7 +2749,7 @@ const singleTypes = {
2715
2749
  if (permissionChecker2.cannot.publish(document)) {
2716
2750
  throw new strapiUtils.errors.ForbiddenError();
2717
2751
  }
2718
- const { locale } = await getDocumentLocaleAndStatus(document);
2752
+ const { locale } = await getDocumentLocaleAndStatus(document, model);
2719
2753
  const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2720
2754
  return publishResult.at(0);
2721
2755
  });
@@ -2738,7 +2772,7 @@ const singleTypes = {
2738
2772
  return ctx.forbidden();
2739
2773
  }
2740
2774
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2741
- const { locale } = await getDocumentLocaleAndStatus(body);
2775
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2742
2776
  const document = await findDocument(sanitizedQuery, model, { locale });
2743
2777
  if (!document) {
2744
2778
  return ctx.notFound();
@@ -2770,7 +2804,7 @@ const singleTypes = {
2770
2804
  return ctx.forbidden();
2771
2805
  }
2772
2806
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2773
- const { locale } = await getDocumentLocaleAndStatus(body);
2807
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2774
2808
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2775
2809
  if (!document) {
2776
2810
  return ctx.notFound();
@@ -2790,7 +2824,7 @@ const singleTypes = {
2790
2824
  const { query } = ctx.request;
2791
2825
  const documentManager2 = getService$1("document-manager");
2792
2826
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2793
- const { locale } = await getDocumentLocaleAndStatus(query);
2827
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2794
2828
  if (permissionChecker2.cannot.read()) {
2795
2829
  return ctx.forbidden();
2796
2830
  }
@@ -2811,7 +2845,7 @@ const uid$1 = {
2811
2845
  async generateUID(ctx) {
2812
2846
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2813
2847
  const { query = {} } = ctx.request;
2814
- const { locale } = await getDocumentLocaleAndStatus(query);
2848
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2815
2849
  await validateUIDField(contentTypeUID, field);
2816
2850
  const uidService = getService$1("uid");
2817
2851
  ctx.body = {
@@ -2823,7 +2857,7 @@ const uid$1 = {
2823
2857
  ctx.request.body
2824
2858
  );
2825
2859
  const { query = {} } = ctx.request;
2826
- const { locale } = await getDocumentLocaleAndStatus(query);
2860
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2827
2861
  await validateUIDField(contentTypeUID, field);
2828
2862
  const uidService = getService$1("uid");
2829
2863
  const isAvailable = await uidService.checkUIDAvailability({
@@ -3466,12 +3500,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3466
3500
  ability: userAbility,
3467
3501
  model
3468
3502
  });
3469
- const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3503
+ const { actionProvider } = strapi2.service("admin::permission");
3504
+ const toSubject = (entity) => {
3505
+ return entity ? permissionsManager.toSubject(entity, model) : model;
3506
+ };
3470
3507
  const can = (action, entity, field) => {
3471
- return userAbility.can(action, toSubject(entity), field);
3508
+ const subject = toSubject(entity);
3509
+ const aliases = actionProvider.unstable_aliases(action, model);
3510
+ return (
3511
+ // Test the original action to see if it passes
3512
+ userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
3513
+ aliases.some((alias) => userAbility.can(alias, subject, field))
3514
+ );
3472
3515
  };
3473
3516
  const cannot = (action, entity, field) => {
3474
- return userAbility.cannot(action, toSubject(entity), field);
3517
+ const subject = toSubject(entity);
3518
+ const aliases = actionProvider.unstable_aliases(action, model);
3519
+ return (
3520
+ // Test both the original action
3521
+ userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
3522
+ aliases.every((alias) => userAbility.cannot(alias, subject, field))
3523
+ );
3475
3524
  };
3476
3525
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3477
3526
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
@@ -4129,7 +4178,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4129
4178
  */
4130
4179
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
4131
4180
  if (!document) {
4132
- return document;
4181
+ return {
4182
+ data: document,
4183
+ meta: {
4184
+ availableLocales: [],
4185
+ availableStatus: []
4186
+ }
4187
+ };
4133
4188
  }
4134
4189
  const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
4135
4190
  if (!hasDraftAndPublish) {
@@ -4237,10 +4292,7 @@ const documentManager = ({ strapi: strapi2 }) => {
4237
4292
  async clone(id, body, uid2) {
4238
4293
  const populate = await buildDeepPopulate(uid2);
4239
4294
  const params = {
4240
- data: {
4241
- ...omitIdField(body),
4242
- [PUBLISHED_AT_ATTRIBUTE]: null
4243
- },
4295
+ data: omitIdField(body),
4244
4296
  populate
4245
4297
  };
4246
4298
  return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));