@strapi/content-manager 5.0.0-rc.8 → 5.0.0

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 (119) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-D0dyDTwq.mjs → ComponentConfigurationPage-DfFSZQxe.mjs} +3 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-D0dyDTwq.mjs.map → ComponentConfigurationPage-DfFSZQxe.mjs.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-DL1MHO8i.js → ComponentConfigurationPage-FqfsxQ1j.js} +3 -3
  4. package/dist/_chunks/{ComponentConfigurationPage-DL1MHO8i.js.map → ComponentConfigurationPage-FqfsxQ1j.js.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-CMaOf-A-.js → EditConfigurationPage-Cn0e8t3I.js} +3 -3
  6. package/dist/_chunks/{EditConfigurationPage-CMaOf-A-.js.map → EditConfigurationPage-Cn0e8t3I.js.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-13b7S5Cq.mjs → EditConfigurationPage-DdPNAbl3.mjs} +3 -3
  8. package/dist/_chunks/{EditConfigurationPage-13b7S5Cq.mjs.map → EditConfigurationPage-DdPNAbl3.mjs.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-C3tIZ8F5.mjs → EditViewPage-B82x_x1b.mjs} +30 -9
  10. package/dist/_chunks/EditViewPage-B82x_x1b.mjs.map +1 -0
  11. package/dist/_chunks/{EditViewPage-BSVmMpRd.js → EditViewPage-DlxEHhUt.js} +30 -9
  12. package/dist/_chunks/EditViewPage-DlxEHhUt.js.map +1 -0
  13. package/dist/_chunks/{Field-DUCVth4C.js → Field-COL25JiC.js} +174 -102
  14. package/dist/_chunks/Field-COL25JiC.js.map +1 -0
  15. package/dist/_chunks/{Field-BvuT8cGL.mjs → Field-DufHXW17.mjs} +172 -100
  16. package/dist/_chunks/Field-DufHXW17.mjs.map +1 -0
  17. package/dist/_chunks/{Form-Cpl4W1ak.js → Form-BssUwrTO.js} +36 -17
  18. package/dist/_chunks/Form-BssUwrTO.js.map +1 -0
  19. package/dist/_chunks/{Form-BZmDNVr9.mjs → Form-u_kAOhwB.mjs} +36 -17
  20. package/dist/_chunks/Form-u_kAOhwB.mjs.map +1 -0
  21. package/dist/_chunks/{History-D4U2YISB.js → History-C9t9UqpO.js} +23 -10
  22. package/dist/_chunks/History-C9t9UqpO.js.map +1 -0
  23. package/dist/_chunks/{History-Cq_Hrzuu.mjs → History-DRwA3oMM.mjs} +24 -11
  24. package/dist/_chunks/History-DRwA3oMM.mjs.map +1 -0
  25. package/dist/_chunks/{ListConfigurationPage-Bny6CdWe.js → ListConfigurationPage-BXYPohh-.js} +14 -4
  26. package/dist/_chunks/ListConfigurationPage-BXYPohh-.js.map +1 -0
  27. package/dist/_chunks/{ListConfigurationPage-W-KQHmBv.mjs → ListConfigurationPage-BxfQJzPk.mjs} +14 -4
  28. package/dist/_chunks/ListConfigurationPage-BxfQJzPk.mjs.map +1 -0
  29. package/dist/_chunks/{ListViewPage-HBBnJa8K.mjs → ListViewPage-CELx2ysp.mjs} +40 -36
  30. package/dist/_chunks/ListViewPage-CELx2ysp.mjs.map +1 -0
  31. package/dist/_chunks/{ListViewPage-O8F1pBJo.js → ListViewPage-D2VD8Szg.js} +43 -39
  32. package/dist/_chunks/ListViewPage-D2VD8Szg.js.map +1 -0
  33. package/dist/_chunks/{NoContentTypePage-CQWChGPw.js → NoContentTypePage-BV9IjJSM.js} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-CQWChGPw.js.map → NoContentTypePage-BV9IjJSM.js.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-B-gIhHWM.mjs → NoContentTypePage-DtJ9jcfk.mjs} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-B-gIhHWM.mjs.map → NoContentTypePage-DtJ9jcfk.mjs.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-XhOPl8wx.mjs → NoPermissionsPage-DWleVYK7.mjs} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-XhOPl8wx.mjs.map → NoPermissionsPage-DWleVYK7.mjs.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-CY46zxnM.js → NoPermissionsPage-Dp8NpF9I.js} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-CY46zxnM.js.map → NoPermissionsPage-Dp8NpF9I.js.map} +1 -1
  41. package/dist/_chunks/{Relations-vFZ6Wasg.mjs → Relations-BTcf5xaw.mjs} +33 -24
  42. package/dist/_chunks/Relations-BTcf5xaw.mjs.map +1 -0
  43. package/dist/_chunks/{Relations-C4gGfZRv.js → Relations-DR7EUgyC.js} +33 -24
  44. package/dist/_chunks/Relations-DR7EUgyC.js.map +1 -0
  45. package/dist/_chunks/{en-uOUIxfcQ.js → en-Bm0D0IWz.js} +13 -12
  46. package/dist/_chunks/{en-uOUIxfcQ.js.map → en-Bm0D0IWz.js.map} +1 -1
  47. package/dist/_chunks/{en-BrCTWlZv.mjs → en-DKV44jRb.mjs} +13 -12
  48. package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-DKV44jRb.mjs.map} +1 -1
  49. package/dist/_chunks/{index-5EMXLEM_.js → index-BdMf2lfT.js} +1899 -1742
  50. package/dist/_chunks/index-BdMf2lfT.js.map +1 -0
  51. package/dist/_chunks/{index-Dpxg3ctD.mjs → index-wnqzm4Q8.mjs} +1919 -1762
  52. package/dist/_chunks/index-wnqzm4Q8.mjs.map +1 -0
  53. package/dist/_chunks/{layout-C0INpKap.mjs → layout-2CfjL0T9.mjs} +8 -7
  54. package/dist/_chunks/layout-2CfjL0T9.mjs.map +1 -0
  55. package/dist/_chunks/{layout-P3eKO1Qy.js → layout-B2MyZU-_.js} +8 -7
  56. package/dist/_chunks/layout-B2MyZU-_.js.map +1 -0
  57. package/dist/_chunks/{relations-B1y0K6LE.js → relations-BH7JJGGe.js} +2 -2
  58. package/dist/_chunks/{relations-B1y0K6LE.js.map → relations-BH7JJGGe.js.map} +1 -1
  59. package/dist/_chunks/{relations-FBRRBWeO.mjs → relations-C0w0GcXi.mjs} +2 -2
  60. package/dist/_chunks/{relations-FBRRBWeO.mjs.map → relations-C0w0GcXi.mjs.map} +1 -1
  61. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  62. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  63. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  64. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  65. package/dist/admin/index.js +2 -1
  66. package/dist/admin/index.js.map +1 -1
  67. package/dist/admin/index.mjs +5 -4
  68. package/dist/admin/src/exports.d.ts +1 -1
  69. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  70. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  71. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  72. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  73. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  74. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  75. package/dist/admin/src/services/api.d.ts +1 -1
  76. package/dist/admin/src/services/components.d.ts +2 -2
  77. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  78. package/dist/admin/src/services/documents.d.ts +19 -17
  79. package/dist/admin/src/services/init.d.ts +1 -1
  80. package/dist/admin/src/services/relations.d.ts +2 -2
  81. package/dist/admin/src/services/uid.d.ts +3 -3
  82. package/dist/admin/src/utils/validation.d.ts +4 -1
  83. package/dist/server/index.js +77 -39
  84. package/dist/server/index.js.map +1 -1
  85. package/dist/server/index.mjs +77 -39
  86. package/dist/server/index.mjs.map +1 -1
  87. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  88. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  89. package/dist/server/src/history/services/history.d.ts.map +1 -1
  90. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  91. package/dist/server/src/history/services/utils.d.ts +1 -0
  92. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  93. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  94. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  95. package/dist/shared/contracts/collection-types.d.ts +3 -1
  96. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  97. package/package.json +12 -12
  98. package/dist/_chunks/EditViewPage-BSVmMpRd.js.map +0 -1
  99. package/dist/_chunks/EditViewPage-C3tIZ8F5.mjs.map +0 -1
  100. package/dist/_chunks/Field-BvuT8cGL.mjs.map +0 -1
  101. package/dist/_chunks/Field-DUCVth4C.js.map +0 -1
  102. package/dist/_chunks/Form-BZmDNVr9.mjs.map +0 -1
  103. package/dist/_chunks/Form-Cpl4W1ak.js.map +0 -1
  104. package/dist/_chunks/History-Cq_Hrzuu.mjs.map +0 -1
  105. package/dist/_chunks/History-D4U2YISB.js.map +0 -1
  106. package/dist/_chunks/ListConfigurationPage-Bny6CdWe.js.map +0 -1
  107. package/dist/_chunks/ListConfigurationPage-W-KQHmBv.mjs.map +0 -1
  108. package/dist/_chunks/ListViewPage-HBBnJa8K.mjs.map +0 -1
  109. package/dist/_chunks/ListViewPage-O8F1pBJo.js.map +0 -1
  110. package/dist/_chunks/Relations-C4gGfZRv.js.map +0 -1
  111. package/dist/_chunks/Relations-vFZ6Wasg.mjs.map +0 -1
  112. package/dist/_chunks/index-5EMXLEM_.js.map +0 -1
  113. package/dist/_chunks/index-Dpxg3ctD.mjs.map +0 -1
  114. package/dist/_chunks/layout-C0INpKap.mjs.map +0 -1
  115. package/dist/_chunks/layout-P3eKO1Qy.js.map +0 -1
  116. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  117. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  118. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  119. package/strapi-server.js +0 -3
@@ -173,7 +173,9 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
173
173
  return strapi2.db.query("plugin::upload.file").findOne({ where: { id: versionRelationData.id } });
174
174
  };
175
175
  const localesService = strapi2.plugin("i18n")?.service("locales");
176
+ const i18nContentTypeService = strapi2.plugin("i18n")?.service("content-types");
176
177
  const getDefaultLocale = async () => localesService ? localesService.getDefaultLocale() : null;
178
+ const isLocalizedContentType = (model) => i18nContentTypeService ? i18nContentTypeService.isLocalizedContentType(model) : false;
177
179
  const getLocaleDictionary = async () => {
178
180
  if (!localesService)
179
181
  return {};
@@ -291,6 +293,7 @@ const createServiceUtils = ({ strapi: strapi2 }) => {
291
293
  getRelationRestoreValue,
292
294
  getMediaRestoreValue,
293
295
  getDefaultLocale,
296
+ isLocalizedContentType,
294
297
  getLocaleDictionary,
295
298
  getRetentionDays,
296
299
  getVersionStatus,
@@ -313,7 +316,13 @@ const createHistoryService = ({ strapi: strapi2 }) => {
313
316
  });
314
317
  },
315
318
  async findVersionsPage(params) {
316
- const locale = params.query.locale || await serviceUtils.getDefaultLocale();
319
+ const model = strapi2.getModel(params.query.contentType);
320
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
321
+ const defaultLocale = await serviceUtils.getDefaultLocale();
322
+ let locale = null;
323
+ if (isLocalizedContentType) {
324
+ locale = params.query.locale || defaultLocale;
325
+ }
317
326
  const [{ results, pagination: pagination2 }, localeDictionary] = await Promise.all([
318
327
  query.findPage({
319
328
  ...params.query,
@@ -358,7 +367,12 @@ const createHistoryService = ({ strapi: strapi2 }) => {
358
367
  if (userToPopulate == null) {
359
368
  return null;
360
369
  }
361
- return strapi2.query("admin::user").findOne({ where: { id: userToPopulate.id } });
370
+ return strapi2.query("admin::user").findOne({
371
+ where: {
372
+ ...userToPopulate.id ? { id: userToPopulate.id } : {},
373
+ ...userToPopulate.documentId ? { documentId: userToPopulate.documentId } : {}
374
+ }
375
+ });
362
376
  })
363
377
  );
364
378
  return {
@@ -529,11 +543,13 @@ const createLifecyclesService = ({ strapi: strapi2 }) => {
529
543
  }
530
544
  const uid2 = context.contentType.uid;
531
545
  const schemas = getSchemas(uid2);
546
+ const model = strapi2.getModel(uid2);
547
+ const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);
532
548
  const localeEntries = await strapi2.db.query(uid2).findMany({
533
549
  where: {
534
550
  documentId,
535
- locale: { $in: locales },
536
- publishedAt: null
551
+ ...isLocalizedContentType ? { locale: { $in: locales } } : {},
552
+ ...contentTypes$1.hasDraftAndPublish(strapi2.contentTypes[uid2]) ? { publishedAt: null } : {}
537
553
  },
538
554
  populate: serviceUtils.getDeepPopulate(
539
555
  uid2,
@@ -1193,6 +1209,11 @@ const { createPolicy } = policy;
1193
1209
  const hasPermissions = createPolicy({
1194
1210
  name: "plugin::content-manager.hasPermissions",
1195
1211
  validator: validateHasPermissionsInput,
1212
+ /**
1213
+ * NOTE: Action aliases are currently not checked at this level (policy).
1214
+ * This is currently the intended behavior to avoid changing the behavior of API related permissions.
1215
+ * If you want to add support for it, please create a dedicated RFC with a list of potential side effect this could have.
1216
+ */
1196
1217
  handler(ctx, config = {}) {
1197
1218
  const { actions = [], hasAtLeastOne = false } = config;
1198
1219
  const { userAbility } = ctx.state;
@@ -1673,7 +1694,7 @@ const updateDocument = async (ctx, opts) => {
1673
1694
  throw new errors.ForbiddenError();
1674
1695
  }
1675
1696
  const pickPermittedFields = documentVersion ? permissionChecker2.sanitizeUpdateInput(documentVersion) : permissionChecker2.sanitizeCreateInput;
1676
- const setCreator = setCreatorFields({ user, isEdition: true });
1697
+ const setCreator = documentVersion ? setCreatorFields({ user, isEdition: true }) : setCreatorFields({ user });
1677
1698
  const sanitizeFn = async.pipe(pickPermittedFields, setCreator);
1678
1699
  const sanitizedBody = await sanitizeFn(body);
1679
1700
  return documentManager2.update(documentVersion?.documentId || id, model, {
@@ -1745,7 +1766,7 @@ const collectionTypes = {
1745
1766
  permissionChecker2,
1746
1767
  model,
1747
1768
  // @ts-expect-error TODO: fix
1748
- { id, locale, publishedAt: null },
1769
+ { documentId: id, locale, publishedAt: null },
1749
1770
  { availableLocales: true, availableStatus: false }
1750
1771
  );
1751
1772
  ctx.body = { data: {}, meta };
@@ -1882,11 +1903,17 @@ const collectionTypes = {
1882
1903
  }
1883
1904
  const isUpdate = !isCreate;
1884
1905
  if (isUpdate) {
1885
- document = await documentManager2.findOne(id, model, { populate, locale });
1886
- if (!document) {
1906
+ const documentExists = documentManager2.exists(model, id);
1907
+ if (!documentExists) {
1887
1908
  throw new errors.NotFoundError("Document not found");
1888
1909
  }
1889
- if (permissionChecker2.can.update(document)) {
1910
+ document = await documentManager2.findOne(id, model, { populate, locale });
1911
+ if (!document) {
1912
+ if (permissionChecker2.cannot.create({ locale }) || permissionChecker2.cannot.publish({ locale })) {
1913
+ throw new errors.ForbiddenError();
1914
+ }
1915
+ document = await updateDocument(ctx);
1916
+ } else if (permissionChecker2.can.update(document)) {
1890
1917
  await updateDocument(ctx);
1891
1918
  }
1892
1919
  }
@@ -1948,7 +1975,9 @@ const collectionTypes = {
1948
1975
  if (permissionChecker2.cannot.unpublish()) {
1949
1976
  return ctx.forbidden();
1950
1977
  }
1951
- const { locale } = await getDocumentLocaleAndStatus(body, model);
1978
+ const { locale } = await getDocumentLocaleAndStatus(body, model, {
1979
+ allowMultipleLocales: true
1980
+ });
1952
1981
  const entityPromises = documentIds.map(
1953
1982
  (documentId) => documentManager2.findLocales(documentId, model, { locale, isPublished: true })
1954
1983
  );
@@ -2299,20 +2328,13 @@ const sanitizeMainField = (model, mainField, userAbility) => {
2299
2328
  userAbility,
2300
2329
  model: model.uid
2301
2330
  });
2302
- if (!isListable(model, mainField)) {
2331
+ const isMainFieldListable = isListable(model, mainField);
2332
+ const canReadMainField = permissionChecker2.can.read(null, mainField);
2333
+ if (!isMainFieldListable || !canReadMainField) {
2303
2334
  return "id";
2304
2335
  }
2305
- if (permissionChecker2.cannot.read(null, mainField)) {
2306
- if (model.uid === "plugin::users-permissions.role") {
2307
- const userPermissionChecker = getService$1("permission-checker").create({
2308
- userAbility,
2309
- model: "plugin::users-permissions.user"
2310
- });
2311
- if (userPermissionChecker.can.read()) {
2312
- return "name";
2313
- }
2314
- }
2315
- return "id";
2336
+ if (model.uid === "plugin::users-permissions.role") {
2337
+ return "name";
2316
2338
  }
2317
2339
  return mainField;
2318
2340
  };
@@ -2345,11 +2367,8 @@ const validateLocale = (sourceUid, targetUid, locale) => {
2345
2367
  const isLocalized = strapi.plugin("i18n").service("content-types").isLocalizedContentType;
2346
2368
  const isSourceLocalized = isLocalized(sourceModel);
2347
2369
  const isTargetLocalized = isLocalized(targetModel);
2348
- let validatedLocale = locale;
2349
- if (!targetModel || !isTargetLocalized)
2350
- validatedLocale = void 0;
2351
2370
  return {
2352
- locale: validatedLocale,
2371
+ locale,
2353
2372
  isSourceLocalized,
2354
2373
  isTargetLocalized
2355
2374
  };
@@ -2452,7 +2471,7 @@ const relations = {
2452
2471
  attribute,
2453
2472
  fieldsToSelect,
2454
2473
  mainField,
2455
- source: { schema: sourceSchema },
2474
+ source: { schema: sourceSchema, isLocalized: isSourceLocalized },
2456
2475
  target: { schema: targetSchema, isLocalized: isTargetLocalized },
2457
2476
  sourceSchema,
2458
2477
  targetSchema,
@@ -2474,7 +2493,8 @@ const relations = {
2474
2493
  fieldsToSelect,
2475
2494
  mainField,
2476
2495
  source: {
2477
- schema: { uid: sourceUid, modelType: sourceModelType }
2496
+ schema: { uid: sourceUid, modelType: sourceModelType },
2497
+ isLocalized: isSourceLocalized
2478
2498
  },
2479
2499
  target: {
2480
2500
  schema: { uid: targetUid },
@@ -2512,12 +2532,16 @@ const relations = {
2512
2532
  } else {
2513
2533
  where.id = id;
2514
2534
  }
2515
- if (status) {
2516
- where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
2535
+ const publishedAt = getPublishedAtClause(status, targetUid);
2536
+ if (!isEmpty(publishedAt)) {
2537
+ where[`${alias}.published_at`] = publishedAt;
2517
2538
  }
2518
- if (filterByLocale) {
2539
+ if (isTargetLocalized && locale) {
2519
2540
  where[`${alias}.locale`] = locale;
2520
2541
  }
2542
+ if (isSourceLocalized && locale) {
2543
+ where.locale = locale;
2544
+ }
2521
2545
  if ((idsToInclude?.length ?? 0) !== 0) {
2522
2546
  where[`${alias}.id`].$notIn = idsToInclude;
2523
2547
  }
@@ -2535,7 +2559,8 @@ const relations = {
2535
2559
  id: { $notIn: uniq(idsToOmit) }
2536
2560
  });
2537
2561
  }
2538
- const res = await strapi.db.query(targetUid).findPage(strapi.get("query-params").transform(targetUid, queryParams));
2562
+ const dbQuery = strapi.get("query-params").transform(targetUid, queryParams);
2563
+ const res = await strapi.db.query(targetUid).findPage(dbQuery);
2539
2564
  ctx.body = {
2540
2565
  ...res,
2541
2566
  results: await addStatusToRelations(targetUid, res.results)
@@ -2570,9 +2595,7 @@ const relations = {
2570
2595
  addFiltersClause(permissionQuery, { id: { $in: loadedIds } });
2571
2596
  const sanitizedRes = await loadRelations({ id: entryId }, targetField, {
2572
2597
  ...strapi.get("query-params").transform(targetUid, permissionQuery),
2573
- ordering: "desc",
2574
- page: ctx.request.query.page,
2575
- pageSize: ctx.request.query.pageSize
2598
+ ordering: "desc"
2576
2599
  });
2577
2600
  const relationsUnion = uniqBy("id", concat(sanitizedRes.results, res.results));
2578
2601
  ctx.body = {
@@ -2659,7 +2682,7 @@ const singleTypes = {
2659
2682
  permissionChecker2,
2660
2683
  model,
2661
2684
  // @ts-expect-error - fix types
2662
- { id: document.documentId, locale, publishedAt: null },
2685
+ { documentId: document.documentId, locale, publishedAt: null },
2663
2686
  { availableLocales: true, availableStatus: false }
2664
2687
  );
2665
2688
  ctx.body = { data: {}, meta };
@@ -3478,12 +3501,27 @@ const createPermissionChecker = (strapi2) => ({ userAbility, model }) => {
3478
3501
  ability: userAbility,
3479
3502
  model
3480
3503
  });
3481
- const toSubject = (entity) => entity ? permissionsManager.toSubject(entity, model) : model;
3504
+ const { actionProvider } = strapi2.service("admin::permission");
3505
+ const toSubject = (entity) => {
3506
+ return entity ? permissionsManager.toSubject(entity, model) : model;
3507
+ };
3482
3508
  const can = (action, entity, field) => {
3483
- return userAbility.can(action, toSubject(entity), field);
3509
+ const subject = toSubject(entity);
3510
+ const aliases = actionProvider.unstable_aliases(action, model);
3511
+ return (
3512
+ // Test the original action to see if it passes
3513
+ userAbility.can(action, subject, field) || // Else try every known alias if at least one of them succeed, then the user "can"
3514
+ aliases.some((alias) => userAbility.can(alias, subject, field))
3515
+ );
3484
3516
  };
3485
3517
  const cannot = (action, entity, field) => {
3486
- return userAbility.cannot(action, toSubject(entity), field);
3518
+ const subject = toSubject(entity);
3519
+ const aliases = actionProvider.unstable_aliases(action, model);
3520
+ return (
3521
+ // Test both the original action
3522
+ userAbility.cannot(action, subject, field) && // and every known alias, if all of them fail (cannot), then the user truly "cannot"
3523
+ aliases.every((alias) => userAbility.cannot(alias, subject, field))
3524
+ );
3487
3525
  };
3488
3526
  const sanitizeOutput = (data, { action = ACTIONS.read } = {}) => {
3489
3527
  return permissionsManager.sanitizeOutput(data, { subject: toSubject(data), action });