@strapi/content-manager 5.55.1 → 5.57.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 (205) hide show
  1. package/dist/admin/components/ConfigurationForm/Form.js +3 -3
  2. package/dist/admin/components/ConfigurationForm/Form.js.map +1 -1
  3. package/dist/admin/components/ConfigurationForm/Form.mjs +2 -2
  4. package/dist/admin/components/ConfigurationForm/Form.mjs.map +1 -1
  5. package/dist/admin/components/RelativeTime.js +9 -0
  6. package/dist/admin/components/RelativeTime.js.map +1 -1
  7. package/dist/admin/components/RelativeTime.mjs +10 -1
  8. package/dist/admin/components/RelativeTime.mjs.map +1 -1
  9. package/dist/admin/features/DocumentRBAC.js +0 -3
  10. package/dist/admin/features/DocumentRBAC.js.map +1 -1
  11. package/dist/admin/features/DocumentRBAC.mjs +1 -4
  12. package/dist/admin/features/DocumentRBAC.mjs.map +1 -1
  13. package/dist/admin/history/components/VersionContent.js +3 -3
  14. package/dist/admin/history/components/VersionContent.js.map +1 -1
  15. package/dist/admin/history/components/VersionContent.mjs +2 -2
  16. package/dist/admin/history/components/VersionContent.mjs.map +1 -1
  17. package/dist/admin/history/pages/History.js +2 -1
  18. package/dist/admin/history/pages/History.js.map +1 -1
  19. package/dist/admin/history/pages/History.mjs +3 -2
  20. package/dist/admin/history/pages/History.mjs.map +1 -1
  21. package/dist/admin/pages/EditView/EditViewPage.js +2 -2
  22. package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
  23. package/dist/admin/pages/EditView/EditViewPage.mjs +2 -2
  24. package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
  25. package/dist/admin/pages/EditView/components/DocumentActions.js +170 -131
  26. package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
  27. package/dist/admin/pages/EditView/components/DocumentActions.mjs +173 -135
  28. package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
  29. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js +1 -0
  30. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js.map +1 -1
  31. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.mjs +1 -0
  32. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.mjs.map +1 -1
  33. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js +3 -3
  34. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js.map +1 -1
  35. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs +2 -2
  36. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs.map +1 -1
  37. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +143 -30
  38. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
  39. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +143 -32
  40. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
  41. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +22 -5
  42. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  43. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +22 -5
  44. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
  45. package/dist/admin/pages/EditView/utils/data.js +3 -3
  46. package/dist/admin/pages/EditView/utils/data.js.map +1 -1
  47. package/dist/admin/pages/EditView/utils/data.mjs +2 -2
  48. package/dist/admin/pages/EditView/utils/data.mjs.map +1 -1
  49. package/dist/admin/pages/ListView/ListViewPage.js +4 -3
  50. package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
  51. package/dist/admin/pages/ListView/ListViewPage.mjs +4 -3
  52. package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
  53. package/dist/admin/preview/pages/Preview.js +2 -1
  54. package/dist/admin/preview/pages/Preview.js.map +1 -1
  55. package/dist/admin/preview/pages/Preview.mjs +3 -2
  56. package/dist/admin/preview/pages/Preview.mjs.map +1 -1
  57. package/dist/admin/services/documents.js +3 -2
  58. package/dist/admin/services/documents.js.map +1 -1
  59. package/dist/admin/services/documents.mjs +2 -2
  60. package/dist/admin/services/documents.mjs.map +1 -1
  61. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +2 -1
  62. package/dist/admin/src/pages/EditView/components/FormInputs/Relations/RelationModal.d.ts +44 -5
  63. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +2 -2
  64. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +4 -4
  65. package/dist/admin/src/services/documents.d.ts +10 -2
  66. package/dist/admin/translations/en.json.js +2 -0
  67. package/dist/admin/translations/en.json.js.map +1 -1
  68. package/dist/admin/translations/en.json.mjs +2 -0
  69. package/dist/admin/translations/en.json.mjs.map +1 -1
  70. package/dist/admin/utils/validation.js +3 -3
  71. package/dist/admin/utils/validation.js.map +1 -1
  72. package/dist/admin/utils/validation.mjs +2 -2
  73. package/dist/admin/utils/validation.mjs.map +1 -1
  74. package/dist/server/controllers/collection-types.js +4 -4
  75. package/dist/server/controllers/collection-types.js.map +1 -1
  76. package/dist/server/controllers/collection-types.mjs +4 -4
  77. package/dist/server/controllers/collection-types.mjs.map +1 -1
  78. package/dist/server/controllers/content-types.js +5 -7
  79. package/dist/server/controllers/content-types.js.map +1 -1
  80. package/dist/server/controllers/content-types.mjs +5 -7
  81. package/dist/server/controllers/content-types.mjs.map +1 -1
  82. package/dist/server/controllers/relations.js +22 -14
  83. package/dist/server/controllers/relations.js.map +1 -1
  84. package/dist/server/controllers/relations.mjs +21 -13
  85. package/dist/server/controllers/relations.mjs.map +1 -1
  86. package/dist/server/controllers/utils/clone.js +3 -4
  87. package/dist/server/controllers/utils/clone.js.map +1 -1
  88. package/dist/server/controllers/utils/clone.mjs +4 -5
  89. package/dist/server/controllers/utils/clone.mjs.map +1 -1
  90. package/dist/server/controllers/validation/index.js +1 -1
  91. package/dist/server/controllers/validation/index.mjs +1 -1
  92. package/dist/server/history/controllers/history-version.js +3 -3
  93. package/dist/server/history/controllers/history-version.js.map +1 -1
  94. package/dist/server/history/controllers/history-version.mjs +3 -3
  95. package/dist/server/history/controllers/history-version.mjs.map +1 -1
  96. package/dist/server/history/services/history.js +4 -4
  97. package/dist/server/history/services/history.js.map +1 -1
  98. package/dist/server/history/services/history.mjs +4 -4
  99. package/dist/server/history/services/history.mjs.map +1 -1
  100. package/dist/server/history/services/lifecycles.js +8 -8
  101. package/dist/server/history/services/lifecycles.js.map +1 -1
  102. package/dist/server/history/services/lifecycles.mjs +3 -3
  103. package/dist/server/history/services/lifecycles.mjs.map +1 -1
  104. package/dist/server/history/services/utils.js +7 -10
  105. package/dist/server/history/services/utils.js.map +1 -1
  106. package/dist/server/history/services/utils.mjs +5 -8
  107. package/dist/server/history/services/utils.mjs.map +1 -1
  108. package/dist/server/mcp/permissions.js +2 -2
  109. package/dist/server/mcp/permissions.js.map +1 -1
  110. package/dist/server/mcp/permissions.mjs +2 -2
  111. package/dist/server/mcp/permissions.mjs.map +1 -1
  112. package/dist/server/mcp/register-content-manager-mcp-tools.js +7 -5
  113. package/dist/server/mcp/register-content-manager-mcp-tools.js.map +1 -1
  114. package/dist/server/mcp/register-content-manager-mcp-tools.mjs +7 -5
  115. package/dist/server/mcp/register-content-manager-mcp-tools.mjs.map +1 -1
  116. package/dist/server/preview/controllers/previewScript.js +30 -15
  117. package/dist/server/preview/controllers/validation/preview.js +3 -3
  118. package/dist/server/preview/controllers/validation/preview.js.map +1 -1
  119. package/dist/server/preview/controllers/validation/preview.mjs +3 -3
  120. package/dist/server/preview/controllers/validation/preview.mjs.map +1 -1
  121. package/dist/server/services/components.js +3 -3
  122. package/dist/server/services/components.js.map +1 -1
  123. package/dist/server/services/components.mjs +3 -3
  124. package/dist/server/services/components.mjs.map +1 -1
  125. package/dist/server/services/content-structure.js +2 -2
  126. package/dist/server/services/content-structure.js.map +1 -1
  127. package/dist/server/services/content-structure.mjs +2 -2
  128. package/dist/server/services/content-structure.mjs.map +1 -1
  129. package/dist/server/services/content-types.js +3 -3
  130. package/dist/server/services/content-types.js.map +1 -1
  131. package/dist/server/services/content-types.mjs +3 -3
  132. package/dist/server/services/content-types.mjs.map +1 -1
  133. package/dist/server/services/data-mapper.js +3 -3
  134. package/dist/server/services/data-mapper.js.map +1 -1
  135. package/dist/server/services/data-mapper.mjs +3 -3
  136. package/dist/server/services/data-mapper.mjs.map +1 -1
  137. package/dist/server/services/document-manager.js +6 -6
  138. package/dist/server/services/document-manager.js.map +1 -1
  139. package/dist/server/services/document-manager.mjs +6 -6
  140. package/dist/server/services/document-manager.mjs.map +1 -1
  141. package/dist/server/services/document-metadata.js +29 -31
  142. package/dist/server/services/document-metadata.js.map +1 -1
  143. package/dist/server/services/document-metadata.mjs +29 -31
  144. package/dist/server/services/document-metadata.mjs.map +1 -1
  145. package/dist/server/services/metrics.js +3 -3
  146. package/dist/server/services/metrics.js.map +1 -1
  147. package/dist/server/services/metrics.mjs +3 -3
  148. package/dist/server/services/metrics.mjs.map +1 -1
  149. package/dist/server/services/permission-checker.js +2 -2
  150. package/dist/server/services/permission-checker.js.map +1 -1
  151. package/dist/server/services/permission-checker.mjs +1 -1
  152. package/dist/server/services/permission-checker.mjs.map +1 -1
  153. package/dist/server/services/permission.js +2 -3
  154. package/dist/server/services/permission.js.map +1 -1
  155. package/dist/server/services/permission.mjs +2 -3
  156. package/dist/server/services/permission.mjs.map +1 -1
  157. package/dist/server/services/populate-builder.js +4 -4
  158. package/dist/server/services/populate-builder.js.map +1 -1
  159. package/dist/server/services/populate-builder.mjs +4 -4
  160. package/dist/server/services/populate-builder.mjs.map +1 -1
  161. package/dist/server/services/utils/configuration/attributes.js +1 -2
  162. package/dist/server/services/utils/configuration/attributes.js.map +1 -1
  163. package/dist/server/services/utils/configuration/attributes.mjs +2 -3
  164. package/dist/server/services/utils/configuration/attributes.mjs.map +1 -1
  165. package/dist/server/services/utils/configuration/settings.js +4 -7
  166. package/dist/server/services/utils/configuration/settings.js.map +1 -1
  167. package/dist/server/services/utils/configuration/settings.mjs +2 -5
  168. package/dist/server/services/utils/configuration/settings.mjs.map +1 -1
  169. package/dist/server/services/utils/draft.js +8 -7
  170. package/dist/server/services/utils/draft.js.map +1 -1
  171. package/dist/server/services/utils/draft.mjs +6 -5
  172. package/dist/server/services/utils/draft.mjs.map +1 -1
  173. package/dist/server/services/utils/populate.js +10 -11
  174. package/dist/server/services/utils/populate.js.map +1 -1
  175. package/dist/server/services/utils/populate.mjs +9 -10
  176. package/dist/server/services/utils/populate.mjs.map +1 -1
  177. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  178. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  179. package/dist/server/src/history/services/utils.d.ts +2 -2
  180. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  181. package/dist/server/src/index.d.ts +1 -1
  182. package/dist/server/src/index.d.ts.map +1 -1
  183. package/dist/server/src/mcp/permissions.d.ts +1 -1
  184. package/dist/server/src/mcp/permissions.d.ts.map +1 -1
  185. package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts +3 -1
  186. package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts.map +1 -1
  187. package/dist/server/src/mcp/types.d.ts +2 -2
  188. package/dist/server/src/services/content-types.d.ts.map +1 -1
  189. package/dist/server/src/services/data-mapper.d.ts +1 -1
  190. package/dist/server/src/services/data-mapper.d.ts.map +1 -1
  191. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  192. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  193. package/dist/server/src/services/index.d.ts +1 -1
  194. package/dist/server/src/services/index.d.ts.map +1 -1
  195. package/dist/server/src/services/metrics.d.ts.map +1 -1
  196. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  197. package/dist/server/src/services/permission.d.ts.map +1 -1
  198. package/dist/server/src/services/populate-builder.d.ts.map +1 -1
  199. package/dist/server/src/services/utils/configuration/index.d.ts +10 -1
  200. package/dist/server/src/services/utils/configuration/index.d.ts.map +1 -1
  201. package/dist/server/src/services/utils/configuration/settings.d.ts +10 -1
  202. package/dist/server/src/services/utils/configuration/settings.d.ts.map +1 -1
  203. package/dist/server/src/services/utils/draft.d.ts.map +1 -1
  204. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  205. package/package.json +10 -10
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var fp = require('lodash/fp');
3
+ var _ = require('lodash');
4
4
  var strapiUtils = require('@strapi/utils');
5
5
  var index = require('../utils/index.js');
6
6
  var relations$1 = require('./validation/relations.js');
@@ -94,9 +94,9 @@ const getPublishedAtClause = (status, uid)=>{
94
94
  const validateLocale = (sourceUid, targetUid, locale)=>{
95
95
  const sourceModel = strapi.getModel(sourceUid);
96
96
  const targetModel = strapi.getModel(targetUid);
97
- const isLocalized = strapi.plugin('i18n').service('content-types').isLocalizedContentType;
98
- const isSourceLocalized = isLocalized(sourceModel);
99
- const isTargetLocalized = isLocalized(targetModel);
97
+ // Without a localization provider, neither side is localized
98
+ const isSourceLocalized = strapi.localization.isLocalizedContentType(sourceModel);
99
+ const isTargetLocalized = strapi.localization.isLocalizedContentType(targetModel);
100
100
  return {
101
101
  locale,
102
102
  isSourceLocalized,
@@ -189,13 +189,15 @@ var relations = {
189
189
  }
190
190
  const modelConfig = isComponent ? await index.getService('components').findConfiguration(sourceSchema) : await index.getService('content-types').findConfiguration(sourceSchema);
191
191
  const targetSchema = strapi.getModel(targetUid);
192
- const mainField = fp.flow(fp.prop(`metadatas.${targetField}.edit.mainField`), (mainField)=>mainField || 'id', (mainField)=>sanitizeMainField(targetSchema, mainField, userAbility))(modelConfig);
193
- const fieldsToSelect = fp.uniq([
194
- mainField,
195
- PUBLISHED_AT_ATTRIBUTE,
196
- UPDATED_AT_ATTRIBUTE,
197
- 'documentId'
198
- ]);
192
+ const mainField = _.flow(_.property(`metadatas.${targetField}.edit.mainField`), (mainField)=>mainField || 'id', (mainField)=>sanitizeMainField(targetSchema, mainField, userAbility))(modelConfig);
193
+ const fieldsToSelect = [
194
+ ...new Set([
195
+ mainField,
196
+ PUBLISHED_AT_ATTRIBUTE,
197
+ UPDATED_AT_ATTRIBUTE,
198
+ 'documentId'
199
+ ])
200
+ ];
199
201
  if (isTargetLocalized) {
200
202
  fieldsToSelect.push('locale');
201
203
  }
@@ -274,12 +276,16 @@ var relations = {
274
276
  * Components -> Specify entity id (they don't have a document id)
275
277
  */ if (sourceModelType === 'contentType') {
276
278
  where.document_id = id;
279
+ const sourcePublishedAt = getPublishedAtClause(status, sourceUid);
280
+ if (!_.isEmpty(sourcePublishedAt)) {
281
+ where.published_at = sourcePublishedAt;
282
+ }
277
283
  } else {
278
284
  where.id = id;
279
285
  }
280
286
  // Add the status and locale filters if they are provided
281
287
  const publishedAt = getPublishedAtClause(status, targetUid);
282
- if (!fp.isEmpty(publishedAt)) {
288
+ if (!_.isEmpty(publishedAt)) {
283
289
  where[`${alias}.published_at`] = publishedAt;
284
290
  }
285
291
  // If target has localization we need to filter by locale
@@ -321,7 +327,9 @@ var relations = {
321
327
  // If we have ids to omit, we should filter them out
322
328
  addFiltersClause(queryParams, {
323
329
  id: {
324
- $notIn: fp.uniq(idsToOmit)
330
+ $notIn: [
331
+ ...new Set(idsToOmit)
332
+ ]
325
333
  }
326
334
  });
327
335
  }
@@ -421,7 +429,7 @@ var relations = {
421
429
  ordering: 'desc'
422
430
  });
423
431
  // NOTE: the order is very important to make sure sanitized relations are kept in priority
424
- const relationsUnion = fp.uniqBy('id', fp.concat(sanitizedRes.results, res.results));
432
+ const relationsUnion = _.uniqBy(_.concat(sanitizedRes.results, res.results), 'id');
425
433
  ctx.body = {
426
434
  pagination: res.pagination || {
427
435
  page: 1,
@@ -1 +1 @@
1
- {"version":3,"file":"relations.js","sources":["../../../server/src/controllers/relations.ts"],"sourcesContent":["import { prop, uniq, uniqBy, concat, flow, isEmpty } from 'lodash/fp';\n\nimport { isOperatorOfType, contentTypes, relations, errors } from '@strapi/utils';\nimport type { Data, Modules, UID } from '@strapi/types';\n\nimport { getService } from '../utils';\nimport { validateFindAvailable, validateFindExisting } from './validation/relations';\nimport { isListable } from '../services/utils/configuration/attributes';\nimport { indexByDocumentId } from './utils/document-status';\n\nconst { PUBLISHED_AT_ATTRIBUTE, UPDATED_AT_ATTRIBUTE } = contentTypes.constants;\n\ninterface RelationEntity {\n id: Data.ID;\n documentId: Modules.Documents.ID;\n updatedAt: string | Date;\n publishedAt?: string | Date;\n [key: string]: unknown;\n}\n\nconst addFiltersClause = (params: any, filtersClause: any) => {\n params.filters = params.filters || {};\n params.filters.$and = params.filters.$and || [];\n params.filters.$and.push(filtersClause);\n};\n\nconst sanitizeMainField = (model: any, mainField: any, userAbility: any) => {\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: model.uid,\n });\n\n // Whether the main field can be displayed or not, regardless of permissions.\n const isMainFieldListable = isListable(model, mainField);\n // Whether the user has the permission to access the model's main field (using RBAC abilities)\n const canReadMainField = permissionChecker.can.read(null, mainField);\n\n if (!isMainFieldListable || !canReadMainField) {\n // Default to 'documentId' if the actual main field shouldn't be displayed\n return 'documentId';\n }\n\n // Edge cases\n\n // 1. Enforce 'name' as the main field for users and permissions' roles\n if (model.uid === 'plugin::users-permissions.role') {\n return 'name';\n }\n\n return mainField;\n};\n\n/**\n *\n * All relations sent to this function should have the same status or no status\n */\nconst addStatusToRelations = async (targetUid: UID.Schema, relations: RelationEntity[]) => {\n if (!contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {\n return relations;\n }\n\n const documentMetadata = getService('document-metadata');\n\n if (!relations.length) {\n return relations;\n }\n\n const firstRelation = relations[0];\n\n const filters: any = {\n documentId: { $in: relations.map((r) => r.documentId) },\n // NOTE: find the \"opposite\" status\n publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true },\n };\n\n const availableStatus = await strapi.query(targetUid).findMany({\n select: ['id', 'documentId', 'locale', 'updatedAt', 'createdAt', 'publishedAt'],\n filters,\n });\n\n const statusByDocumentId = indexByDocumentId(availableStatus);\n\n return relations.map((relation: RelationEntity) => {\n const candidates = statusByDocumentId.get(relation.documentId as string) || [];\n const availableStatuses = relation.locale\n ? candidates.filter((c) => c.locale === relation.locale)\n : candidates;\n\n return {\n ...relation,\n status: documentMetadata.getStatus(relation, availableStatuses),\n };\n });\n};\n\nconst getPublishedAtClause = (status: string, uid: UID.Schema) => {\n const model = strapi.getModel(uid);\n\n /**\n * If dp is disabled, ignore the filter\n */\n if (!model || !contentTypes.hasDraftAndPublish(model)) {\n return {};\n }\n\n // Prioritize the draft status in case it's not provided\n return status === 'published' ? { $notNull: true } : { $null: true };\n};\n\nconst validateLocale = (sourceUid: UID.Schema, targetUid: UID.ContentType, locale?: string) => {\n const sourceModel = strapi.getModel(sourceUid);\n const targetModel = strapi.getModel(targetUid);\n\n const isLocalized = strapi.plugin('i18n').service('content-types').isLocalizedContentType;\n const isSourceLocalized = isLocalized(sourceModel);\n const isTargetLocalized = isLocalized(targetModel);\n\n return {\n locale,\n isSourceLocalized,\n isTargetLocalized,\n };\n};\n\nconst validateStatus = (\n sourceUid: UID.Schema,\n status?: Modules.Documents.Params.PublicationStatus.Kind\n) => {\n const sourceModel = strapi.getModel(sourceUid);\n\n const isDP = contentTypes.hasDraftAndPublish;\n const isSourceDP = isDP(sourceModel);\n\n // Default to draft if not set\n if (!isSourceDP && sourceModel.modelType === 'contentType') {\n return { status: undefined };\n }\n\n switch (status) {\n case 'published':\n return { status: 'published' };\n default:\n // Assign to draft if the status is not valid\n return { status: 'draft' };\n }\n};\n\nexport default {\n async extractAndValidateRequestInfo(ctx: any, id?: Data.ID) {\n const { userAbility } = ctx.state;\n const { model, targetField } = ctx.params;\n\n const sourceSchema = strapi.getModel(model);\n if (!sourceSchema) {\n throw new errors.ValidationError(`The model ${model} doesn't exist`);\n }\n\n const attribute: any = sourceSchema.attributes[targetField];\n if (!attribute || attribute.type !== 'relation') {\n throw new errors.ValidationError(\n `The relational field ${targetField} doesn't exist on ${model}`\n );\n }\n\n const sourceUid = model;\n const targetUid = attribute.target;\n\n const { locale, isSourceLocalized, isTargetLocalized } = validateLocale(\n sourceUid,\n targetUid,\n ctx.request?.query?.locale\n );\n const { status } = validateStatus(sourceUid, ctx.request?.query?.status);\n\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model,\n });\n\n const isComponent = sourceSchema.modelType === 'component';\n if (!isComponent) {\n if (permissionChecker.cannot.read(null, targetField)) {\n return ctx.forbidden();\n }\n }\n\n let entryId: string | number | null = null;\n\n if (id) {\n const where: Record<string, any> = {};\n\n if (!isComponent) {\n where.documentId = id;\n\n if (status) {\n where.publishedAt = getPublishedAtClause(status, sourceUid);\n }\n\n if (locale && isSourceLocalized) {\n where.locale = locale;\n }\n } else {\n // If the source is a component, we only need to filter by the\n // component's entity id\n where.id = id;\n }\n\n const permissionQuery = await permissionChecker.sanitizedQuery.read(ctx.query);\n const populate = await getService('populate-builder')(model)\n .populateFromQuery(permissionQuery)\n .build();\n\n const currentEntity = await strapi.db.query(model).findOne({\n where,\n populate,\n });\n\n // We need to check if the entity exists\n // and if the user has the permission to read it in this way\n // There may be multiple entities (publication states) under this\n // documentId + locale. We only need to check if one exists\n if (!currentEntity) {\n throw new errors.NotFoundError();\n }\n\n if (!isComponent) {\n if (permissionChecker.cannot.read(currentEntity, targetField)) {\n throw new errors.ForbiddenError();\n }\n }\n\n entryId = currentEntity.id;\n }\n\n const modelConfig = isComponent\n ? await getService('components').findConfiguration(sourceSchema)\n : await getService('content-types').findConfiguration(sourceSchema);\n\n const targetSchema = strapi.getModel(targetUid);\n\n const mainField = flow(\n prop(`metadatas.${targetField}.edit.mainField`),\n (mainField) => mainField || 'id',\n (mainField) => sanitizeMainField(targetSchema, mainField, userAbility)\n )(modelConfig);\n\n const fieldsToSelect = uniq([\n mainField,\n PUBLISHED_AT_ATTRIBUTE,\n UPDATED_AT_ATTRIBUTE,\n 'documentId',\n ]);\n\n if (isTargetLocalized) {\n fieldsToSelect.push('locale');\n }\n\n return {\n entryId,\n locale,\n status,\n attribute,\n fieldsToSelect,\n mainField,\n source: { schema: sourceSchema, isLocalized: isSourceLocalized },\n target: { schema: targetSchema, isLocalized: isTargetLocalized },\n sourceSchema,\n targetSchema,\n targetField,\n };\n },\n\n /**\n * Used to find new relations to add in a relational field.\n *\n * Component and document relations are dealt a bit differently (they don't have a document_id).\n */\n async findAvailable(ctx: any) {\n const { id } = ctx.request.query;\n\n await validateFindAvailable(ctx.request.query);\n\n const {\n locale,\n status,\n targetField,\n fieldsToSelect,\n mainField,\n source: {\n schema: { uid: sourceUid, modelType: sourceModelType },\n isLocalized: isSourceLocalized,\n },\n target: {\n schema: { uid: targetUid },\n isLocalized: isTargetLocalized,\n },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const {\n idsToOmit,\n idsToInclude,\n // `_q` is the public query parameter name; keep the alias grep-able.\n _q: search,\n ...query\n } = ctx.request.query;\n\n const permissionChecker = getService('permission-checker').create({\n userAbility: ctx.state.userAbility,\n model: targetUid,\n });\n const permissionQuery = await permissionChecker.sanitizedQuery.read(query);\n\n const queryParams = {\n sort: mainField,\n // cannot select other fields as the user may not have the permissions\n fields: fieldsToSelect,\n ...permissionQuery,\n };\n\n // If no status is requested, we find all the draft relations and later update them\n // with the latest available status\n addFiltersClause(queryParams, {\n publishedAt: getPublishedAtClause(status, targetUid),\n });\n\n // We will only filter by locale if the target content type is localized\n const filterByLocale = isTargetLocalized && locale;\n if (filterByLocale) {\n addFiltersClause(queryParams, { locale });\n }\n\n if (id) {\n /**\n * Exclude the relations that are already related to the source\n *\n * We also optionally filter the target relations by the requested\n * status and locale if provided.\n */\n const subQuery = strapi.db.queryBuilder(sourceUid);\n\n // The alias refers to the DB table of the target content type model\n const alias = subQuery.getAlias();\n\n const where: Record<string, any> = {\n [`${alias}.id`]: { $notNull: true },\n [`${alias}.document_id`]: { $notNull: true },\n };\n\n /**\n * Content Types -> Specify document id\n * Components -> Specify entity id (they don't have a document id)\n */\n if (sourceModelType === 'contentType') {\n where.document_id = id;\n } else {\n where.id = id;\n }\n\n // Add the status and locale filters if they are provided\n const publishedAt = getPublishedAtClause(status, targetUid);\n if (!isEmpty(publishedAt)) {\n where[`${alias}.published_at`] = publishedAt;\n }\n\n // If target has localization we need to filter by locale\n if (isTargetLocalized && locale) {\n where[`${alias}.locale`] = locale;\n }\n\n if (isSourceLocalized && locale) {\n where.locale = locale;\n }\n\n /**\n * UI can provide a list of ids to omit,\n * those are the relations user set in the UI but has not persisted.\n * We don't want to include them in the available relations.\n */\n if ((idsToInclude?.length ?? 0) !== 0) {\n where[`${alias}.id`].$notIn = idsToInclude;\n }\n\n const knexSubQuery = subQuery\n .where(where)\n .join({ alias, targetField })\n .select(`${alias}.id`)\n .getKnexQuery();\n\n addFiltersClause(queryParams, {\n id: { $notIn: knexSubQuery },\n });\n }\n\n /**\n * Apply a filter to the mainField based on the search query and filter operator\n * searching should be allowed only on mainField for permission reasons\n */\n if (search) {\n const filter = isOperatorOfType('where', query._filter) ? query._filter : '$containsi';\n addFiltersClause(queryParams, { [mainField]: { [filter]: search } });\n }\n\n if (idsToOmit?.length > 0) {\n // If we have ids to omit, we should filter them out\n addFiltersClause(queryParams, {\n id: { $notIn: uniq(idsToOmit) },\n });\n }\n\n const dbQuery = strapi.get('query-params').transform(targetUid, queryParams);\n\n const res = await strapi.db.query(targetUid).findPage(dbQuery);\n\n ctx.body = {\n ...res,\n results: await addStatusToRelations(targetUid, res.results),\n };\n },\n\n async findExisting(ctx: any) {\n const { userAbility } = ctx.state;\n const { id } = ctx.params;\n\n await validateFindExisting(ctx.request.query);\n\n const {\n entryId,\n attribute,\n targetField,\n fieldsToSelect,\n status,\n source: { schema: sourceSchema },\n target: { schema: targetSchema },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const { uid: sourceUid } = sourceSchema;\n const { uid: targetUid } = targetSchema;\n\n const permissionQuery = await getService('permission-checker')\n .create({ userAbility, model: targetUid })\n .sanitizedQuery.read({ fields: fieldsToSelect });\n\n /**\n * loadPages can not be used for single relations,\n * this unifies the loading regardless of it's type\n *\n * NOTE: Relations need to be loaded using any db.query method\n * to ensure the proper ordering is applied\n */\n const dbQuery = strapi.db.query(sourceUid);\n const loadRelations = relations.isAnyToMany(attribute)\n ? (...args: Parameters<typeof dbQuery.loadPages>) => dbQuery.loadPages(...args)\n : (...args: Parameters<typeof dbQuery.load>) =>\n dbQuery\n .load(...args)\n // Ensure response is an array\n .then((res) => ({ results: res ? [res] : [] }));\n\n const filters: {\n publishedAt?: Record<string, any>;\n } = {};\n\n if (sourceSchema?.options?.draftAndPublish || sourceSchema?.modelType === 'component') {\n if (targetSchema?.options?.draftAndPublish) {\n if (status === 'published') {\n filters.publishedAt = { $notNull: true };\n } else {\n filters.publishedAt = { $null: true };\n }\n }\n } else if (targetSchema?.options?.draftAndPublish) {\n // NOTE: we must return the drafts as some targets might not have a published version yet\n filters.publishedAt = { $null: true };\n }\n\n /**\n * If user does not have access to specific relations (custom conditions),\n * only the ids of the relations are returned.\n *\n * - First query loads all the ids.\n * - Second one also loads the main field, and excludes forbidden relations.\n *\n * The response contains the union of the two queries.\n */\n const res = await loadRelations({ id: entryId }, targetField, {\n select: ['id', 'documentId', 'locale', 'publishedAt', 'updatedAt'],\n ordering: 'desc',\n page: ctx.request.query.page,\n pageSize: ctx.request.query.pageSize,\n filters,\n });\n\n /**\n * Add all ids to load in permissionQuery\n * If any of the relations are not accessible, the permissionQuery will exclude them\n */\n const loadedIds = res.results.map((item: any) => item.id);\n addFiltersClause(permissionQuery, { id: { $in: loadedIds } });\n\n /**\n * Load the relations with the main field, the sanitized permission query\n * will exclude the relations the user does not have access to.\n *\n * Pagination is not necessary as the permissionQuery contains the ids to load.\n */\n const sanitizedRes = await loadRelations({ id: entryId }, targetField, {\n ...strapi.get('query-params').transform(targetUid, permissionQuery),\n ordering: 'desc',\n });\n\n // NOTE: the order is very important to make sure sanitized relations are kept in priority\n const relationsUnion = uniqBy('id', concat(sanitizedRes.results, res.results));\n\n ctx.body = {\n pagination: res.pagination || {\n page: 1,\n pageCount: 1,\n pageSize: 10,\n total: relationsUnion.length,\n },\n results: await addStatusToRelations(targetUid, relationsUnion),\n };\n },\n};\n"],"names":["PUBLISHED_AT_ATTRIBUTE","UPDATED_AT_ATTRIBUTE","contentTypes","constants","addFiltersClause","params","filtersClause","filters","$and","push","sanitizeMainField","model","mainField","userAbility","permissionChecker","getService","create","uid","isMainFieldListable","isListable","canReadMainField","can","read","addStatusToRelations","targetUid","relations","hasDraftAndPublish","strapi","getModel","documentMetadata","length","firstRelation","documentId","$in","map","r","publishedAt","$null","$notNull","availableStatus","query","findMany","select","statusByDocumentId","indexByDocumentId","relation","candidates","get","availableStatuses","locale","filter","c","status","getStatus","getPublishedAtClause","validateLocale","sourceUid","sourceModel","targetModel","isLocalized","plugin","service","isLocalizedContentType","isSourceLocalized","isTargetLocalized","validateStatus","isDP","isSourceDP","modelType","undefined","extractAndValidateRequestInfo","ctx","id","state","targetField","sourceSchema","errors","ValidationError","attribute","attributes","type","target","request","isComponent","cannot","forbidden","entryId","where","permissionQuery","sanitizedQuery","populate","populateFromQuery","build","currentEntity","db","findOne","NotFoundError","ForbiddenError","modelConfig","findConfiguration","targetSchema","flow","prop","fieldsToSelect","uniq","source","schema","findAvailable","validateFindAvailable","sourceModelType","idsToOmit","idsToInclude","_q","search","queryParams","sort","fields","filterByLocale","subQuery","queryBuilder","alias","getAlias","document_id","isEmpty","$notIn","knexSubQuery","join","getKnexQuery","isOperatorOfType","_filter","dbQuery","transform","res","findPage","body","results","findExisting","validateFindExisting","loadRelations","isAnyToMany","args","loadPages","load","then","options","draftAndPublish","ordering","page","pageSize","loadedIds","item","sanitizedRes","relationsUnion","uniqBy","concat","pagination","pageCount","total"],"mappings":"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"}
1
+ {"version":3,"file":"relations.js","sources":["../../../server/src/controllers/relations.ts"],"sourcesContent":["import { property, uniqBy, concat, flow, isEmpty } from 'lodash';\n\nimport { isOperatorOfType, contentTypes, relations, errors } from '@strapi/utils';\nimport type { Data, Modules, UID } from '@strapi/types';\n\nimport { getService } from '../utils';\nimport { validateFindAvailable, validateFindExisting } from './validation/relations';\nimport { isListable } from '../services/utils/configuration/attributes';\nimport { indexByDocumentId } from './utils/document-status';\n\nconst { PUBLISHED_AT_ATTRIBUTE, UPDATED_AT_ATTRIBUTE } = contentTypes.constants;\n\ninterface RelationEntity {\n id: Data.ID;\n documentId: Modules.Documents.ID;\n updatedAt: string | Date;\n publishedAt?: string | Date;\n [key: string]: unknown;\n}\n\nconst addFiltersClause = (params: any, filtersClause: any) => {\n params.filters = params.filters || {};\n params.filters.$and = params.filters.$and || [];\n params.filters.$and.push(filtersClause);\n};\n\nconst sanitizeMainField = (model: any, mainField: any, userAbility: any) => {\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: model.uid,\n });\n\n // Whether the main field can be displayed or not, regardless of permissions.\n const isMainFieldListable = isListable(model, mainField);\n // Whether the user has the permission to access the model's main field (using RBAC abilities)\n const canReadMainField = permissionChecker.can.read(null, mainField);\n\n if (!isMainFieldListable || !canReadMainField) {\n // Default to 'documentId' if the actual main field shouldn't be displayed\n return 'documentId';\n }\n\n // Edge cases\n\n // 1. Enforce 'name' as the main field for users and permissions' roles\n if (model.uid === 'plugin::users-permissions.role') {\n return 'name';\n }\n\n return mainField;\n};\n\n/**\n *\n * All relations sent to this function should have the same status or no status\n */\nconst addStatusToRelations = async (targetUid: UID.Schema, relations: RelationEntity[]) => {\n if (!contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {\n return relations;\n }\n\n const documentMetadata = getService('document-metadata');\n\n if (!relations.length) {\n return relations;\n }\n\n const firstRelation = relations[0];\n\n const filters: any = {\n documentId: { $in: relations.map((r) => r.documentId) },\n // NOTE: find the \"opposite\" status\n publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true },\n };\n\n const availableStatus = await strapi.query(targetUid).findMany({\n select: ['id', 'documentId', 'locale', 'updatedAt', 'createdAt', 'publishedAt'],\n filters,\n });\n\n const statusByDocumentId = indexByDocumentId(availableStatus);\n\n return relations.map((relation: RelationEntity) => {\n const candidates = statusByDocumentId.get(relation.documentId as string) || [];\n const availableStatuses = relation.locale\n ? candidates.filter((c) => c.locale === relation.locale)\n : candidates;\n\n return {\n ...relation,\n status: documentMetadata.getStatus(relation, availableStatuses),\n };\n });\n};\n\nconst getPublishedAtClause = (status: string, uid: UID.Schema) => {\n const model = strapi.getModel(uid);\n\n /**\n * If dp is disabled, ignore the filter\n */\n if (!model || !contentTypes.hasDraftAndPublish(model)) {\n return {};\n }\n\n // Prioritize the draft status in case it's not provided\n return status === 'published' ? { $notNull: true } : { $null: true };\n};\n\nconst validateLocale = (sourceUid: UID.Schema, targetUid: UID.ContentType, locale?: string) => {\n const sourceModel = strapi.getModel(sourceUid);\n const targetModel = strapi.getModel(targetUid);\n\n // Without a localization provider, neither side is localized\n const isSourceLocalized = strapi.localization.isLocalizedContentType(sourceModel);\n const isTargetLocalized = strapi.localization.isLocalizedContentType(targetModel);\n\n return {\n locale,\n isSourceLocalized,\n isTargetLocalized,\n };\n};\n\nconst validateStatus = (\n sourceUid: UID.Schema,\n status?: Modules.Documents.Params.PublicationStatus.Kind\n) => {\n const sourceModel = strapi.getModel(sourceUid);\n\n const isDP = contentTypes.hasDraftAndPublish;\n const isSourceDP = isDP(sourceModel);\n\n // Default to draft if not set\n if (!isSourceDP && sourceModel.modelType === 'contentType') {\n return { status: undefined };\n }\n\n switch (status) {\n case 'published':\n return { status: 'published' };\n default:\n // Assign to draft if the status is not valid\n return { status: 'draft' };\n }\n};\n\nexport default {\n async extractAndValidateRequestInfo(ctx: any, id?: Data.ID) {\n const { userAbility } = ctx.state;\n const { model, targetField } = ctx.params;\n\n const sourceSchema = strapi.getModel(model);\n if (!sourceSchema) {\n throw new errors.ValidationError(`The model ${model} doesn't exist`);\n }\n\n const attribute: any = sourceSchema.attributes[targetField];\n if (!attribute || attribute.type !== 'relation') {\n throw new errors.ValidationError(\n `The relational field ${targetField} doesn't exist on ${model}`\n );\n }\n\n const sourceUid = model;\n const targetUid = attribute.target;\n\n const { locale, isSourceLocalized, isTargetLocalized } = validateLocale(\n sourceUid,\n targetUid,\n ctx.request?.query?.locale\n );\n const { status } = validateStatus(sourceUid, ctx.request?.query?.status);\n\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model,\n });\n\n const isComponent = sourceSchema.modelType === 'component';\n if (!isComponent) {\n if (permissionChecker.cannot.read(null, targetField)) {\n return ctx.forbidden();\n }\n }\n\n let entryId: string | number | null = null;\n\n if (id) {\n const where: Record<string, any> = {};\n\n if (!isComponent) {\n where.documentId = id;\n\n if (status) {\n where.publishedAt = getPublishedAtClause(status, sourceUid);\n }\n\n if (locale && isSourceLocalized) {\n where.locale = locale;\n }\n } else {\n // If the source is a component, we only need to filter by the\n // component's entity id\n where.id = id;\n }\n\n const permissionQuery = await permissionChecker.sanitizedQuery.read(ctx.query);\n const populate = await getService('populate-builder')(model)\n .populateFromQuery(permissionQuery)\n .build();\n\n const currentEntity = await strapi.db.query(model).findOne({\n where,\n populate,\n });\n\n // We need to check if the entity exists\n // and if the user has the permission to read it in this way\n // There may be multiple entities (publication states) under this\n // documentId + locale. We only need to check if one exists\n if (!currentEntity) {\n throw new errors.NotFoundError();\n }\n\n if (!isComponent) {\n if (permissionChecker.cannot.read(currentEntity, targetField)) {\n throw new errors.ForbiddenError();\n }\n }\n\n entryId = currentEntity.id;\n }\n\n const modelConfig = isComponent\n ? await getService('components').findConfiguration(sourceSchema)\n : await getService('content-types').findConfiguration(sourceSchema);\n\n const targetSchema = strapi.getModel(targetUid);\n\n const mainField = flow(\n property(`metadatas.${targetField}.edit.mainField`),\n (mainField) => mainField || 'id',\n (mainField) => sanitizeMainField(targetSchema, mainField, userAbility)\n )(modelConfig);\n\n const fieldsToSelect = [\n ...new Set([mainField, PUBLISHED_AT_ATTRIBUTE, UPDATED_AT_ATTRIBUTE, 'documentId']),\n ];\n\n if (isTargetLocalized) {\n fieldsToSelect.push('locale');\n }\n\n return {\n entryId,\n locale,\n status,\n attribute,\n fieldsToSelect,\n mainField,\n source: { schema: sourceSchema, isLocalized: isSourceLocalized },\n target: { schema: targetSchema, isLocalized: isTargetLocalized },\n sourceSchema,\n targetSchema,\n targetField,\n };\n },\n\n /**\n * Used to find new relations to add in a relational field.\n *\n * Component and document relations are dealt a bit differently (they don't have a document_id).\n */\n async findAvailable(ctx: any) {\n const { id } = ctx.request.query;\n\n await validateFindAvailable(ctx.request.query);\n\n const {\n locale,\n status,\n targetField,\n fieldsToSelect,\n mainField,\n source: {\n schema: { uid: sourceUid, modelType: sourceModelType },\n isLocalized: isSourceLocalized,\n },\n target: {\n schema: { uid: targetUid },\n isLocalized: isTargetLocalized,\n },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const {\n idsToOmit,\n idsToInclude,\n // `_q` is the public query parameter name; keep the alias grep-able.\n _q: search,\n ...query\n } = ctx.request.query;\n\n const permissionChecker = getService('permission-checker').create({\n userAbility: ctx.state.userAbility,\n model: targetUid,\n });\n const permissionQuery = await permissionChecker.sanitizedQuery.read(query);\n\n const queryParams = {\n sort: mainField,\n // cannot select other fields as the user may not have the permissions\n fields: fieldsToSelect,\n ...permissionQuery,\n };\n\n // If no status is requested, we find all the draft relations and later update them\n // with the latest available status\n addFiltersClause(queryParams, {\n publishedAt: getPublishedAtClause(status, targetUid),\n });\n\n // We will only filter by locale if the target content type is localized\n const filterByLocale = isTargetLocalized && locale;\n if (filterByLocale) {\n addFiltersClause(queryParams, { locale });\n }\n\n if (id) {\n /**\n * Exclude the relations that are already related to the source\n *\n * We also optionally filter the target relations by the requested\n * status and locale if provided.\n */\n const subQuery = strapi.db.queryBuilder(sourceUid);\n\n // The alias refers to the DB table of the target content type model\n const alias = subQuery.getAlias();\n\n const where: Record<string, any> = {\n [`${alias}.id`]: { $notNull: true },\n [`${alias}.document_id`]: { $notNull: true },\n };\n\n /**\n * Content Types -> Specify document id\n * Components -> Specify entity id (they don't have a document id)\n */\n if (sourceModelType === 'contentType') {\n where.document_id = id;\n\n const sourcePublishedAt = getPublishedAtClause(status, sourceUid);\n if (!isEmpty(sourcePublishedAt)) {\n where.published_at = sourcePublishedAt;\n }\n } else {\n where.id = id;\n }\n\n // Add the status and locale filters if they are provided\n const publishedAt = getPublishedAtClause(status, targetUid);\n if (!isEmpty(publishedAt)) {\n where[`${alias}.published_at`] = publishedAt;\n }\n\n // If target has localization we need to filter by locale\n if (isTargetLocalized && locale) {\n where[`${alias}.locale`] = locale;\n }\n\n if (isSourceLocalized && locale) {\n where.locale = locale;\n }\n\n /**\n * UI can provide a list of ids to omit,\n * those are the relations user set in the UI but has not persisted.\n * We don't want to include them in the available relations.\n */\n if ((idsToInclude?.length ?? 0) !== 0) {\n where[`${alias}.id`].$notIn = idsToInclude;\n }\n\n const knexSubQuery = subQuery\n .where(where)\n .join({ alias, targetField })\n .select(`${alias}.id`)\n .getKnexQuery();\n\n addFiltersClause(queryParams, {\n id: { $notIn: knexSubQuery },\n });\n }\n\n /**\n * Apply a filter to the mainField based on the search query and filter operator\n * searching should be allowed only on mainField for permission reasons\n */\n if (search) {\n const filter = isOperatorOfType('where', query._filter) ? query._filter : '$containsi';\n addFiltersClause(queryParams, { [mainField]: { [filter]: search } });\n }\n\n if (idsToOmit?.length > 0) {\n // If we have ids to omit, we should filter them out\n addFiltersClause(queryParams, {\n id: { $notIn: [...new Set(idsToOmit)] },\n });\n }\n\n const dbQuery = strapi.get('query-params').transform(targetUid, queryParams);\n\n const res = await strapi.db.query(targetUid).findPage(dbQuery);\n\n ctx.body = {\n ...res,\n results: await addStatusToRelations(targetUid, res.results),\n };\n },\n\n async findExisting(ctx: any) {\n const { userAbility } = ctx.state;\n const { id } = ctx.params;\n\n await validateFindExisting(ctx.request.query);\n\n const {\n entryId,\n attribute,\n targetField,\n fieldsToSelect,\n status,\n source: { schema: sourceSchema },\n target: { schema: targetSchema },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const { uid: sourceUid } = sourceSchema;\n const { uid: targetUid } = targetSchema;\n\n const permissionQuery = await getService('permission-checker')\n .create({ userAbility, model: targetUid })\n .sanitizedQuery.read({ fields: fieldsToSelect });\n\n /**\n * loadPages can not be used for single relations,\n * this unifies the loading regardless of it's type\n *\n * NOTE: Relations need to be loaded using any db.query method\n * to ensure the proper ordering is applied\n */\n const dbQuery = strapi.db.query(sourceUid);\n const loadRelations = relations.isAnyToMany(attribute)\n ? (...args: Parameters<typeof dbQuery.loadPages>) => dbQuery.loadPages(...args)\n : (...args: Parameters<typeof dbQuery.load>) =>\n dbQuery\n .load(...args)\n // Ensure response is an array\n .then((res) => ({ results: res ? [res] : [] }));\n\n const filters: {\n publishedAt?: Record<string, any>;\n } = {};\n\n if (sourceSchema?.options?.draftAndPublish || sourceSchema?.modelType === 'component') {\n if (targetSchema?.options?.draftAndPublish) {\n if (status === 'published') {\n filters.publishedAt = { $notNull: true };\n } else {\n filters.publishedAt = { $null: true };\n }\n }\n } else if (targetSchema?.options?.draftAndPublish) {\n // NOTE: we must return the drafts as some targets might not have a published version yet\n filters.publishedAt = { $null: true };\n }\n\n /**\n * If user does not have access to specific relations (custom conditions),\n * only the ids of the relations are returned.\n *\n * - First query loads all the ids.\n * - Second one also loads the main field, and excludes forbidden relations.\n *\n * The response contains the union of the two queries.\n */\n const res = await loadRelations({ id: entryId }, targetField, {\n select: ['id', 'documentId', 'locale', 'publishedAt', 'updatedAt'],\n ordering: 'desc',\n page: ctx.request.query.page,\n pageSize: ctx.request.query.pageSize,\n filters,\n });\n\n /**\n * Add all ids to load in permissionQuery\n * If any of the relations are not accessible, the permissionQuery will exclude them\n */\n const loadedIds = res.results.map((item: any) => item.id);\n addFiltersClause(permissionQuery, { id: { $in: loadedIds } });\n\n /**\n * Load the relations with the main field, the sanitized permission query\n * will exclude the relations the user does not have access to.\n *\n * Pagination is not necessary as the permissionQuery contains the ids to load.\n */\n const sanitizedRes = await loadRelations({ id: entryId }, targetField, {\n ...strapi.get('query-params').transform(targetUid, permissionQuery),\n ordering: 'desc',\n });\n\n // NOTE: the order is very important to make sure sanitized relations are kept in priority\n const relationsUnion = uniqBy(concat(sanitizedRes.results, res.results), 'id');\n\n ctx.body = {\n pagination: res.pagination || {\n page: 1,\n pageCount: 1,\n pageSize: 10,\n total: relationsUnion.length,\n },\n results: await addStatusToRelations(targetUid, relationsUnion),\n };\n },\n};\n"],"names":["PUBLISHED_AT_ATTRIBUTE","UPDATED_AT_ATTRIBUTE","contentTypes","constants","addFiltersClause","params","filtersClause","filters","$and","push","sanitizeMainField","model","mainField","userAbility","permissionChecker","getService","create","uid","isMainFieldListable","isListable","canReadMainField","can","read","addStatusToRelations","targetUid","relations","hasDraftAndPublish","strapi","getModel","documentMetadata","length","firstRelation","documentId","$in","map","r","publishedAt","$null","$notNull","availableStatus","query","findMany","select","statusByDocumentId","indexByDocumentId","relation","candidates","get","availableStatuses","locale","filter","c","status","getStatus","getPublishedAtClause","validateLocale","sourceUid","sourceModel","targetModel","isSourceLocalized","localization","isLocalizedContentType","isTargetLocalized","validateStatus","isDP","isSourceDP","modelType","undefined","extractAndValidateRequestInfo","ctx","id","state","targetField","sourceSchema","errors","ValidationError","attribute","attributes","type","target","request","isComponent","cannot","forbidden","entryId","where","permissionQuery","sanitizedQuery","populate","populateFromQuery","build","currentEntity","db","findOne","NotFoundError","ForbiddenError","modelConfig","findConfiguration","targetSchema","flow","property","fieldsToSelect","Set","source","schema","isLocalized","findAvailable","validateFindAvailable","sourceModelType","idsToOmit","idsToInclude","_q","search","queryParams","sort","fields","filterByLocale","subQuery","queryBuilder","alias","getAlias","document_id","sourcePublishedAt","isEmpty","published_at","$notIn","knexSubQuery","join","getKnexQuery","isOperatorOfType","_filter","dbQuery","transform","res","findPage","body","results","findExisting","validateFindExisting","loadRelations","isAnyToMany","args","loadPages","load","then","options","draftAndPublish","ordering","page","pageSize","loadedIds","item","sanitizedRes","relationsUnion","uniqBy","concat","pagination","pageCount","total"],"mappings":";;;;;;;;;AAUA,MAAM,EAAEA,sBAAsB,EAAEC,oBAAoB,EAAE,GAAGC,yBAAaC,SAAS;AAU/E,MAAMC,gBAAAA,GAAmB,CAACC,MAAAA,EAAaC,aAAAA,GAAAA;AACrCD,IAAAA,MAAAA,CAAOE,OAAO,GAAGF,MAAAA,CAAOE,OAAO,IAAI,EAAC;IACpCF,MAAAA,CAAOE,OAAO,CAACC,IAAI,GAAGH,OAAOE,OAAO,CAACC,IAAI,IAAI,EAAE;AAC/CH,IAAAA,MAAAA,CAAOE,OAAO,CAACC,IAAI,CAACC,IAAI,CAACH,aAAAA,CAAAA;AAC3B,CAAA;AAEA,MAAMI,iBAAAA,GAAoB,CAACC,KAAAA,EAAYC,SAAAA,EAAgBC,WAAAA,GAAAA;AACrD,IAAA,MAAMC,iBAAAA,GAAoBC,gBAAAA,CAAW,oBAAA,CAAA,CAAsBC,MAAM,CAAC;AAChEH,QAAAA,WAAAA;AACAF,QAAAA,KAAAA,EAAOA,MAAMM;AACf,KAAA,CAAA;;IAGA,MAAMC,mBAAAA,GAAsBC,sBAAWR,KAAAA,EAAOC,SAAAA,CAAAA;;AAE9C,IAAA,MAAMQ,mBAAmBN,iBAAAA,CAAkBO,GAAG,CAACC,IAAI,CAAC,IAAA,EAAMV,SAAAA,CAAAA;IAE1D,IAAI,CAACM,mBAAAA,IAAuB,CAACE,gBAAAA,EAAkB;;QAE7C,OAAO,YAAA;AACT,IAAA;;;IAKA,IAAIT,KAAAA,CAAMM,GAAG,KAAK,gCAAA,EAAkC;QAClD,OAAO,MAAA;AACT,IAAA;IAEA,OAAOL,SAAAA;AACT,CAAA;AAEA;;;IAIA,MAAMW,oBAAAA,GAAuB,OAAOC,SAAAA,EAAuBC,SAAAA,GAAAA;AACzD,IAAA,IAAI,CAACvB,wBAAAA,CAAawB,kBAAkB,CAACC,MAAAA,CAAOC,QAAQ,CAACJ,SAAAA,CAAAA,CAAAA,EAAa;QAChE,OAAOC,SAAAA;AACT,IAAA;AAEA,IAAA,MAAMI,mBAAmBd,gBAAAA,CAAW,mBAAA,CAAA;IAEpC,IAAI,CAACU,SAAAA,CAAUK,MAAM,EAAE;QACrB,OAAOL,SAAAA;AACT,IAAA;IAEA,MAAMM,aAAAA,GAAgBN,SAAS,CAAC,CAAA,CAAE;AAElC,IAAA,MAAMlB,OAAAA,GAAe;QACnByB,UAAAA,EAAY;AAAEC,YAAAA,GAAAA,EAAKR,UAAUS,GAAG,CAAC,CAACC,CAAAA,GAAMA,EAAEH,UAAU;AAAE,SAAA;;QAEtDI,WAAAA,EAAaL,aAAAA,CAAcK,WAAW,KAAK,IAAA,GAAO;YAAEC,KAAAA,EAAO;SAAK,GAAI;YAAEC,QAAAA,EAAU;AAAK;AACvF,KAAA;AAEA,IAAA,MAAMC,kBAAkB,MAAMZ,MAAAA,CAAOa,KAAK,CAAChB,SAAAA,CAAAA,CAAWiB,QAAQ,CAAC;QAC7DC,MAAAA,EAAQ;AAAC,YAAA,IAAA;AAAM,YAAA,YAAA;AAAc,YAAA,QAAA;AAAU,YAAA,WAAA;AAAa,YAAA,WAAA;AAAa,YAAA;AAAc,SAAA;AAC/EnC,QAAAA;AACF,KAAA,CAAA;AAEA,IAAA,MAAMoC,qBAAqBC,gCAAAA,CAAkBL,eAAAA,CAAAA;IAE7C,OAAOd,SAAAA,CAAUS,GAAG,CAAC,CAACW,QAAAA,GAAAA;AACpB,QAAA,MAAMC,aAAaH,kBAAAA,CAAmBI,GAAG,CAACF,QAAAA,CAASb,UAAU,KAAe,EAAE;AAC9E,QAAA,MAAMgB,iBAAAA,GAAoBH,QAAAA,CAASI,MAAM,GACrCH,WAAWI,MAAM,CAAC,CAACC,CAAAA,GAAMA,CAAAA,CAAEF,MAAM,KAAKJ,QAAAA,CAASI,MAAM,CAAA,GACrDH,UAAAA;QAEJ,OAAO;AACL,YAAA,GAAGD,QAAQ;YACXO,MAAAA,EAAQvB,gBAAAA,CAAiBwB,SAAS,CAACR,QAAAA,EAAUG,iBAAAA;AAC/C,SAAA;AACF,IAAA,CAAA,CAAA;AACF,CAAA;AAEA,MAAMM,oBAAAA,GAAuB,CAACF,MAAAA,EAAgBnC,GAAAA,GAAAA;IAC5C,MAAMN,KAAAA,GAAQgB,MAAAA,CAAOC,QAAQ,CAACX,GAAAA,CAAAA;AAE9B;;AAEC,MACD,IAAI,CAACN,KAAAA,IAAS,CAACT,wBAAAA,CAAawB,kBAAkB,CAACf,KAAAA,CAAAA,EAAQ;AACrD,QAAA,OAAO,EAAC;AACV,IAAA;;AAGA,IAAA,OAAOyC,WAAW,WAAA,GAAc;QAAEd,QAAAA,EAAU;KAAK,GAAI;QAAED,KAAAA,EAAO;AAAK,KAAA;AACrE,CAAA;AAEA,MAAMkB,cAAAA,GAAiB,CAACC,SAAAA,EAAuBhC,SAAAA,EAA4ByB,MAAAA,GAAAA;IACzE,MAAMQ,WAAAA,GAAc9B,MAAAA,CAAOC,QAAQ,CAAC4B,SAAAA,CAAAA;IACpC,MAAME,WAAAA,GAAc/B,MAAAA,CAAOC,QAAQ,CAACJ,SAAAA,CAAAA;;AAGpC,IAAA,MAAMmC,iBAAAA,GAAoBhC,MAAAA,CAAOiC,YAAY,CAACC,sBAAsB,CAACJ,WAAAA,CAAAA;AACrE,IAAA,MAAMK,iBAAAA,GAAoBnC,MAAAA,CAAOiC,YAAY,CAACC,sBAAsB,CAACH,WAAAA,CAAAA;IAErE,OAAO;AACLT,QAAAA,MAAAA;AACAU,QAAAA,iBAAAA;AACAG,QAAAA;AACF,KAAA;AACF,CAAA;AAEA,MAAMC,cAAAA,GAAiB,CACrBP,SAAAA,EACAJ,MAAAA,GAAAA;IAEA,MAAMK,WAAAA,GAAc9B,MAAAA,CAAOC,QAAQ,CAAC4B,SAAAA,CAAAA;IAEpC,MAAMQ,IAAAA,GAAO9D,yBAAawB,kBAAkB;AAC5C,IAAA,MAAMuC,aAAaD,IAAAA,CAAKP,WAAAA,CAAAA;;AAGxB,IAAA,IAAI,CAACQ,UAAAA,IAAcR,WAAAA,CAAYS,SAAS,KAAK,aAAA,EAAe;QAC1D,OAAO;YAAEd,MAAAA,EAAQe;AAAU,SAAA;AAC7B,IAAA;IAEA,OAAQf,MAAAA;QACN,KAAK,WAAA;YACH,OAAO;gBAAEA,MAAAA,EAAQ;AAAY,aAAA;AAC/B,QAAA;;YAEE,OAAO;gBAAEA,MAAAA,EAAQ;AAAQ,aAAA;AAC7B;AACF,CAAA;AAEA,gBAAe;IACb,MAAMgB,6BAAAA,CAAAA,CAA8BC,GAAQ,EAAEC,EAAY,EAAA;AACxD,QAAA,MAAM,EAAEzD,WAAW,EAAE,GAAGwD,IAAIE,KAAK;AACjC,QAAA,MAAM,EAAE5D,KAAK,EAAE6D,WAAW,EAAE,GAAGH,IAAIhE,MAAM;QAEzC,MAAMoE,YAAAA,GAAe9C,MAAAA,CAAOC,QAAQ,CAACjB,KAAAA,CAAAA;AACrC,QAAA,IAAI,CAAC8D,YAAAA,EAAc;YACjB,MAAM,IAAIC,mBAAOC,eAAe,CAAC,CAAC,UAAU,EAAEhE,KAAAA,CAAM,cAAc,CAAC,CAAA;AACrE,QAAA;AAEA,QAAA,MAAMiE,SAAAA,GAAiBH,YAAAA,CAAaI,UAAU,CAACL,WAAAA,CAAY;AAC3D,QAAA,IAAI,CAACI,SAAAA,IAAaA,SAAAA,CAAUE,IAAI,KAAK,UAAA,EAAY;YAC/C,MAAM,IAAIJ,kBAAAA,CAAOC,eAAe,CAC9B,CAAC,qBAAqB,EAAEH,WAAAA,CAAY,kBAAkB,EAAE7D,KAAAA,CAAAA,CAAO,CAAA;AAEnE,QAAA;AAEA,QAAA,MAAM6C,SAAAA,GAAY7C,KAAAA;QAClB,MAAMa,SAAAA,GAAYoD,UAAUG,MAAM;AAElC,QAAA,MAAM,EAAE9B,MAAM,EAAEU,iBAAiB,EAAEG,iBAAiB,EAAE,GAAGP,cAAAA,CACvDC,SAAAA,EACAhC,SAAAA,EACA6C,GAAAA,CAAIW,OAAO,EAAExC,KAAAA,EAAOS,MAAAA,CAAAA;QAEtB,MAAM,EAAEG,MAAM,EAAE,GAAGW,eAAeP,SAAAA,EAAWa,GAAAA,CAAIW,OAAO,EAAExC,KAAAA,EAAOY,MAAAA,CAAAA;AAEjE,QAAA,MAAMtC,iBAAAA,GAAoBC,gBAAAA,CAAW,oBAAA,CAAA,CAAsBC,MAAM,CAAC;AAChEH,YAAAA,WAAAA;AACAF,YAAAA;AACF,SAAA,CAAA;QAEA,MAAMsE,WAAAA,GAAcR,YAAAA,CAAaP,SAAS,KAAK,WAAA;AAC/C,QAAA,IAAI,CAACe,WAAAA,EAAa;AAChB,YAAA,IAAInE,kBAAkBoE,MAAM,CAAC5D,IAAI,CAAC,MAAMkD,WAAAA,CAAAA,EAAc;AACpD,gBAAA,OAAOH,IAAIc,SAAS,EAAA;AACtB,YAAA;AACF,QAAA;AAEA,QAAA,IAAIC,OAAAA,GAAkC,IAAA;AAEtC,QAAA,IAAId,EAAAA,EAAI;AACN,YAAA,MAAMe,QAA6B,EAAC;AAEpC,YAAA,IAAI,CAACJ,WAAAA,EAAa;AAChBI,gBAAAA,KAAAA,CAAMrD,UAAU,GAAGsC,EAAAA;AAEnB,gBAAA,IAAIlB,MAAAA,EAAQ;oBACViC,KAAAA,CAAMjD,WAAW,GAAGkB,oBAAAA,CAAqBF,MAAAA,EAAQI,SAAAA,CAAAA;AACnD,gBAAA;AAEA,gBAAA,IAAIP,UAAUU,iBAAAA,EAAmB;AAC/B0B,oBAAAA,KAAAA,CAAMpC,MAAM,GAAGA,MAAAA;AACjB,gBAAA;YACF,CAAA,MAAO;;;AAGLoC,gBAAAA,KAAAA,CAAMf,EAAE,GAAGA,EAAAA;AACb,YAAA;YAEA,MAAMgB,eAAAA,GAAkB,MAAMxE,iBAAAA,CAAkByE,cAAc,CAACjE,IAAI,CAAC+C,IAAI7B,KAAK,CAAA;YAC7E,MAAMgD,QAAAA,GAAW,MAAMzE,gBAAAA,CAAW,kBAAA,CAAA,CAAoBJ,OACnD8E,iBAAiB,CAACH,iBAClBI,KAAK,EAAA;YAER,MAAMC,aAAAA,GAAgB,MAAMhE,MAAAA,CAAOiE,EAAE,CAACpD,KAAK,CAAC7B,KAAAA,CAAAA,CAAOkF,OAAO,CAAC;AACzDR,gBAAAA,KAAAA;AACAG,gBAAAA;AACF,aAAA,CAAA;;;;;AAMA,YAAA,IAAI,CAACG,aAAAA,EAAe;gBAClB,MAAM,IAAIjB,mBAAOoB,aAAa,EAAA;AAChC,YAAA;AAEA,YAAA,IAAI,CAACb,WAAAA,EAAa;AAChB,gBAAA,IAAInE,kBAAkBoE,MAAM,CAAC5D,IAAI,CAACqE,eAAenB,WAAAA,CAAAA,EAAc;oBAC7D,MAAM,IAAIE,mBAAOqB,cAAc,EAAA;AACjC,gBAAA;AACF,YAAA;AAEAX,YAAAA,OAAAA,GAAUO,cAAcrB,EAAE;AAC5B,QAAA;AAEA,QAAA,MAAM0B,WAAAA,GAAcf,WAAAA,GAChB,MAAMlE,gBAAAA,CAAW,YAAA,CAAA,CAAckF,iBAAiB,CAACxB,YAAAA,CAAAA,GACjD,MAAM1D,gBAAAA,CAAW,eAAA,CAAA,CAAiBkF,iBAAiB,CAACxB,YAAAA,CAAAA;QAExD,MAAMyB,YAAAA,GAAevE,MAAAA,CAAOC,QAAQ,CAACJ,SAAAA,CAAAA;AAErC,QAAA,MAAMZ,YAAYuF,MAAAA,CAChBC,UAAAA,CAAS,CAAC,UAAU,EAAE5B,YAAY,eAAe,CAAC,GAClD,CAAC5D,SAAAA,GAAcA,aAAa,IAAA,EAC5B,CAACA,YAAcF,iBAAAA,CAAkBwF,YAAAA,EAActF,WAAWC,WAAAA,CAAAA,CAAAA,CAC1DmF,WAAAA,CAAAA;AAEF,QAAA,MAAMK,cAAAA,GAAiB;AAClB,YAAA,GAAA,IAAIC,GAAAA,CAAI;AAAC1F,gBAAAA,SAAAA;AAAWZ,gBAAAA,sBAAAA;AAAwBC,gBAAAA,oBAAAA;AAAsB,gBAAA;AAAa,aAAA;AACnF,SAAA;AAED,QAAA,IAAI6D,iBAAAA,EAAmB;AACrBuC,YAAAA,cAAAA,CAAe5F,IAAI,CAAC,QAAA,CAAA;AACtB,QAAA;QAEA,OAAO;AACL2E,YAAAA,OAAAA;AACAnC,YAAAA,MAAAA;AACAG,YAAAA,MAAAA;AACAwB,YAAAA,SAAAA;AACAyB,YAAAA,cAAAA;AACAzF,YAAAA,SAAAA;YACA2F,MAAAA,EAAQ;gBAAEC,MAAAA,EAAQ/B,YAAAA;gBAAcgC,WAAAA,EAAa9C;AAAkB,aAAA;YAC/DoB,MAAAA,EAAQ;gBAAEyB,MAAAA,EAAQN,YAAAA;gBAAcO,WAAAA,EAAa3C;AAAkB,aAAA;AAC/DW,YAAAA,YAAAA;AACAyB,YAAAA,YAAAA;AACA1B,YAAAA;AACF,SAAA;AACF,IAAA,CAAA;AAEA;;;;MAKA,MAAMkC,eAAcrC,GAAQ,EAAA;AAC1B,QAAA,MAAM,EAAEC,EAAE,EAAE,GAAGD,GAAAA,CAAIW,OAAO,CAACxC,KAAK;AAEhC,QAAA,MAAMmE,iCAAAA,CAAsBtC,GAAAA,CAAIW,OAAO,CAACxC,KAAK,CAAA;QAE7C,MAAM,EACJS,MAAM,EACNG,MAAM,EACNoB,WAAW,EACX6B,cAAc,EACdzF,SAAS,EACT2F,MAAAA,EAAQ,EACNC,QAAQ,EAAEvF,GAAAA,EAAKuC,SAAS,EAAEU,SAAAA,EAAW0C,eAAe,EAAE,EACtDH,aAAa9C,iBAAiB,EAC/B,EACDoB,MAAAA,EAAQ,EACNyB,QAAQ,EAAEvF,GAAAA,EAAKO,SAAS,EAAE,EAC1BiF,aAAa3C,iBAAiB,EAC/B,EACF,GAAG,MAAM,IAAI,CAACM,6BAA6B,CAACC,GAAAA,EAAKC,EAAAA,CAAAA;AAElD,QAAA,MAAM,EACJuC,SAAS,EACTC,YAAY;QAEZC,EAAAA,EAAIC,MAAM,EACV,GAAGxE,KAAAA,EACJ,GAAG6B,GAAAA,CAAIW,OAAO,CAACxC,KAAK;AAErB,QAAA,MAAM1B,iBAAAA,GAAoBC,gBAAAA,CAAW,oBAAA,CAAA,CAAsBC,MAAM,CAAC;YAChEH,WAAAA,EAAawD,GAAAA,CAAIE,KAAK,CAAC1D,WAAW;YAClCF,KAAAA,EAAOa;AACT,SAAA,CAAA;AACA,QAAA,MAAM8D,kBAAkB,MAAMxE,iBAAAA,CAAkByE,cAAc,CAACjE,IAAI,CAACkB,KAAAA,CAAAA;AAEpE,QAAA,MAAMyE,WAAAA,GAAc;YAClBC,IAAAA,EAAMtG,SAAAA;;YAENuG,MAAAA,EAAQd,cAAAA;AACR,YAAA,GAAGf;AACL,SAAA;;;AAIAlF,QAAAA,gBAAAA,CAAiB6G,WAAAA,EAAa;AAC5B7E,YAAAA,WAAAA,EAAakB,qBAAqBF,MAAAA,EAAQ5B,SAAAA;AAC5C,SAAA,CAAA;;AAGA,QAAA,MAAM4F,iBAAiBtD,iBAAAA,IAAqBb,MAAAA;AAC5C,QAAA,IAAImE,cAAAA,EAAgB;AAClBhH,YAAAA,gBAAAA,CAAiB6G,WAAAA,EAAa;AAAEhE,gBAAAA;AAAO,aAAA,CAAA;AACzC,QAAA;AAEA,QAAA,IAAIqB,EAAAA,EAAI;AACN;;;;;AAKC,UACD,MAAM+C,QAAAA,GAAW1F,MAAAA,CAAOiE,EAAE,CAAC0B,YAAY,CAAC9D,SAAAA,CAAAA;;YAGxC,MAAM+D,KAAAA,GAAQF,SAASG,QAAQ,EAAA;AAE/B,YAAA,MAAMnC,KAAAA,GAA6B;AACjC,gBAAA,CAAC,CAAA,EAAGkC,KAAAA,CAAM,GAAG,CAAC,GAAG;oBAAEjF,QAAAA,EAAU;AAAK,iBAAA;AAClC,gBAAA,CAAC,CAAA,EAAGiF,KAAAA,CAAM,YAAY,CAAC,GAAG;oBAAEjF,QAAAA,EAAU;AAAK;AAC7C,aAAA;AAEA;;;UAIA,IAAIsE,oBAAoB,aAAA,EAAe;AACrCvB,gBAAAA,KAAAA,CAAMoC,WAAW,GAAGnD,EAAAA;gBAEpB,MAAMoD,iBAAAA,GAAoBpE,qBAAqBF,MAAAA,EAAQI,SAAAA,CAAAA;gBACvD,IAAI,CAACmE,UAAQD,iBAAAA,CAAAA,EAAoB;AAC/BrC,oBAAAA,KAAAA,CAAMuC,YAAY,GAAGF,iBAAAA;AACvB,gBAAA;YACF,CAAA,MAAO;AACLrC,gBAAAA,KAAAA,CAAMf,EAAE,GAAGA,EAAAA;AACb,YAAA;;YAGA,MAAMlC,WAAAA,GAAckB,qBAAqBF,MAAAA,EAAQ5B,SAAAA,CAAAA;YACjD,IAAI,CAACmG,UAAQvF,WAAAA,CAAAA,EAAc;AACzBiD,gBAAAA,KAAK,CAAC,CAAA,EAAGkC,KAAAA,CAAM,aAAa,CAAC,CAAC,GAAGnF,WAAAA;AACnC,YAAA;;AAGA,YAAA,IAAI0B,qBAAqBb,MAAAA,EAAQ;AAC/BoC,gBAAAA,KAAK,CAAC,CAAA,EAAGkC,KAAAA,CAAM,OAAO,CAAC,CAAC,GAAGtE,MAAAA;AAC7B,YAAA;AAEA,YAAA,IAAIU,qBAAqBV,MAAAA,EAAQ;AAC/BoC,gBAAAA,KAAAA,CAAMpC,MAAM,GAAGA,MAAAA;AACjB,YAAA;AAEA;;;;AAIC,UACD,IAAI,CAAC6D,cAAchF,MAAAA,IAAU,CAAA,MAAO,CAAA,EAAG;gBACrCuD,KAAK,CAAC,GAAGkC,KAAAA,CAAM,GAAG,CAAC,CAAC,CAACM,MAAM,GAAGf,YAAAA;AAChC,YAAA;AAEA,YAAA,MAAMgB,eAAeT,QAAAA,CAClBhC,KAAK,CAACA,KAAAA,CAAAA,CACN0C,IAAI,CAAC;AAAER,gBAAAA,KAAAA;AAAO/C,gBAAAA;AAAY,aAAA,CAAA,CAC1B9B,MAAM,CAAC,CAAA,EAAG6E,MAAM,GAAG,CAAC,EACpBS,YAAY,EAAA;AAEf5H,YAAAA,gBAAAA,CAAiB6G,WAAAA,EAAa;gBAC5B3C,EAAAA,EAAI;oBAAEuD,MAAAA,EAAQC;AAAa;AAC7B,aAAA,CAAA;AACF,QAAA;AAEA;;;AAGC,QACD,IAAId,MAAAA,EAAQ;YACV,MAAM9D,MAAAA,GAAS+E,6BAAiB,OAAA,EAASzF,KAAAA,CAAM0F,OAAO,CAAA,GAAI1F,KAAAA,CAAM0F,OAAO,GAAG,YAAA;AAC1E9H,YAAAA,gBAAAA,CAAiB6G,WAAAA,EAAa;AAAE,gBAAA,CAACrG,YAAY;AAAE,oBAAA,CAACsC,SAAS8D;AAAO;AAAE,aAAA,CAAA;AACpE,QAAA;QAEA,IAAIH,SAAAA,EAAW/E,SAAS,CAAA,EAAG;;AAEzB1B,YAAAA,gBAAAA,CAAiB6G,WAAAA,EAAa;gBAC5B3C,EAAAA,EAAI;oBAAEuD,MAAAA,EAAQ;AAAI,wBAAA,GAAA,IAAIvB,GAAAA,CAAIO,SAAAA;AAAW;AAAC;AACxC,aAAA,CAAA;AACF,QAAA;AAEA,QAAA,MAAMsB,UAAUxG,MAAAA,CAAOoB,GAAG,CAAC,cAAA,CAAA,CAAgBqF,SAAS,CAAC5G,SAAAA,EAAWyF,WAAAA,CAAAA;QAEhE,MAAMoB,GAAAA,GAAM,MAAM1G,MAAAA,CAAOiE,EAAE,CAACpD,KAAK,CAAChB,SAAAA,CAAAA,CAAW8G,QAAQ,CAACH,OAAAA,CAAAA;AAEtD9D,QAAAA,GAAAA,CAAIkE,IAAI,GAAG;AACT,YAAA,GAAGF,GAAG;AACNG,YAAAA,OAAAA,EAAS,MAAMjH,oBAAAA,CAAqBC,SAAAA,EAAW6G,GAAAA,CAAIG,OAAO;AAC5D,SAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,cAAapE,GAAQ,EAAA;AACzB,QAAA,MAAM,EAAExD,WAAW,EAAE,GAAGwD,IAAIE,KAAK;AACjC,QAAA,MAAM,EAAED,EAAE,EAAE,GAAGD,IAAIhE,MAAM;AAEzB,QAAA,MAAMqI,gCAAAA,CAAqBrE,GAAAA,CAAIW,OAAO,CAACxC,KAAK,CAAA;AAE5C,QAAA,MAAM,EACJ4C,OAAO,EACPR,SAAS,EACTJ,WAAW,EACX6B,cAAc,EACdjD,MAAM,EACNmD,MAAAA,EAAQ,EAAEC,MAAAA,EAAQ/B,YAAY,EAAE,EAChCM,MAAAA,EAAQ,EAAEyB,MAAAA,EAAQN,YAAY,EAAE,EACjC,GAAG,MAAM,IAAI,CAAC9B,6BAA6B,CAACC,GAAAA,EAAKC,EAAAA,CAAAA;AAElD,QAAA,MAAM,EAAErD,GAAAA,EAAKuC,SAAS,EAAE,GAAGiB,YAAAA;AAC3B,QAAA,MAAM,EAAExD,GAAAA,EAAKO,SAAS,EAAE,GAAG0E,YAAAA;AAE3B,QAAA,MAAMZ,eAAAA,GAAkB,MAAMvE,gBAAAA,CAAW,oBAAA,CAAA,CACtCC,MAAM,CAAC;AAAEH,YAAAA,WAAAA;YAAaF,KAAAA,EAAOa;SAAU,CAAA,CACvC+D,cAAc,CAACjE,IAAI,CAAC;YAAE6F,MAAAA,EAAQd;AAAe,SAAA,CAAA;AAEhD;;;;;;AAMC,QACD,MAAM8B,OAAAA,GAAUxG,MAAAA,CAAOiE,EAAE,CAACpD,KAAK,CAACgB,SAAAA,CAAAA;AAChC,QAAA,MAAMmF,gBAAgBlH,qBAAAA,CAAUmH,WAAW,CAAChE,SAAAA,CAAAA,GACxC,CAAC,GAAGiE,IAAAA,GAA+CV,OAAAA,CAAQW,SAAS,CAAA,GAAID,IAAAA,CAAAA,GACxE,CAAC,GAAGA,IAAAA,GACFV,QACGY,IAAI,CAAA,GAAIF,KACT;aACCG,IAAI,CAAC,CAACX,GAAAA,IAAS;AAAEG,oBAAAA,OAAAA,EAASH,GAAAA,GAAM;AAACA,wBAAAA;AAAI,qBAAA,GAAG;iBAAG,CAAA,CAAA;AAEpD,QAAA,MAAM9H,UAEF,EAAC;AAEL,QAAA,IAAIkE,YAAAA,EAAcwE,OAAAA,EAASC,eAAAA,IAAmBzE,YAAAA,EAAcP,cAAc,WAAA,EAAa;YACrF,IAAIgC,YAAAA,EAAc+C,SAASC,eAAAA,EAAiB;AAC1C,gBAAA,IAAI9F,WAAW,WAAA,EAAa;AAC1B7C,oBAAAA,OAAAA,CAAQ6B,WAAW,GAAG;wBAAEE,QAAAA,EAAU;AAAK,qBAAA;gBACzC,CAAA,MAAO;AACL/B,oBAAAA,OAAAA,CAAQ6B,WAAW,GAAG;wBAAEC,KAAAA,EAAO;AAAK,qBAAA;AACtC,gBAAA;AACF,YAAA;QACF,CAAA,MAAO,IAAI6D,YAAAA,EAAc+C,OAAAA,EAASC,eAAAA,EAAiB;;AAEjD3I,YAAAA,OAAAA,CAAQ6B,WAAW,GAAG;gBAAEC,KAAAA,EAAO;AAAK,aAAA;AACtC,QAAA;AAEA;;;;;;;;QASA,MAAMgG,GAAAA,GAAM,MAAMM,aAAAA,CAAc;YAAErE,EAAAA,EAAIc;AAAQ,SAAA,EAAGZ,WAAAA,EAAa;YAC5D9B,MAAAA,EAAQ;AAAC,gBAAA,IAAA;AAAM,gBAAA,YAAA;AAAc,gBAAA,QAAA;AAAU,gBAAA,aAAA;AAAe,gBAAA;AAAY,aAAA;YAClEyG,QAAAA,EAAU,MAAA;AACVC,YAAAA,IAAAA,EAAM/E,GAAAA,CAAIW,OAAO,CAACxC,KAAK,CAAC4G,IAAI;AAC5BC,YAAAA,QAAAA,EAAUhF,GAAAA,CAAIW,OAAO,CAACxC,KAAK,CAAC6G,QAAQ;AACpC9I,YAAAA;AACF,SAAA,CAAA;AAEA;;;QAIA,MAAM+I,SAAAA,GAAYjB,GAAAA,CAAIG,OAAO,CAACtG,GAAG,CAAC,CAACqH,IAAAA,GAAcA,IAAAA,CAAKjF,EAAE,CAAA;AACxDlE,QAAAA,gBAAAA,CAAiBkF,eAAAA,EAAiB;YAAEhB,EAAAA,EAAI;gBAAErC,GAAAA,EAAKqH;AAAU;AAAE,SAAA,CAAA;AAE3D;;;;;QAMA,MAAME,YAAAA,GAAe,MAAMb,aAAAA,CAAc;YAAErE,EAAAA,EAAIc;AAAQ,SAAA,EAAGZ,WAAAA,EAAa;AACrE,YAAA,GAAG7C,OAAOoB,GAAG,CAAC,gBAAgBqF,SAAS,CAAC5G,WAAW8D,eAAAA,CAAgB;YACnE6D,QAAAA,EAAU;AACZ,SAAA,CAAA;;QAGA,MAAMM,cAAAA,GAAiBC,SAAOC,QAAAA,CAAOH,YAAAA,CAAahB,OAAO,EAAEH,GAAAA,CAAIG,OAAO,CAAA,EAAG,IAAA,CAAA;AAEzEnE,QAAAA,GAAAA,CAAIkE,IAAI,GAAG;YACTqB,UAAAA,EAAYvB,GAAAA,CAAIuB,UAAU,IAAI;gBAC5BR,IAAAA,EAAM,CAAA;gBACNS,SAAAA,EAAW,CAAA;gBACXR,QAAAA,EAAU,EAAA;AACVS,gBAAAA,KAAAA,EAAOL,eAAe3H;AACxB,aAAA;YACA0G,OAAAA,EAAS,MAAMjH,qBAAqBC,SAAAA,EAAWiI,cAAAA;AACjD,SAAA;AACF,IAAA;AACF,CAAA;;;;"}
@@ -1,4 +1,4 @@
1
- import { uniqBy, concat, isEmpty, uniq, flow, prop } from 'lodash/fp';
1
+ import { uniqBy, concat, isEmpty, flow, property } from 'lodash';
2
2
  import { contentTypes, relations as relations$1, isOperatorOfType, errors } from '@strapi/utils';
3
3
  import { getService } from '../utils/index.mjs';
4
4
  import { validateFindExisting, validateFindAvailable } from './validation/relations.mjs';
@@ -92,9 +92,9 @@ const getPublishedAtClause = (status, uid)=>{
92
92
  const validateLocale = (sourceUid, targetUid, locale)=>{
93
93
  const sourceModel = strapi.getModel(sourceUid);
94
94
  const targetModel = strapi.getModel(targetUid);
95
- const isLocalized = strapi.plugin('i18n').service('content-types').isLocalizedContentType;
96
- const isSourceLocalized = isLocalized(sourceModel);
97
- const isTargetLocalized = isLocalized(targetModel);
95
+ // Without a localization provider, neither side is localized
96
+ const isSourceLocalized = strapi.localization.isLocalizedContentType(sourceModel);
97
+ const isTargetLocalized = strapi.localization.isLocalizedContentType(targetModel);
98
98
  return {
99
99
  locale,
100
100
  isSourceLocalized,
@@ -187,13 +187,15 @@ var relations = {
187
187
  }
188
188
  const modelConfig = isComponent ? await getService('components').findConfiguration(sourceSchema) : await getService('content-types').findConfiguration(sourceSchema);
189
189
  const targetSchema = strapi.getModel(targetUid);
190
- const mainField = flow(prop(`metadatas.${targetField}.edit.mainField`), (mainField)=>mainField || 'id', (mainField)=>sanitizeMainField(targetSchema, mainField, userAbility))(modelConfig);
191
- const fieldsToSelect = uniq([
192
- mainField,
193
- PUBLISHED_AT_ATTRIBUTE,
194
- UPDATED_AT_ATTRIBUTE,
195
- 'documentId'
196
- ]);
190
+ const mainField = flow(property(`metadatas.${targetField}.edit.mainField`), (mainField)=>mainField || 'id', (mainField)=>sanitizeMainField(targetSchema, mainField, userAbility))(modelConfig);
191
+ const fieldsToSelect = [
192
+ ...new Set([
193
+ mainField,
194
+ PUBLISHED_AT_ATTRIBUTE,
195
+ UPDATED_AT_ATTRIBUTE,
196
+ 'documentId'
197
+ ])
198
+ ];
197
199
  if (isTargetLocalized) {
198
200
  fieldsToSelect.push('locale');
199
201
  }
@@ -272,6 +274,10 @@ var relations = {
272
274
  * Components -> Specify entity id (they don't have a document id)
273
275
  */ if (sourceModelType === 'contentType') {
274
276
  where.document_id = id;
277
+ const sourcePublishedAt = getPublishedAtClause(status, sourceUid);
278
+ if (!isEmpty(sourcePublishedAt)) {
279
+ where.published_at = sourcePublishedAt;
280
+ }
275
281
  } else {
276
282
  where.id = id;
277
283
  }
@@ -319,7 +325,9 @@ var relations = {
319
325
  // If we have ids to omit, we should filter them out
320
326
  addFiltersClause(queryParams, {
321
327
  id: {
322
- $notIn: uniq(idsToOmit)
328
+ $notIn: [
329
+ ...new Set(idsToOmit)
330
+ ]
323
331
  }
324
332
  });
325
333
  }
@@ -419,7 +427,7 @@ var relations = {
419
427
  ordering: 'desc'
420
428
  });
421
429
  // NOTE: the order is very important to make sure sanitized relations are kept in priority
422
- const relationsUnion = uniqBy('id', concat(sanitizedRes.results, res.results));
430
+ const relationsUnion = uniqBy(concat(sanitizedRes.results, res.results), 'id');
423
431
  ctx.body = {
424
432
  pagination: res.pagination || {
425
433
  page: 1,
@@ -1 +1 @@
1
- {"version":3,"file":"relations.mjs","sources":["../../../server/src/controllers/relations.ts"],"sourcesContent":["import { prop, uniq, uniqBy, concat, flow, isEmpty } from 'lodash/fp';\n\nimport { isOperatorOfType, contentTypes, relations, errors } from '@strapi/utils';\nimport type { Data, Modules, UID } from '@strapi/types';\n\nimport { getService } from '../utils';\nimport { validateFindAvailable, validateFindExisting } from './validation/relations';\nimport { isListable } from '../services/utils/configuration/attributes';\nimport { indexByDocumentId } from './utils/document-status';\n\nconst { PUBLISHED_AT_ATTRIBUTE, UPDATED_AT_ATTRIBUTE } = contentTypes.constants;\n\ninterface RelationEntity {\n id: Data.ID;\n documentId: Modules.Documents.ID;\n updatedAt: string | Date;\n publishedAt?: string | Date;\n [key: string]: unknown;\n}\n\nconst addFiltersClause = (params: any, filtersClause: any) => {\n params.filters = params.filters || {};\n params.filters.$and = params.filters.$and || [];\n params.filters.$and.push(filtersClause);\n};\n\nconst sanitizeMainField = (model: any, mainField: any, userAbility: any) => {\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: model.uid,\n });\n\n // Whether the main field can be displayed or not, regardless of permissions.\n const isMainFieldListable = isListable(model, mainField);\n // Whether the user has the permission to access the model's main field (using RBAC abilities)\n const canReadMainField = permissionChecker.can.read(null, mainField);\n\n if (!isMainFieldListable || !canReadMainField) {\n // Default to 'documentId' if the actual main field shouldn't be displayed\n return 'documentId';\n }\n\n // Edge cases\n\n // 1. Enforce 'name' as the main field for users and permissions' roles\n if (model.uid === 'plugin::users-permissions.role') {\n return 'name';\n }\n\n return mainField;\n};\n\n/**\n *\n * All relations sent to this function should have the same status or no status\n */\nconst addStatusToRelations = async (targetUid: UID.Schema, relations: RelationEntity[]) => {\n if (!contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {\n return relations;\n }\n\n const documentMetadata = getService('document-metadata');\n\n if (!relations.length) {\n return relations;\n }\n\n const firstRelation = relations[0];\n\n const filters: any = {\n documentId: { $in: relations.map((r) => r.documentId) },\n // NOTE: find the \"opposite\" status\n publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true },\n };\n\n const availableStatus = await strapi.query(targetUid).findMany({\n select: ['id', 'documentId', 'locale', 'updatedAt', 'createdAt', 'publishedAt'],\n filters,\n });\n\n const statusByDocumentId = indexByDocumentId(availableStatus);\n\n return relations.map((relation: RelationEntity) => {\n const candidates = statusByDocumentId.get(relation.documentId as string) || [];\n const availableStatuses = relation.locale\n ? candidates.filter((c) => c.locale === relation.locale)\n : candidates;\n\n return {\n ...relation,\n status: documentMetadata.getStatus(relation, availableStatuses),\n };\n });\n};\n\nconst getPublishedAtClause = (status: string, uid: UID.Schema) => {\n const model = strapi.getModel(uid);\n\n /**\n * If dp is disabled, ignore the filter\n */\n if (!model || !contentTypes.hasDraftAndPublish(model)) {\n return {};\n }\n\n // Prioritize the draft status in case it's not provided\n return status === 'published' ? { $notNull: true } : { $null: true };\n};\n\nconst validateLocale = (sourceUid: UID.Schema, targetUid: UID.ContentType, locale?: string) => {\n const sourceModel = strapi.getModel(sourceUid);\n const targetModel = strapi.getModel(targetUid);\n\n const isLocalized = strapi.plugin('i18n').service('content-types').isLocalizedContentType;\n const isSourceLocalized = isLocalized(sourceModel);\n const isTargetLocalized = isLocalized(targetModel);\n\n return {\n locale,\n isSourceLocalized,\n isTargetLocalized,\n };\n};\n\nconst validateStatus = (\n sourceUid: UID.Schema,\n status?: Modules.Documents.Params.PublicationStatus.Kind\n) => {\n const sourceModel = strapi.getModel(sourceUid);\n\n const isDP = contentTypes.hasDraftAndPublish;\n const isSourceDP = isDP(sourceModel);\n\n // Default to draft if not set\n if (!isSourceDP && sourceModel.modelType === 'contentType') {\n return { status: undefined };\n }\n\n switch (status) {\n case 'published':\n return { status: 'published' };\n default:\n // Assign to draft if the status is not valid\n return { status: 'draft' };\n }\n};\n\nexport default {\n async extractAndValidateRequestInfo(ctx: any, id?: Data.ID) {\n const { userAbility } = ctx.state;\n const { model, targetField } = ctx.params;\n\n const sourceSchema = strapi.getModel(model);\n if (!sourceSchema) {\n throw new errors.ValidationError(`The model ${model} doesn't exist`);\n }\n\n const attribute: any = sourceSchema.attributes[targetField];\n if (!attribute || attribute.type !== 'relation') {\n throw new errors.ValidationError(\n `The relational field ${targetField} doesn't exist on ${model}`\n );\n }\n\n const sourceUid = model;\n const targetUid = attribute.target;\n\n const { locale, isSourceLocalized, isTargetLocalized } = validateLocale(\n sourceUid,\n targetUid,\n ctx.request?.query?.locale\n );\n const { status } = validateStatus(sourceUid, ctx.request?.query?.status);\n\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model,\n });\n\n const isComponent = sourceSchema.modelType === 'component';\n if (!isComponent) {\n if (permissionChecker.cannot.read(null, targetField)) {\n return ctx.forbidden();\n }\n }\n\n let entryId: string | number | null = null;\n\n if (id) {\n const where: Record<string, any> = {};\n\n if (!isComponent) {\n where.documentId = id;\n\n if (status) {\n where.publishedAt = getPublishedAtClause(status, sourceUid);\n }\n\n if (locale && isSourceLocalized) {\n where.locale = locale;\n }\n } else {\n // If the source is a component, we only need to filter by the\n // component's entity id\n where.id = id;\n }\n\n const permissionQuery = await permissionChecker.sanitizedQuery.read(ctx.query);\n const populate = await getService('populate-builder')(model)\n .populateFromQuery(permissionQuery)\n .build();\n\n const currentEntity = await strapi.db.query(model).findOne({\n where,\n populate,\n });\n\n // We need to check if the entity exists\n // and if the user has the permission to read it in this way\n // There may be multiple entities (publication states) under this\n // documentId + locale. We only need to check if one exists\n if (!currentEntity) {\n throw new errors.NotFoundError();\n }\n\n if (!isComponent) {\n if (permissionChecker.cannot.read(currentEntity, targetField)) {\n throw new errors.ForbiddenError();\n }\n }\n\n entryId = currentEntity.id;\n }\n\n const modelConfig = isComponent\n ? await getService('components').findConfiguration(sourceSchema)\n : await getService('content-types').findConfiguration(sourceSchema);\n\n const targetSchema = strapi.getModel(targetUid);\n\n const mainField = flow(\n prop(`metadatas.${targetField}.edit.mainField`),\n (mainField) => mainField || 'id',\n (mainField) => sanitizeMainField(targetSchema, mainField, userAbility)\n )(modelConfig);\n\n const fieldsToSelect = uniq([\n mainField,\n PUBLISHED_AT_ATTRIBUTE,\n UPDATED_AT_ATTRIBUTE,\n 'documentId',\n ]);\n\n if (isTargetLocalized) {\n fieldsToSelect.push('locale');\n }\n\n return {\n entryId,\n locale,\n status,\n attribute,\n fieldsToSelect,\n mainField,\n source: { schema: sourceSchema, isLocalized: isSourceLocalized },\n target: { schema: targetSchema, isLocalized: isTargetLocalized },\n sourceSchema,\n targetSchema,\n targetField,\n };\n },\n\n /**\n * Used to find new relations to add in a relational field.\n *\n * Component and document relations are dealt a bit differently (they don't have a document_id).\n */\n async findAvailable(ctx: any) {\n const { id } = ctx.request.query;\n\n await validateFindAvailable(ctx.request.query);\n\n const {\n locale,\n status,\n targetField,\n fieldsToSelect,\n mainField,\n source: {\n schema: { uid: sourceUid, modelType: sourceModelType },\n isLocalized: isSourceLocalized,\n },\n target: {\n schema: { uid: targetUid },\n isLocalized: isTargetLocalized,\n },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const {\n idsToOmit,\n idsToInclude,\n // `_q` is the public query parameter name; keep the alias grep-able.\n _q: search,\n ...query\n } = ctx.request.query;\n\n const permissionChecker = getService('permission-checker').create({\n userAbility: ctx.state.userAbility,\n model: targetUid,\n });\n const permissionQuery = await permissionChecker.sanitizedQuery.read(query);\n\n const queryParams = {\n sort: mainField,\n // cannot select other fields as the user may not have the permissions\n fields: fieldsToSelect,\n ...permissionQuery,\n };\n\n // If no status is requested, we find all the draft relations and later update them\n // with the latest available status\n addFiltersClause(queryParams, {\n publishedAt: getPublishedAtClause(status, targetUid),\n });\n\n // We will only filter by locale if the target content type is localized\n const filterByLocale = isTargetLocalized && locale;\n if (filterByLocale) {\n addFiltersClause(queryParams, { locale });\n }\n\n if (id) {\n /**\n * Exclude the relations that are already related to the source\n *\n * We also optionally filter the target relations by the requested\n * status and locale if provided.\n */\n const subQuery = strapi.db.queryBuilder(sourceUid);\n\n // The alias refers to the DB table of the target content type model\n const alias = subQuery.getAlias();\n\n const where: Record<string, any> = {\n [`${alias}.id`]: { $notNull: true },\n [`${alias}.document_id`]: { $notNull: true },\n };\n\n /**\n * Content Types -> Specify document id\n * Components -> Specify entity id (they don't have a document id)\n */\n if (sourceModelType === 'contentType') {\n where.document_id = id;\n } else {\n where.id = id;\n }\n\n // Add the status and locale filters if they are provided\n const publishedAt = getPublishedAtClause(status, targetUid);\n if (!isEmpty(publishedAt)) {\n where[`${alias}.published_at`] = publishedAt;\n }\n\n // If target has localization we need to filter by locale\n if (isTargetLocalized && locale) {\n where[`${alias}.locale`] = locale;\n }\n\n if (isSourceLocalized && locale) {\n where.locale = locale;\n }\n\n /**\n * UI can provide a list of ids to omit,\n * those are the relations user set in the UI but has not persisted.\n * We don't want to include them in the available relations.\n */\n if ((idsToInclude?.length ?? 0) !== 0) {\n where[`${alias}.id`].$notIn = idsToInclude;\n }\n\n const knexSubQuery = subQuery\n .where(where)\n .join({ alias, targetField })\n .select(`${alias}.id`)\n .getKnexQuery();\n\n addFiltersClause(queryParams, {\n id: { $notIn: knexSubQuery },\n });\n }\n\n /**\n * Apply a filter to the mainField based on the search query and filter operator\n * searching should be allowed only on mainField for permission reasons\n */\n if (search) {\n const filter = isOperatorOfType('where', query._filter) ? query._filter : '$containsi';\n addFiltersClause(queryParams, { [mainField]: { [filter]: search } });\n }\n\n if (idsToOmit?.length > 0) {\n // If we have ids to omit, we should filter them out\n addFiltersClause(queryParams, {\n id: { $notIn: uniq(idsToOmit) },\n });\n }\n\n const dbQuery = strapi.get('query-params').transform(targetUid, queryParams);\n\n const res = await strapi.db.query(targetUid).findPage(dbQuery);\n\n ctx.body = {\n ...res,\n results: await addStatusToRelations(targetUid, res.results),\n };\n },\n\n async findExisting(ctx: any) {\n const { userAbility } = ctx.state;\n const { id } = ctx.params;\n\n await validateFindExisting(ctx.request.query);\n\n const {\n entryId,\n attribute,\n targetField,\n fieldsToSelect,\n status,\n source: { schema: sourceSchema },\n target: { schema: targetSchema },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const { uid: sourceUid } = sourceSchema;\n const { uid: targetUid } = targetSchema;\n\n const permissionQuery = await getService('permission-checker')\n .create({ userAbility, model: targetUid })\n .sanitizedQuery.read({ fields: fieldsToSelect });\n\n /**\n * loadPages can not be used for single relations,\n * this unifies the loading regardless of it's type\n *\n * NOTE: Relations need to be loaded using any db.query method\n * to ensure the proper ordering is applied\n */\n const dbQuery = strapi.db.query(sourceUid);\n const loadRelations = relations.isAnyToMany(attribute)\n ? (...args: Parameters<typeof dbQuery.loadPages>) => dbQuery.loadPages(...args)\n : (...args: Parameters<typeof dbQuery.load>) =>\n dbQuery\n .load(...args)\n // Ensure response is an array\n .then((res) => ({ results: res ? [res] : [] }));\n\n const filters: {\n publishedAt?: Record<string, any>;\n } = {};\n\n if (sourceSchema?.options?.draftAndPublish || sourceSchema?.modelType === 'component') {\n if (targetSchema?.options?.draftAndPublish) {\n if (status === 'published') {\n filters.publishedAt = { $notNull: true };\n } else {\n filters.publishedAt = { $null: true };\n }\n }\n } else if (targetSchema?.options?.draftAndPublish) {\n // NOTE: we must return the drafts as some targets might not have a published version yet\n filters.publishedAt = { $null: true };\n }\n\n /**\n * If user does not have access to specific relations (custom conditions),\n * only the ids of the relations are returned.\n *\n * - First query loads all the ids.\n * - Second one also loads the main field, and excludes forbidden relations.\n *\n * The response contains the union of the two queries.\n */\n const res = await loadRelations({ id: entryId }, targetField, {\n select: ['id', 'documentId', 'locale', 'publishedAt', 'updatedAt'],\n ordering: 'desc',\n page: ctx.request.query.page,\n pageSize: ctx.request.query.pageSize,\n filters,\n });\n\n /**\n * Add all ids to load in permissionQuery\n * If any of the relations are not accessible, the permissionQuery will exclude them\n */\n const loadedIds = res.results.map((item: any) => item.id);\n addFiltersClause(permissionQuery, { id: { $in: loadedIds } });\n\n /**\n * Load the relations with the main field, the sanitized permission query\n * will exclude the relations the user does not have access to.\n *\n * Pagination is not necessary as the permissionQuery contains the ids to load.\n */\n const sanitizedRes = await loadRelations({ id: entryId }, targetField, {\n ...strapi.get('query-params').transform(targetUid, permissionQuery),\n ordering: 'desc',\n });\n\n // NOTE: the order is very important to make sure sanitized relations are kept in priority\n const relationsUnion = uniqBy('id', concat(sanitizedRes.results, res.results));\n\n ctx.body = {\n pagination: res.pagination || {\n page: 1,\n pageCount: 1,\n pageSize: 10,\n total: relationsUnion.length,\n },\n results: await addStatusToRelations(targetUid, relationsUnion),\n };\n },\n};\n"],"names":["PUBLISHED_AT_ATTRIBUTE","UPDATED_AT_ATTRIBUTE","contentTypes","constants","addFiltersClause","params","filtersClause","filters","$and","push","sanitizeMainField","model","mainField","userAbility","permissionChecker","getService","create","uid","isMainFieldListable","isListable","canReadMainField","can","read","addStatusToRelations","targetUid","relations","hasDraftAndPublish","strapi","getModel","documentMetadata","length","firstRelation","documentId","$in","map","r","publishedAt","$null","$notNull","availableStatus","query","findMany","select","statusByDocumentId","indexByDocumentId","relation","candidates","get","availableStatuses","locale","filter","c","status","getStatus","getPublishedAtClause","validateLocale","sourceUid","sourceModel","targetModel","isLocalized","plugin","service","isLocalizedContentType","isSourceLocalized","isTargetLocalized","validateStatus","isDP","isSourceDP","modelType","undefined","extractAndValidateRequestInfo","ctx","id","state","targetField","sourceSchema","errors","ValidationError","attribute","attributes","type","target","request","isComponent","cannot","forbidden","entryId","where","permissionQuery","sanitizedQuery","populate","populateFromQuery","build","currentEntity","db","findOne","NotFoundError","ForbiddenError","modelConfig","findConfiguration","targetSchema","flow","prop","fieldsToSelect","uniq","source","schema","findAvailable","validateFindAvailable","sourceModelType","idsToOmit","idsToInclude","_q","search","queryParams","sort","fields","filterByLocale","subQuery","queryBuilder","alias","getAlias","document_id","isEmpty","$notIn","knexSubQuery","join","getKnexQuery","isOperatorOfType","_filter","dbQuery","transform","res","findPage","body","results","findExisting","validateFindExisting","loadRelations","isAnyToMany","args","loadPages","load","then","options","draftAndPublish","ordering","page","pageSize","loadedIds","item","sanitizedRes","relationsUnion","uniqBy","concat","pagination","pageCount","total"],"mappings":"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"}
1
+ {"version":3,"file":"relations.mjs","sources":["../../../server/src/controllers/relations.ts"],"sourcesContent":["import { property, uniqBy, concat, flow, isEmpty } from 'lodash';\n\nimport { isOperatorOfType, contentTypes, relations, errors } from '@strapi/utils';\nimport type { Data, Modules, UID } from '@strapi/types';\n\nimport { getService } from '../utils';\nimport { validateFindAvailable, validateFindExisting } from './validation/relations';\nimport { isListable } from '../services/utils/configuration/attributes';\nimport { indexByDocumentId } from './utils/document-status';\n\nconst { PUBLISHED_AT_ATTRIBUTE, UPDATED_AT_ATTRIBUTE } = contentTypes.constants;\n\ninterface RelationEntity {\n id: Data.ID;\n documentId: Modules.Documents.ID;\n updatedAt: string | Date;\n publishedAt?: string | Date;\n [key: string]: unknown;\n}\n\nconst addFiltersClause = (params: any, filtersClause: any) => {\n params.filters = params.filters || {};\n params.filters.$and = params.filters.$and || [];\n params.filters.$and.push(filtersClause);\n};\n\nconst sanitizeMainField = (model: any, mainField: any, userAbility: any) => {\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: model.uid,\n });\n\n // Whether the main field can be displayed or not, regardless of permissions.\n const isMainFieldListable = isListable(model, mainField);\n // Whether the user has the permission to access the model's main field (using RBAC abilities)\n const canReadMainField = permissionChecker.can.read(null, mainField);\n\n if (!isMainFieldListable || !canReadMainField) {\n // Default to 'documentId' if the actual main field shouldn't be displayed\n return 'documentId';\n }\n\n // Edge cases\n\n // 1. Enforce 'name' as the main field for users and permissions' roles\n if (model.uid === 'plugin::users-permissions.role') {\n return 'name';\n }\n\n return mainField;\n};\n\n/**\n *\n * All relations sent to this function should have the same status or no status\n */\nconst addStatusToRelations = async (targetUid: UID.Schema, relations: RelationEntity[]) => {\n if (!contentTypes.hasDraftAndPublish(strapi.getModel(targetUid))) {\n return relations;\n }\n\n const documentMetadata = getService('document-metadata');\n\n if (!relations.length) {\n return relations;\n }\n\n const firstRelation = relations[0];\n\n const filters: any = {\n documentId: { $in: relations.map((r) => r.documentId) },\n // NOTE: find the \"opposite\" status\n publishedAt: firstRelation.publishedAt !== null ? { $null: true } : { $notNull: true },\n };\n\n const availableStatus = await strapi.query(targetUid).findMany({\n select: ['id', 'documentId', 'locale', 'updatedAt', 'createdAt', 'publishedAt'],\n filters,\n });\n\n const statusByDocumentId = indexByDocumentId(availableStatus);\n\n return relations.map((relation: RelationEntity) => {\n const candidates = statusByDocumentId.get(relation.documentId as string) || [];\n const availableStatuses = relation.locale\n ? candidates.filter((c) => c.locale === relation.locale)\n : candidates;\n\n return {\n ...relation,\n status: documentMetadata.getStatus(relation, availableStatuses),\n };\n });\n};\n\nconst getPublishedAtClause = (status: string, uid: UID.Schema) => {\n const model = strapi.getModel(uid);\n\n /**\n * If dp is disabled, ignore the filter\n */\n if (!model || !contentTypes.hasDraftAndPublish(model)) {\n return {};\n }\n\n // Prioritize the draft status in case it's not provided\n return status === 'published' ? { $notNull: true } : { $null: true };\n};\n\nconst validateLocale = (sourceUid: UID.Schema, targetUid: UID.ContentType, locale?: string) => {\n const sourceModel = strapi.getModel(sourceUid);\n const targetModel = strapi.getModel(targetUid);\n\n // Without a localization provider, neither side is localized\n const isSourceLocalized = strapi.localization.isLocalizedContentType(sourceModel);\n const isTargetLocalized = strapi.localization.isLocalizedContentType(targetModel);\n\n return {\n locale,\n isSourceLocalized,\n isTargetLocalized,\n };\n};\n\nconst validateStatus = (\n sourceUid: UID.Schema,\n status?: Modules.Documents.Params.PublicationStatus.Kind\n) => {\n const sourceModel = strapi.getModel(sourceUid);\n\n const isDP = contentTypes.hasDraftAndPublish;\n const isSourceDP = isDP(sourceModel);\n\n // Default to draft if not set\n if (!isSourceDP && sourceModel.modelType === 'contentType') {\n return { status: undefined };\n }\n\n switch (status) {\n case 'published':\n return { status: 'published' };\n default:\n // Assign to draft if the status is not valid\n return { status: 'draft' };\n }\n};\n\nexport default {\n async extractAndValidateRequestInfo(ctx: any, id?: Data.ID) {\n const { userAbility } = ctx.state;\n const { model, targetField } = ctx.params;\n\n const sourceSchema = strapi.getModel(model);\n if (!sourceSchema) {\n throw new errors.ValidationError(`The model ${model} doesn't exist`);\n }\n\n const attribute: any = sourceSchema.attributes[targetField];\n if (!attribute || attribute.type !== 'relation') {\n throw new errors.ValidationError(\n `The relational field ${targetField} doesn't exist on ${model}`\n );\n }\n\n const sourceUid = model;\n const targetUid = attribute.target;\n\n const { locale, isSourceLocalized, isTargetLocalized } = validateLocale(\n sourceUid,\n targetUid,\n ctx.request?.query?.locale\n );\n const { status } = validateStatus(sourceUid, ctx.request?.query?.status);\n\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model,\n });\n\n const isComponent = sourceSchema.modelType === 'component';\n if (!isComponent) {\n if (permissionChecker.cannot.read(null, targetField)) {\n return ctx.forbidden();\n }\n }\n\n let entryId: string | number | null = null;\n\n if (id) {\n const where: Record<string, any> = {};\n\n if (!isComponent) {\n where.documentId = id;\n\n if (status) {\n where.publishedAt = getPublishedAtClause(status, sourceUid);\n }\n\n if (locale && isSourceLocalized) {\n where.locale = locale;\n }\n } else {\n // If the source is a component, we only need to filter by the\n // component's entity id\n where.id = id;\n }\n\n const permissionQuery = await permissionChecker.sanitizedQuery.read(ctx.query);\n const populate = await getService('populate-builder')(model)\n .populateFromQuery(permissionQuery)\n .build();\n\n const currentEntity = await strapi.db.query(model).findOne({\n where,\n populate,\n });\n\n // We need to check if the entity exists\n // and if the user has the permission to read it in this way\n // There may be multiple entities (publication states) under this\n // documentId + locale. We only need to check if one exists\n if (!currentEntity) {\n throw new errors.NotFoundError();\n }\n\n if (!isComponent) {\n if (permissionChecker.cannot.read(currentEntity, targetField)) {\n throw new errors.ForbiddenError();\n }\n }\n\n entryId = currentEntity.id;\n }\n\n const modelConfig = isComponent\n ? await getService('components').findConfiguration(sourceSchema)\n : await getService('content-types').findConfiguration(sourceSchema);\n\n const targetSchema = strapi.getModel(targetUid);\n\n const mainField = flow(\n property(`metadatas.${targetField}.edit.mainField`),\n (mainField) => mainField || 'id',\n (mainField) => sanitizeMainField(targetSchema, mainField, userAbility)\n )(modelConfig);\n\n const fieldsToSelect = [\n ...new Set([mainField, PUBLISHED_AT_ATTRIBUTE, UPDATED_AT_ATTRIBUTE, 'documentId']),\n ];\n\n if (isTargetLocalized) {\n fieldsToSelect.push('locale');\n }\n\n return {\n entryId,\n locale,\n status,\n attribute,\n fieldsToSelect,\n mainField,\n source: { schema: sourceSchema, isLocalized: isSourceLocalized },\n target: { schema: targetSchema, isLocalized: isTargetLocalized },\n sourceSchema,\n targetSchema,\n targetField,\n };\n },\n\n /**\n * Used to find new relations to add in a relational field.\n *\n * Component and document relations are dealt a bit differently (they don't have a document_id).\n */\n async findAvailable(ctx: any) {\n const { id } = ctx.request.query;\n\n await validateFindAvailable(ctx.request.query);\n\n const {\n locale,\n status,\n targetField,\n fieldsToSelect,\n mainField,\n source: {\n schema: { uid: sourceUid, modelType: sourceModelType },\n isLocalized: isSourceLocalized,\n },\n target: {\n schema: { uid: targetUid },\n isLocalized: isTargetLocalized,\n },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const {\n idsToOmit,\n idsToInclude,\n // `_q` is the public query parameter name; keep the alias grep-able.\n _q: search,\n ...query\n } = ctx.request.query;\n\n const permissionChecker = getService('permission-checker').create({\n userAbility: ctx.state.userAbility,\n model: targetUid,\n });\n const permissionQuery = await permissionChecker.sanitizedQuery.read(query);\n\n const queryParams = {\n sort: mainField,\n // cannot select other fields as the user may not have the permissions\n fields: fieldsToSelect,\n ...permissionQuery,\n };\n\n // If no status is requested, we find all the draft relations and later update them\n // with the latest available status\n addFiltersClause(queryParams, {\n publishedAt: getPublishedAtClause(status, targetUid),\n });\n\n // We will only filter by locale if the target content type is localized\n const filterByLocale = isTargetLocalized && locale;\n if (filterByLocale) {\n addFiltersClause(queryParams, { locale });\n }\n\n if (id) {\n /**\n * Exclude the relations that are already related to the source\n *\n * We also optionally filter the target relations by the requested\n * status and locale if provided.\n */\n const subQuery = strapi.db.queryBuilder(sourceUid);\n\n // The alias refers to the DB table of the target content type model\n const alias = subQuery.getAlias();\n\n const where: Record<string, any> = {\n [`${alias}.id`]: { $notNull: true },\n [`${alias}.document_id`]: { $notNull: true },\n };\n\n /**\n * Content Types -> Specify document id\n * Components -> Specify entity id (they don't have a document id)\n */\n if (sourceModelType === 'contentType') {\n where.document_id = id;\n\n const sourcePublishedAt = getPublishedAtClause(status, sourceUid);\n if (!isEmpty(sourcePublishedAt)) {\n where.published_at = sourcePublishedAt;\n }\n } else {\n where.id = id;\n }\n\n // Add the status and locale filters if they are provided\n const publishedAt = getPublishedAtClause(status, targetUid);\n if (!isEmpty(publishedAt)) {\n where[`${alias}.published_at`] = publishedAt;\n }\n\n // If target has localization we need to filter by locale\n if (isTargetLocalized && locale) {\n where[`${alias}.locale`] = locale;\n }\n\n if (isSourceLocalized && locale) {\n where.locale = locale;\n }\n\n /**\n * UI can provide a list of ids to omit,\n * those are the relations user set in the UI but has not persisted.\n * We don't want to include them in the available relations.\n */\n if ((idsToInclude?.length ?? 0) !== 0) {\n where[`${alias}.id`].$notIn = idsToInclude;\n }\n\n const knexSubQuery = subQuery\n .where(where)\n .join({ alias, targetField })\n .select(`${alias}.id`)\n .getKnexQuery();\n\n addFiltersClause(queryParams, {\n id: { $notIn: knexSubQuery },\n });\n }\n\n /**\n * Apply a filter to the mainField based on the search query and filter operator\n * searching should be allowed only on mainField for permission reasons\n */\n if (search) {\n const filter = isOperatorOfType('where', query._filter) ? query._filter : '$containsi';\n addFiltersClause(queryParams, { [mainField]: { [filter]: search } });\n }\n\n if (idsToOmit?.length > 0) {\n // If we have ids to omit, we should filter them out\n addFiltersClause(queryParams, {\n id: { $notIn: [...new Set(idsToOmit)] },\n });\n }\n\n const dbQuery = strapi.get('query-params').transform(targetUid, queryParams);\n\n const res = await strapi.db.query(targetUid).findPage(dbQuery);\n\n ctx.body = {\n ...res,\n results: await addStatusToRelations(targetUid, res.results),\n };\n },\n\n async findExisting(ctx: any) {\n const { userAbility } = ctx.state;\n const { id } = ctx.params;\n\n await validateFindExisting(ctx.request.query);\n\n const {\n entryId,\n attribute,\n targetField,\n fieldsToSelect,\n status,\n source: { schema: sourceSchema },\n target: { schema: targetSchema },\n } = await this.extractAndValidateRequestInfo(ctx, id);\n\n const { uid: sourceUid } = sourceSchema;\n const { uid: targetUid } = targetSchema;\n\n const permissionQuery = await getService('permission-checker')\n .create({ userAbility, model: targetUid })\n .sanitizedQuery.read({ fields: fieldsToSelect });\n\n /**\n * loadPages can not be used for single relations,\n * this unifies the loading regardless of it's type\n *\n * NOTE: Relations need to be loaded using any db.query method\n * to ensure the proper ordering is applied\n */\n const dbQuery = strapi.db.query(sourceUid);\n const loadRelations = relations.isAnyToMany(attribute)\n ? (...args: Parameters<typeof dbQuery.loadPages>) => dbQuery.loadPages(...args)\n : (...args: Parameters<typeof dbQuery.load>) =>\n dbQuery\n .load(...args)\n // Ensure response is an array\n .then((res) => ({ results: res ? [res] : [] }));\n\n const filters: {\n publishedAt?: Record<string, any>;\n } = {};\n\n if (sourceSchema?.options?.draftAndPublish || sourceSchema?.modelType === 'component') {\n if (targetSchema?.options?.draftAndPublish) {\n if (status === 'published') {\n filters.publishedAt = { $notNull: true };\n } else {\n filters.publishedAt = { $null: true };\n }\n }\n } else if (targetSchema?.options?.draftAndPublish) {\n // NOTE: we must return the drafts as some targets might not have a published version yet\n filters.publishedAt = { $null: true };\n }\n\n /**\n * If user does not have access to specific relations (custom conditions),\n * only the ids of the relations are returned.\n *\n * - First query loads all the ids.\n * - Second one also loads the main field, and excludes forbidden relations.\n *\n * The response contains the union of the two queries.\n */\n const res = await loadRelations({ id: entryId }, targetField, {\n select: ['id', 'documentId', 'locale', 'publishedAt', 'updatedAt'],\n ordering: 'desc',\n page: ctx.request.query.page,\n pageSize: ctx.request.query.pageSize,\n filters,\n });\n\n /**\n * Add all ids to load in permissionQuery\n * If any of the relations are not accessible, the permissionQuery will exclude them\n */\n const loadedIds = res.results.map((item: any) => item.id);\n addFiltersClause(permissionQuery, { id: { $in: loadedIds } });\n\n /**\n * Load the relations with the main field, the sanitized permission query\n * will exclude the relations the user does not have access to.\n *\n * Pagination is not necessary as the permissionQuery contains the ids to load.\n */\n const sanitizedRes = await loadRelations({ id: entryId }, targetField, {\n ...strapi.get('query-params').transform(targetUid, permissionQuery),\n ordering: 'desc',\n });\n\n // NOTE: the order is very important to make sure sanitized relations are kept in priority\n const relationsUnion = uniqBy(concat(sanitizedRes.results, res.results), 'id');\n\n ctx.body = {\n pagination: res.pagination || {\n page: 1,\n pageCount: 1,\n pageSize: 10,\n total: relationsUnion.length,\n },\n results: await addStatusToRelations(targetUid, relationsUnion),\n };\n },\n};\n"],"names":["PUBLISHED_AT_ATTRIBUTE","UPDATED_AT_ATTRIBUTE","contentTypes","constants","addFiltersClause","params","filtersClause","filters","$and","push","sanitizeMainField","model","mainField","userAbility","permissionChecker","getService","create","uid","isMainFieldListable","isListable","canReadMainField","can","read","addStatusToRelations","targetUid","relations","hasDraftAndPublish","strapi","getModel","documentMetadata","length","firstRelation","documentId","$in","map","r","publishedAt","$null","$notNull","availableStatus","query","findMany","select","statusByDocumentId","indexByDocumentId","relation","candidates","get","availableStatuses","locale","filter","c","status","getStatus","getPublishedAtClause","validateLocale","sourceUid","sourceModel","targetModel","isSourceLocalized","localization","isLocalizedContentType","isTargetLocalized","validateStatus","isDP","isSourceDP","modelType","undefined","extractAndValidateRequestInfo","ctx","id","state","targetField","sourceSchema","errors","ValidationError","attribute","attributes","type","target","request","isComponent","cannot","forbidden","entryId","where","permissionQuery","sanitizedQuery","populate","populateFromQuery","build","currentEntity","db","findOne","NotFoundError","ForbiddenError","modelConfig","findConfiguration","targetSchema","flow","property","fieldsToSelect","Set","source","schema","isLocalized","findAvailable","validateFindAvailable","sourceModelType","idsToOmit","idsToInclude","_q","search","queryParams","sort","fields","filterByLocale","subQuery","queryBuilder","alias","getAlias","document_id","sourcePublishedAt","isEmpty","published_at","$notIn","knexSubQuery","join","getKnexQuery","isOperatorOfType","_filter","dbQuery","transform","res","findPage","body","results","findExisting","validateFindExisting","loadRelations","isAnyToMany","args","loadPages","load","then","options","draftAndPublish","ordering","page","pageSize","loadedIds","item","sanitizedRes","relationsUnion","uniqBy","concat","pagination","pageCount","total"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var fp = require('lodash/fp');
4
3
  var strapiUtils = require('@strapi/utils');
5
4
 
6
5
  const { isVisibleAttribute } = strapiUtils.contentTypes;
@@ -111,9 +110,9 @@ const getProhibitedCloningFields = (uid, pathPrefix = [])=>{
111
110
  case 'relation':
112
111
  {
113
112
  if (canCreate(attributePath)) return body;
114
- return fp.set(attributePath, {
113
+ return strapiUtils.objects.set(body, attributePath, {
115
114
  set: []
116
- }, body);
115
+ });
117
116
  }
118
117
  // Go deeper into the component
119
118
  case 'component':
@@ -127,7 +126,7 @@ const getProhibitedCloningFields = (uid, pathPrefix = [])=>{
127
126
  default:
128
127
  {
129
128
  if (canCreate(attributePath)) return body;
130
- return fp.set(attributePath, null, body);
129
+ return strapiUtils.objects.set(body, attributePath, null);
131
130
  }
132
131
  }
133
132
  }, body);
@@ -1 +1 @@
1
- {"version":3,"file":"clone.js","sources":["../../../../server/src/controllers/utils/clone.ts"],"sourcesContent":["import { set } from 'lodash/fp';\nimport { contentTypes } from '@strapi/utils';\nimport { ProhibitedCloningField } from '../../../../shared/contracts/collection-types';\n\nconst { isVisibleAttribute } = contentTypes;\n\n/**\n * Use an array of strings to represent the path to a field, so we can show breadcrumbs in the admin\n * We can't use special characters as delimiters, because the path includes display names\n * for dynamic zone components, which can contain any character.\n */\n\nfunction checkRelation(model: any, attributeName: any, path: string[]): ProhibitedCloningField[] {\n // we don't care about createdBy, updatedBy, localizations etc.\n if (!isVisibleAttribute(model, attributeName)) {\n // Return empty array and not null so we can always spread the result\n return [];\n }\n\n /**\n * Only one-to-many and one-to-one (when they're reversed, not one-way) are dangerous,\n * because the other relations don't \"steal\" the relation from the entry we're cloning\n */\n const { relation, inversedBy, mappedBy } = model.attributes[attributeName];\n\n if (\n ['oneToOne', 'oneToMany'].includes(relation) &&\n [mappedBy, inversedBy].some((key) => key != null)\n ) {\n return [[[...path, attributeName], 'relation']];\n }\n\n return [];\n}\n\nconst getProhibitedCloningFields = (\n uid: any,\n pathPrefix: string[] = []\n): ProhibitedCloningField[] => {\n const model = strapi.getModel(uid);\n\n const prohibitedFields = Object.keys(model.attributes).reduce<ProhibitedCloningField[]>(\n (acc, attributeName) => {\n const attribute: any = model.attributes[attributeName];\n const attributePath = [...pathPrefix, attributeName];\n\n switch (attribute.type) {\n case 'relation':\n return [...acc, ...checkRelation(model, attributeName, pathPrefix)];\n case 'component':\n return [...acc, ...getProhibitedCloningFields(attribute.component, attributePath)];\n case 'dynamiczone':\n return [\n ...acc,\n ...(attribute.components || []).flatMap((componentUID: any) =>\n getProhibitedCloningFields(componentUID, [\n ...attributePath,\n strapi.getModel(componentUID).info.displayName,\n ])\n ),\n ];\n case 'uid':\n return [...acc, [attributePath, 'unique']];\n default:\n if (attribute?.unique) {\n return [...acc, [attributePath, 'unique']];\n }\n return acc;\n }\n },\n []\n );\n\n return prohibitedFields;\n};\n\n/**\n * Iterates all attributes of the content type, and removes the ones that are not creatable.\n * - If it's a relation, it sets the value to [] or null.\n * - If it's a regular attribute, it sets the value to null.\n * When cloning, if you don't set a field it will be copied from the original entry. So we need to\n * remove the fields that the user can't create.\n */\nconst excludeNotCreatableFields =\n (uid: any, permissionChecker: any): ((body: any, path?: any[]) => any) =>\n (body: any, path = []): any => {\n const model = strapi.getModel(uid);\n const canCreate = (path: any) => permissionChecker.can.create(null, path);\n\n return Object.keys(model.attributes).reduce((body, attributeName) => {\n const attribute = model.attributes[attributeName];\n const attributePath = [...path, attributeName].join('.');\n\n // Ignore the attribute if it's not visible\n if (!isVisibleAttribute(model, attributeName)) {\n return body;\n }\n\n switch (attribute.type) {\n // Relation should be empty if the user can't create it\n case 'relation': {\n if (canCreate(attributePath)) return body;\n return set(attributePath, { set: [] }, body);\n }\n // Go deeper into the component\n case 'component': {\n return excludeNotCreatableFields(attribute.component, permissionChecker)(body, [\n ...path,\n attributeName,\n ] as any);\n }\n // Attribute should be null if the user can't create it\n default: {\n if (canCreate(attributePath)) return body;\n return set(attributePath, null, body);\n }\n }\n }, body);\n };\n\nexport { getProhibitedCloningFields, excludeNotCreatableFields };\n"],"names":["isVisibleAttribute","contentTypes","checkRelation","model","attributeName","path","relation","inversedBy","mappedBy","attributes","includes","some","key","getProhibitedCloningFields","uid","pathPrefix","strapi","getModel","prohibitedFields","Object","keys","reduce","acc","attribute","attributePath","type","component","components","flatMap","componentUID","info","displayName","unique","excludeNotCreatableFields","permissionChecker","body","canCreate","can","create","join","set"],"mappings":"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"}
1
+ {"version":3,"file":"clone.js","sources":["../../../../server/src/controllers/utils/clone.ts"],"sourcesContent":["import { objects, contentTypes } from '@strapi/utils';\n\nimport { ProhibitedCloningField } from '../../../../shared/contracts/collection-types';\n\nconst { isVisibleAttribute } = contentTypes;\n\n/**\n * Use an array of strings to represent the path to a field, so we can show breadcrumbs in the admin\n * We can't use special characters as delimiters, because the path includes display names\n * for dynamic zone components, which can contain any character.\n */\n\nfunction checkRelation(model: any, attributeName: any, path: string[]): ProhibitedCloningField[] {\n // we don't care about createdBy, updatedBy, localizations etc.\n if (!isVisibleAttribute(model, attributeName)) {\n // Return empty array and not null so we can always spread the result\n return [];\n }\n\n /**\n * Only one-to-many and one-to-one (when they're reversed, not one-way) are dangerous,\n * because the other relations don't \"steal\" the relation from the entry we're cloning\n */\n const { relation, inversedBy, mappedBy } = model.attributes[attributeName];\n\n if (\n ['oneToOne', 'oneToMany'].includes(relation) &&\n [mappedBy, inversedBy].some((key) => key != null)\n ) {\n return [[[...path, attributeName], 'relation']];\n }\n\n return [];\n}\n\nconst getProhibitedCloningFields = (\n uid: any,\n pathPrefix: string[] = []\n): ProhibitedCloningField[] => {\n const model = strapi.getModel(uid);\n\n const prohibitedFields = Object.keys(model.attributes).reduce<ProhibitedCloningField[]>(\n (acc, attributeName) => {\n const attribute: any = model.attributes[attributeName];\n const attributePath = [...pathPrefix, attributeName];\n\n switch (attribute.type) {\n case 'relation':\n return [...acc, ...checkRelation(model, attributeName, pathPrefix)];\n case 'component':\n return [...acc, ...getProhibitedCloningFields(attribute.component, attributePath)];\n case 'dynamiczone':\n return [\n ...acc,\n ...(attribute.components || []).flatMap((componentUID: any) =>\n getProhibitedCloningFields(componentUID, [\n ...attributePath,\n strapi.getModel(componentUID).info.displayName,\n ])\n ),\n ];\n case 'uid':\n return [...acc, [attributePath, 'unique']];\n default:\n if (attribute?.unique) {\n return [...acc, [attributePath, 'unique']];\n }\n return acc;\n }\n },\n []\n );\n\n return prohibitedFields;\n};\n\n/**\n * Iterates all attributes of the content type, and removes the ones that are not creatable.\n * - If it's a relation, it sets the value to [] or null.\n * - If it's a regular attribute, it sets the value to null.\n * When cloning, if you don't set a field it will be copied from the original entry. So we need to\n * remove the fields that the user can't create.\n */\nconst excludeNotCreatableFields =\n (uid: any, permissionChecker: any): ((body: any, path?: any[]) => any) =>\n (body: any, path = []): any => {\n const model = strapi.getModel(uid);\n const canCreate = (path: any) => permissionChecker.can.create(null, path);\n\n return Object.keys(model.attributes).reduce((body, attributeName) => {\n const attribute = model.attributes[attributeName];\n const attributePath = [...path, attributeName].join('.');\n\n // Ignore the attribute if it's not visible\n if (!isVisibleAttribute(model, attributeName)) {\n return body;\n }\n\n switch (attribute.type) {\n // Relation should be empty if the user can't create it\n case 'relation': {\n if (canCreate(attributePath)) return body;\n return objects.set(body, attributePath, { set: [] });\n }\n // Go deeper into the component\n case 'component': {\n return excludeNotCreatableFields(attribute.component, permissionChecker)(body, [\n ...path,\n attributeName,\n ] as any);\n }\n // Attribute should be null if the user can't create it\n default: {\n if (canCreate(attributePath)) return body;\n return objects.set(body, attributePath, null);\n }\n }\n }, body);\n };\n\nexport { getProhibitedCloningFields, excludeNotCreatableFields };\n"],"names":["isVisibleAttribute","contentTypes","checkRelation","model","attributeName","path","relation","inversedBy","mappedBy","attributes","includes","some","key","getProhibitedCloningFields","uid","pathPrefix","strapi","getModel","prohibitedFields","Object","keys","reduce","acc","attribute","attributePath","type","component","components","flatMap","componentUID","info","displayName","unique","excludeNotCreatableFields","permissionChecker","body","canCreate","can","create","join","objects","set"],"mappings":";;;;AAIA,MAAM,EAAEA,kBAAkB,EAAE,GAAGC,wBAAAA;AAE/B;;;;AAIC,IAED,SAASC,aAAAA,CAAcC,KAAU,EAAEC,aAAkB,EAAEC,IAAc,EAAA;;IAEnE,IAAI,CAACL,kBAAAA,CAAmBG,KAAAA,EAAOC,aAAAA,CAAAA,EAAgB;;AAE7C,QAAA,OAAO,EAAE;AACX,IAAA;AAEA;;;AAGC,MACD,MAAM,EAAEE,QAAQ,EAAEC,UAAU,EAAEC,QAAQ,EAAE,GAAGL,KAAAA,CAAMM,UAAU,CAACL,aAAAA,CAAc;IAE1E,IACE;AAAC,QAAA,UAAA;AAAY,QAAA;KAAY,CAACM,QAAQ,CAACJ,QAAAA,CAAAA,IACnC;AAACE,QAAAA,QAAAA;AAAUD,QAAAA;AAAW,KAAA,CAACI,IAAI,CAAC,CAACC,GAAAA,GAAQA,OAAO,IAAA,CAAA,EAC5C;QACA,OAAO;AAAC,YAAA;AAAC,gBAAA;AAAIP,oBAAAA,GAAAA,IAAAA;AAAMD,oBAAAA;AAAc,iBAAA;AAAE,gBAAA;AAAW;AAAC,SAAA;AACjD,IAAA;AAEA,IAAA,OAAO,EAAE;AACX;AAEA,MAAMS,0BAAAA,GAA6B,CACjCC,GAAAA,EACAC,UAAAA,GAAuB,EAAE,GAAA;IAEzB,MAAMZ,KAAAA,GAAQa,MAAAA,CAAOC,QAAQ,CAACH,GAAAA,CAAAA;IAE9B,MAAMI,gBAAAA,GAAmBC,MAAAA,CAAOC,IAAI,CAACjB,KAAAA,CAAMM,UAAU,CAAA,CAAEY,MAAM,CAC3D,CAACC,GAAAA,EAAKlB,aAAAA,GAAAA;AACJ,QAAA,MAAMmB,SAAAA,GAAiBpB,KAAAA,CAAMM,UAAU,CAACL,aAAAA,CAAc;AACtD,QAAA,MAAMoB,aAAAA,GAAgB;AAAIT,YAAAA,GAAAA,UAAAA;AAAYX,YAAAA;AAAc,SAAA;AAEpD,QAAA,OAAQmB,UAAUE,IAAI;YACpB,KAAK,UAAA;gBACH,OAAO;AAAIH,oBAAAA,GAAAA,GAAAA;AAAQpB,oBAAAA,GAAAA,aAAAA,CAAcC,OAAOC,aAAAA,EAAeW,UAAAA;AAAY,iBAAA;YACrE,KAAK,WAAA;gBACH,OAAO;AAAIO,oBAAAA,GAAAA,GAAAA;uBAAQT,0BAAAA,CAA2BU,SAAAA,CAAUG,SAAS,EAAEF,aAAAA;AAAe,iBAAA;YACpF,KAAK,aAAA;gBACH,OAAO;AACFF,oBAAAA,GAAAA,GAAAA;AACA,oBAAA,GAACC,CAAAA,SAAAA,CAAUI,UAAU,IAAI,EAAC,EAAGC,OAAO,CAAC,CAACC,YAAAA,GACvChB,0BAAAA,CAA2BgB,YAAAA,EAAc;AACpCL,4BAAAA,GAAAA,aAAAA;AACHR,4BAAAA,MAAAA,CAAOC,QAAQ,CAACY,YAAAA,CAAAA,CAAcC,IAAI,CAACC;AACpC,yBAAA,CAAA;AAEJ,iBAAA;YACH,KAAK,KAAA;gBACH,OAAO;AAAIT,oBAAAA,GAAAA,GAAAA;AAAK,oBAAA;AAACE,wBAAAA,aAAAA;AAAe,wBAAA;AAAS;AAAC,iBAAA;AAC5C,YAAA;AACE,gBAAA,IAAID,WAAWS,MAAAA,EAAQ;oBACrB,OAAO;AAAIV,wBAAAA,GAAAA,GAAAA;AAAK,wBAAA;AAACE,4BAAAA,aAAAA;AAAe,4BAAA;AAAS;AAAC,qBAAA;AAC5C,gBAAA;gBACA,OAAOF,GAAAA;AACX;AACF,IAAA,CAAA,EACA,EAAE,CAAA;IAGJ,OAAOJ,gBAAAA;AACT;AAEA;;;;;;IAOA,MAAMe,4BACJ,CAACnB,GAAAA,EAAUoB,oBACX,CAACC,IAAAA,EAAW9B,OAAO,EAAE,GAAA;QACnB,MAAMF,KAAAA,GAAQa,MAAAA,CAAOC,QAAQ,CAACH,GAAAA,CAAAA;QAC9B,MAAMsB,SAAAA,GAAY,CAAC/B,IAAAA,GAAc6B,iBAAAA,CAAkBG,GAAG,CAACC,MAAM,CAAC,IAAA,EAAMjC,IAAAA,CAAAA;QAEpE,OAAOc,MAAAA,CAAOC,IAAI,CAACjB,KAAAA,CAAMM,UAAU,CAAA,CAAEY,MAAM,CAAC,CAACc,IAAAA,EAAM/B,aAAAA,GAAAA;AACjD,YAAA,MAAMmB,SAAAA,GAAYpB,KAAAA,CAAMM,UAAU,CAACL,aAAAA,CAAc;AACjD,YAAA,MAAMoB,aAAAA,GAAgB;AAAInB,gBAAAA,GAAAA,IAAAA;AAAMD,gBAAAA;AAAc,aAAA,CAACmC,IAAI,CAAC,GAAA,CAAA;;YAGpD,IAAI,CAACvC,kBAAAA,CAAmBG,KAAAA,EAAOC,aAAAA,CAAAA,EAAgB;gBAC7C,OAAO+B,IAAAA;AACT,YAAA;AAEA,YAAA,OAAQZ,UAAUE,IAAI;;gBAEpB,KAAK,UAAA;AAAY,oBAAA;wBACf,IAAIW,SAAAA,CAAUZ,gBAAgB,OAAOW,IAAAA;AACrC,wBAAA,OAAOK,mBAAAA,CAAQC,GAAG,CAACN,IAAAA,EAAMX,aAAAA,EAAe;AAAEiB,4BAAAA,GAAAA,EAAK;AAAG,yBAAA,CAAA;AACpD,oBAAA;;gBAEA,KAAK,WAAA;AAAa,oBAAA;AAChB,wBAAA,OAAOR,yBAAAA,CAA0BV,SAAAA,CAAUG,SAAS,EAAEQ,mBAAmBC,IAAAA,EAAM;AAC1E9B,4BAAAA,GAAAA,IAAAA;AACHD,4BAAAA;AACD,yBAAA,CAAA;AACH,oBAAA;;AAEA,gBAAA;AAAS,oBAAA;wBACP,IAAIgC,SAAAA,CAAUZ,gBAAgB,OAAOW,IAAAA;AACrC,wBAAA,OAAOK,mBAAAA,CAAQC,GAAG,CAACN,IAAAA,EAAMX,aAAAA,EAAe,IAAA,CAAA;AAC1C,oBAAA;AACF;QACF,CAAA,EAAGW,IAAAA,CAAAA;AACL,IAAA;;;;;"}
@@ -1,5 +1,4 @@
1
- import { set } from 'lodash/fp';
2
- import { contentTypes } from '@strapi/utils';
1
+ import { contentTypes, objects } from '@strapi/utils';
3
2
 
4
3
  const { isVisibleAttribute } = contentTypes;
5
4
  /**
@@ -109,9 +108,9 @@ const getProhibitedCloningFields = (uid, pathPrefix = [])=>{
109
108
  case 'relation':
110
109
  {
111
110
  if (canCreate(attributePath)) return body;
112
- return set(attributePath, {
111
+ return objects.set(body, attributePath, {
113
112
  set: []
114
- }, body);
113
+ });
115
114
  }
116
115
  // Go deeper into the component
117
116
  case 'component':
@@ -125,7 +124,7 @@ const getProhibitedCloningFields = (uid, pathPrefix = [])=>{
125
124
  default:
126
125
  {
127
126
  if (canCreate(attributePath)) return body;
128
- return set(attributePath, null, body);
127
+ return objects.set(body, attributePath, null);
129
128
  }
130
129
  }
131
130
  }, body);