@strapi/content-manager 5.46.0 → 5.47.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 (197) hide show
  1. package/dist/admin/constants/hooks.js +5 -0
  2. package/dist/admin/constants/hooks.js.map +1 -1
  3. package/dist/admin/constants/hooks.mjs +5 -0
  4. package/dist/admin/constants/hooks.mjs.map +1 -1
  5. package/dist/admin/history/components/VersionInputRenderer.js +64 -26
  6. package/dist/admin/history/components/VersionInputRenderer.js.map +1 -1
  7. package/dist/admin/history/components/VersionInputRenderer.mjs +63 -27
  8. package/dist/admin/history/components/VersionInputRenderer.mjs.map +1 -1
  9. package/dist/admin/pages/ComponentConfigurationPage.js +2 -45
  10. package/dist/admin/pages/ComponentConfigurationPage.js.map +1 -1
  11. package/dist/admin/pages/ComponentConfigurationPage.mjs +3 -46
  12. package/dist/admin/pages/ComponentConfigurationPage.mjs.map +1 -1
  13. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +4 -4
  14. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  15. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +4 -4
  16. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
  17. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js +11 -3
  18. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js.map +1 -1
  19. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs +11 -3
  20. package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs.map +1 -1
  21. package/dist/admin/pages/ListView/ListViewPage.js +1 -0
  22. package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
  23. package/dist/admin/pages/ListView/ListViewPage.mjs +1 -0
  24. package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
  25. package/dist/admin/pages/ListView/components/Filters.js +38 -4
  26. package/dist/admin/pages/ListView/components/Filters.js.map +1 -1
  27. package/dist/admin/pages/ListView/components/Filters.mjs +39 -5
  28. package/dist/admin/pages/ListView/components/Filters.mjs.map +1 -1
  29. package/dist/admin/pages/formatComponentConfigurationEditLayout.js +58 -0
  30. package/dist/admin/pages/formatComponentConfigurationEditLayout.js.map +1 -0
  31. package/dist/admin/pages/formatComponentConfigurationEditLayout.mjs +56 -0
  32. package/dist/admin/pages/formatComponentConfigurationEditLayout.mjs.map +1 -0
  33. package/dist/admin/src/constants/hooks.d.ts +23 -0
  34. package/dist/admin/src/exports.d.ts +1 -0
  35. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +27 -1
  36. package/dist/admin/src/pages/EditView/components/FormInputs/Relations/Relations.d.ts +9 -5
  37. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +4 -2
  38. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +38 -6
  39. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -5
  40. package/dist/admin/src/pages/ListView/components/Filters.d.ts +3 -4
  41. package/dist/admin/src/pages/formatComponentConfigurationEditLayout.d.ts +15 -0
  42. package/dist/admin/translations/cs.json.js +0 -1
  43. package/dist/admin/translations/cs.json.js.map +1 -1
  44. package/dist/admin/translations/cs.json.mjs +0 -1
  45. package/dist/admin/translations/cs.json.mjs.map +1 -1
  46. package/dist/admin/translations/de.json.js +0 -1
  47. package/dist/admin/translations/de.json.js.map +1 -1
  48. package/dist/admin/translations/de.json.mjs +0 -1
  49. package/dist/admin/translations/de.json.mjs.map +1 -1
  50. package/dist/admin/translations/en.json.js +0 -1
  51. package/dist/admin/translations/en.json.js.map +1 -1
  52. package/dist/admin/translations/en.json.mjs +0 -1
  53. package/dist/admin/translations/en.json.mjs.map +1 -1
  54. package/dist/admin/translations/es.json.js +0 -1
  55. package/dist/admin/translations/es.json.js.map +1 -1
  56. package/dist/admin/translations/es.json.mjs +0 -1
  57. package/dist/admin/translations/es.json.mjs.map +1 -1
  58. package/dist/admin/translations/fr.json.js +0 -1
  59. package/dist/admin/translations/fr.json.js.map +1 -1
  60. package/dist/admin/translations/fr.json.mjs +0 -1
  61. package/dist/admin/translations/fr.json.mjs.map +1 -1
  62. package/dist/admin/translations/nl.json.js +0 -1
  63. package/dist/admin/translations/nl.json.js.map +1 -1
  64. package/dist/admin/translations/nl.json.mjs +0 -1
  65. package/dist/admin/translations/nl.json.mjs.map +1 -1
  66. package/dist/admin/translations/pl.json.js +0 -1
  67. package/dist/admin/translations/pl.json.js.map +1 -1
  68. package/dist/admin/translations/pl.json.mjs +0 -1
  69. package/dist/admin/translations/pl.json.mjs.map +1 -1
  70. package/dist/admin/translations/ru.json.js +0 -1
  71. package/dist/admin/translations/ru.json.js.map +1 -1
  72. package/dist/admin/translations/ru.json.mjs +0 -1
  73. package/dist/admin/translations/ru.json.mjs.map +1 -1
  74. package/dist/admin/translations/sk.json.js +175 -9
  75. package/dist/admin/translations/sk.json.js.map +1 -1
  76. package/dist/admin/translations/sk.json.mjs +175 -9
  77. package/dist/admin/translations/sk.json.mjs.map +1 -1
  78. package/dist/admin/translations/uk.json.js +0 -1
  79. package/dist/admin/translations/uk.json.js.map +1 -1
  80. package/dist/admin/translations/uk.json.mjs +0 -1
  81. package/dist/admin/translations/uk.json.mjs.map +1 -1
  82. package/dist/admin/translations/zh-Hans.json.js +0 -1
  83. package/dist/admin/translations/zh-Hans.json.js.map +1 -1
  84. package/dist/admin/translations/zh-Hans.json.mjs +0 -1
  85. package/dist/admin/translations/zh-Hans.json.mjs.map +1 -1
  86. package/dist/server/bootstrap.js +4 -0
  87. package/dist/server/bootstrap.js.map +1 -1
  88. package/dist/server/bootstrap.mjs +4 -0
  89. package/dist/server/bootstrap.mjs.map +1 -1
  90. package/dist/server/controllers/collection-types.js +9 -5
  91. package/dist/server/controllers/collection-types.js.map +1 -1
  92. package/dist/server/controllers/collection-types.mjs +10 -6
  93. package/dist/server/controllers/collection-types.mjs.map +1 -1
  94. package/dist/server/mcp/derive-content-type-mcp-tools.js +524 -0
  95. package/dist/server/mcp/derive-content-type-mcp-tools.js.map +1 -0
  96. package/dist/server/mcp/derive-content-type-mcp-tools.mjs +518 -0
  97. package/dist/server/mcp/derive-content-type-mcp-tools.mjs.map +1 -0
  98. package/dist/server/mcp/handlers/collection-handlers.js +404 -0
  99. package/dist/server/mcp/handlers/collection-handlers.js.map +1 -0
  100. package/dist/server/mcp/handlers/collection-handlers.mjs +395 -0
  101. package/dist/server/mcp/handlers/collection-handlers.mjs.map +1 -0
  102. package/dist/server/mcp/handlers/constants.js +10 -0
  103. package/dist/server/mcp/handlers/constants.js.map +1 -0
  104. package/dist/server/mcp/handlers/constants.mjs +6 -0
  105. package/dist/server/mcp/handlers/constants.mjs.map +1 -0
  106. package/dist/server/mcp/handlers/single-type-handlers.js +344 -0
  107. package/dist/server/mcp/handlers/single-type-handlers.js.map +1 -0
  108. package/dist/server/mcp/handlers/single-type-handlers.mjs +336 -0
  109. package/dist/server/mcp/handlers/single-type-handlers.mjs.map +1 -0
  110. package/dist/server/mcp/permissions.js +138 -0
  111. package/dist/server/mcp/permissions.js.map +1 -0
  112. package/dist/server/mcp/permissions.mjs +131 -0
  113. package/dist/server/mcp/permissions.mjs.map +1 -0
  114. package/dist/server/mcp/register-content-manager-mcp-tools.js +30 -0
  115. package/dist/server/mcp/register-content-manager-mcp-tools.js.map +1 -0
  116. package/dist/server/mcp/register-content-manager-mcp-tools.mjs +28 -0
  117. package/dist/server/mcp/register-content-manager-mcp-tools.mjs.map +1 -0
  118. package/dist/server/mcp/schemas/blocks-schema.js +124 -0
  119. package/dist/server/mcp/schemas/blocks-schema.js.map +1 -0
  120. package/dist/server/mcp/schemas/blocks-schema.mjs +122 -0
  121. package/dist/server/mcp/schemas/blocks-schema.mjs.map +1 -0
  122. package/dist/server/mcp/schemas/data-schema.js +252 -0
  123. package/dist/server/mcp/schemas/data-schema.js.map +1 -0
  124. package/dist/server/mcp/schemas/data-schema.mjs +248 -0
  125. package/dist/server/mcp/schemas/data-schema.mjs.map +1 -0
  126. package/dist/server/mcp/schemas/filters-schema.js +111 -0
  127. package/dist/server/mcp/schemas/filters-schema.js.map +1 -0
  128. package/dist/server/mcp/schemas/filters-schema.mjs +107 -0
  129. package/dist/server/mcp/schemas/filters-schema.mjs.map +1 -0
  130. package/dist/server/mcp/schemas/input-schemas.js +18 -0
  131. package/dist/server/mcp/schemas/input-schemas.js.map +1 -0
  132. package/dist/server/mcp/schemas/input-schemas.mjs +13 -0
  133. package/dist/server/mcp/schemas/input-schemas.mjs.map +1 -0
  134. package/dist/server/mcp/schemas/output-schemas.js +48 -0
  135. package/dist/server/mcp/schemas/output-schemas.js.map +1 -0
  136. package/dist/server/mcp/schemas/output-schemas.mjs +44 -0
  137. package/dist/server/mcp/schemas/output-schemas.mjs.map +1 -0
  138. package/dist/server/mcp/schemas/sort-schema.js +80 -0
  139. package/dist/server/mcp/schemas/sort-schema.js.map +1 -0
  140. package/dist/server/mcp/schemas/sort-schema.mjs +76 -0
  141. package/dist/server/mcp/schemas/sort-schema.mjs.map +1 -0
  142. package/dist/server/mcp/utils.js +43 -0
  143. package/dist/server/mcp/utils.js.map +1 -0
  144. package/dist/server/mcp/utils.mjs +39 -0
  145. package/dist/server/mcp/utils.mjs.map +1 -0
  146. package/dist/server/services/index.js +1 -1
  147. package/dist/server/services/index.js.map +1 -1
  148. package/dist/server/services/permission-checker.js +4 -1
  149. package/dist/server/services/permission-checker.js.map +1 -1
  150. package/dist/server/services/permission-checker.mjs +1 -1
  151. package/dist/server/services/permission-checker.mjs.map +1 -1
  152. package/dist/server/services/utils/populate.js +3 -3
  153. package/dist/server/services/utils/populate.js.map +1 -1
  154. package/dist/server/services/utils/populate.mjs +3 -3
  155. package/dist/server/services/utils/populate.mjs.map +1 -1
  156. package/dist/server/src/bootstrap.d.ts.map +1 -1
  157. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  158. package/dist/server/src/index.d.ts +3 -3
  159. package/dist/server/src/mcp/derive-content-type-mcp-tools.d.ts +12 -0
  160. package/dist/server/src/mcp/derive-content-type-mcp-tools.d.ts.map +1 -0
  161. package/dist/server/src/mcp/handlers/collection-handlers.d.ts +69 -0
  162. package/dist/server/src/mcp/handlers/collection-handlers.d.ts.map +1 -0
  163. package/dist/server/src/mcp/handlers/constants.d.ts +4 -0
  164. package/dist/server/src/mcp/handlers/constants.d.ts.map +1 -0
  165. package/dist/server/src/mcp/handlers/index.d.ts +3 -0
  166. package/dist/server/src/mcp/handlers/index.d.ts.map +1 -0
  167. package/dist/server/src/mcp/handlers/single-type-handlers.d.ts +66 -0
  168. package/dist/server/src/mcp/handlers/single-type-handlers.d.ts.map +1 -0
  169. package/dist/server/src/mcp/permissions.d.ts +49 -0
  170. package/dist/server/src/mcp/permissions.d.ts.map +1 -0
  171. package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts +8 -0
  172. package/dist/server/src/mcp/register-content-manager-mcp-tools.d.ts.map +1 -0
  173. package/dist/server/src/mcp/schemas/blocks-schema.d.ts +8 -0
  174. package/dist/server/src/mcp/schemas/blocks-schema.d.ts.map +1 -0
  175. package/dist/server/src/mcp/schemas/data-schema.d.ts +36 -0
  176. package/dist/server/src/mcp/schemas/data-schema.d.ts.map +1 -0
  177. package/dist/server/src/mcp/schemas/filters-schema.d.ts +22 -0
  178. package/dist/server/src/mcp/schemas/filters-schema.d.ts.map +1 -0
  179. package/dist/server/src/mcp/schemas/index.d.ts +7 -0
  180. package/dist/server/src/mcp/schemas/index.d.ts.map +1 -0
  181. package/dist/server/src/mcp/schemas/input-schemas.d.ts +10 -0
  182. package/dist/server/src/mcp/schemas/input-schemas.d.ts.map +1 -0
  183. package/dist/server/src/mcp/schemas/output-schemas.d.ts +18 -0
  184. package/dist/server/src/mcp/schemas/output-schemas.d.ts.map +1 -0
  185. package/dist/server/src/mcp/schemas/sort-schema.d.ts +24 -0
  186. package/dist/server/src/mcp/schemas/sort-schema.d.ts.map +1 -0
  187. package/dist/server/src/mcp/types.d.ts +31 -0
  188. package/dist/server/src/mcp/types.d.ts.map +1 -0
  189. package/dist/server/src/mcp/utils.d.ts +21 -0
  190. package/dist/server/src/mcp/utils.d.ts.map +1 -0
  191. package/dist/server/src/services/index.d.ts +3 -3
  192. package/dist/server/src/services/permission-checker.d.ts +13 -3
  193. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  194. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  195. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  196. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  197. package/package.json +10 -8
@@ -0,0 +1,336 @@
1
+ import { errors, async, setCreatorFields } from '@strapi/utils';
2
+ import { getService } from '../../utils/index.mjs';
3
+ import { getDocumentLocaleAndStatus } from '../../controllers/validation/dimensions.mjs';
4
+ import { formatDocumentWithMetadata } from '../../controllers/utils/metadata.mjs';
5
+ import { getPopulateForLocalizations } from '../../services/utils/populate.mjs';
6
+ import { MCP_NOT_FOUND_DOCUMENT } from './constants.mjs';
7
+ import { isContentTypeLocalized } from '../permissions.mjs';
8
+ import { ok } from '../utils.mjs';
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Shared create-or-update logic mirroring single-types controller
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Core write logic shared by the single-type write handler.
15
+ * Creates the document when none exists; updates the existing draft otherwise.
16
+ * Enforces RBAC create/update permission and sanitizes input + output.
17
+ */ const singleCreateOrUpdate = async (strapi, uid, context, args)=>{
18
+ const { userAbility, user } = context;
19
+ const { data, locale } = args;
20
+ // TODO: fix UID.SingleType assignability in @strapi/types
21
+ const typedUid = uid;
22
+ const documentManager = getService('document-manager');
23
+ const permissionChecker = getService('permission-checker').create({
24
+ userAbility,
25
+ model: uid
26
+ });
27
+ if (permissionChecker.cannot.create() && permissionChecker.cannot.update()) {
28
+ throw new errors.ForbiddenError();
29
+ }
30
+ const sanitizedQuery = await permissionChecker.sanitizedQuery.update({
31
+ locale
32
+ });
33
+ const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({
34
+ locale
35
+ }, uid);
36
+ const populate = await getService('populate-builder')(typedUid).populateFromQuery(sanitizedQuery).populateDeep(Infinity).countRelations().withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
37
+ const draftFindQuery = {
38
+ ...sanitizedQuery,
39
+ populate,
40
+ locale: resolvedLocale,
41
+ status: 'draft'
42
+ };
43
+ const [documentVersion, otherDocumentVersion] = await Promise.all([
44
+ documentManager.findMany(draftFindQuery, typedUid).then((docs)=>docs[0]),
45
+ strapi.db.query(typedUid).findOne({
46
+ select: [
47
+ 'documentId'
48
+ ]
49
+ })
50
+ ]);
51
+ const documentId = otherDocumentVersion?.documentId;
52
+ if (documentVersion) {
53
+ if (permissionChecker.cannot.update(documentVersion)) {
54
+ throw new errors.ForbiddenError();
55
+ }
56
+ } else if (permissionChecker.cannot.create()) {
57
+ throw new errors.ForbiddenError();
58
+ }
59
+ const sanitizeInput = documentVersion ? permissionChecker.sanitizeUpdateInput(documentVersion) : permissionChecker.sanitizeCreateInput;
60
+ const isEdition = documentVersion !== null && documentVersion !== undefined;
61
+ const sanitizedData = setCreatorFields({
62
+ user,
63
+ isEdition
64
+ })(await sanitizeInput(data));
65
+ const formatted = await strapi.db.transaction(async ()=>{
66
+ let doc;
67
+ if (documentId === undefined) {
68
+ doc = await documentManager.create(typedUid, {
69
+ data: sanitizedData,
70
+ ...sanitizedQuery,
71
+ locale: resolvedLocale
72
+ });
73
+ } else {
74
+ doc = await documentManager.update(documentId, typedUid, {
75
+ data: sanitizedData,
76
+ populate,
77
+ locale: resolvedLocale
78
+ });
79
+ }
80
+ const sanitizedDocument = await permissionChecker.sanitizeOutput(doc);
81
+ return formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);
82
+ });
83
+ return ok(formatted);
84
+ };
85
+ // ---------------------------------------------------------------------------
86
+ // Handler factories
87
+ // ---------------------------------------------------------------------------
88
+ /**
89
+ * Creates a handler for reading the single-type document.
90
+ * Returns available locale metadata when the requested locale version does not exist.
91
+ * Enforces RBAC read permission.
92
+ */ const createSingleGetHandler = (uid)=>(strapi, context)=>async ({ args })=>{
93
+ const { userAbility } = context;
94
+ const { locale, status } = args;
95
+ // TODO: fix UID.SingleType assignability in @strapi/types
96
+ const typedUid = uid;
97
+ const permissionChecker = getService('permission-checker').create({
98
+ userAbility,
99
+ model: uid
100
+ });
101
+ if (permissionChecker.cannot.read()) {
102
+ throw new errors.ForbiddenError();
103
+ }
104
+ const permissionQuery = await permissionChecker.sanitizedQuery.read({
105
+ locale,
106
+ status
107
+ });
108
+ const { locale: resolvedLocale, status: resolvedStatus } = await getDocumentLocaleAndStatus({
109
+ locale,
110
+ status
111
+ }, uid);
112
+ const populate = await getService('populate-builder')(typedUid).populateFromQuery(permissionQuery).populateDeep(Infinity).countRelations().withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
113
+ const versionFindQuery = {
114
+ ...permissionQuery,
115
+ populate,
116
+ locale: resolvedLocale,
117
+ status: resolvedStatus
118
+ };
119
+ const version = await getService('document-manager').findMany(versionFindQuery, typedUid).then((docs)=>docs[0]);
120
+ if (!version) {
121
+ if (permissionChecker.cannot.create()) {
122
+ throw new errors.ForbiddenError();
123
+ }
124
+ const document = await strapi.db.query(typedUid).findOne({});
125
+ if (!document) {
126
+ throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);
127
+ }
128
+ const { meta } = await formatDocumentWithMetadata(permissionChecker, typedUid, {
129
+ documentId: document.documentId,
130
+ locale: resolvedLocale,
131
+ publishedAt: null
132
+ }, {
133
+ availableLocales: true,
134
+ availableStatus: false
135
+ });
136
+ return ok({
137
+ data: {},
138
+ meta
139
+ });
140
+ }
141
+ if (permissionChecker.cannot.read(version)) {
142
+ throw new errors.ForbiddenError();
143
+ }
144
+ const sanitizedDocument = await permissionChecker.sanitizeOutput(version);
145
+ const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);
146
+ return ok(result);
147
+ };
148
+ /**
149
+ * Creates a handler for creating or updating the single-type document.
150
+ * Delegates to `singleCreateOrUpdate`; enforces RBAC create/update permission.
151
+ */ const createSingleWriteHandler = (uid)=>(strapi, context)=>async ({ args })=>{
152
+ return singleCreateOrUpdate(strapi, uid, context, args);
153
+ };
154
+ /**
155
+ * Creates a handler for deleting the single-type document (or a specific locale).
156
+ * Enforces RBAC delete permission on every locale version before deletion.
157
+ */ const createSingleDeleteHandler = (uid)=>(strapi, context)=>async ({ args })=>{
158
+ const { userAbility } = context;
159
+ const { locale } = args;
160
+ // TODO: fix UID.SingleType assignability in @strapi/types
161
+ const typedUid = uid;
162
+ const documentManager = getService('document-manager');
163
+ const permissionChecker = getService('permission-checker').create({
164
+ userAbility,
165
+ model: uid
166
+ });
167
+ if (permissionChecker.cannot.delete()) {
168
+ throw new errors.ForbiddenError();
169
+ }
170
+ const sanitizedQuery = await permissionChecker.sanitizedQuery.delete({
171
+ locale
172
+ });
173
+ const populate = await getService('populate-builder')(typedUid).populateFromQuery(sanitizedQuery).populateDeep(Infinity).countRelations().withPopulateOverride(getPopulateForLocalizations(typedUid)).build();
174
+ const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({
175
+ locale
176
+ }, uid);
177
+ const isLocalized = isContentTypeLocalized(strapi, uid);
178
+ const localeForQuery = isLocalized === true ? resolvedLocale : undefined;
179
+ const documentLocales = await documentManager.findLocales(undefined, typedUid, {
180
+ populate,
181
+ locale: localeForQuery
182
+ });
183
+ if (documentLocales.length === 0) {
184
+ throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);
185
+ }
186
+ for (const document of documentLocales){
187
+ if (permissionChecker.cannot.delete(document)) {
188
+ throw new errors.ForbiddenError();
189
+ }
190
+ }
191
+ const deletedEntity = await documentManager.delete(documentLocales[0].documentId, typedUid, {
192
+ locale: localeForQuery
193
+ });
194
+ const sanitizedResult = await permissionChecker.sanitizeOutput(deletedEntity);
195
+ return ok({
196
+ data: sanitizedResult
197
+ });
198
+ };
199
+ /**
200
+ * Creates a handler for publishing the single-type document draft.
201
+ * Enforces RBAC publish permission; throws NotFound when the draft is missing.
202
+ */ const createSinglePublishHandler = (uid)=>(strapi, context)=>async ({ args })=>{
203
+ const { userAbility } = context;
204
+ const { locale } = args;
205
+ // TODO: fix UID.SingleType assignability in @strapi/types
206
+ const typedUid = uid;
207
+ const documentManager = getService('document-manager');
208
+ const permissionChecker = getService('permission-checker').create({
209
+ userAbility,
210
+ model: uid
211
+ });
212
+ if (permissionChecker.cannot.publish()) {
213
+ throw new errors.ForbiddenError();
214
+ }
215
+ const publishedDocument = await strapi.db.transaction(async ()=>{
216
+ const sanitizedQuery = await permissionChecker.sanitizedQuery.publish({
217
+ locale
218
+ });
219
+ const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({
220
+ locale
221
+ }, uid);
222
+ const publishFindQuery = {
223
+ ...sanitizedQuery,
224
+ locale: resolvedLocale,
225
+ status: 'draft'
226
+ };
227
+ const document = await getService('document-manager').findMany(publishFindQuery, typedUid).then((docs)=>docs[0]);
228
+ if (!document) {
229
+ throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);
230
+ }
231
+ if (permissionChecker.cannot.publish(document)) {
232
+ throw new errors.ForbiddenError();
233
+ }
234
+ const publishResult = await documentManager.publish(document.documentId, typedUid, {
235
+ locale: resolvedLocale
236
+ });
237
+ return publishResult?.at(0);
238
+ });
239
+ const sanitizedDocument = await permissionChecker.sanitizeOutput(publishedDocument);
240
+ const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);
241
+ return ok(result);
242
+ };
243
+ /**
244
+ * Creates a handler for unpublishing the single-type document.
245
+ * Optionally discards the draft in the same transaction when `discardDraft` is true.
246
+ * Enforces RBAC unpublish (and discard) permission.
247
+ */ const createSingleUnpublishHandler = (uid)=>(strapi, context)=>async ({ args })=>{
248
+ const { userAbility } = context;
249
+ const { locale, discardDraft } = args;
250
+ // TODO: fix UID.SingleType assignability in @strapi/types
251
+ const typedUid = uid;
252
+ const documentManager = getService('document-manager');
253
+ const permissionChecker = getService('permission-checker').create({
254
+ userAbility,
255
+ model: uid
256
+ });
257
+ if (permissionChecker.cannot.unpublish()) {
258
+ throw new errors.ForbiddenError();
259
+ }
260
+ if (discardDraft === true && permissionChecker.cannot.discard()) {
261
+ throw new errors.ForbiddenError();
262
+ }
263
+ const sanitizedQuery = await permissionChecker.sanitizedQuery.unpublish({
264
+ locale
265
+ });
266
+ const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({
267
+ locale
268
+ }, uid);
269
+ const unpublishFindQuery = {
270
+ ...sanitizedQuery,
271
+ locale: resolvedLocale
272
+ };
273
+ const document = await getService('document-manager').findMany(unpublishFindQuery, typedUid).then((docs)=>docs[0]);
274
+ if (!document) {
275
+ throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);
276
+ }
277
+ if (permissionChecker.cannot.unpublish(document)) {
278
+ throw new errors.ForbiddenError();
279
+ }
280
+ if (discardDraft === true && permissionChecker.cannot.discard(document)) {
281
+ throw new errors.ForbiddenError();
282
+ }
283
+ const result = await strapi.db.transaction(async ()=>{
284
+ if (discardDraft === true) {
285
+ await documentManager.discardDraft(document.documentId, typedUid, {
286
+ locale: resolvedLocale
287
+ });
288
+ }
289
+ return async.pipe((doc)=>documentManager.unpublish(doc.documentId, typedUid, {
290
+ locale: resolvedLocale
291
+ }), permissionChecker.sanitizeOutput, (doc)=>formatDocumentWithMetadata(permissionChecker, typedUid, doc))(document);
292
+ });
293
+ return ok(result);
294
+ };
295
+ /**
296
+ * Creates a handler for discarding the draft of the single-type document.
297
+ * Restores the published version as the draft. Enforces RBAC discard permission.
298
+ */ const createSingleDiscardDraftHandler = (uid)=>(_strapi, context)=>async ({ args })=>{
299
+ const { userAbility } = context;
300
+ const { locale } = args;
301
+ // TODO: fix UID.SingleType assignability in @strapi/types
302
+ const typedUid = uid;
303
+ const documentManager = getService('document-manager');
304
+ const permissionChecker = getService('permission-checker').create({
305
+ userAbility,
306
+ model: uid
307
+ });
308
+ if (permissionChecker.cannot.discard()) {
309
+ throw new errors.ForbiddenError();
310
+ }
311
+ const sanitizedQuery = await permissionChecker.sanitizedQuery.discard({
312
+ locale
313
+ });
314
+ const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({
315
+ locale
316
+ }, uid);
317
+ const discardFindQuery = {
318
+ ...sanitizedQuery,
319
+ locale: resolvedLocale,
320
+ status: 'published'
321
+ };
322
+ const document = await getService('document-manager').findMany(discardFindQuery, typedUid).then((docs)=>docs[0]);
323
+ if (!document) {
324
+ throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);
325
+ }
326
+ if (permissionChecker.cannot.discard(document)) {
327
+ throw new errors.ForbiddenError();
328
+ }
329
+ const discardedDocument = await async.pipe((doc)=>documentManager.discardDraft(doc.documentId, typedUid, {
330
+ locale: resolvedLocale
331
+ }), permissionChecker.sanitizeOutput, (doc)=>formatDocumentWithMetadata(permissionChecker, typedUid, doc))(document);
332
+ return ok(discardedDocument);
333
+ };
334
+
335
+ export { createSingleDeleteHandler, createSingleDiscardDraftHandler, createSingleGetHandler, createSinglePublishHandler, createSingleUnpublishHandler, createSingleWriteHandler, singleCreateOrUpdate };
336
+ //# sourceMappingURL=single-type-handlers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-type-handlers.mjs","sources":["../../../../server/src/mcp/handlers/single-type-handlers.ts"],"sourcesContent":["import { errors, async as asyncPipe, setCreatorFields } from '@strapi/utils';\nimport type { Core, Modules, UID } from '@strapi/types';\n\nimport { getService } from '../../utils';\nimport { getDocumentLocaleAndStatus } from '../../controllers/validation/dimensions';\nimport { formatDocumentWithMetadata } from '../../controllers/utils/metadata';\nimport { getPopulateForLocalizations } from '../../services/utils/populate';\nimport { MCP_NOT_FOUND_DOCUMENT } from './constants';\nimport { isContentTypeLocalized } from '../permissions';\nimport { ok } from '../utils';\n\ntype McpDocumentQuery = {\n populate?: unknown;\n locale?: string;\n status?: string;\n filters?: unknown;\n sort?: unknown;\n pagination?: unknown;\n [key: string]: unknown;\n};\n\ntype McpFindManyParams = Parameters<Modules.Documents.ServiceInstance['findMany']>[0];\n\n// ---------------------------------------------------------------------------\n// Input arg schemas — used for type-safe narrowing from Record<string, unknown>\n// ---------------------------------------------------------------------------\n\ntype SingleLocaleArgs = { locale?: string };\ntype SingleGetArgs = SingleLocaleArgs & { status?: 'draft' | 'published' };\ntype SingleUnpublishArgs = SingleLocaleArgs & { discardDraft?: boolean };\ntype SingleWriteArgs = { data: Record<string, unknown>; locale?: string };\n\n// ---------------------------------------------------------------------------\n// Shared create-or-update logic mirroring single-types controller\n// ---------------------------------------------------------------------------\n\n/**\n * Core write logic shared by the single-type write handler.\n * Creates the document when none exists; updates the existing draft otherwise.\n * Enforces RBAC create/update permission and sanitizes input + output.\n */\nexport const singleCreateOrUpdate = async (\n strapi: Core.Strapi,\n uid: UID.SingleType,\n context: Modules.MCP.McpHandlerContext,\n args: SingleWriteArgs\n): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility, user } = context;\n const { data, locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.create() && permissionChecker.cannot.update()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.update({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(sanitizedQuery)\n .populateDeep(Infinity)\n .countRelations()\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const draftFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n populate,\n locale: resolvedLocale,\n status: 'draft',\n };\n const [documentVersion, otherDocumentVersion] = await Promise.all([\n documentManager\n .findMany(draftFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]),\n strapi.db.query(typedUid).findOne({ select: ['documentId'] }),\n ]);\n\n const documentId = otherDocumentVersion?.documentId;\n\n if (documentVersion) {\n if (permissionChecker.cannot.update(documentVersion)) {\n throw new errors.ForbiddenError();\n }\n } else if (permissionChecker.cannot.create()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizeInput = documentVersion\n ? permissionChecker.sanitizeUpdateInput(documentVersion)\n : permissionChecker.sanitizeCreateInput;\n\n const isEdition = documentVersion !== null && documentVersion !== undefined;\n const sanitizedData = setCreatorFields({ user, isEdition })(await sanitizeInput(data)) as Record<\n string,\n unknown\n >;\n\n const formatted = await strapi.db.transaction(async () => {\n let doc: any;\n\n if (documentId === undefined) {\n doc = await documentManager.create(typedUid, {\n data: sanitizedData,\n ...sanitizedQuery,\n locale: resolvedLocale,\n });\n } else {\n doc = await documentManager.update(documentId, typedUid, {\n data: sanitizedData,\n populate,\n locale: resolvedLocale,\n });\n }\n\n const sanitizedDocument = await permissionChecker.sanitizeOutput(doc);\n return formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);\n });\n\n return ok(formatted as Record<string, unknown>);\n};\n\n// ---------------------------------------------------------------------------\n// Handler factories\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a handler for reading the single-type document.\n * Returns available locale metadata when the requested locale version does not exist.\n * Enforces RBAC read permission.\n */\nexport const createSingleGetHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleGetArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale, status } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.read()) {\n throw new errors.ForbiddenError();\n }\n\n const permissionQuery = await permissionChecker.sanitizedQuery.read({ locale, status });\n const { locale: resolvedLocale, status: resolvedStatus } = await getDocumentLocaleAndStatus(\n { locale, status },\n uid\n );\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(permissionQuery)\n .populateDeep(Infinity)\n .countRelations()\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const versionFindQuery: McpDocumentQuery = {\n ...permissionQuery,\n populate,\n locale: resolvedLocale,\n status: resolvedStatus,\n };\n const version = await getService('document-manager')\n .findMany(versionFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!version) {\n if (permissionChecker.cannot.create()) {\n throw new errors.ForbiddenError();\n }\n\n const document = await strapi.db.query(typedUid).findOne({});\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n const { meta } = await formatDocumentWithMetadata(\n permissionChecker,\n typedUid,\n {\n documentId: document.documentId,\n locale: resolvedLocale,\n publishedAt: null,\n } as Parameters<typeof formatDocumentWithMetadata>[2],\n { availableLocales: true, availableStatus: false }\n );\n\n return ok({ data: {}, meta } as Record<string, unknown>);\n }\n\n if (permissionChecker.cannot.read(version)) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedDocument = await permissionChecker.sanitizeOutput(version);\n const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for creating or updating the single-type document.\n * Delegates to `singleCreateOrUpdate`; enforces RBAC create/update permission.\n */\nexport const createSingleWriteHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({\n args,\n }: {\n args: Record<string, unknown>;\n }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n return singleCreateOrUpdate(strapi, uid, context, args as SingleWriteArgs);\n };\n\n/**\n * Creates a handler for deleting the single-type document (or a specific locale).\n * Enforces RBAC delete permission on every locale version before deletion.\n */\nexport const createSingleDeleteHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.delete()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.delete({ locale });\n\n const populate = await getService('populate-builder')(typedUid)\n .populateFromQuery(sanitizedQuery)\n .populateDeep(Infinity)\n .countRelations()\n .withPopulateOverride(getPopulateForLocalizations(typedUid))\n .build();\n\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const isLocalized = isContentTypeLocalized(strapi, uid);\n\n const localeForQuery = isLocalized === true ? resolvedLocale : undefined;\n\n const documentLocales = await documentManager.findLocales(undefined, typedUid, {\n populate,\n locale: localeForQuery,\n });\n\n if (documentLocales.length === 0) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n for (const document of documentLocales) {\n if (permissionChecker.cannot.delete(document)) {\n throw new errors.ForbiddenError();\n }\n }\n\n const deletedEntity = await documentManager.delete(documentLocales[0].documentId, typedUid, {\n locale: localeForQuery,\n });\n\n const sanitizedResult = await permissionChecker.sanitizeOutput(deletedEntity);\n\n return ok({ data: sanitizedResult } as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for publishing the single-type document draft.\n * Enforces RBAC publish permission; throws NotFound when the draft is missing.\n */\nexport const createSinglePublishHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.publish()) {\n throw new errors.ForbiddenError();\n }\n\n const publishedDocument = await strapi.db.transaction(async () => {\n const sanitizedQuery = await permissionChecker.sanitizedQuery.publish({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const publishFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n locale: resolvedLocale,\n status: 'draft',\n };\n const document = await getService('document-manager')\n .findMany(publishFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.publish(document)) {\n throw new errors.ForbiddenError();\n }\n\n const publishResult = await documentManager.publish(document.documentId, typedUid, {\n locale: resolvedLocale,\n });\n\n return publishResult?.at(0);\n });\n\n const sanitizedDocument = await permissionChecker.sanitizeOutput(publishedDocument);\n const result = await formatDocumentWithMetadata(permissionChecker, typedUid, sanitizedDocument);\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for unpublishing the single-type document.\n * Optionally discards the draft in the same transaction when `discardDraft` is true.\n * Enforces RBAC unpublish (and discard) permission.\n */\nexport const createSingleUnpublishHandler =\n (uid: UID.SingleType) =>\n (strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleUnpublishArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale, discardDraft } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.unpublish()) {\n throw new errors.ForbiddenError();\n }\n\n if (discardDraft === true && permissionChecker.cannot.discard()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.unpublish({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const unpublishFindQuery: McpDocumentQuery = { ...sanitizedQuery, locale: resolvedLocale };\n const document = await getService('document-manager')\n .findMany(unpublishFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.unpublish(document)) {\n throw new errors.ForbiddenError();\n }\n\n if (discardDraft === true && permissionChecker.cannot.discard(document)) {\n throw new errors.ForbiddenError();\n }\n\n const result = await strapi.db.transaction(async () => {\n if (discardDraft === true) {\n await documentManager.discardDraft(document.documentId, typedUid, {\n locale: resolvedLocale,\n });\n }\n\n return asyncPipe.pipe(\n (doc: any) =>\n documentManager.unpublish(doc.documentId, typedUid, { locale: resolvedLocale }),\n permissionChecker.sanitizeOutput,\n (doc: any) => formatDocumentWithMetadata(permissionChecker, typedUid, doc)\n )(document);\n });\n\n return ok(result as Record<string, unknown>);\n };\n\n/**\n * Creates a handler for discarding the draft of the single-type document.\n * Restores the published version as the draft. Enforces RBAC discard permission.\n */\nexport const createSingleDiscardDraftHandler =\n (uid: UID.SingleType) =>\n (_strapi: Core.Strapi, context: Modules.MCP.McpHandlerContext) =>\n async ({ args }: { args: SingleLocaleArgs }): Promise<Modules.MCP.McpToolHandlerReturn> => {\n const { userAbility } = context;\n const { locale } = args;\n // TODO: fix UID.SingleType assignability in @strapi/types\n const typedUid = uid as UID.ContentType;\n\n const documentManager = getService('document-manager');\n const permissionChecker = getService('permission-checker').create({\n userAbility,\n model: uid as string,\n });\n\n if (permissionChecker.cannot.discard()) {\n throw new errors.ForbiddenError();\n }\n\n const sanitizedQuery = await permissionChecker.sanitizedQuery.discard({ locale });\n const { locale: resolvedLocale } = await getDocumentLocaleAndStatus({ locale }, uid);\n\n const discardFindQuery: McpDocumentQuery = {\n ...sanitizedQuery,\n locale: resolvedLocale,\n status: 'published',\n };\n const document = await getService('document-manager')\n .findMany(discardFindQuery as McpFindManyParams, typedUid)\n .then((docs: any[]) => docs[0]);\n\n if (!document) {\n throw new errors.NotFoundError(MCP_NOT_FOUND_DOCUMENT);\n }\n\n if (permissionChecker.cannot.discard(document)) {\n throw new errors.ForbiddenError();\n }\n\n const discardedDocument = await asyncPipe.pipe(\n (doc: any) =>\n documentManager.discardDraft(doc.documentId, typedUid, { locale: resolvedLocale }),\n permissionChecker.sanitizeOutput,\n (doc: any) => formatDocumentWithMetadata(permissionChecker, typedUid, doc)\n )(document);\n\n return ok(discardedDocument as Record<string, unknown>);\n };\n"],"names":["singleCreateOrUpdate","strapi","uid","context","args","userAbility","user","data","locale","typedUid","documentManager","getService","permissionChecker","create","model","cannot","update","errors","ForbiddenError","sanitizedQuery","resolvedLocale","getDocumentLocaleAndStatus","populate","populateFromQuery","populateDeep","Infinity","countRelations","withPopulateOverride","getPopulateForLocalizations","build","draftFindQuery","status","documentVersion","otherDocumentVersion","Promise","all","findMany","then","docs","db","query","findOne","select","documentId","sanitizeInput","sanitizeUpdateInput","sanitizeCreateInput","isEdition","undefined","sanitizedData","setCreatorFields","formatted","transaction","doc","sanitizedDocument","sanitizeOutput","formatDocumentWithMetadata","ok","createSingleGetHandler","read","permissionQuery","resolvedStatus","versionFindQuery","version","document","NotFoundError","MCP_NOT_FOUND_DOCUMENT","meta","publishedAt","availableLocales","availableStatus","result","createSingleWriteHandler","createSingleDeleteHandler","delete","isLocalized","isContentTypeLocalized","localeForQuery","documentLocales","findLocales","length","deletedEntity","sanitizedResult","createSinglePublishHandler","publish","publishedDocument","publishFindQuery","publishResult","at","createSingleUnpublishHandler","discardDraft","unpublish","discard","unpublishFindQuery","asyncPipe","pipe","createSingleDiscardDraftHandler","_strapi","discardFindQuery","discardedDocument"],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ 'use strict';
2
+
3
+ var strapiUtils = require('@strapi/utils');
4
+ var index = require('../utils/index.js');
5
+
6
+ /** Returns true if the content type identified by `uid` has the i18n `localized` plugin option enabled. */ const isContentTypeLocalized = (strapi, uid)=>{
7
+ const ct = strapi.contentTypes?.[uid];
8
+ if (ct === undefined) return false;
9
+ return ct.pluginOptions?.i18n?.localized === true;
10
+ };
11
+ const localeDefaultDescription = (defaultLocale, allowedLocales)=>{
12
+ if (defaultLocale !== null && allowedLocales.includes(defaultLocale)) {
13
+ return `Defaults to "${defaultLocale}".`;
14
+ }
15
+ return 'Defaults to the default locale.';
16
+ };
17
+ /**
18
+ * Builds the base locale Zod schema for a derived MCP tool input.
19
+ * When `localeCodes` is provided, constrains the field to a `z.enum` of available codes
20
+ * with an optional default; otherwise falls back to a plain optional string.
21
+ */ const buildLocaleSchema = (localeCodes, defaultLocale)=>{
22
+ if (localeCodes !== null && localeCodes.length > 0) {
23
+ let schema = strapiUtils.z.enum(localeCodes).optional();
24
+ if (defaultLocale !== null && localeCodes.includes(defaultLocale)) {
25
+ schema = schema.default(defaultLocale);
26
+ }
27
+ return schema.describe(`Locale code. Available: ${localeCodes.join(', ')}. ${localeDefaultDescription(defaultLocale, localeCodes)}`);
28
+ }
29
+ return strapiUtils.z.string().optional().describe('Locale code (e.g. "en", "fr"). Defaults to the default locale.');
30
+ };
31
+ /**
32
+ * Narrows the base locale schema to only locales the session is permitted to access
33
+ * for the given action + uid combination.
34
+ *
35
+ * Returns the base schema unchanged when:
36
+ * - localeCodes is null (i18n not installed)
37
+ * - the content type is not localized
38
+ * - all installed locales are permitted for this action
39
+ *
40
+ * Returns z.never().optional() when no locales are permitted, keeping the tool
41
+ * registered but signalling no valid locale input.
42
+ */ const resolvePermittedLocaleSchema = (strapi, context, action, uid, localeCodes, defaultLocale, baseLocaleSchema)=>{
43
+ if (localeCodes === null) return baseLocaleSchema;
44
+ const isLocalized = isContentTypeLocalized(strapi, uid);
45
+ if (isLocalized === false) {
46
+ return strapiUtils.z.string().optional().describe('This content type is not localized. Locale is ignored.');
47
+ }
48
+ const permissionChecker = index.getService('permission-checker').create({
49
+ userAbility: context.userAbility,
50
+ model: uid
51
+ });
52
+ const permitted = getPermittedLocales(permissionChecker, action, localeCodes);
53
+ if (permitted === null) return baseLocaleSchema;
54
+ if (permitted.length === 0) {
55
+ return strapiUtils.z.never().optional().describe('No locale access for this action.');
56
+ }
57
+ let schema = strapiUtils.z.enum(permitted).optional();
58
+ if (defaultLocale !== null && permitted.includes(defaultLocale)) {
59
+ schema = schema.default(defaultLocale);
60
+ }
61
+ return schema.describe(`Locale code. Permitted: ${permitted.join(', ')}. ${localeDefaultDescription(defaultLocale, permitted)}`);
62
+ };
63
+ /**
64
+ * Recursively resolves leaf field paths for a component, matching the nested
65
+ * path format used by CASL rules (e.g. 'SEO.title', 'SEO.og.image').
66
+ *
67
+ * The admin RBAC system decomposes component attrs into nested paths and removes
68
+ * the parent key — so checking `ability.can(action, uid, 'SEO')` returns false
69
+ * even when the user has full access to the component's sub-fields.
70
+ */ const getComponentLeafPaths = (strapi, componentUid, prefix, visited = new Set())=>{
71
+ if (visited.has(componentUid) === true) return [
72
+ prefix
73
+ ];
74
+ const component = strapi.components[componentUid];
75
+ if (component === undefined) return [
76
+ prefix
77
+ ];
78
+ visited.add(componentUid);
79
+ const paths = [];
80
+ for (const [key, attr] of Object.entries(component.attributes)){
81
+ if (key === 'id') {
82
+ continue;
83
+ }
84
+ const fieldPath = `${prefix}.${key}`;
85
+ if (attr.type === 'component' && attr.component !== undefined) {
86
+ paths.push(...getComponentLeafPaths(strapi, attr.component, fieldPath, visited));
87
+ } else {
88
+ paths.push(fieldPath);
89
+ }
90
+ }
91
+ visited.delete(componentUid);
92
+ return paths.length > 0 ? paths : [
93
+ prefix
94
+ ];
95
+ };
96
+ /**
97
+ * Returns the subset of attribute keys the session may access for `action` on `uid`.
98
+ * Returns `null` when all fields are permitted (caller should skip field filtering).
99
+ * Component attributes are resolved to their nested leaf paths before checking CASL rules.
100
+ */ const getPermittedFields = (strapi, userAbility, action, uid, attributes)=>{
101
+ const allKeys = Object.keys(attributes);
102
+ const permitted = allKeys.filter((key)=>{
103
+ if (userAbility.can(action, uid, key) === true) return true;
104
+ // Component attrs: CASL rules use nested paths (e.g. 'SEO.title').
105
+ // Check if at least one sub-field path is permitted.
106
+ const attr = attributes[key];
107
+ if (attr.type === 'component' && attr.component !== undefined) {
108
+ const leafPaths = getComponentLeafPaths(strapi, attr.component, key);
109
+ return leafPaths.some((path)=>userAbility.can(action, uid, path) === true);
110
+ }
111
+ return false;
112
+ });
113
+ if (permitted.length === allKeys.length) {
114
+ return null;
115
+ }
116
+ return new Set(permitted);
117
+ };
118
+ /**
119
+ * Filters `localeCodes` to only those the session may access for `action`.
120
+ * Returns `null` when all locales are permitted (caller should use the unfiltered base schema).
121
+ * Returns an empty tuple-like array when no locale is permitted.
122
+ */ const getPermittedLocales = (permissionChecker, action, localeCodes)=>{
123
+ const permitted = localeCodes.filter((code)=>permissionChecker.cannot(action, {
124
+ locale: code
125
+ }) === false);
126
+ if (permitted.length === localeCodes.length) {
127
+ return null;
128
+ }
129
+ return permitted.length > 0 ? permitted : [];
130
+ };
131
+
132
+ exports.buildLocaleSchema = buildLocaleSchema;
133
+ exports.getComponentLeafPaths = getComponentLeafPaths;
134
+ exports.getPermittedFields = getPermittedFields;
135
+ exports.getPermittedLocales = getPermittedLocales;
136
+ exports.isContentTypeLocalized = isContentTypeLocalized;
137
+ exports.resolvePermittedLocaleSchema = resolvePermittedLocaleSchema;
138
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sources":["../../../server/src/mcp/permissions.ts"],"sourcesContent":["import { z } from '@strapi/utils';\nimport type { Core, Modules, Struct, UID } from '@strapi/types';\n\nimport { getService } from '../utils';\nimport type { ContentManagerModelForMcp } from './types';\n\n/** Returns true if the content type identified by `uid` has the i18n `localized` plugin option enabled. */\nexport const isContentTypeLocalized = (strapi: Core.Strapi, uid: string): boolean => {\n const ct = strapi.contentTypes?.[uid as UID.ContentType];\n if (ct === undefined) return false;\n return (\n (ct as { pluginOptions?: { i18n?: { localized?: boolean } } }).pluginOptions?.i18n\n ?.localized === true\n );\n};\n\nconst localeDefaultDescription = (\n defaultLocale: string | null,\n allowedLocales: readonly string[]\n): string => {\n if (defaultLocale !== null && allowedLocales.includes(defaultLocale)) {\n return `Defaults to \"${defaultLocale}\".`;\n }\n\n return 'Defaults to the default locale.';\n};\n\n/**\n * Builds the base locale Zod schema for a derived MCP tool input.\n * When `localeCodes` is provided, constrains the field to a `z.enum` of available codes\n * with an optional default; otherwise falls back to a plain optional string.\n */\nexport const buildLocaleSchema = (\n localeCodes: [string, ...string[]] | null,\n defaultLocale: string | null\n): z.ZodTypeAny => {\n if (localeCodes !== null && localeCodes.length > 0) {\n let schema: z.ZodTypeAny = z.enum(localeCodes).optional();\n\n if (defaultLocale !== null && localeCodes.includes(defaultLocale)) {\n schema = schema.default(defaultLocale);\n }\n\n return schema.describe(\n `Locale code. Available: ${localeCodes.join(', ')}. ${localeDefaultDescription(defaultLocale, localeCodes)}`\n );\n }\n\n return z\n .string()\n .optional()\n .describe('Locale code (e.g. \"en\", \"fr\"). Defaults to the default locale.');\n};\n\n/**\n * Narrows the base locale schema to only locales the session is permitted to access\n * for the given action + uid combination.\n *\n * Returns the base schema unchanged when:\n * - localeCodes is null (i18n not installed)\n * - the content type is not localized\n * - all installed locales are permitted for this action\n *\n * Returns z.never().optional() when no locales are permitted, keeping the tool\n * registered but signalling no valid locale input.\n */\nexport const resolvePermittedLocaleSchema = (\n strapi: Core.Strapi,\n context: Modules.MCP.McpHandlerContext,\n action: string,\n uid: string,\n localeCodes: [string, ...string[]] | null,\n defaultLocale: string | null,\n baseLocaleSchema: z.ZodTypeAny\n): z.ZodTypeAny => {\n if (localeCodes === null) return baseLocaleSchema;\n\n const isLocalized = isContentTypeLocalized(strapi, uid);\n if (isLocalized === false) {\n return z.string().optional().describe('This content type is not localized. Locale is ignored.');\n }\n\n const permissionChecker = getService('permission-checker').create({\n userAbility: context.userAbility,\n model: uid,\n });\n const permitted = getPermittedLocales(permissionChecker, action, localeCodes);\n if (permitted === null) return baseLocaleSchema;\n if (permitted.length === 0) {\n return z.never().optional().describe('No locale access for this action.');\n }\n\n let schema: z.ZodTypeAny = z.enum(permitted).optional();\n\n if (defaultLocale !== null && permitted.includes(defaultLocale)) {\n schema = schema.default(defaultLocale);\n }\n\n return schema.describe(\n `Locale code. Permitted: ${permitted.join(', ')}. ${localeDefaultDescription(defaultLocale, permitted)}`\n );\n};\n\n/**\n * Recursively resolves leaf field paths for a component, matching the nested\n * path format used by CASL rules (e.g. 'SEO.title', 'SEO.og.image').\n *\n * The admin RBAC system decomposes component attrs into nested paths and removes\n * the parent key — so checking `ability.can(action, uid, 'SEO')` returns false\n * even when the user has full access to the component's sub-fields.\n */\nexport const getComponentLeafPaths = (\n strapi: Core.Strapi,\n componentUid: string,\n prefix: string,\n visited: Set<string> = new Set()\n): string[] => {\n if (visited.has(componentUid) === true) return [prefix];\n\n type ComponentEntry = { attributes: Record<string, { type: string; component?: string }> };\n const component = (strapi.components as unknown as Record<string, ComponentEntry | undefined>)[\n componentUid\n ];\n if (component === undefined) return [prefix];\n\n visited.add(componentUid);\n const paths: string[] = [];\n\n for (const [key, attr] of Object.entries(component.attributes)) {\n if (key === 'id') {\n // skip system id field — it is not a user-facing permission path\n // eslint-disable-next-line no-continue\n continue;\n }\n const fieldPath = `${prefix}.${key}`;\n\n if (attr.type === 'component' && attr.component !== undefined) {\n paths.push(...getComponentLeafPaths(strapi, attr.component, fieldPath, visited));\n } else {\n paths.push(fieldPath);\n }\n }\n\n visited.delete(componentUid);\n\n return paths.length > 0 ? paths : [prefix];\n};\n\n/**\n * Returns the subset of attribute keys the session may access for `action` on `uid`.\n * Returns `null` when all fields are permitted (caller should skip field filtering).\n * Component attributes are resolved to their nested leaf paths before checking CASL rules.\n */\nexport const getPermittedFields = (\n strapi: Core.Strapi,\n userAbility: Modules.MCP.McpHandlerContext['userAbility'],\n action: string,\n uid: string,\n attributes: Struct.SchemaAttributes\n): Set<string> | null => {\n const allKeys = Object.keys(attributes);\n const permitted = allKeys.filter((key) => {\n if (userAbility.can(action, uid, key) === true) return true;\n\n // Component attrs: CASL rules use nested paths (e.g. 'SEO.title').\n // Check if at least one sub-field path is permitted.\n const attr = attributes[key] as { type: string; component?: string };\n if (attr.type === 'component' && attr.component !== undefined) {\n const leafPaths = getComponentLeafPaths(strapi, attr.component, key);\n return leafPaths.some((path) => userAbility.can(action, uid, path) === true);\n }\n\n return false;\n });\n\n if (permitted.length === allKeys.length) {\n return null;\n }\n\n return new Set(permitted);\n};\n\n/**\n * Filters `localeCodes` to only those the session may access for `action`.\n * Returns `null` when all locales are permitted (caller should use the unfiltered base schema).\n * Returns an empty tuple-like array when no locale is permitted.\n */\nexport const getPermittedLocales = (\n permissionChecker: { cannot: (action: string, entity?: unknown) => boolean },\n action: string,\n localeCodes: [string, ...string[]]\n): [string, ...string[]] | null => {\n const permitted = localeCodes.filter(\n (code) => permissionChecker.cannot(action, { locale: code }) === false\n );\n\n if (permitted.length === localeCodes.length) {\n return null;\n }\n\n return permitted.length > 0\n ? (permitted as [string, ...string[]])\n : ([] as unknown as [string, ...string[]]);\n};\n\n// Re-export for use in handler files (avoids needing to import from permissions in each handler)\nexport type { ContentManagerModelForMcp };\n"],"names":["isContentTypeLocalized","strapi","uid","ct","contentTypes","undefined","pluginOptions","i18n","localized","localeDefaultDescription","defaultLocale","allowedLocales","includes","buildLocaleSchema","localeCodes","length","schema","z","enum","optional","default","describe","join","string","resolvePermittedLocaleSchema","context","action","baseLocaleSchema","isLocalized","permissionChecker","getService","create","userAbility","model","permitted","getPermittedLocales","never","getComponentLeafPaths","componentUid","prefix","visited","Set","has","component","components","add","paths","key","attr","Object","entries","attributes","fieldPath","type","push","delete","getPermittedFields","allKeys","keys","filter","can","leafPaths","some","path","code","cannot","locale"],"mappings":"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"}