@strapi/content-manager 0.0.0-experimental.3c73a4c6f6073abdf1608121a200c3d4d87b1aa8 → 0.0.0-experimental.438960f273755509510c3610187d9deb520ba2a0

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 (141) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-BZIaEffq.js → ComponentConfigurationPage-3feZ0gyp.js} +3 -3
  3. package/dist/_chunks/{ComponentConfigurationPage-BZIaEffq.js.map → ComponentConfigurationPage-3feZ0gyp.js.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-Cxz51Sve.mjs → ComponentConfigurationPage-DkUdgHD9.mjs} +3 -3
  5. package/dist/_chunks/{ComponentConfigurationPage-Cxz51Sve.mjs.map → ComponentConfigurationPage-DkUdgHD9.mjs.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-CM62NN0L.js → EditConfigurationPage-B0KA-x9U.js} +3 -3
  7. package/dist/_chunks/{EditConfigurationPage-CM62NN0L.js.map → EditConfigurationPage-B0KA-x9U.js.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-CZLbgfIp.mjs → EditConfigurationPage-Ox5wFgpq.mjs} +3 -3
  9. package/dist/_chunks/{EditConfigurationPage-CZLbgfIp.mjs.map → EditConfigurationPage-Ox5wFgpq.mjs.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-CU7724gt.js → EditViewPage-OMv9CogC.js} +68 -47
  11. package/dist/_chunks/EditViewPage-OMv9CogC.js.map +1 -0
  12. package/dist/_chunks/{EditViewPage-CzuJgWWp.mjs → EditViewPage-foKE8Al3.mjs} +69 -48
  13. package/dist/_chunks/EditViewPage-foKE8Al3.mjs.map +1 -0
  14. package/dist/_chunks/{Field-QtUSh5mU.mjs → Field-CLqZcnnc.mjs} +579 -227
  15. package/dist/_chunks/Field-CLqZcnnc.mjs.map +1 -0
  16. package/dist/_chunks/{Field-Dh1yZyqy.js → Field-u09MCk3G.js} +581 -229
  17. package/dist/_chunks/Field-u09MCk3G.js.map +1 -0
  18. package/dist/_chunks/{Form-BOR8NOe1.js → Form-B9c_Ti0q.js} +52 -34
  19. package/dist/_chunks/Form-B9c_Ti0q.js.map +1 -0
  20. package/dist/_chunks/{Form-COLpvlnv.mjs → Form-CU4hRyJf.mjs} +54 -36
  21. package/dist/_chunks/Form-CU4hRyJf.mjs.map +1 -0
  22. package/dist/_chunks/{History-Bu53Yfw-.mjs → History-BFyFzpSS.mjs} +159 -42
  23. package/dist/_chunks/History-BFyFzpSS.mjs.map +1 -0
  24. package/dist/_chunks/{History-CW2akQ6h.js → History-OlickLyX.js} +158 -41
  25. package/dist/_chunks/History-OlickLyX.js.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-TqrmwjPN.mjs → ListConfigurationPage-Bu5Z_39o.mjs} +58 -48
  27. package/dist/_chunks/ListConfigurationPage-Bu5Z_39o.mjs.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-jzdhEk_u.js → ListConfigurationPage-D0AAi_cW.js} +57 -46
  29. package/dist/_chunks/ListConfigurationPage-D0AAi_cW.js.map +1 -0
  30. package/dist/_chunks/{ListViewPage-B3bMOrMv.js → ListViewPage--lV5p8Qi.js} +105 -104
  31. package/dist/_chunks/ListViewPage--lV5p8Qi.js.map +1 -0
  32. package/dist/_chunks/{ListViewPage-BO_mOXIl.mjs → ListViewPage-BAHxSPux.mjs} +103 -102
  33. package/dist/_chunks/ListViewPage-BAHxSPux.mjs.map +1 -0
  34. package/dist/_chunks/{NoContentTypePage-DqB0QV0k.mjs → NoContentTypePage-C6SMXW77.mjs} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-DqB0QV0k.mjs.map → NoContentTypePage-C6SMXW77.mjs.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-D77xsNHj.js → NoContentTypePage-Dxl9oZqL.js} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-D77xsNHj.js.map → NoContentTypePage-Dxl9oZqL.js.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-C6qTGogm.js → NoPermissionsPage-BY1-rMng.js} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-C6qTGogm.js.map → NoPermissionsPage-BY1-rMng.js.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-DTXi042N.mjs → NoPermissionsPage-o9BXzQeI.mjs} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-DTXi042N.mjs.map → NoPermissionsPage-o9BXzQeI.mjs.map} +1 -1
  42. package/dist/_chunks/{Relations-CJ4qdkRo.mjs → Relations-BAK95JHc.mjs} +33 -24
  43. package/dist/_chunks/Relations-BAK95JHc.mjs.map +1 -0
  44. package/dist/_chunks/{Relations-B6fb2POW.js → Relations-CHfwGkBG.js} +33 -24
  45. package/dist/_chunks/Relations-CHfwGkBG.js.map +1 -0
  46. package/dist/_chunks/{en-DZXjRiWA.js → en-Bm0D0IWz.js} +19 -15
  47. package/dist/_chunks/{en-DZXjRiWA.js.map → en-Bm0D0IWz.js.map} +1 -1
  48. package/dist/_chunks/{en-9GwRW_ku.mjs → en-DKV44jRb.mjs} +19 -15
  49. package/dist/_chunks/{en-9GwRW_ku.mjs.map → en-DKV44jRb.mjs.map} +1 -1
  50. package/dist/_chunks/{index-Dahjdw4h.mjs → index-CxlpxzA5.mjs} +1034 -869
  51. package/dist/_chunks/index-CxlpxzA5.mjs.map +1 -0
  52. package/dist/_chunks/{index-DcUu-_72.js → index-_Mlmsefd.js} +1024 -859
  53. package/dist/_chunks/index-_Mlmsefd.js.map +1 -0
  54. package/dist/_chunks/{layout-omucV6TV.mjs → layout-Cr0H40au.mjs} +27 -14
  55. package/dist/_chunks/layout-Cr0H40au.mjs.map +1 -0
  56. package/dist/_chunks/{layout-jcY4dyUG.js → layout-vcHVgSr1.js} +25 -12
  57. package/dist/_chunks/layout-vcHVgSr1.js.map +1 -0
  58. package/dist/_chunks/{relations-CN0-aw6p.mjs → relations-Dq60voyX.mjs} +2 -2
  59. package/dist/_chunks/{relations-CN0-aw6p.mjs.map → relations-Dq60voyX.mjs.map} +1 -1
  60. package/dist/_chunks/{relations-DGzD7ORa.js → relations-hXUB80SH.js} +2 -2
  61. package/dist/_chunks/{relations-DGzD7ORa.js.map → relations-hXUB80SH.js.map} +1 -1
  62. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  63. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  64. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  65. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  66. package/dist/admin/index.js +2 -1
  67. package/dist/admin/index.js.map +1 -1
  68. package/dist/admin/index.mjs +3 -2
  69. package/dist/admin/src/exports.d.ts +1 -1
  70. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  71. package/dist/admin/src/history/index.d.ts +3 -0
  72. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  73. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  74. package/dist/admin/src/index.d.ts +1 -0
  75. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
  76. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  77. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  78. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  79. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  80. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +6 -58
  81. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  82. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  83. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  84. package/dist/admin/src/preview/constants.d.ts +1 -0
  85. package/dist/admin/src/preview/index.d.ts +4 -0
  86. package/dist/admin/src/services/api.d.ts +1 -1
  87. package/dist/admin/src/services/components.d.ts +2 -2
  88. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  89. package/dist/admin/src/services/documents.d.ts +19 -17
  90. package/dist/admin/src/services/init.d.ts +1 -1
  91. package/dist/admin/src/services/relations.d.ts +2 -2
  92. package/dist/admin/src/services/uid.d.ts +3 -3
  93. package/dist/admin/src/utils/validation.d.ts +4 -1
  94. package/dist/server/index.js +223 -122
  95. package/dist/server/index.js.map +1 -1
  96. package/dist/server/index.mjs +224 -123
  97. package/dist/server/index.mjs.map +1 -1
  98. package/dist/server/src/bootstrap.d.ts.map +1 -1
  99. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  100. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  101. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  102. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  103. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  104. package/dist/server/src/history/services/history.d.ts.map +1 -1
  105. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  106. package/dist/server/src/history/services/utils.d.ts +2 -1
  107. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  108. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  109. package/dist/server/src/preview/constants.d.ts +2 -0
  110. package/dist/server/src/preview/constants.d.ts.map +1 -0
  111. package/dist/server/src/preview/index.d.ts +4 -0
  112. package/dist/server/src/preview/index.d.ts.map +1 -0
  113. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  114. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  115. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  116. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  117. package/dist/shared/contracts/collection-types.d.ts +3 -1
  118. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  119. package/package.json +13 -13
  120. package/dist/_chunks/EditViewPage-CU7724gt.js.map +0 -1
  121. package/dist/_chunks/EditViewPage-CzuJgWWp.mjs.map +0 -1
  122. package/dist/_chunks/Field-Dh1yZyqy.js.map +0 -1
  123. package/dist/_chunks/Field-QtUSh5mU.mjs.map +0 -1
  124. package/dist/_chunks/Form-BOR8NOe1.js.map +0 -1
  125. package/dist/_chunks/Form-COLpvlnv.mjs.map +0 -1
  126. package/dist/_chunks/History-Bu53Yfw-.mjs.map +0 -1
  127. package/dist/_chunks/History-CW2akQ6h.js.map +0 -1
  128. package/dist/_chunks/ListConfigurationPage-TqrmwjPN.mjs.map +0 -1
  129. package/dist/_chunks/ListConfigurationPage-jzdhEk_u.js.map +0 -1
  130. package/dist/_chunks/ListViewPage-B3bMOrMv.js.map +0 -1
  131. package/dist/_chunks/ListViewPage-BO_mOXIl.mjs.map +0 -1
  132. package/dist/_chunks/Relations-B6fb2POW.js.map +0 -1
  133. package/dist/_chunks/Relations-CJ4qdkRo.mjs.map +0 -1
  134. package/dist/_chunks/index-Dahjdw4h.mjs.map +0 -1
  135. package/dist/_chunks/index-DcUu-_72.js.map +0 -1
  136. package/dist/_chunks/layout-jcY4dyUG.js.map +0 -1
  137. package/dist/_chunks/layout-omucV6TV.mjs.map +0 -1
  138. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  139. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  140. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  141. package/strapi-server.js +0 -3
@@ -199,7 +199,9 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
199
199
  return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
200
200
  };
201
201
  const localesService = strapi2.plugin("i18n")?.service("locales");
202
+ const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
202
203
  const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
204
+ const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
203
205
  const getLocaleDictionary = async () => {
204
206
  if (!localesService)
205
207
  return {};
@@ -226,20 +228,25 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
226
228
  const meta = await documentMetadataService.getMetadata(contentTypeUid, document);
227
229
  return documentMetadataService.getStatus(document, meta.availableStatus);
228
230
  };
229
- const getDeepPopulate2 = (uid2) => {
231
+ const getDeepPopulate2 = (uid2, useDatabaseSyntax = false) => {
230
232
  const model = strapi2.getModel(uid2);
231
233
  const attributes = Object.entries(model.attributes);
234
+ const fieldSelector = useDatabaseSyntax ? "select" : "fields";
232
235
  return attributes.reduce((acc, [attributeName, attribute]) => {
233
236
  switch (attribute.type) {
234
237
  case "relation": {
238
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
239
+ if (isMorphRelation) {
240
+ break;
241
+ }
235
242
  const isVisible2 = strapiUtils.contentTypes.isVisibleAttribute(model, attributeName);
236
243
  if (isVisible2) {
237
- acc[attributeName] = { fields: ["documentId", "locale", "publishedAt"] };
244
+ acc[attributeName] = { [fieldSelector]: ["documentId", "locale", "publishedAt"] };
238
245
  }
239
246
  break;
240
247
  }
241
248
  case "media": {
242
- acc[attributeName] = { fields: ["id"] };
249
+ acc[attributeName] = { [fieldSelector]: ["id"] };
243
250
  break;
244
251
  }
245
252
  case "component": {
@@ -312,6 +319,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
312
319
  getRelationRestoreValue,
313
320
  getMediaRestoreValue,
314
321
  getDefaultLocale,
322
+ isLocalizedContentType,
315
323
  getLocaleDictionary,
316
324
  getRetentionDays,
317
325
  getVersionStatus,
@@ -334,7 +342,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
334
342
  });
335
343
  },
336
344
  async findVersionsPage(params) {
337
- const locale = params.query.locale || await serviceUtils.getDefaultLocale();
345
+ const model = strapi2.getModel(params.query.contentType);
346
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
347
+ const defaultLocale = await serviceUtils.getDefaultLocale();
348
+ let locale = null;
349
+ if (isLocalizedContentType) {
350
+ locale = params.query.locale || defaultLocale;
351
+ }
338
352
  const [{ results, pagination }, localeDictionary] = await Promise.all([
339
353
  query.findPage({
340
354
  ...params.query,
@@ -379,7 +393,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
379
393
  if (userToPopulate == null) {
380
394
  return null;
381
395
  }
382
- return strapi2.query("admin::user").findOne({ where: { id: userToPopulate.id } });
396
+ return strapi2.query("admin::user").findOne({
397
+ where: {
398
+ ...userToPopulate.id ? { id: userToPopulate.id } : {},
399
+ ...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
400
+ }
401
+ });
383
402
  })
384
403
  );
385
404
  return {
@@ -490,13 +509,47 @@ const createHistoryService = ({ strapi: strapi2 }) => {
490
509
  }
491
510
  };
492
511
  };
512
+ const shouldCreateHistoryVersion = (context) => {
513
+ if (!strapi.requestContext.get()?.request.url.startsWith("/content-manager")) {
514
+ return false;
515
+ }
516
+ if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
517
+ return false;
518
+ }
519
+ if (context.action === "update" && strapi.requestContext.get()?.request.url.endsWith("/actions/publish")) {
520
+ return false;
521
+ }
522
+ if (!context.contentType.uid.startsWith("api::")) {
523
+ return false;
524
+ }
525
+ return true;
526
+ };
527
+ const getSchemas = (uid2) => {
528
+ const attributesSchema = strapi.getModel(uid2).attributes;
529
+ const componentsSchemas = Object.keys(attributesSchema).reduce(
530
+ (currentComponentSchemas, key) => {
531
+ const fieldSchema = attributesSchema[key];
532
+ if (fieldSchema.type === "component") {
533
+ const componentSchema = strapi.getModel(fieldSchema.component).attributes;
534
+ return {
535
+ ...currentComponentSchemas,
536
+ [fieldSchema.component]: componentSchema
537
+ };
538
+ }
539
+ return currentComponentSchemas;
540
+ },
541
+ {}
542
+ );
543
+ return {
544
+ schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
545
+ componentsSchemas
546
+ };
547
+ };
493
548
  const createLifecyclesService = ({ strapi: strapi2 }) => {
494
549
  const state = {
495
550
  deleteExpiredJob: null,
496
551
  isInitialized: false
497
552
  };
498
- const query = strapi2.db.query(HISTORY_VERSION_UID);
499
- const historyService = getService(strapi2, "history");
500
553
  const serviceUtils = createServiceUtils({ strapi: strapi2 });
501
554
  return {
502
555
  async bootstrap() {
@@ -504,60 +557,45 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
504
557
  return;
505
558
  }
506
559
  strapi2.documents.use(async (context, next) => {
507
- if (!strapi2.requestContext.get()?.request.url.startsWith("/content-manager")) {
508
- return next();
509
- }
510
- if (context.action !== "create" && context.action !== "update" && context.action !== "clone" && context.action !== "publish" && context.action !== "unpublish" && context.action !== "discardDraft") {
511
- return next();
512
- }
513
- const contentTypeUid = context.contentType.uid;
514
- if (!contentTypeUid.startsWith("api::")) {
515
- return next();
516
- }
517
560
  const result = await next();
518
- const documentContext = {
519
- documentId: context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId,
520
- locale: context.params?.locale
521
- };
561
+ if (!shouldCreateHistoryVersion(context)) {
562
+ return result;
563
+ }
564
+ const documentId = context.action === "create" || context.action === "clone" ? result.documentId : context.params.documentId;
522
565
  const defaultLocale = await serviceUtils.getDefaultLocale();
523
- const locale = documentContext.locale || defaultLocale;
524
- if (Array.isArray(locale)) {
525
- strapi2.log.warn(
526
- "[Content manager history middleware]: An array of locales was provided, but only a single locale is supported for the findOne operation."
527
- );
528
- return next();
566
+ const locales = fp.castArray(context.params?.locale || defaultLocale);
567
+ if (!locales.length) {
568
+ return result;
529
569
  }
530
- const document = await strapi2.documents(contentTypeUid).findOne({
531
- documentId: documentContext.documentId,
532
- locale,
533
- populate: serviceUtils.getDeepPopulate(contentTypeUid)
570
+ const uid2 = context.contentType.uid;
571
+ const schemas = getSchemas(uid2);
572
+ const model = strapi2.getModel(uid2);
573
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
574
+ const localeEntries = await strapi2.db.query(uid2).findMany({
575
+ where: {
576
+ documentId,
577
+ ...isLocalizedContentType ? { locale: { $in: locales } } : {},
578
+ ...strapiUtils.contentTypes.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
579
+ },
580
+ populate: serviceUtils.getDeepPopulate(
581
+ uid2,
582
+ true
583
+ /* use database syntax */
584
+ )
534
585
  });
535
- const status = await serviceUtils.getVersionStatus(contentTypeUid, document);
536
- const attributesSchema = strapi2.getModel(contentTypeUid).attributes;
537
- const componentsSchemas = Object.keys(
538
- attributesSchema
539
- ).reduce((currentComponentSchemas, key) => {
540
- const fieldSchema = attributesSchema[key];
541
- if (fieldSchema.type === "component") {
542
- const componentSchema = strapi2.getModel(fieldSchema.component).attributes;
543
- return {
544
- ...currentComponentSchemas,
545
- [fieldSchema.component]: componentSchema
546
- };
547
- }
548
- return currentComponentSchemas;
549
- }, {});
550
586
  await strapi2.db.transaction(async ({ onCommit }) => {
551
- onCommit(() => {
552
- historyService.createVersion({
553
- contentType: contentTypeUid,
554
- data: fp.omit(FIELDS_TO_IGNORE, document),
555
- schema: fp.omit(FIELDS_TO_IGNORE, attributesSchema),
556
- componentsSchemas,
557
- relatedDocumentId: documentContext.documentId,
558
- locale,
559
- status
560
- });
587
+ onCommit(async () => {
588
+ for (const entry of localeEntries) {
589
+ const status = await serviceUtils.getVersionStatus(uid2, entry);
590
+ await getService(strapi2, "history").createVersion({
591
+ contentType: uid2,
592
+ data: fp.omit(FIELDS_TO_IGNORE, entry),
593
+ relatedDocumentId: documentId,
594
+ locale: entry.locale,
595
+ status,
596
+ ...schemas
597
+ });
598
+ }
561
599
  });
562
600
  });
563
601
  return result;
@@ -565,7 +603,7 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
565
603
  state.deleteExpiredJob = nodeSchedule.scheduleJob("0 0 * * *", () => {
566
604
  const retentionDaysInMilliseconds = serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1e3;
567
605
  const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);
568
- query.deleteMany({
606
+ strapi2.db.query(HISTORY_VERSION_UID).deleteMany({
569
607
  where: {
570
608
  created_at: {
571
609
  $lt: expirationDate.toISOString()
@@ -657,7 +695,7 @@ const historyVersion = {
657
695
  }
658
696
  }
659
697
  };
660
- const getFeature = () => {
698
+ const getFeature$1 = () => {
661
699
  if (strapi.ee.features.isEnabled("cms-content-history")) {
662
700
  return {
663
701
  register({ strapi: strapi2 }) {
@@ -680,7 +718,7 @@ const getFeature = () => {
680
718
  }
681
719
  };
682
720
  };
683
- const history = getFeature();
721
+ const history = getFeature$1();
684
722
  const register = async ({ strapi: strapi2 }) => {
685
723
  await history.register?.({ strapi: strapi2 });
686
724
  };
@@ -688,6 +726,18 @@ const ALLOWED_WEBHOOK_EVENTS = {
688
726
  ENTRY_PUBLISH: "entry.publish",
689
727
  ENTRY_UNPUBLISH: "entry.unpublish"
690
728
  };
729
+ const FEATURE_ID = "preview";
730
+ const getFeature = () => {
731
+ if (!strapi.features.future.isEnabled(FEATURE_ID)) {
732
+ return {};
733
+ }
734
+ return {
735
+ bootstrap() {
736
+ console.log("Bootstrapping preview server");
737
+ }
738
+ };
739
+ };
740
+ const preview = getFeature();
691
741
  const bootstrap = async () => {
692
742
  Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {
693
743
  strapi.get("webhookStore").addAllowedEvent(key, value);
@@ -697,6 +747,7 @@ const bootstrap = async () => {
697
747
  await getService$1("content-types").syncConfigurations();
698
748
  await getService$1("permission").registerPermissions();
699
749
  await history.bootstrap?.({ strapi });
750
+ await preview.bootstrap?.({ strapi });
700
751
  };
701
752
  const destroy = async ({ strapi: strapi2 }) => {
702
753
  await history.destroy?.({ strapi: strapi2 });
@@ -1197,6 +1248,11 @@ const { createPolicy } = strapiUtils.policy;
1197
1248
  const hasPermissions = createPolicy({
1198
1249
  name: "plugin::content-manager.hasPermissions",
1199
1250
  validator: validateHasPermissionsInput,
1251
+ /**
1252
+ * NOTE: Action aliases are currently not checked at this level (policy).
1253
+ * This is currently the intended behavior to avoid changing the behavior of API related permissions.
1254
+ * If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
1255
+ */
1200
1256
  handler(ctx, config = {}) {
1201
1257
  const { actions = [], hasAtLeastOne = false } = config;
1202
1258
  const { userAbility } = ctx.state;
@@ -1590,9 +1646,11 @@ const multipleLocaleSchema = strapiUtils.yup.lazy(
1590
1646
  (value) => Array.isArray(value) ? strapiUtils.yup.array().of(singleLocaleSchema.required()) : singleLocaleSchema
1591
1647
  );
1592
1648
  const statusSchema = strapiUtils.yup.mixed().oneOf(["draft", "published"], "Invalid status");
1593
- const getDocumentLocaleAndStatus = async (request, opts = { allowMultipleLocales: false }) => {
1649
+ const getDocumentLocaleAndStatus = async (request, model, opts = { allowMultipleLocales: false }) => {
1594
1650
  const { allowMultipleLocales } = opts;
1595
- const { locale, status, ...rest } = request || {};
1651
+ const { locale, status: providedStatus, ...rest } = request || {};
1652
+ const defaultStatus = strapiUtils.contentTypes.hasDraftAndPublish(strapi.getModel(model)) ? void 0 : "published";
1653
+ const status = providedStatus !== void 0 ? providedStatus : defaultStatus;
1596
1654
  const schema = strapiUtils.yup.object().shape({
1597
1655
  locale: allowMultipleLocales ? multipleLocaleSchema : singleLocaleSchema,
1598
1656
  status: statusSchema
@@ -1640,7 +1698,7 @@ const createDocument = async (ctx, opts) => {
1640
1698
  const setCreator = strapiUtils.setCreatorFields({ user });
1641
1699
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1642
1700
  const sanitizedBody = await sanitizeFn(body);
1643
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(body);
1701
+ const { locale, status } = await getDocumentLocaleAndStatus(body, model);
1644
1702
  return documentManager2.create(model, {
1645
1703
  data: sanitizedBody,
1646
1704
  locale,
@@ -1659,7 +1717,7 @@ const updateDocument = async (ctx, opts) => {
1659
1717
  }
1660
1718
  const permissionQuery = await permissionChecker2.sanitizedQuery.update(ctx.query);
1661
1719
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1662
- const { locale } = await getDocumentLocaleAndStatus(body);
1720
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1663
1721
  const [documentVersion, documentExists] = await Promise.all([
1664
1722
  documentManager2.findOne(id, model, { populate, locale, status: "draft" }),
1665
1723
  documentManager2.exists(model, id)
@@ -1675,7 +1733,7 @@ const updateDocument = async (ctx, opts) => {
1675
1733
  throw new strapiUtils.errors.ForbiddenError();
1676
1734
  }
1677
1735
  const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
1678
- const setCreator = strapiUtils.setCreatorFields({ user, isEdition: true });
1736
+ const setCreator = documentVersion ? strapiUtils.setCreatorFields({ user, isEdition: true }) : strapiUtils.setCreatorFields({ user });
1679
1737
  const sanitizeFn = strapiUtils.async.pipe(pickPermittedFields, setCreator);
1680
1738
  const sanitizedBody = await sanitizeFn(body);
1681
1739
  return documentManager2.update(documentVersion?.documentId || id, model, {
@@ -1697,7 +1755,7 @@ const collectionTypes = {
1697
1755
  }
1698
1756
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
1699
1757
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(1).countRelations({ toOne: false, toMany: true }).build();
1700
- const { locale, status } = await getDocumentLocaleAndStatus(query);
1758
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
1701
1759
  const { results: documents, pagination } = await documentManager2.findPage(
1702
1760
  { ...permissionQuery, populate, locale, status },
1703
1761
  model
@@ -1732,7 +1790,7 @@ const collectionTypes = {
1732
1790
  }
1733
1791
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
1734
1792
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1735
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
1793
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
1736
1794
  const version = await documentManager2.findOne(id, model, {
1737
1795
  populate,
1738
1796
  locale,
@@ -1747,7 +1805,7 @@ const collectionTypes = {
1747
1805
  permissionChecker2,
1748
1806
  model,
1749
1807
  // @ts-expect-error TODO: fix
1750
- { id, locale, publishedAt: null },
1808
+ { documentId: id, locale, publishedAt: null },
1751
1809
  { availableLocales: true, availableStatus: false }
1752
1810
  );
1753
1811
  ctx.body = { data: {}, meta };
@@ -1799,7 +1857,7 @@ const collectionTypes = {
1799
1857
  }
1800
1858
  const permissionQuery = await permissionChecker2.sanitizedQuery.create(ctx.query);
1801
1859
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1802
- const { locale } = await getDocumentLocaleAndStatus(body);
1860
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1803
1861
  const document = await documentManager2.findOne(id, model, {
1804
1862
  populate,
1805
1863
  locale,
@@ -1844,7 +1902,7 @@ const collectionTypes = {
1844
1902
  }
1845
1903
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(ctx.query);
1846
1904
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1847
- const { locale } = await getDocumentLocaleAndStatus(ctx.query);
1905
+ const { locale } = await getDocumentLocaleAndStatus(ctx.query, model);
1848
1906
  const documentLocales = await documentManager2.findLocales(id, model, { populate, locale });
1849
1907
  if (documentLocales.length === 0) {
1850
1908
  return ctx.notFound();
@@ -1873,11 +1931,34 @@ const collectionTypes = {
1873
1931
  const publishedDocument = await strapi.db.transaction(async () => {
1874
1932
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1875
1933
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1876
- const document = id ? await updateDocument(ctx, { populate }) : await createDocument(ctx, { populate });
1934
+ let document;
1935
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1936
+ const isCreate = fp.isNil(id);
1937
+ if (isCreate) {
1938
+ if (permissionChecker2.cannot.create()) {
1939
+ throw new strapiUtils.errors.ForbiddenError();
1940
+ }
1941
+ document = await createDocument(ctx, { populate });
1942
+ }
1943
+ const isUpdate = !isCreate;
1944
+ if (isUpdate) {
1945
+ const documentExists = documentManager2.exists(model, id);
1946
+ if (!documentExists) {
1947
+ throw new strapiUtils.errors.NotFoundError("Document not found");
1948
+ }
1949
+ document = await documentManager2.findOne(id, model, { populate, locale });
1950
+ if (!document) {
1951
+ if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
1952
+ throw new strapiUtils.errors.ForbiddenError();
1953
+ }
1954
+ document = await updateDocument(ctx);
1955
+ } else if (permissionChecker2.can.update(document)) {
1956
+ await updateDocument(ctx);
1957
+ }
1958
+ }
1877
1959
  if (permissionChecker2.cannot.publish(document)) {
1878
1960
  throw new strapiUtils.errors.ForbiddenError();
1879
1961
  }
1880
- const { locale } = await getDocumentLocaleAndStatus(body);
1881
1962
  const publishResult = await documentManager2.publish(document.documentId, model, {
1882
1963
  locale
1883
1964
  // TODO: Allow setting creator fields on publish
@@ -1904,7 +1985,9 @@ const collectionTypes = {
1904
1985
  }
1905
1986
  const permissionQuery = await permissionChecker2.sanitizedQuery.publish(ctx.query);
1906
1987
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().build();
1907
- const { locale } = await getDocumentLocaleAndStatus(body, { allowMultipleLocales: true });
1988
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
1989
+ allowMultipleLocales: true
1990
+ });
1908
1991
  const entityPromises = documentIds.map(
1909
1992
  (documentId) => documentManager2.findLocales(documentId, model, { populate, locale, isPublished: false })
1910
1993
  );
@@ -1931,7 +2014,9 @@ const collectionTypes = {
1931
2014
  if (permissionChecker2.cannot.unpublish()) {
1932
2015
  return ctx.forbidden();
1933
2016
  }
1934
- const { locale } = await getDocumentLocaleAndStatus(body);
2017
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
2018
+ allowMultipleLocales: true
2019
+ });
1935
2020
  const entityPromises = documentIds.map(
1936
2021
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1937
2022
  );
@@ -1964,7 +2049,7 @@ const collectionTypes = {
1964
2049
  }
1965
2050
  const permissionQuery = await permissionChecker2.sanitizedQuery.unpublish(ctx.query);
1966
2051
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
1967
- const { locale } = await getDocumentLocaleAndStatus(body);
2052
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
1968
2053
  const document = await documentManager2.findOne(id, model, {
1969
2054
  populate,
1970
2055
  locale,
@@ -2001,7 +2086,7 @@ const collectionTypes = {
2001
2086
  }
2002
2087
  const permissionQuery = await permissionChecker2.sanitizedQuery.discard(ctx.query);
2003
2088
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2004
- const { locale } = await getDocumentLocaleAndStatus(body);
2089
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2005
2090
  const document = await documentManager2.findOne(id, model, {
2006
2091
  populate,
2007
2092
  locale,
@@ -2032,7 +2117,7 @@ const collectionTypes = {
2032
2117
  }
2033
2118
  const permissionQuery = await permissionChecker2.sanitizedQuery.delete(query);
2034
2119
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2035
- const { locale } = await getDocumentLocaleAndStatus(body);
2120
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2036
2121
  const documentLocales = await documentManager2.findLocales(documentIds, model, {
2037
2122
  populate,
2038
2123
  locale
@@ -2059,7 +2144,7 @@ const collectionTypes = {
2059
2144
  }
2060
2145
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(ctx.query);
2061
2146
  const populate = await getService$1("populate-builder")(model).populateFromQuery(permissionQuery).build();
2062
- const { locale, status = "draft" } = await getDocumentLocaleAndStatus(ctx.query);
2147
+ const { locale, status } = await getDocumentLocaleAndStatus(ctx.query, model);
2063
2148
  const entity = await documentManager2.findOne(id, model, { populate, locale, status });
2064
2149
  if (!entity) {
2065
2150
  return ctx.notFound();
@@ -2082,7 +2167,7 @@ const collectionTypes = {
2082
2167
  if (permissionChecker2.cannot.read()) {
2083
2168
  return ctx.forbidden();
2084
2169
  }
2085
- const entities = await documentManager2.findMany(
2170
+ const documents = await documentManager2.findMany(
2086
2171
  {
2087
2172
  filters: {
2088
2173
  documentId: ids
@@ -2091,7 +2176,7 @@ const collectionTypes = {
2091
2176
  },
2092
2177
  model
2093
2178
  );
2094
- if (!entities) {
2179
+ if (!documents) {
2095
2180
  return ctx.notFound();
2096
2181
  }
2097
2182
  const number = await documentManager2.countManyEntriesDraftRelations(ids, model, locale);
@@ -2282,20 +2367,13 @@ const sanitizeMainField = (model, mainField, userAbility) => {
2282
2367
  userAbility,
2283
2368
  model: model.uid
2284
2369
  });
2285
- if (!isListable(model, mainField)) {
2370
+ const isMainFieldListable = isListable(model, mainField);
2371
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2372
+ if (!isMainFieldListable || !canReadMainField) {
2286
2373
  return "id";
2287
2374
  }
2288
- if (permissionChecker2.cannot.read(null, mainField)) {
2289
- if (model.uid === "plugin::users-permissions.role") {
2290
- const userPermissionChecker = getService$1("permission-checker").create({
2291
- userAbility,
2292
- model: "plugin::users-permissions.user"
2293
- });
2294
- if (userPermissionChecker.can.read()) {
2295
- return "name";
2296
- }
2297
- }
2298
- return "id";
2375
+ if (model.uid === "plugin::users-permissions.role") {
2376
+ return "name";
2299
2377
  }
2300
2378
  return mainField;
2301
2379
  };
@@ -2328,11 +2406,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
2328
2406
  const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
2329
2407
  const isSourceLocalized = isLocalized(sourceModel);
2330
2408
  const isTargetLocalized = isLocalized(targetModel);
2331
- let validatedLocale = locale;
2332
- if (!targetModel || !isTargetLocalized)
2333
- validatedLocale = void 0;
2334
2409
  return {
2335
- locale: validatedLocale,
2410
+ locale,
2336
2411
  isSourceLocalized,
2337
2412
  isTargetLocalized
2338
2413
  };
@@ -2435,7 +2510,7 @@ const relations = {
2435
2510
  attribute,
2436
2511
  fieldsToSelect,
2437
2512
  mainField,
2438
- source: { schema: sourceSchema },
2513
+ source: { schema: sourceSchema, isLocalized: isSourceLocalized },
2439
2514
  target: { schema: targetSchema, isLocalized: isTargetLocalized },
2440
2515
  sourceSchema,
2441
2516
  targetSchema,
@@ -2457,7 +2532,8 @@ const relations = {
2457
2532
  fieldsToSelect,
2458
2533
  mainField,
2459
2534
  source: {
2460
- schema: { uid: sourceUid, modelType: sourceModelType }
2535
+ schema: { uid: sourceUid, modelType: sourceModelType },
2536
+ isLocalized: isSourceLocalized
2461
2537
  },
2462
2538
  target: {
2463
2539
  schema: { uid: targetUid },
@@ -2495,12 +2571,16 @@ const relations = {
2495
2571
  } else {
2496
2572
  where.id = id;
2497
2573
  }
2498
- if (status) {
2499
- where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
2574
+ const publishedAt = getPublishedAtClause(status, targetUid);
2575
+ if (!fp.isEmpty(publishedAt)) {
2576
+ where[`${alias}.published_at`] = publishedAt;
2500
2577
  }
2501
- if (filterByLocale) {
2578
+ if (isTargetLocalized && locale) {
2502
2579
  where[`${alias}.locale`] = locale;
2503
2580
  }
2581
+ if (isSourceLocalized && locale) {
2582
+ where.locale = locale;
2583
+ }
2504
2584
  if ((idsToInclude?.length ?? 0) !== 0) {
2505
2585
  where[`${alias}.id`].$notIn = idsToInclude;
2506
2586
  }
@@ -2518,7 +2598,8 @@ const relations = {
2518
2598
  id: { $notIn: fp.uniq(idsToOmit) }
2519
2599
  });
2520
2600
  }
2521
- const res = await strapi.db.query(targetUid).findPage(strapi.get("query-params").transform(targetUid, queryParams));
2601
+ const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
2602
+ const res = await strapi.db.query(targetUid).findPage(dbQuery);
2522
2603
  ctx.body = {
2523
2604
  ...res,
2524
2605
  results: await addStatusToRelations(targetUid, res.results)
@@ -2553,9 +2634,7 @@ const relations = {
2553
2634
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2554
2635
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2555
2636
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2556
- ordering: "desc",
2557
- page: ctx.request.query.page,
2558
- pageSize: ctx.request.query.pageSize
2637
+ ordering: "desc"
2559
2638
  });
2560
2639
  const relationsUnion = fp.uniqBy("id", fp.concat(sanitizedRes.results, res.results));
2561
2640
  ctx.body = {
@@ -2587,7 +2666,7 @@ const createOrUpdateDocument = async (ctx, opts) => {
2587
2666
  throw new strapiUtils.errors.ForbiddenError();
2588
2667
  }
2589
2668
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.update(query);
2590
- const { locale } = await getDocumentLocaleAndStatus(body);
2669
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2591
2670
  const [documentVersion, otherDocumentVersion] = await Promise.all([
2592
2671
  findDocument(sanitizedQuery, model, { locale, status: "draft" }),
2593
2672
  // Find the first document to check if it exists
@@ -2628,7 +2707,7 @@ const singleTypes = {
2628
2707
  return ctx.forbidden();
2629
2708
  }
2630
2709
  const permissionQuery = await permissionChecker2.sanitizedQuery.read(query);
2631
- const { locale, status } = await getDocumentLocaleAndStatus(query);
2710
+ const { locale, status } = await getDocumentLocaleAndStatus(query, model);
2632
2711
  const version = await findDocument(permissionQuery, model, { locale, status });
2633
2712
  if (!version) {
2634
2713
  if (permissionChecker2.cannot.create()) {
@@ -2642,7 +2721,7 @@ const singleTypes = {
2642
2721
  permissionChecker2,
2643
2722
  model,
2644
2723
  // @ts-expect-error - fix types
2645
- { id: document.documentId, locale, publishedAt: null },
2724
+ { documentId: document.documentId, locale, publishedAt: null },
2646
2725
  { availableLocales: true, availableStatus: false }
2647
2726
  );
2648
2727
  ctx.body = { data: {}, meta };
@@ -2673,7 +2752,7 @@ const singleTypes = {
2673
2752
  }
2674
2753
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.delete(query);
2675
2754
  const populate = await buildPopulateFromQuery(sanitizedQuery, model);
2676
- const { locale } = await getDocumentLocaleAndStatus(query);
2755
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2677
2756
  const documentLocales = await documentManager2.findLocales(void 0, model, {
2678
2757
  populate,
2679
2758
  locale
@@ -2710,7 +2789,7 @@ const singleTypes = {
2710
2789
  if (permissionChecker2.cannot.publish(document)) {
2711
2790
  throw new strapiUtils.errors.ForbiddenError();
2712
2791
  }
2713
- const { locale } = await getDocumentLocaleAndStatus(document);
2792
+ const { locale } = await getDocumentLocaleAndStatus(document, model);
2714
2793
  const publishResult = await documentManager2.publish(document.documentId, model, { locale });
2715
2794
  return publishResult.at(0);
2716
2795
  });
@@ -2733,7 +2812,7 @@ const singleTypes = {
2733
2812
  return ctx.forbidden();
2734
2813
  }
2735
2814
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.unpublish(query);
2736
- const { locale } = await getDocumentLocaleAndStatus(body);
2815
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2737
2816
  const document = await findDocument(sanitizedQuery, model, { locale });
2738
2817
  if (!document) {
2739
2818
  return ctx.notFound();
@@ -2765,7 +2844,7 @@ const singleTypes = {
2765
2844
  return ctx.forbidden();
2766
2845
  }
2767
2846
  const sanitizedQuery = await permissionChecker2.sanitizedQuery.discard(query);
2768
- const { locale } = await getDocumentLocaleAndStatus(body);
2847
+ const { locale } = await getDocumentLocaleAndStatus(body, model);
2769
2848
  const document = await findDocument(sanitizedQuery, model, { locale, status: "published" });
2770
2849
  if (!document) {
2771
2850
  return ctx.notFound();
@@ -2785,7 +2864,7 @@ const singleTypes = {
2785
2864
  const { query } = ctx.request;
2786
2865
  const documentManager2 = getService$1("document-manager");
2787
2866
  const permissionChecker2 = getService$1("permission-checker").create({ userAbility, model });
2788
- const { locale } = await getDocumentLocaleAndStatus(query);
2867
+ const { locale } = await getDocumentLocaleAndStatus(query, model);
2789
2868
  if (permissionChecker2.cannot.read()) {
2790
2869
  return ctx.forbidden();
2791
2870
  }
@@ -2806,7 +2885,7 @@ const uid$1 = {
2806
2885
  async generateUID(ctx) {
2807
2886
  const { contentTypeUID, field, data } = await validateGenerateUIDInput(ctx.request.body);
2808
2887
  const { query = {} } = ctx.request;
2809
- const { locale } = await getDocumentLocaleAndStatus(query);
2888
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2810
2889
  await validateUIDField(contentTypeUID, field);
2811
2890
  const uidService = getService$1("uid");
2812
2891
  ctx.body = {
@@ -2818,7 +2897,7 @@ const uid$1 = {
2818
2897
  ctx.request.body
2819
2898
  );
2820
2899
  const { query = {} } = ctx.request;
2821
- const { locale } = await getDocumentLocaleAndStatus(query);
2900
+ const { locale } = await getDocumentLocaleAndStatus(query, contentTypeUID);
2822
2901
  await validateUIDField(contentTypeUID, field);
2823
2902
  const uidService = getService$1("uid");
2824
2903
  const isAvailable = await uidService.checkUIDAvailability({
@@ -3461,12 +3540,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3461
3540
  ability: userAbility,
3462
3541
  model
3463
3542
  });
3464
- const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3543
+ const { actionProvider } = strapi2.service("admin::permission");
3544
+ const toSubject = (entity) => {
3545
+ return entity ? permissionsManager.toSubject(entity, model) : model;
3546
+ };
3465
3547
  const can = (action, entity, field) => {
3466
- return userAbility.can(action, toSubject(entity), field);
3548
+ const subject = toSubject(entity);
3549
+ const aliases = actionProvider.unstable_aliases(action, model);
3550
+ return (
3551
+ // Test the original action to see if it passes
3552
+ userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
3553
+ aliases.some((alias) => userAbility.can(alias, subject, field))
3554
+ );
3467
3555
  };
3468
3556
  const cannot = (action, entity, field) => {
3469
- return userAbility.cannot(action, toSubject(entity), field);
3557
+ const subject = toSubject(entity);
3558
+ const aliases = actionProvider.unstable_aliases(action, model);
3559
+ return (
3560
+ // Test both the original action
3561
+ userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
3562
+ aliases.every((alias) => userAbility.cannot(alias, subject, field))
3563
+ );
3470
3564
  };
3471
3565
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3472
3566
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });
@@ -3743,6 +3837,10 @@ const getDeepPopulateDraftCount = (uid2) => {
3743
3837
  const attribute = model.attributes[attributeName];
3744
3838
  switch (attribute.type) {
3745
3839
  case "relation": {
3840
+ const isMorphRelation = attribute.relation.toLowerCase().startsWith("morph");
3841
+ if (isMorphRelation) {
3842
+ break;
3843
+ }
3746
3844
  if (isVisibleAttribute$1(model, attributeName)) {
3747
3845
  populateAcc[attributeName] = {
3748
3846
  count: true,
@@ -4120,7 +4218,13 @@ const documentMetadata = ({ strapi: strapi2 }) => ({
4120
4218
  */
4121
4219
  async formatDocumentWithMetadata(uid2, document, opts = {}) {
4122
4220
  if (!document) {
4123
- return document;
4221
+ return {
4222
+ data: document,
4223
+ meta: {
4224
+ availableLocales: [],
4225
+ availableStatus: []
4226
+ }
4227
+ };
4124
4228
  }
4125
4229
  const hasDraftAndPublish = strapiUtils.contentTypes.hasDraftAndPublish(strapi2.getModel(uid2));
4126
4230
  if (!hasDraftAndPublish) {
@@ -4228,10 +4332,7 @@ const documentManager = ({ strapi: strapi2 }) => {
4228
4332
  async clone(id, body, uid2) {
4229
4333
  const populate = await buildDeepPopulate(uid2);
4230
4334
  const params = {
4231
- data: {
4232
- ...omitIdField(body),
4233
- [PUBLISHED_AT_ATTRIBUTE]: null
4234
- },
4335
+ data: omitIdField(body),
4235
4336
  populate
4236
4337
  };
4237
4338
  return strapi2.documents(uid2).clone({ ...params, documentId: id }).then((result) => result?.entries.at(0));