@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
@@ -1,5 +1,5 @@
1
1
  import strapiUtils, { validateYupSchema, errors, async, contentTypes as contentTypes$1, yup as yup$1, validateYupSchemaSync, policy, traverse, setCreatorFields, isOperatorOfType, relations as relations$1, traverseEntity, pagination } from "@strapi/utils";
2
- import { pick, omit, difference, intersection, pipe, propOr, isEqual, isEmpty, set, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, isNil as isNil$1, getOr, propEq, merge, groupBy, castArray } from "lodash/fp";
2
+ import { pick, omit, difference, castArray, intersection, pipe, propOr, isEqual, isEmpty, set, isNil as isNil$1, has, prop, assoc, mapValues, flow, uniq, uniqBy, concat, getOr, propEq, merge, groupBy } from "lodash/fp";
3
3
  import "@strapi/types";
4
4
  import * as yup from "yup";
5
5
  import { scheduleJob } from "node-schedule";
@@ -200,9 +200,10 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
200
200
  const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
201
201
  return documentMetadataService.getStatus(document, meta.availableStatus);
202
202
  };
203
- const getDeepPopulate2 = (uid2) => {
203
+ const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
204
204
  const model = strapi2.getModel(uid2);
205
205
  const attributes = Object.entries(model.attributes);
206
+ const fieldSelector = useDatabaseSyntax ? "select" : "fields";
206
207
  return attributes.reduce((acc, [attributeName, attribute]) => {
207
208
  switch (attribute.type) {
208
209
  case "relation": {
@@ -212,12 +213,12 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
212
213
  }
213
214
  const isVisible2 = contentTypes$1.isVisibleAttribute(model, attributeName);
214
215
  if (isVisible2) {
215
- acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
216
+ acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
216
217
  }
217
218
  break;
218
219
  }
219
220
  case "media": {
220
- acc[attributeName] = { fields: ["id"] };
221
+ acc[attributeName] = { [fieldSelector]: ["id"] };
221
222
  break;
222
223
  }
223
224
  case "component": {
@@ -468,6 +469,42 @@ const createHistoryService = ({ strapi: strapi2 }) => {
468
469
  }
469
470
  };
470
471
  };
472
+ const shouldCreateHistoryVersion = (context) => {
473
+ if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
474
+ return false;
475
+ }
476
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
477
+ return false;
478
+ }
479
+ if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
480
+ return false;
481
+ }
482
+ if (!context.contentType.uid.startsWith("api::")) {
483
+ return false;
484
+ }
485
+ return true;
486
+ };
487
+ const getSchemas = (uid2) => {
488
+ const attributesSchema = strapi.getModel(uid2).attributes;
489
+ const componentsSchemas = Object.keys(attributesSchema).reduce(
490
+ (currentComponentSchemas, key) => {
491
+ const fieldSchema = attributesSchema[key];
492
+ if (fieldSchema.type === "component") {
493
+ const componentSchema = strapi.getModel(fieldSchema.component).attributes;
494
+ return {
495
+ ...currentComponentSchemas,
496
+ [fieldSchema.component]: componentSchema
497
+ };
498
+ }
499
+ return currentComponentSchemas;
500
+ },
501
+ {}
502
+ );
503
+ return {
504
+ schema: omit(FIELDS_TO_IGNORE, attributesSchema),
505
+ componentsSchemas
506
+ };
507
+ };
471
508
  const createLifecyclesService = ({ strapi: strapi2 }) => {
472
509
  const state = {
473
510
  deleteExpiredJob: null,
@@ -480,63 +517,43 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
480
517
  return;
481
518
  }
482
519
  strapi2.documents.use(async (context, next) => {
483
- if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
484
- return next();
485
- }
486
- if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
487
- return next();
488
- }
489
- if (context.action === "update" && strapi2.requestContext.get()?.request.url.endsWith("/actions/publish")) {
490
- return next();
491
- }
492
- const contentTypeUid = context.contentType.uid;
493
- if (!contentTypeUid.startsWith("api::")) {
494
- return next();
495
- }
496
520
  const result = await next();
497
- const documentContext = {
498
- documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
499
- locale: context.params?.locale
500
- };
521
+ if (!shouldCreateHistoryVersion(context)) {
522
+ return result;
523
+ }
524
+ const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
501
525
  const defaultLocale = await serviceUtils.getDefaultLocale();
502
- const locale = documentContext.locale || defaultLocale;
503
- if (Array.isArray(locale)) {
504
- strapi2.log.warn(
505
- "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
506
- );
507
- return next();
526
+ const locales = castArray(context.params?.locale || defaultLocale);
527
+ if (!locales.length) {
528
+ return result;
508
529
  }
509
- const document = await strapi2.documents(contentTypeUid).findOne({
510
- documentId: documentContext.documentId,
511
- locale,
512
- populate: serviceUtils.getDeepPopulate(contentTypeUid)
530
+ const uid2 = context.contentType.uid;
531
+ const schemas = getSchemas(uid2);
532
+ const localeEntries = await strapi2.db.query(uid2).findMany({
533
+ where: {
534
+ documentId,
535
+ locale: { $in: locales },
536
+ publishedAt: null
537
+ },
538
+ populate: serviceUtils.getDeepPopulate(
539
+ uid2,
540
+ true
541
+ /* use database syntax */
542
+ )
513
543
  });
514
- const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
515
- const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
516
- const componentsSchemas = Object.keys(
517
- attributesSchema
518
- ).reduce((currentComponentSchemas, key) => {
519
- const fieldSchema = attributesSchema[key];
520
- if (fieldSchema.type === "component") {
521
- const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
522
- return {
523
- ...currentComponentSchemas,
524
- [fieldSchema.component]: componentSchema
525
- };
526
- }
527
- return currentComponentSchemas;
528
- }, {});
529
544
  await strapi2.db.transaction(async ({ onCommit }) => {
530
- onCommit(() => {
531
- getService(strapi2, "history").createVersion({
532
- contentType: contentTypeUid,
533
- data: omit(FIELDS_TO_IGNORE, document),
534
- schema: omit(FIELDS_TO_IGNORE, attributesSchema),
535
- componentsSchemas,
536
- relatedDocumentId: documentContext.documentId,
537
- locale,
538
- status
539
- });
545
+ onCommit(async () => {
546
+ for (const entry of localeEntries) {
547
+ const status = await serviceUtils.getVersionStatus(uid2, entry);
548
+ await getService(strapi2, "history").createVersion({
549
+ contentType: uid2,
550
+ data: omit(FIELDS_TO_IGNORE, entry),
551
+ relatedDocumentId: documentId,
552
+ locale: entry.locale,
553
+ status,
554
+ ...schemas
555
+ });
556
+ }
540
557
  });
541
558
  });
542
559
  return result;
@@ -1176,6 +1193,11 @@ const { createPolicy } = policy;
1176
1193
  const hasPermissions = createPolicy({
1177
1194
  name: "plugin::content-manager.hasPermissions",
1178
1195
  validator: validateHasPermissionsInput,
1196
+ /**
1197
+ * NOTE: Action aliases are currently not checked at this level (policy).
1198
+ * This is currently the intended behavior to avoid changing the behavior of API related permissions.
1199
+ * If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
1200
+ */
1179
1201
  handler(ctx, config = {}) {
1180
1202
  const { actions = [], hasAtLeastOne = false } = config;
1181
1203
  const { userAbility } = ctx.state;
@@ -1569,9 +1591,11 @@ const multipleLocaleSchema = yup$1.lazy(
1569
1591
  (value) => Array.isArray(value) ? yup$1.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1570
1592
  );
1571
1593
  const statusSchema = yup$1.mixed().oneOf(["draft", "published"], "Invalid status");
1572
- const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1594
+ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
1573
1595
  const { allowMultipleLocales } = opts;
1574
- const { locale, status, ...rest } = request || {};
1596
+ const { locale, status: providedStatus, ...rest } = request || {};
1597
+ const defaultStatus = contentTypes$1.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
1598
+ const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
1575
1599
  const schema = yup$1.object().shape({
1576
1600
  locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1577
1601
  status: statusSchema
@@ -1619,7 +1643,7 @@ const createDocument = async (ctx, opts) => {
1619
1643
  const setCreator = setCreatorFields({ user });
1620
1644
  const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
1621
1645
  const sanitizedBody = await sanitizeFn(body);
1622
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1646
+ const { locale, status } = await getDocumentLocaleAndStatus(body, model);
1623
1647
  return documentManager2.create(model, {
1624
1648
  data: sanitizedBody,
1625
1649
  locale,
@@ -1638,7 +1662,7 @@ const updateDocument = async (ctx, opts) => {
1638
1662
  }
1639
1663
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1640
1664
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1641
- const { locale } = await getDocumentLocaleAndStatus(body);
1665
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1642
1666
  const [documentVersion, documentExists] = await Promise.all([
1643
1667
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1644
1668
  documentManager2.exists(model, id)
@@ -1676,7 +1700,7 @@ const collectionTypes = {
1676
1700
  }
1677
1701
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1678
1702
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1679
- const { locale, status } = await getDocumentLocaleAndStatus(query);
1703
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
1680
1704
  const { results: documents, pagination: pagination2 } = await documentManager2.findPage(
1681
1705
  { ...permissionQuery, populate, locale, status },
1682
1706
  model
@@ -1711,7 +1735,7 @@ const collectionTypes = {
1711
1735
  }
1712
1736
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1713
1737
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1714
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1738
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1715
1739
  const version = await documentManager2.findOne(id, model, {
1716
1740
  populate,
1717
1741
  locale,
@@ -1778,7 +1802,7 @@ const collectionTypes = {
1778
1802
  }
1779
1803
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1780
1804
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1781
- const { locale } = await getDocumentLocaleAndStatus(body);
1805
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1782
1806
  const document = await documentManager2.findOne(id, model, {
1783
1807
  populate,
1784
1808
  locale,
@@ -1823,7 +1847,7 @@ const collectionTypes = {
1823
1847
  }
1824
1848
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1825
1849
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1826
- const { locale } = await getDocumentLocaleAndStatus(ctx.query);
1850
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
1827
1851
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1828
1852
  if (documentLocales.length === 0) {
1829
1853
  return ctx.notFound();
@@ -1852,11 +1876,28 @@ const collectionTypes = {
1852
1876
  const publishedDocument = await strapi.db.transaction(async () => {
1853
1877
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1854
1878
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1855
- const document = id ? await updateDocument(ctx, { populate }) : await createDocument(ctx, { populate });
1879
+ let document;
1880
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1881
+ const isCreate = isNil$1(id);
1882
+ if (isCreate) {
1883
+ if (permissionChecker2.cannot.create()) {
1884
+ throw new errors.ForbiddenError();
1885
+ }
1886
+ document = await createDocument(ctx, { populate });
1887
+ }
1888
+ const isUpdate = !isCreate;
1889
+ if (isUpdate) {
1890
+ document = await documentManager2.findOne(id, model, { populate, locale });
1891
+ if (!document) {
1892
+ throw new errors.NotFoundError("Document not found");
1893
+ }
1894
+ if (permissionChecker2.can.update(document)) {
1895
+ await updateDocument(ctx);
1896
+ }
1897
+ }
1856
1898
  if (permissionChecker2.cannot.publish(document)) {
1857
1899
  throw new errors.ForbiddenError();
1858
1900
  }
1859
- const { locale } = await getDocumentLocaleAndStatus(body);
1860
1901
  const publishResult = await documentManager2.publish(document.documentId, model, {
1861
1902
  locale
1862
1903
  // TODO: Allow setting creator fields on publish
@@ -1883,7 +1924,9 @@ const collectionTypes = {
1883
1924
  }
1884
1925
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1885
1926
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1886
- const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
1927
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
1928
+ allowMultipleLocales: true
1929
+ });
1887
1930
  const entityPromises = documentIds.map(
1888
1931
  (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1889
1932
  );
@@ -1910,7 +1953,7 @@ const collectionTypes = {
1910
1953
  if (permissionChecker2.cannot.unpublish()) {
1911
1954
  return ctx.forbidden();
1912
1955
  }
1913
- const { locale } = await getDocumentLocaleAndStatus(body);
1956
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1914
1957
  const entityPromises = documentIds.map(
1915
1958
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1916
1959
  );
@@ -1943,7 +1986,7 @@ const collectionTypes = {
1943
1986
  }
1944
1987
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1945
1988
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1946
- const { locale } = await getDocumentLocaleAndStatus(body);
1989
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1947
1990
  const document = await documentManager2.findOne(id, model, {
1948
1991
  populate,
1949
1992
  locale,
@@ -1980,7 +2023,7 @@ const collectionTypes = {
1980
2023
  }
1981
2024
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
1982
2025
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1983
- const { locale } = await getDocumentLocaleAndStatus(body);
2026
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1984
2027
  const document = await documentManager2.findOne(id, model, {
1985
2028
  populate,
1986
2029
  locale,
@@ -2011,7 +2054,7 @@ const collectionTypes = {
2011
2054
  }
2012
2055
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
2013
2056
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2014
- const { locale } = await getDocumentLocaleAndStatus(body);
2057
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2015
2058
  const documentLocales = await documentManager2.findLocales(documentIds, model, {
2016
2059
  populate,
2017
2060
  locale
@@ -2038,7 +2081,7 @@ const collectionTypes = {
2038
2081
  }
2039
2082
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2040
2083
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2041
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
2084
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
2042
2085
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2043
2086
  if (!entity) {
2044
2087
  return ctx.notFound();
@@ -2261,20 +2304,13 @@ const sanitizeMainField = (model, mainField, userAbility) => {
2261
2304
  userAbility,
2262
2305
  model: model.uid
2263
2306
  });
2264
- if (!isListable(model, mainField)) {
2307
+ const isMainFieldListable = isListable(model, mainField);
2308
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2309
+ if (!isMainFieldListable || !canReadMainField) {
2265
2310
  return "id";
2266
2311
  }
2267
- if (permissionChecker2.cannot.read(null, mainField)) {
2268
- if (model.uid === "plugin::users-permissions.role") {
2269
- const userPermissionChecker = getService$1("permission-checker").create({
2270
- userAbility,
2271
- model: "plugin::users-permissions.user"
2272
- });
2273
- if (userPermissionChecker.can.read()) {
2274
- return "name";
2275
- }
2276
- }
2277
- return "id";
2312
+ if (model.uid === "plugin::users-permissions.role") {
2313
+ return "name";
2278
2314
  }
2279
2315
  return mainField;
2280
2316
  };
@@ -2532,9 +2568,7 @@ const relations = {
2532
2568
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2533
2569
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2534
2570
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2535
- ordering: "desc",
2536
- page: ctx.request.query.page,
2537
- pageSize: ctx.request.query.pageSize
2571
+ ordering: "desc"
2538
2572
  });
2539
2573
  const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
2540
2574
  ctx.body = {
@@ -2566,7 +2600,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
2566
2600
  throw new errors.ForbiddenError();
2567
2601
  }
2568
2602
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2569
- const { locale } = await getDocumentLocaleAndStatus(body);
2603
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2570
2604
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2571
2605
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2572
2606
  // Find the first document to check if it exists
@@ -2607,7 +2641,7 @@ const singleTypes = {
2607
2641
  return ctx.forbidden();
2608
2642
  }
2609
2643
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2610
- const { locale, status } = await getDocumentLocaleAndStatus(query);
2644
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
2611
2645
  const version = await findDocument(permissionQuery, model, { locale, status });
2612
2646
  if (!version) {
2613
2647
  if (permissionChecker2.cannot.create()) {
@@ -2652,7 +2686,7 @@ const singleTypes = {
2652
2686
  }
2653
2687
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2654
2688
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2655
- const { locale } = await getDocumentLocaleAndStatus(query);
2689
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2656
2690
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2657
2691
  populate,
2658
2692
  locale
@@ -2689,7 +2723,7 @@ const singleTypes = {
2689
2723
  if (permissionChecker2.cannot.publish(document)) {
2690
2724
  throw new errors.ForbiddenError();
2691
2725
  }
2692
- const { locale } = await getDocumentLocaleAndStatus(document);
2726
+ const { locale } = await getDocumentLocaleAndStatus(document, model);
2693
2727
  const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2694
2728
  return publishResult.at(0);
2695
2729
  });
@@ -2712,7 +2746,7 @@ const singleTypes = {
2712
2746
  return ctx.forbidden();
2713
2747
  }
2714
2748
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2715
- const { locale } = await getDocumentLocaleAndStatus(body);
2749
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2716
2750
  const document = await findDocument(sanitizedQuery, model, { locale });
2717
2751
  if (!document) {
2718
2752
  return ctx.notFound();
@@ -2744,7 +2778,7 @@ const singleTypes = {
2744
2778
  return ctx.forbidden();
2745
2779
  }
2746
2780
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2747
- const { locale } = await getDocumentLocaleAndStatus(body);
2781
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2748
2782
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2749
2783
  if (!document) {
2750
2784
  return ctx.notFound();
@@ -2764,7 +2798,7 @@ const singleTypes = {
2764
2798
  const { query } = ctx.request;
2765
2799
  const documentManager2 = getService$1("document-manager");
2766
2800
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2767
- const { locale } = await getDocumentLocaleAndStatus(query);
2801
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2768
2802
  if (permissionChecker2.cannot.read()) {
2769
2803
  return ctx.forbidden();
2770
2804
  }
@@ -2785,7 +2819,7 @@ const uid$1 = {
2785
2819
  async generateUID(ctx) {
2786
2820
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2787
2821
  const { query = {} } = ctx.request;
2788
- const { locale } = await getDocumentLocaleAndStatus(query);
2822
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2789
2823
  await validateUIDField(contentTypeUID, field);
2790
2824
  const uidService = getService$1("uid");
2791
2825
  ctx.body = {
@@ -2797,7 +2831,7 @@ const uid$1 = {
2797
2831
  ctx.request.body
2798
2832
  );
2799
2833
  const { query = {} } = ctx.request;
2800
- const { locale } = await getDocumentLocaleAndStatus(query);
2834
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2801
2835
  await validateUIDField(contentTypeUID, field);
2802
2836
  const uidService = getService$1("uid");
2803
2837
  const isAvailable = await uidService.checkUIDAvailability({
@@ -3440,12 +3474,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3440
3474
  ability: userAbility,
3441
3475
  model
3442
3476
  });
3443
- const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3477
+ const { actionProvider } = strapi2.service("admin::permission");
3478
+ const toSubject = (entity) => {
3479
+ return entity ? permissionsManager.toSubject(entity, model) : model;
3480
+ };
3444
3481
  const can = (action, entity, field) => {
3445
- return userAbility.can(action, toSubject(entity), field);
3482
+ const subject = toSubject(entity);
3483
+ const aliases = actionProvider.unstable_aliases(action, model);
3484
+ return (
3485
+ // Test the original action to see if it passes
3486
+ userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
3487
+ aliases.some((alias) => userAbility.can(alias, subject, field))
3488
+ );
3446
3489
  };
3447
3490
  const cannot = (action, entity, field) => {
3448
- return userAbility.cannot(action, toSubject(entity), field);
3491
+ const subject = toSubject(entity);
3492
+ const aliases = actionProvider.unstable_aliases(action, model);
3493
+ return (
3494
+ // Test both the original action
3495
+ userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
3496
+ aliases.every((alias) => userAbility.cannot(alias, subject, field))
3497
+ );
3449
3498
  };
3450
3499
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3451
3500
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
@@ -4103,7 +4152,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4103
4152
  */
4104
4153
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
4105
4154
  if (!document) {
4106
- return document;
4155
+ return {
4156
+ data: document,
4157
+ meta: {
4158
+ availableLocales: [],
4159
+ availableStatus: []
4160
+ }
4161
+ };
4107
4162
  }
4108
4163
  const hasDraftAndPublish = contentTypes$1.hasDraftAndPublish(strapi2.getModel(uid2));
4109
4164
  if (!hasDraftAndPublish) {
@@ -4211,10 +4266,7 @@ const documentManager = ({ strapi: strapi2 }) => {
4211
4266
  async clone(id, body, uid2) {
4212
4267
  const populate = await buildDeepPopulate(uid2);
4213
4268
  const params = {
4214
- data: {
4215
- ...omitIdField(body),
4216
- [PUBLISHED_AT_ATTRIBUTE]: null
4217
- },
4269
+ data: omitIdField(body),
4218
4270
  populate
4219
4271
  };
4220
4272
  return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));