@strapi/upload 5.56.0 → 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 (208) hide show
  1. package/dist/admin/hooks/useTracking.js +2 -8
  2. package/dist/admin/hooks/useTracking.js.map +1 -1
  3. package/dist/admin/hooks/useTracking.mjs +3 -8
  4. package/dist/admin/hooks/useTracking.mjs.map +1 -1
  5. package/dist/admin/legacy/hooks/useTracking.js +3 -1
  6. package/dist/admin/legacy/hooks/useTracking.js.map +1 -1
  7. package/dist/admin/legacy/hooks/useTracking.mjs +3 -1
  8. package/dist/admin/legacy/hooks/useTracking.mjs.map +1 -1
  9. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js +2 -1
  10. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.js.map +1 -1
  11. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs +2 -1
  12. package/dist/admin/legacy/pages/App/ConfigureTheView/ConfigureTheView.mjs.map +1 -1
  13. package/dist/admin/legacy/pages/App/MediaLibrary.js +2 -1
  14. package/dist/admin/legacy/pages/App/MediaLibrary.js.map +1 -1
  15. package/dist/admin/legacy/pages/App/MediaLibrary.mjs +2 -1
  16. package/dist/admin/legacy/pages/App/MediaLibrary.mjs.map +1 -1
  17. package/dist/admin/pages/Assets/AssetsPage.js +24 -12
  18. package/dist/admin/pages/Assets/AssetsPage.js.map +1 -1
  19. package/dist/admin/pages/Assets/AssetsPage.mjs +25 -13
  20. package/dist/admin/pages/Assets/AssetsPage.mjs.map +1 -1
  21. package/dist/admin/pages/Assets/components/AssetActions.js +326 -0
  22. package/dist/admin/pages/Assets/components/AssetActions.js.map +1 -0
  23. package/dist/admin/pages/Assets/components/AssetActions.mjs +324 -0
  24. package/dist/admin/pages/Assets/components/AssetActions.mjs.map +1 -0
  25. package/dist/admin/pages/Assets/components/AssetActionsMenu.js +28 -309
  26. package/dist/admin/pages/Assets/components/AssetActionsMenu.js.map +1 -1
  27. package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs +31 -312
  28. package/dist/admin/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
  29. package/dist/admin/pages/Assets/components/AssetContextMenu.js +79 -0
  30. package/dist/admin/pages/Assets/components/AssetContextMenu.js.map +1 -0
  31. package/dist/admin/pages/Assets/components/AssetContextMenu.mjs +77 -0
  32. package/dist/admin/pages/Assets/components/AssetContextMenu.mjs.map +1 -0
  33. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js +87 -5
  34. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -1
  35. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +89 -7
  36. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -1
  37. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +3 -3
  38. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  39. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +3 -3
  40. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  41. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js +62 -5
  42. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.js.map +1 -1
  43. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs +60 -6
  44. package/dist/admin/pages/Assets/components/AssetDetails/useCropImg.mjs.map +1 -1
  45. package/dist/admin/pages/Assets/components/AssetsGrid.js +27 -4
  46. package/dist/admin/pages/Assets/components/AssetsGrid.js.map +1 -1
  47. package/dist/admin/pages/Assets/components/AssetsGrid.mjs +27 -4
  48. package/dist/admin/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  49. package/dist/admin/pages/Assets/components/AssetsTable.js +27 -4
  50. package/dist/admin/pages/Assets/components/AssetsTable.js.map +1 -1
  51. package/dist/admin/pages/Assets/components/AssetsTable.mjs +27 -4
  52. package/dist/admin/pages/Assets/components/AssetsTable.mjs.map +1 -1
  53. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js +77 -0
  54. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.js.map +1 -0
  55. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs +75 -0
  56. package/dist/admin/pages/Assets/components/CursorAnchoredMenu.mjs.map +1 -0
  57. package/dist/admin/pages/Assets/components/FolderActions.js +139 -0
  58. package/dist/admin/pages/Assets/components/FolderActions.js.map +1 -0
  59. package/dist/admin/pages/Assets/components/FolderActions.mjs +137 -0
  60. package/dist/admin/pages/Assets/components/FolderActions.mjs.map +1 -0
  61. package/dist/admin/pages/Assets/components/FolderActionsMenu.js +25 -119
  62. package/dist/admin/pages/Assets/components/FolderActionsMenu.js.map +1 -1
  63. package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs +27 -121
  64. package/dist/admin/pages/Assets/components/FolderActionsMenu.mjs.map +1 -1
  65. package/dist/admin/pages/Assets/components/FolderContextMenu.js +67 -0
  66. package/dist/admin/pages/Assets/components/FolderContextMenu.js.map +1 -0
  67. package/dist/admin/pages/Assets/components/FolderContextMenu.mjs +65 -0
  68. package/dist/admin/pages/Assets/components/FolderContextMenu.mjs.map +1 -0
  69. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js +139 -45
  70. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
  71. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs +140 -47
  72. package/dist/admin/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
  73. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js +115 -0
  74. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.js.map +1 -0
  75. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs +113 -0
  76. package/dist/admin/pages/Assets/components/FolderTree/FolderTreeRowMenu.mjs.map +1 -0
  77. package/dist/admin/pages/Assets/components/ItemContextMenu.js +125 -0
  78. package/dist/admin/pages/Assets/components/ItemContextMenu.js.map +1 -0
  79. package/dist/admin/pages/Assets/components/ItemContextMenu.mjs +122 -0
  80. package/dist/admin/pages/Assets/components/ItemContextMenu.mjs.map +1 -0
  81. package/dist/admin/pages/Assets/components/MainAreaContextMenu.js +88 -63
  82. package/dist/admin/pages/Assets/components/MainAreaContextMenu.js.map +1 -1
  83. package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs +88 -63
  84. package/dist/admin/pages/Assets/components/MainAreaContextMenu.mjs.map +1 -1
  85. package/dist/admin/pages/Assets/components/SelectionActions.js +111 -0
  86. package/dist/admin/pages/Assets/components/SelectionActions.js.map +1 -0
  87. package/dist/admin/pages/Assets/components/SelectionActions.mjs +109 -0
  88. package/dist/admin/pages/Assets/components/SelectionActions.mjs.map +1 -0
  89. package/dist/admin/pages/Assets/components/SelectionContextMenu.js +82 -0
  90. package/dist/admin/pages/Assets/components/SelectionContextMenu.js.map +1 -0
  91. package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs +80 -0
  92. package/dist/admin/pages/Assets/components/SelectionContextMenu.mjs.map +1 -0
  93. package/dist/admin/pages/Assets/hooks/useAssetSelection.js +10 -0
  94. package/dist/admin/pages/Assets/hooks/useAssetSelection.js.map +1 -1
  95. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs +10 -0
  96. package/dist/admin/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
  97. package/dist/admin/pages/SettingsPage/SettingsPage.js +8 -1
  98. package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
  99. package/dist/admin/pages/SettingsPage/SettingsPage.mjs +8 -1
  100. package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
  101. package/dist/admin/src/hooks/useTracking.d.ts +0 -7
  102. package/dist/admin/src/pages/Assets/components/AssetActions.d.ts +70 -0
  103. package/dist/admin/src/pages/Assets/components/AssetActionsMenu.d.ts +5 -14
  104. package/dist/admin/src/pages/Assets/components/AssetContextMenu.d.ts +27 -0
  105. package/dist/admin/src/pages/Assets/components/AssetDetails/useCropImg.d.ts +16 -0
  106. package/dist/admin/src/pages/Assets/components/CursorAnchoredMenu.d.ts +32 -0
  107. package/dist/admin/src/pages/Assets/components/FolderActions.d.ts +48 -0
  108. package/dist/admin/src/pages/Assets/components/FolderActionsMenu.d.ts +4 -8
  109. package/dist/admin/src/pages/Assets/components/FolderContextMenu.d.ts +21 -0
  110. package/dist/admin/src/pages/Assets/components/FolderTree/FolderTree.d.ts +5 -1
  111. package/dist/admin/src/pages/Assets/components/FolderTree/FolderTreeRowMenu.d.ts +25 -0
  112. package/dist/admin/src/pages/Assets/components/ItemContextMenu.d.ts +53 -0
  113. package/dist/admin/src/pages/Assets/components/MainAreaContextMenu.d.ts +15 -1
  114. package/dist/admin/src/pages/Assets/components/SelectionActions.d.ts +40 -0
  115. package/dist/admin/src/pages/Assets/components/SelectionContextMenu.d.ts +25 -0
  116. package/dist/admin/src/pages/Assets/hooks/useAssetSelection.d.ts +5 -0
  117. package/dist/admin/src/utils/mediaLibraryVersion.d.ts +18 -0
  118. package/dist/admin/translations/en.json.js +8 -3
  119. package/dist/admin/translations/en.json.js.map +1 -1
  120. package/dist/admin/translations/en.json.mjs +8 -3
  121. package/dist/admin/translations/en.json.mjs.map +1 -1
  122. package/dist/admin/utils/mediaLibraryVersion.js +24 -0
  123. package/dist/admin/utils/mediaLibraryVersion.js.map +1 -0
  124. package/dist/admin/utils/mediaLibraryVersion.mjs +20 -0
  125. package/dist/admin/utils/mediaLibraryVersion.mjs.map +1 -0
  126. package/dist/server/controllers/admin-file.js +2 -2
  127. package/dist/server/controllers/admin-file.js.map +1 -1
  128. package/dist/server/controllers/admin-file.mjs +2 -2
  129. package/dist/server/controllers/admin-file.mjs.map +1 -1
  130. package/dist/server/controllers/admin-folder.js +5 -5
  131. package/dist/server/controllers/admin-folder.js.map +1 -1
  132. package/dist/server/controllers/admin-folder.mjs +5 -5
  133. package/dist/server/controllers/admin-folder.mjs.map +1 -1
  134. package/dist/server/controllers/content-api.js +30 -7
  135. package/dist/server/controllers/content-api.js.map +1 -1
  136. package/dist/server/controllers/content-api.mjs +30 -7
  137. package/dist/server/controllers/content-api.mjs.map +1 -1
  138. package/dist/server/controllers/validation/admin/folder-file.js +4 -4
  139. package/dist/server/controllers/validation/admin/folder-file.js.map +1 -1
  140. package/dist/server/controllers/validation/admin/folder-file.mjs +2 -2
  141. package/dist/server/controllers/validation/admin/folder-file.mjs.map +1 -1
  142. package/dist/server/controllers/validation/admin/folder.js +3 -4
  143. package/dist/server/controllers/validation/admin/folder.js.map +1 -1
  144. package/dist/server/controllers/validation/admin/folder.mjs +3 -4
  145. package/dist/server/controllers/validation/admin/folder.mjs.map +1 -1
  146. package/dist/server/controllers/validation/admin/upload.js +1 -2
  147. package/dist/server/controllers/validation/admin/upload.js.map +1 -1
  148. package/dist/server/controllers/validation/admin/upload.mjs +1 -2
  149. package/dist/server/controllers/validation/admin/upload.mjs.map +1 -1
  150. package/dist/server/controllers/validation/admin/utils.js +1 -2
  151. package/dist/server/controllers/validation/admin/utils.js.map +1 -1
  152. package/dist/server/controllers/validation/admin/utils.mjs +1 -2
  153. package/dist/server/controllers/validation/admin/utils.mjs.map +1 -1
  154. package/dist/server/migrations/unsign-richtext-and-blocks-urls.js +2 -2
  155. package/dist/server/migrations/unsign-richtext-and-blocks-urls.js.map +1 -1
  156. package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs +1 -1
  157. package/dist/server/migrations/unsign-richtext-and-blocks-urls.mjs.map +1 -1
  158. package/dist/server/routes/content-api.js +3 -3
  159. package/dist/server/routes/content-api.js.map +1 -1
  160. package/dist/server/routes/content-api.mjs +3 -3
  161. package/dist/server/routes/content-api.mjs.map +1 -1
  162. package/dist/server/routes/validation/upload.js +8 -0
  163. package/dist/server/routes/validation/upload.js.map +1 -1
  164. package/dist/server/routes/validation/upload.mjs +8 -0
  165. package/dist/server/routes/validation/upload.mjs.map +1 -1
  166. package/dist/server/services/api-upload-folder.js +3 -3
  167. package/dist/server/services/api-upload-folder.js.map +1 -1
  168. package/dist/server/services/api-upload-folder.mjs +3 -3
  169. package/dist/server/services/api-upload-folder.mjs.map +1 -1
  170. package/dist/server/services/extensions/utils.js +19 -15
  171. package/dist/server/services/extensions/utils.js.map +1 -1
  172. package/dist/server/services/extensions/utils.mjs +19 -15
  173. package/dist/server/services/extensions/utils.mjs.map +1 -1
  174. package/dist/server/services/file.js +2 -2
  175. package/dist/server/services/file.js.map +1 -1
  176. package/dist/server/services/file.mjs +1 -1
  177. package/dist/server/services/file.mjs.map +1 -1
  178. package/dist/server/services/folder.js +5 -5
  179. package/dist/server/services/folder.js.map +1 -1
  180. package/dist/server/services/folder.mjs +5 -5
  181. package/dist/server/services/folder.mjs.map +1 -1
  182. package/dist/server/services/provider.js +3 -4
  183. package/dist/server/services/provider.js.map +1 -1
  184. package/dist/server/services/provider.mjs +3 -4
  185. package/dist/server/services/provider.mjs.map +1 -1
  186. package/dist/server/services/upload.js +5 -6
  187. package/dist/server/services/upload.js.map +1 -1
  188. package/dist/server/services/upload.mjs +4 -5
  189. package/dist/server/services/upload.mjs.map +1 -1
  190. package/dist/server/services/weekly-metrics.js +2 -2
  191. package/dist/server/services/weekly-metrics.js.map +1 -1
  192. package/dist/server/services/weekly-metrics.mjs +2 -2
  193. package/dist/server/services/weekly-metrics.mjs.map +1 -1
  194. package/dist/server/src/controllers/admin-folder.d.ts.map +1 -1
  195. package/dist/server/src/controllers/content-api.d.ts.map +1 -1
  196. package/dist/server/src/controllers/validation/admin/folder.d.ts.map +1 -1
  197. package/dist/server/src/controllers/validation/admin/upload.d.ts.map +1 -1
  198. package/dist/server/src/controllers/validation/admin/utils.d.ts.map +1 -1
  199. package/dist/server/src/index.d.ts.map +1 -1
  200. package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
  201. package/dist/server/src/routes/validation/upload.d.ts +4 -0
  202. package/dist/server/src/routes/validation/upload.d.ts.map +1 -1
  203. package/dist/server/src/services/extensions/utils.d.ts +33 -1
  204. package/dist/server/src/services/extensions/utils.d.ts.map +1 -1
  205. package/dist/server/src/services/index.d.ts.map +1 -1
  206. package/dist/server/src/services/provider.d.ts.map +1 -1
  207. package/dist/server/src/services/upload.d.ts.map +1 -1
  208. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"admin-file.js","sources":["../../../server/src/controllers/admin-file.ts"],"sourcesContent":["import { merge } from 'lodash/fp';\nimport { async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { validateGenerateAIMetadataBody } from './validation/admin/ai-metadata';\n\nexport default {\n async find(ctx: Context) {\n const {\n state: { userAbility },\n } = ctx;\n\n const defaultQuery = { populate: { folder: true } };\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // validate the incoming user query params\n await pm.validateQuery(ctx.query);\n\n const query = await async.pipe(\n // Start by sanitizing the incoming query\n (q) => pm.sanitizeQuery(q),\n // Add the default query which should not be validated or sanitized\n (q) => merge(defaultQuery, q),\n // Add the dynamic filters based on permissions' conditions\n (q) => pm.addPermissionsQueryTo(q)\n )(ctx.query);\n\n const { results: files, pagination } = await getService('upload').findPage(query);\n\n // Sign file urls for private providers\n const signedFiles = await async.map(files, getService('file').signFileUrls);\n\n const sanitizedFiles = await pm.sanitizeOutput(signedFiles);\n\n return { results: sanitizedFiles, pagination };\n },\n\n async findOne(ctx: Context) {\n const {\n state: { userAbility },\n params: { id },\n } = ctx;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.read,\n FILE_MODEL_UID,\n id\n );\n\n const signedFile = await getService('file').signFileUrls(file);\n ctx.body = await pm.sanitizeOutput(signedFile);\n },\n\n async destroy(ctx: Context) {\n const { id } = ctx.params;\n const { userAbility } = ctx.state;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const [body] = await Promise.all([\n pm.sanitizeOutput(file, { action: ACTIONS.read }),\n getService('upload').remove(file),\n ]);\n\n ctx.body = body;\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/pending-count`\n *\n * How many images a backfill job would have to process, i.e. those still\n * missing AI metadata, alongside the total image count.\n */\n async getAIMetadataPendingCount(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n const { imagesWithoutMetadataCount, totalImages } =\n await aiMetadataService.countImagesWithoutMetadata();\n\n ctx.body = {\n imagesWithoutMetadataCount,\n totalImages,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to get AI metadata count';\n\n strapi.log.error('Failed to get AI metadata count', {\n message,\n error,\n });\n\n ctx.badRequest(message);\n }\n },\n\n /**\n * `POST /upload/ai-metadata-jobs`\n *\n * Create a backfill job that generates AI metadata for every image still\n * missing it, and return the job so the client can poll it. Processing runs\n * detached from this request; see `generateAIMetadata` for the synchronous\n * counterpart that works on an explicit selection.\n */\n async createAIMetadataJob(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n // Get count first to check if there are images to process\n const result = await aiMetadataService.countImagesWithoutMetadata();\n\n if (result.imagesWithoutMetadataCount === 0) {\n ctx.body = {\n count: 0,\n message: 'No images without metadata found',\n };\n return;\n }\n\n // Create job\n const jobService = getService('aiMetadataJobs');\n const jobId = await jobService.createJob();\n\n // Start async processing (fire and forget)\n aiMetadataService.processExistingFiles(jobId, ctx.state.user).catch((err: Error) => {\n strapi.log.error('AI metadata job failed:', err);\n });\n\n // Return immediately with job ID\n ctx.body = {\n jobId,\n status: 'pending',\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to generate AI metadata';\n const cause = error instanceof Error && error.cause ? String(error.cause) : undefined;\n\n strapi.log.error('AI metadata generation failed in controller', {\n message,\n cause,\n error,\n });\n\n ctx.badRequest(cause ? `${message}: ${cause}` : message);\n }\n },\n\n /**\n * `POST /upload/actions/generate-ai-metadata`\n *\n * Generate AI metadata for the explicit selection of files in the body,\n * synchronously: the request resolves once every file has been processed and\n * reports the outcome per file, so a single bad id or a non-image in the\n * selection never fails the whole batch.\n *\n * For the whole-library backfill, see `createAIMetadataJob`.\n */\n async generateAIMetadata(ctx: Context) {\n const { userAbility } = ctx.state;\n const { body } = ctx.request;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const { fileIds } = await validateGenerateAIMetadataBody(body);\n\n const aiMetadataService = getService('aiMetadata');\n\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n const results = await aiMetadataService.generateForFiles(fileIds, ctx.state.user);\n\n ctx.body = { data: results };\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/latest`\n *\n * The most recent still-active backfill job, so a client that reloads mid-run\n * can pick the progress bar back up. 404s when nothing is running.\n */\n async getLatestAIMetadataJob(ctx: Context) {\n if ((await getService('aiMetadata').isEnabled()) === false) {\n return ctx.notFound();\n }\n\n const jobService = getService('aiMetadataJobs');\n const job = await jobService.getLatestActiveJob();\n\n if (!job) {\n return ctx.notFound('No active job found');\n }\n\n ctx.body = job;\n },\n};\n"],"names":["find","ctx","state","userAbility","defaultQuery","populate","folder","pm","strapi","service","createPermissionsManager","ability","action","ACTIONS","read","model","FILE_MODEL_UID","isAllowed","forbidden","validateQuery","query","async","pipe","q","sanitizeQuery","merge","addPermissionsQueryTo","results","files","pagination","getService","findPage","signedFiles","map","signFileUrls","sanitizedFiles","sanitizeOutput","findOne","params","id","file","findEntityAndCheckPermissions","signedFile","body","destroy","update","Promise","all","remove","getAIMetadataPendingCount","aiMetadataService","isEnabled","badRequest","imagesWithoutMetadataCount","totalImages","countImagesWithoutMetadata","error","message","Error","log","createAIMetadataJob","result","count","jobService","jobId","createJob","processExistingFiles","user","catch","err","status","cause","String","undefined","generateAIMetadata","request","fileIds","validateGenerateAIMetadataBody","generateForFiles","data","getLatestAIMetadataJob","notFound","job","getLatestActiveJob"],"mappings":"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"}
1
+ {"version":3,"file":"admin-file.js","sources":["../../../server/src/controllers/admin-file.ts"],"sourcesContent":["import { merge } from 'lodash';\nimport { async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { validateGenerateAIMetadataBody } from './validation/admin/ai-metadata';\n\nexport default {\n async find(ctx: Context) {\n const {\n state: { userAbility },\n } = ctx;\n\n const defaultQuery = { populate: { folder: true } };\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // validate the incoming user query params\n await pm.validateQuery(ctx.query);\n\n const query = await async.pipe(\n // Start by sanitizing the incoming query\n (q) => pm.sanitizeQuery(q),\n // Add the default query which should not be validated or sanitized\n (q) => merge({}, defaultQuery, q),\n // Add the dynamic filters based on permissions' conditions\n (q) => pm.addPermissionsQueryTo(q)\n )(ctx.query);\n\n const { results: files, pagination } = await getService('upload').findPage(query);\n\n // Sign file urls for private providers\n const signedFiles = await async.map(files, getService('file').signFileUrls);\n\n const sanitizedFiles = await pm.sanitizeOutput(signedFiles);\n\n return { results: sanitizedFiles, pagination };\n },\n\n async findOne(ctx: Context) {\n const {\n state: { userAbility },\n params: { id },\n } = ctx;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.read,\n FILE_MODEL_UID,\n id\n );\n\n const signedFile = await getService('file').signFileUrls(file);\n ctx.body = await pm.sanitizeOutput(signedFile);\n },\n\n async destroy(ctx: Context) {\n const { id } = ctx.params;\n const { userAbility } = ctx.state;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const [body] = await Promise.all([\n pm.sanitizeOutput(file, { action: ACTIONS.read }),\n getService('upload').remove(file),\n ]);\n\n ctx.body = body;\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/pending-count`\n *\n * How many images a backfill job would have to process, i.e. those still\n * missing AI metadata, alongside the total image count.\n */\n async getAIMetadataPendingCount(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n const { imagesWithoutMetadataCount, totalImages } =\n await aiMetadataService.countImagesWithoutMetadata();\n\n ctx.body = {\n imagesWithoutMetadataCount,\n totalImages,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to get AI metadata count';\n\n strapi.log.error('Failed to get AI metadata count', {\n message,\n error,\n });\n\n ctx.badRequest(message);\n }\n },\n\n /**\n * `POST /upload/ai-metadata-jobs`\n *\n * Create a backfill job that generates AI metadata for every image still\n * missing it, and return the job so the client can poll it. Processing runs\n * detached from this request; see `generateAIMetadata` for the synchronous\n * counterpart that works on an explicit selection.\n */\n async createAIMetadataJob(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n // Get count first to check if there are images to process\n const result = await aiMetadataService.countImagesWithoutMetadata();\n\n if (result.imagesWithoutMetadataCount === 0) {\n ctx.body = {\n count: 0,\n message: 'No images without metadata found',\n };\n return;\n }\n\n // Create job\n const jobService = getService('aiMetadataJobs');\n const jobId = await jobService.createJob();\n\n // Start async processing (fire and forget)\n aiMetadataService.processExistingFiles(jobId, ctx.state.user).catch((err: Error) => {\n strapi.log.error('AI metadata job failed:', err);\n });\n\n // Return immediately with job ID\n ctx.body = {\n jobId,\n status: 'pending',\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to generate AI metadata';\n const cause = error instanceof Error && error.cause ? String(error.cause) : undefined;\n\n strapi.log.error('AI metadata generation failed in controller', {\n message,\n cause,\n error,\n });\n\n ctx.badRequest(cause ? `${message}: ${cause}` : message);\n }\n },\n\n /**\n * `POST /upload/actions/generate-ai-metadata`\n *\n * Generate AI metadata for the explicit selection of files in the body,\n * synchronously: the request resolves once every file has been processed and\n * reports the outcome per file, so a single bad id or a non-image in the\n * selection never fails the whole batch.\n *\n * For the whole-library backfill, see `createAIMetadataJob`.\n */\n async generateAIMetadata(ctx: Context) {\n const { userAbility } = ctx.state;\n const { body } = ctx.request;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const { fileIds } = await validateGenerateAIMetadataBody(body);\n\n const aiMetadataService = getService('aiMetadata');\n\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n const results = await aiMetadataService.generateForFiles(fileIds, ctx.state.user);\n\n ctx.body = { data: results };\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/latest`\n *\n * The most recent still-active backfill job, so a client that reloads mid-run\n * can pick the progress bar back up. 404s when nothing is running.\n */\n async getLatestAIMetadataJob(ctx: Context) {\n if ((await getService('aiMetadata').isEnabled()) === false) {\n return ctx.notFound();\n }\n\n const jobService = getService('aiMetadataJobs');\n const job = await jobService.getLatestActiveJob();\n\n if (!job) {\n return ctx.notFound('No active job found');\n }\n\n ctx.body = job;\n },\n};\n"],"names":["find","ctx","state","userAbility","defaultQuery","populate","folder","pm","strapi","service","createPermissionsManager","ability","action","ACTIONS","read","model","FILE_MODEL_UID","isAllowed","forbidden","validateQuery","query","async","pipe","q","sanitizeQuery","merge","addPermissionsQueryTo","results","files","pagination","getService","findPage","signedFiles","map","signFileUrls","sanitizedFiles","sanitizeOutput","findOne","params","id","file","findEntityAndCheckPermissions","signedFile","body","destroy","update","Promise","all","remove","getAIMetadataPendingCount","aiMetadataService","isEnabled","badRequest","imagesWithoutMetadataCount","totalImages","countImagesWithoutMetadata","error","message","Error","log","createAIMetadataJob","result","count","jobService","jobId","createJob","processExistingFiles","user","catch","err","status","cause","String","undefined","generateAIMetadata","request","fileIds","validateGenerateAIMetadataBody","generateForFiles","data","getLatestAIMetadataJob","notFound","job","getLatestActiveJob"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { merge } from 'lodash/fp';
1
+ import { merge } from 'lodash';
2
2
  import { async } from '@strapi/utils';
3
3
  import { getService } from '../utils/index.mjs';
4
4
  import { FILE_MODEL_UID, ACTIONS } from '../constants.mjs';
@@ -25,7 +25,7 @@ var adminFile = {
25
25
  await pm.validateQuery(ctx.query);
26
26
  const query = await async.pipe(// Start by sanitizing the incoming query
27
27
  (q)=>pm.sanitizeQuery(q), // Add the default query which should not be validated or sanitized
28
- (q)=>merge(defaultQuery, q), // Add the dynamic filters based on permissions' conditions
28
+ (q)=>merge({}, defaultQuery, q), // Add the dynamic filters based on permissions' conditions
29
29
  (q)=>pm.addPermissionsQueryTo(q))(ctx.query);
30
30
  const { results: files, pagination } = await getService('upload').findPage(query);
31
31
  // Sign file urls for private providers
@@ -1 +1 @@
1
- {"version":3,"file":"admin-file.mjs","sources":["../../../server/src/controllers/admin-file.ts"],"sourcesContent":["import { merge } from 'lodash/fp';\nimport { async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { validateGenerateAIMetadataBody } from './validation/admin/ai-metadata';\n\nexport default {\n async find(ctx: Context) {\n const {\n state: { userAbility },\n } = ctx;\n\n const defaultQuery = { populate: { folder: true } };\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // validate the incoming user query params\n await pm.validateQuery(ctx.query);\n\n const query = await async.pipe(\n // Start by sanitizing the incoming query\n (q) => pm.sanitizeQuery(q),\n // Add the default query which should not be validated or sanitized\n (q) => merge(defaultQuery, q),\n // Add the dynamic filters based on permissions' conditions\n (q) => pm.addPermissionsQueryTo(q)\n )(ctx.query);\n\n const { results: files, pagination } = await getService('upload').findPage(query);\n\n // Sign file urls for private providers\n const signedFiles = await async.map(files, getService('file').signFileUrls);\n\n const sanitizedFiles = await pm.sanitizeOutput(signedFiles);\n\n return { results: sanitizedFiles, pagination };\n },\n\n async findOne(ctx: Context) {\n const {\n state: { userAbility },\n params: { id },\n } = ctx;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.read,\n FILE_MODEL_UID,\n id\n );\n\n const signedFile = await getService('file').signFileUrls(file);\n ctx.body = await pm.sanitizeOutput(signedFile);\n },\n\n async destroy(ctx: Context) {\n const { id } = ctx.params;\n const { userAbility } = ctx.state;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const [body] = await Promise.all([\n pm.sanitizeOutput(file, { action: ACTIONS.read }),\n getService('upload').remove(file),\n ]);\n\n ctx.body = body;\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/pending-count`\n *\n * How many images a backfill job would have to process, i.e. those still\n * missing AI metadata, alongside the total image count.\n */\n async getAIMetadataPendingCount(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n const { imagesWithoutMetadataCount, totalImages } =\n await aiMetadataService.countImagesWithoutMetadata();\n\n ctx.body = {\n imagesWithoutMetadataCount,\n totalImages,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to get AI metadata count';\n\n strapi.log.error('Failed to get AI metadata count', {\n message,\n error,\n });\n\n ctx.badRequest(message);\n }\n },\n\n /**\n * `POST /upload/ai-metadata-jobs`\n *\n * Create a backfill job that generates AI metadata for every image still\n * missing it, and return the job so the client can poll it. Processing runs\n * detached from this request; see `generateAIMetadata` for the synchronous\n * counterpart that works on an explicit selection.\n */\n async createAIMetadataJob(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n // Get count first to check if there are images to process\n const result = await aiMetadataService.countImagesWithoutMetadata();\n\n if (result.imagesWithoutMetadataCount === 0) {\n ctx.body = {\n count: 0,\n message: 'No images without metadata found',\n };\n return;\n }\n\n // Create job\n const jobService = getService('aiMetadataJobs');\n const jobId = await jobService.createJob();\n\n // Start async processing (fire and forget)\n aiMetadataService.processExistingFiles(jobId, ctx.state.user).catch((err: Error) => {\n strapi.log.error('AI metadata job failed:', err);\n });\n\n // Return immediately with job ID\n ctx.body = {\n jobId,\n status: 'pending',\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to generate AI metadata';\n const cause = error instanceof Error && error.cause ? String(error.cause) : undefined;\n\n strapi.log.error('AI metadata generation failed in controller', {\n message,\n cause,\n error,\n });\n\n ctx.badRequest(cause ? `${message}: ${cause}` : message);\n }\n },\n\n /**\n * `POST /upload/actions/generate-ai-metadata`\n *\n * Generate AI metadata for the explicit selection of files in the body,\n * synchronously: the request resolves once every file has been processed and\n * reports the outcome per file, so a single bad id or a non-image in the\n * selection never fails the whole batch.\n *\n * For the whole-library backfill, see `createAIMetadataJob`.\n */\n async generateAIMetadata(ctx: Context) {\n const { userAbility } = ctx.state;\n const { body } = ctx.request;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const { fileIds } = await validateGenerateAIMetadataBody(body);\n\n const aiMetadataService = getService('aiMetadata');\n\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n const results = await aiMetadataService.generateForFiles(fileIds, ctx.state.user);\n\n ctx.body = { data: results };\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/latest`\n *\n * The most recent still-active backfill job, so a client that reloads mid-run\n * can pick the progress bar back up. 404s when nothing is running.\n */\n async getLatestAIMetadataJob(ctx: Context) {\n if ((await getService('aiMetadata').isEnabled()) === false) {\n return ctx.notFound();\n }\n\n const jobService = getService('aiMetadataJobs');\n const job = await jobService.getLatestActiveJob();\n\n if (!job) {\n return ctx.notFound('No active job found');\n }\n\n ctx.body = job;\n },\n};\n"],"names":["find","ctx","state","userAbility","defaultQuery","populate","folder","pm","strapi","service","createPermissionsManager","ability","action","ACTIONS","read","model","FILE_MODEL_UID","isAllowed","forbidden","validateQuery","query","async","pipe","q","sanitizeQuery","merge","addPermissionsQueryTo","results","files","pagination","getService","findPage","signedFiles","map","signFileUrls","sanitizedFiles","sanitizeOutput","findOne","params","id","file","findEntityAndCheckPermissions","signedFile","body","destroy","update","Promise","all","remove","getAIMetadataPendingCount","aiMetadataService","isEnabled","badRequest","imagesWithoutMetadataCount","totalImages","countImagesWithoutMetadata","error","message","Error","log","createAIMetadataJob","result","count","jobService","jobId","createJob","processExistingFiles","user","catch","err","status","cause","String","undefined","generateAIMetadata","request","fileIds","validateGenerateAIMetadataBody","generateForFiles","data","getLatestAIMetadataJob","notFound","job","getLatestActiveJob"],"mappings":"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"}
1
+ {"version":3,"file":"admin-file.mjs","sources":["../../../server/src/controllers/admin-file.ts"],"sourcesContent":["import { merge } from 'lodash';\nimport { async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { validateGenerateAIMetadataBody } from './validation/admin/ai-metadata';\n\nexport default {\n async find(ctx: Context) {\n const {\n state: { userAbility },\n } = ctx;\n\n const defaultQuery = { populate: { folder: true } };\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // validate the incoming user query params\n await pm.validateQuery(ctx.query);\n\n const query = await async.pipe(\n // Start by sanitizing the incoming query\n (q) => pm.sanitizeQuery(q),\n // Add the default query which should not be validated or sanitized\n (q) => merge({}, defaultQuery, q),\n // Add the dynamic filters based on permissions' conditions\n (q) => pm.addPermissionsQueryTo(q)\n )(ctx.query);\n\n const { results: files, pagination } = await getService('upload').findPage(query);\n\n // Sign file urls for private providers\n const signedFiles = await async.map(files, getService('file').signFileUrls);\n\n const sanitizedFiles = await pm.sanitizeOutput(signedFiles);\n\n return { results: sanitizedFiles, pagination };\n },\n\n async findOne(ctx: Context) {\n const {\n state: { userAbility },\n params: { id },\n } = ctx;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.read,\n FILE_MODEL_UID,\n id\n );\n\n const signedFile = await getService('file').signFileUrls(file);\n ctx.body = await pm.sanitizeOutput(signedFile);\n },\n\n async destroy(ctx: Context) {\n const { id } = ctx.params;\n const { userAbility } = ctx.state;\n\n const { pm, file } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const [body] = await Promise.all([\n pm.sanitizeOutput(file, { action: ACTIONS.read }),\n getService('upload').remove(file),\n ]);\n\n ctx.body = body;\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/pending-count`\n *\n * How many images a backfill job would have to process, i.e. those still\n * missing AI metadata, alongside the total image count.\n */\n async getAIMetadataPendingCount(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n const { imagesWithoutMetadataCount, totalImages } =\n await aiMetadataService.countImagesWithoutMetadata();\n\n ctx.body = {\n imagesWithoutMetadataCount,\n totalImages,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to get AI metadata count';\n\n strapi.log.error('Failed to get AI metadata count', {\n message,\n error,\n });\n\n ctx.badRequest(message);\n }\n },\n\n /**\n * `POST /upload/ai-metadata-jobs`\n *\n * Create a backfill job that generates AI metadata for every image still\n * missing it, and return the job so the client can poll it. Processing runs\n * detached from this request; see `generateAIMetadata` for the synchronous\n * counterpart that works on an explicit selection.\n */\n async createAIMetadataJob(ctx: Context) {\n const { userAbility } = ctx.state;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // Check if AI service is enabled\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n try {\n // Get count first to check if there are images to process\n const result = await aiMetadataService.countImagesWithoutMetadata();\n\n if (result.imagesWithoutMetadataCount === 0) {\n ctx.body = {\n count: 0,\n message: 'No images without metadata found',\n };\n return;\n }\n\n // Create job\n const jobService = getService('aiMetadataJobs');\n const jobId = await jobService.createJob();\n\n // Start async processing (fire and forget)\n aiMetadataService.processExistingFiles(jobId, ctx.state.user).catch((err: Error) => {\n strapi.log.error('AI metadata job failed:', err);\n });\n\n // Return immediately with job ID\n ctx.body = {\n jobId,\n status: 'pending',\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to generate AI metadata';\n const cause = error instanceof Error && error.cause ? String(error.cause) : undefined;\n\n strapi.log.error('AI metadata generation failed in controller', {\n message,\n cause,\n error,\n });\n\n ctx.badRequest(cause ? `${message}: ${cause}` : message);\n }\n },\n\n /**\n * `POST /upload/actions/generate-ai-metadata`\n *\n * Generate AI metadata for the explicit selection of files in the body,\n * synchronously: the request resolves once every file has been processed and\n * reports the outcome per file, so a single bad id or a non-image in the\n * selection never fails the whole batch.\n *\n * For the whole-library backfill, see `createAIMetadataJob`.\n */\n async generateAIMetadata(ctx: Context) {\n const { userAbility } = ctx.state;\n const { body } = ctx.request;\n\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const { fileIds } = await validateGenerateAIMetadataBody(body);\n\n const aiMetadataService = getService('aiMetadata');\n\n if (!(await aiMetadataService.isEnabled())) {\n return ctx.badRequest('AI Metadata service is not enabled');\n }\n\n const results = await aiMetadataService.generateForFiles(fileIds, ctx.state.user);\n\n ctx.body = { data: results };\n },\n\n /**\n * `GET /upload/ai-metadata-jobs/latest`\n *\n * The most recent still-active backfill job, so a client that reloads mid-run\n * can pick the progress bar back up. 404s when nothing is running.\n */\n async getLatestAIMetadataJob(ctx: Context) {\n if ((await getService('aiMetadata').isEnabled()) === false) {\n return ctx.notFound();\n }\n\n const jobService = getService('aiMetadataJobs');\n const job = await jobService.getLatestActiveJob();\n\n if (!job) {\n return ctx.notFound('No active job found');\n }\n\n ctx.body = job;\n },\n};\n"],"names":["find","ctx","state","userAbility","defaultQuery","populate","folder","pm","strapi","service","createPermissionsManager","ability","action","ACTIONS","read","model","FILE_MODEL_UID","isAllowed","forbidden","validateQuery","query","async","pipe","q","sanitizeQuery","merge","addPermissionsQueryTo","results","files","pagination","getService","findPage","signedFiles","map","signFileUrls","sanitizedFiles","sanitizeOutput","findOne","params","id","file","findEntityAndCheckPermissions","signedFile","body","destroy","update","Promise","all","remove","getAIMetadataPendingCount","aiMetadataService","isEnabled","badRequest","imagesWithoutMetadataCount","totalImages","countImagesWithoutMetadata","error","message","Error","log","createAIMetadataJob","result","count","jobService","jobId","createJob","processExistingFiles","user","catch","err","status","cause","String","undefined","generateAIMetadata","request","fileIds","validateGenerateAIMetadataBody","generateForFiles","data","getLatestAIMetadataJob","notFound","job","getLatestActiveJob"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var fp = require('lodash/fp');
3
+ var _ = require('lodash');
4
4
  var index = require('../utils/index.js');
5
5
  var constants = require('../constants.js');
6
6
  var folder = require('./validation/admin/folder.js');
@@ -14,7 +14,7 @@ var adminFolder = {
14
14
  });
15
15
  await permissionsManager.validateQuery(ctx.query);
16
16
  const query = await permissionsManager.sanitizeQuery(ctx.query);
17
- const { results } = await strapi.db.query(constants.FOLDER_MODEL_UID).findPage(strapi.get('query-params').transform(constants.FOLDER_MODEL_UID, fp.defaultsDeep({
17
+ const { results } = await strapi.db.query(constants.FOLDER_MODEL_UID).findPage(strapi.get('query-params').transform(constants.FOLDER_MODEL_UID, _.defaultsDeep({}, query, {
18
18
  filters: {
19
19
  id
20
20
  },
@@ -26,7 +26,7 @@ var adminFolder = {
26
26
  count: true
27
27
  }
28
28
  }
29
- }, query)));
29
+ })));
30
30
  if (results.length === 0) {
31
31
  return ctx.notFound('folder not found');
32
32
  }
@@ -41,7 +41,7 @@ var adminFolder = {
41
41
  });
42
42
  await permissionsManager.validateQuery(ctx.query);
43
43
  const query = await permissionsManager.sanitizeQuery(ctx.query);
44
- const results = await strapi.db.query(constants.FOLDER_MODEL_UID).findMany(strapi.get('query-params').transform(constants.FOLDER_MODEL_UID, fp.defaultsDeep({
44
+ const results = await strapi.db.query(constants.FOLDER_MODEL_UID).findMany(strapi.get('query-params').transform(constants.FOLDER_MODEL_UID, _.defaultsDeep({}, query, {
45
45
  populate: {
46
46
  children: {
47
47
  count: true
@@ -50,7 +50,7 @@ var adminFolder = {
50
50
  count: true
51
51
  }
52
52
  }
53
- }, query)));
53
+ })));
54
54
  ctx.body = {
55
55
  data: await permissionsManager.sanitizeOutput(results)
56
56
  };
@@ -1 +1 @@
1
- {"version":3,"file":"admin-folder.js","sources":["../../../server/src/controllers/admin-folder.ts"],"sourcesContent":["import { defaultsDeep } from 'lodash/fp';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { FOLDER_MODEL_UID } from '../constants';\nimport { validateCreateFolder, validateUpdateFolder } from './validation/admin/folder';\n\nexport default {\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const { results } = await strapi.db.query(FOLDER_MODEL_UID).findPage(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep(\n {\n filters: { id },\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n },\n query\n )\n )\n );\n\n if (results.length === 0) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results[0]),\n };\n },\n\n async find(ctx: Context) {\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const results = await strapi.db.query(FOLDER_MODEL_UID).findMany(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep(\n {\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n },\n query\n )\n )\n );\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results),\n };\n },\n async create(ctx: Context) {\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n await validateCreateFolder(body);\n\n const folderService = getService('folder');\n\n const folder = await folderService.create(body, { user });\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n ctx.created({\n data: await permissionsManager.sanitizeOutput(folder),\n });\n },\n\n async update(ctx: Context) {\n const { id } = ctx.params;\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await validateUpdateFolder(id)(body);\n\n const folderService = getService('folder');\n\n const updatedFolder = await folderService.update(id, body, { user });\n\n if (!updatedFolder) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(updatedFolder),\n };\n },\n\n async getStructure(ctx: Context) {\n const { getStructure } = getService('folder');\n\n const structure = await getStructure();\n\n ctx.body = {\n data: structure,\n };\n },\n};\n"],"names":["findOne","ctx","id","params","permissionsManager","strapi","service","createPermissionsManager","ability","state","userAbility","model","FOLDER_MODEL_UID","validateQuery","query","sanitizeQuery","results","db","findPage","get","transform","defaultsDeep","filters","populate","children","count","files","length","notFound","body","data","sanitizeOutput","find","findMany","create","user","request","validateCreateFolder","folderService","getService","folder","created","update","validateUpdateFolder","updatedFolder","getStructure","structure"],"mappings":";;;;;;;AAQA,kBAAe;AACb,IAAA,MAAMA,SAAQC,GAAY,EAAA;AACxB,QAAA,MAAM,EAAEC,EAAE,EAAE,GAAGD,IAAIE,MAAM;AAEzB,QAAA,MAAMC,qBAAqBC,MAAAA,CAAOC,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtFC,OAAAA,EAASP,GAAAA,CAAIQ,KAAK,CAACC,WAAW;YAC9BC,KAAAA,EAAOC;AACT,SAAA,CAAA;AAEA,QAAA,MAAMR,kBAAAA,CAAmBS,aAAa,CAACZ,GAAAA,CAAIa,KAAK,CAAA;AAChD,QAAA,MAAMA,QAAQ,MAAMV,kBAAAA,CAAmBW,aAAa,CAACd,IAAIa,KAAK,CAAA;QAE9D,MAAM,EAAEE,OAAO,EAAE,GAAG,MAAMX,MAAAA,CAAOY,EAAE,CAACH,KAAK,CAACF,4BAAkBM,QAAQ,CAClEb,OAAOc,GAAG,CAAC,gBAAgBC,SAAS,CAClCR,4BACAS,eAAAA,CACE;YACEC,OAAAA,EAAS;AAAEpB,gBAAAA;AAAG,aAAA;YACdqB,QAAAA,EAAU;gBACRC,QAAAA,EAAU;oBACRC,KAAAA,EAAO;AACT,iBAAA;gBACAC,KAAAA,EAAO;oBACLD,KAAAA,EAAO;AACT;AACF;SACF,EACAX,KAAAA,CAAAA,CAAAA,CAAAA;QAKN,IAAIE,OAAAA,CAAQW,MAAM,KAAK,CAAA,EAAG;YACxB,OAAO1B,GAAAA,CAAI2B,QAAQ,CAAC,kBAAA,CAAA;AACtB,QAAA;AAEA3B,QAAAA,GAAAA,CAAI4B,IAAI,GAAG;AACTC,YAAAA,IAAAA,EAAM,MAAM1B,kBAAAA,CAAmB2B,cAAc,CAACf,OAAO,CAAC,CAAA,CAAE;AAC1D,SAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMgB,MAAK/B,GAAY,EAAA;AACrB,QAAA,MAAMG,qBAAqBC,MAAAA,CAAOC,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtFC,OAAAA,EAASP,GAAAA,CAAIQ,KAAK,CAACC,WAAW;YAC9BC,KAAAA,EAAOC;AACT,SAAA,CAAA;AAEA,QAAA,MAAMR,kBAAAA,CAAmBS,aAAa,CAACZ,GAAAA,CAAIa,KAAK,CAAA;AAChD,QAAA,MAAMA,QAAQ,MAAMV,kBAAAA,CAAmBW,aAAa,CAACd,IAAIa,KAAK,CAAA;AAE9D,QAAA,MAAME,UAAU,MAAMX,MAAAA,CAAOY,EAAE,CAACH,KAAK,CAACF,0BAAAA,CAAAA,CAAkBqB,QAAQ,CAC9D5B,OAAOc,GAAG,CAAC,gBAAgBC,SAAS,CAClCR,4BACAS,eAAAA,CACE;YACEE,QAAAA,EAAU;gBACRC,QAAAA,EAAU;oBACRC,KAAAA,EAAO;AACT,iBAAA;gBACAC,KAAAA,EAAO;oBACLD,KAAAA,EAAO;AACT;AACF;SACF,EACAX,KAAAA,CAAAA,CAAAA,CAAAA;AAKNb,QAAAA,GAAAA,CAAI4B,IAAI,GAAG;YACTC,IAAAA,EAAM,MAAM1B,kBAAAA,CAAmB2B,cAAc,CAACf,OAAAA;AAChD,SAAA;AACF,IAAA,CAAA;AACA,IAAA,MAAMkB,QAAOjC,GAAY,EAAA;AACvB,QAAA,MAAM,EAAEkC,IAAI,EAAE,GAAGlC,IAAIQ,KAAK;AAC1B,QAAA,MAAM,EAAEoB,IAAI,EAAE,GAAG5B,IAAImC,OAAO;AAE5B,QAAA,MAAMC,2BAAAA,CAAqBR,IAAAA,CAAAA;AAE3B,QAAA,MAAMS,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AAEjC,QAAA,MAAMC,QAAAA,GAAS,MAAMF,aAAAA,CAAcJ,MAAM,CAACL,IAAAA,EAAM;AAAEM,YAAAA;AAAK,SAAA,CAAA;AAEvD,QAAA,MAAM/B,qBAAqBC,MAAAA,CAAOC,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtFC,OAAAA,EAASP,GAAAA,CAAIQ,KAAK,CAACC,WAAW;YAC9BC,KAAAA,EAAOC;AACT,SAAA,CAAA;AAEAX,QAAAA,GAAAA,CAAIwC,OAAO,CAAC;YACVX,IAAAA,EAAM,MAAM1B,kBAAAA,CAAmB2B,cAAc,CAACS,QAAAA;AAChD,SAAA,CAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAME,QAAOzC,GAAY,EAAA;AACvB,QAAA,MAAM,EAAEC,EAAE,EAAE,GAAGD,IAAIE,MAAM;AACzB,QAAA,MAAM,EAAEgC,IAAI,EAAE,GAAGlC,IAAIQ,KAAK;AAC1B,QAAA,MAAM,EAAEoB,IAAI,EAAE,GAAG5B,IAAImC,OAAO;AAE5B,QAAA,MAAMhC,qBAAqBC,MAAAA,CAAOC,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtFC,OAAAA,EAASP,GAAAA,CAAIQ,KAAK,CAACC,WAAW;YAC9BC,KAAAA,EAAOC;AACT,SAAA,CAAA;AAEA,QAAA,MAAM+B,4BAAqBzC,EAAAA,CAAAA,CAAI2B,IAAAA,CAAAA;AAE/B,QAAA,MAAMS,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AAEjC,QAAA,MAAMK,gBAAgB,MAAMN,aAAAA,CAAcI,MAAM,CAACxC,IAAI2B,IAAAA,EAAM;AAAEM,YAAAA;AAAK,SAAA,CAAA;AAElE,QAAA,IAAI,CAACS,aAAAA,EAAe;YAClB,OAAO3C,GAAAA,CAAI2B,QAAQ,CAAC,kBAAA,CAAA;AACtB,QAAA;AAEA3B,QAAAA,GAAAA,CAAI4B,IAAI,GAAG;YACTC,IAAAA,EAAM,MAAM1B,kBAAAA,CAAmB2B,cAAc,CAACa,aAAAA;AAChD,SAAA;AACF,IAAA,CAAA;AAEA,IAAA,MAAMC,cAAa5C,GAAY,EAAA;AAC7B,QAAA,MAAM,EAAE4C,YAAY,EAAE,GAAGN,gBAAAA,CAAW,QAAA,CAAA;AAEpC,QAAA,MAAMO,YAAY,MAAMD,YAAAA,EAAAA;AAExB5C,QAAAA,GAAAA,CAAI4B,IAAI,GAAG;YACTC,IAAAA,EAAMgB;AACR,SAAA;AACF,IAAA;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"admin-folder.js","sources":["../../../server/src/controllers/admin-folder.ts"],"sourcesContent":["import { defaultsDeep } from 'lodash';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { FOLDER_MODEL_UID } from '../constants';\nimport { validateCreateFolder, validateUpdateFolder } from './validation/admin/folder';\n\nexport default {\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const { results } = await strapi.db.query(FOLDER_MODEL_UID).findPage(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep({}, query, {\n filters: { id },\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n })\n )\n );\n\n if (results.length === 0) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results[0]),\n };\n },\n\n async find(ctx: Context) {\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const results = await strapi.db.query(FOLDER_MODEL_UID).findMany(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep({}, query, {\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n })\n )\n );\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results),\n };\n },\n async create(ctx: Context) {\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n await validateCreateFolder(body);\n\n const folderService = getService('folder');\n\n const folder = await folderService.create(body, { user });\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n ctx.created({\n data: await permissionsManager.sanitizeOutput(folder),\n });\n },\n\n async update(ctx: Context) {\n const { id } = ctx.params;\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await validateUpdateFolder(id)(body);\n\n const folderService = getService('folder');\n\n const updatedFolder = await folderService.update(id, body, { user });\n\n if (!updatedFolder) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(updatedFolder),\n };\n },\n\n async getStructure(ctx: Context) {\n const { getStructure } = getService('folder');\n\n const structure = await getStructure();\n\n ctx.body = {\n data: structure,\n };\n },\n};\n"],"names":["findOne","ctx","id","params","permissionsManager","strapi","service","createPermissionsManager","ability","state","userAbility","model","FOLDER_MODEL_UID","validateQuery","query","sanitizeQuery","results","db","findPage","get","transform","defaultsDeep","filters","populate","children","count","files","length","notFound","body","data","sanitizeOutput","find","findMany","create","user","request","validateCreateFolder","folderService","getService","folder","created","update","validateUpdateFolder","updatedFolder","getStructure","structure"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { defaultsDeep } from 'lodash/fp';
1
+ import { defaultsDeep } from 'lodash';
2
2
  import { getService } from '../utils/index.mjs';
3
3
  import { FOLDER_MODEL_UID } from '../constants.mjs';
4
4
  import { validateUpdateFolder, validateCreateFolder } from './validation/admin/folder.mjs';
@@ -12,7 +12,7 @@ var adminFolder = {
12
12
  });
13
13
  await permissionsManager.validateQuery(ctx.query);
14
14
  const query = await permissionsManager.sanitizeQuery(ctx.query);
15
- const { results } = await strapi.db.query(FOLDER_MODEL_UID).findPage(strapi.get('query-params').transform(FOLDER_MODEL_UID, defaultsDeep({
15
+ const { results } = await strapi.db.query(FOLDER_MODEL_UID).findPage(strapi.get('query-params').transform(FOLDER_MODEL_UID, defaultsDeep({}, query, {
16
16
  filters: {
17
17
  id
18
18
  },
@@ -24,7 +24,7 @@ var adminFolder = {
24
24
  count: true
25
25
  }
26
26
  }
27
- }, query)));
27
+ })));
28
28
  if (results.length === 0) {
29
29
  return ctx.notFound('folder not found');
30
30
  }
@@ -39,7 +39,7 @@ var adminFolder = {
39
39
  });
40
40
  await permissionsManager.validateQuery(ctx.query);
41
41
  const query = await permissionsManager.sanitizeQuery(ctx.query);
42
- const results = await strapi.db.query(FOLDER_MODEL_UID).findMany(strapi.get('query-params').transform(FOLDER_MODEL_UID, defaultsDeep({
42
+ const results = await strapi.db.query(FOLDER_MODEL_UID).findMany(strapi.get('query-params').transform(FOLDER_MODEL_UID, defaultsDeep({}, query, {
43
43
  populate: {
44
44
  children: {
45
45
  count: true
@@ -48,7 +48,7 @@ var adminFolder = {
48
48
  count: true
49
49
  }
50
50
  }
51
- }, query)));
51
+ })));
52
52
  ctx.body = {
53
53
  data: await permissionsManager.sanitizeOutput(results)
54
54
  };
@@ -1 +1 @@
1
- {"version":3,"file":"admin-folder.mjs","sources":["../../../server/src/controllers/admin-folder.ts"],"sourcesContent":["import { defaultsDeep } from 'lodash/fp';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { FOLDER_MODEL_UID } from '../constants';\nimport { validateCreateFolder, validateUpdateFolder } from './validation/admin/folder';\n\nexport default {\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const { results } = await strapi.db.query(FOLDER_MODEL_UID).findPage(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep(\n {\n filters: { id },\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n },\n query\n )\n )\n );\n\n if (results.length === 0) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results[0]),\n };\n },\n\n async find(ctx: Context) {\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const results = await strapi.db.query(FOLDER_MODEL_UID).findMany(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep(\n {\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n },\n query\n )\n )\n );\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results),\n };\n },\n async create(ctx: Context) {\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n await validateCreateFolder(body);\n\n const folderService = getService('folder');\n\n const folder = await folderService.create(body, { user });\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n ctx.created({\n data: await permissionsManager.sanitizeOutput(folder),\n });\n },\n\n async update(ctx: Context) {\n const { id } = ctx.params;\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await validateUpdateFolder(id)(body);\n\n const folderService = getService('folder');\n\n const updatedFolder = await folderService.update(id, body, { user });\n\n if (!updatedFolder) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(updatedFolder),\n };\n },\n\n async getStructure(ctx: Context) {\n const { getStructure } = getService('folder');\n\n const structure = await getStructure();\n\n ctx.body = {\n data: structure,\n };\n },\n};\n"],"names":["findOne","ctx","id","params","permissionsManager","strapi","service","createPermissionsManager","ability","state","userAbility","model","FOLDER_MODEL_UID","validateQuery","query","sanitizeQuery","results","db","findPage","get","transform","defaultsDeep","filters","populate","children","count","files","length","notFound","body","data","sanitizeOutput","find","findMany","create","user","request","validateCreateFolder","folderService","getService","folder","created","update","validateUpdateFolder","updatedFolder","getStructure","structure"],"mappings":"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"}
1
+ {"version":3,"file":"admin-folder.mjs","sources":["../../../server/src/controllers/admin-folder.ts"],"sourcesContent":["import { defaultsDeep } from 'lodash';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { FOLDER_MODEL_UID } from '../constants';\nimport { validateCreateFolder, validateUpdateFolder } from './validation/admin/folder';\n\nexport default {\n async findOne(ctx: Context) {\n const { id } = ctx.params;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const { results } = await strapi.db.query(FOLDER_MODEL_UID).findPage(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep({}, query, {\n filters: { id },\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n })\n )\n );\n\n if (results.length === 0) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results[0]),\n };\n },\n\n async find(ctx: Context) {\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await permissionsManager.validateQuery(ctx.query);\n const query = await permissionsManager.sanitizeQuery(ctx.query);\n\n const results = await strapi.db.query(FOLDER_MODEL_UID).findMany(\n strapi.get('query-params').transform(\n FOLDER_MODEL_UID,\n defaultsDeep({}, query, {\n populate: {\n children: {\n count: true,\n },\n files: {\n count: true,\n },\n },\n })\n )\n );\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(results),\n };\n },\n async create(ctx: Context) {\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n await validateCreateFolder(body);\n\n const folderService = getService('folder');\n\n const folder = await folderService.create(body, { user });\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n ctx.created({\n data: await permissionsManager.sanitizeOutput(folder),\n });\n },\n\n async update(ctx: Context) {\n const { id } = ctx.params;\n const { user } = ctx.state;\n const { body } = ctx.request;\n\n const permissionsManager = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n await validateUpdateFolder(id)(body);\n\n const folderService = getService('folder');\n\n const updatedFolder = await folderService.update(id, body, { user });\n\n if (!updatedFolder) {\n return ctx.notFound('folder not found');\n }\n\n ctx.body = {\n data: await permissionsManager.sanitizeOutput(updatedFolder),\n };\n },\n\n async getStructure(ctx: Context) {\n const { getStructure } = getService('folder');\n\n const structure = await getStructure();\n\n ctx.body = {\n data: structure,\n };\n },\n};\n"],"names":["findOne","ctx","id","params","permissionsManager","strapi","service","createPermissionsManager","ability","state","userAbility","model","FOLDER_MODEL_UID","validateQuery","query","sanitizeQuery","results","db","findPage","get","transform","defaultsDeep","filters","populate","children","count","files","length","notFound","body","data","sanitizeOutput","find","findMany","create","user","request","validateCreateFolder","folderService","getService","folder","created","update","validateUpdateFolder","updatedFolder","getStructure","structure"],"mappings":"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"}
@@ -11,7 +11,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
12
12
  var ___default = /*#__PURE__*/_interopDefault(_);
13
13
 
14
- const { ValidationError } = utils.errors;
14
+ const { ValidationError, NotFoundError } = utils.errors;
15
15
  var contentApi = (({ strapi })=>{
16
16
  const sanitizeOutput = async (data, ctx)=>{
17
17
  const schema = strapi.getModel(constants.FILE_MODEL_UID);
@@ -36,6 +36,21 @@ var contentApi = (({ strapi })=>{
36
36
  route
37
37
  });
38
38
  };
39
+ // Files can be addressed by numeric id or documentId (1:1, files have no draft & publish)
40
+ const resolveFileId = async (id)=>{
41
+ if (/^\d+$/.test(String(id))) {
42
+ return id;
43
+ }
44
+ const file = await strapi.db.query(constants.FILE_MODEL_UID).findOne({
45
+ where: {
46
+ documentId: id
47
+ },
48
+ select: [
49
+ 'id'
50
+ ]
51
+ });
52
+ return file?.id;
53
+ };
39
54
  return {
40
55
  async find (ctx) {
41
56
  await validateQuery(ctx.query, ctx);
@@ -57,10 +72,10 @@ var contentApi = (({ strapi })=>{
57
72
  };
58
73
  },
59
74
  async findOne (ctx) {
60
- const { params: { id } } = ctx;
61
75
  await validateQuery(ctx.query, ctx);
62
76
  const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);
63
- const file = await index.getService('upload').findOne(id, sanitizedQuery.populate);
77
+ const id = await resolveFileId(ctx.params.id);
78
+ const file = id ? await index.getService('upload').findOne(id, sanitizedQuery.populate) : null;
64
79
  if (!file) {
65
80
  return ctx.notFound('file.notFound');
66
81
  }
@@ -68,8 +83,8 @@ var contentApi = (({ strapi })=>{
68
83
  ctx.body = await sanitizeOutput(signedFile, ctx);
69
84
  },
70
85
  async destroy (ctx) {
71
- const { params: { id } } = ctx;
72
- const file = await index.getService('upload').findOne(id);
86
+ const id = await resolveFileId(ctx.params.id);
87
+ const file = id ? await index.getService('upload').findOne(id) : null;
73
88
  if (!file) {
74
89
  return ctx.notFound('file.notFound');
75
90
  }
@@ -83,7 +98,11 @@ var contentApi = (({ strapi })=>{
83
98
  if (!id || typeof id !== 'string' && typeof id !== 'number') {
84
99
  throw new ValidationError('File id is required and must be a single value');
85
100
  }
86
- const result = await index.getService('upload').updateFileInfo(id, data.fileInfo);
101
+ const fileId = await resolveFileId(id);
102
+ if (!fileId) {
103
+ throw new NotFoundError();
104
+ }
105
+ const result = await index.getService('upload').updateFileInfo(fileId, data.fileInfo);
87
106
  const signedResult = await index.getService('file').signFileUrls(result);
88
107
  ctx.body = await sanitizeOutput(signedResult, ctx);
89
108
  },
@@ -101,8 +120,12 @@ var contentApi = (({ strapi })=>{
101
120
  if (!id || typeof id !== 'string' && typeof id !== 'number') {
102
121
  throw new ValidationError('File id is required and must be a single value');
103
122
  }
123
+ const fileId = await resolveFileId(id);
124
+ if (!fileId) {
125
+ throw new NotFoundError();
126
+ }
104
127
  const data = await upload.validateUploadBody(filteredBody);
105
- const replacedFiles = await index.getService('upload').replace(id, {
128
+ const replacedFiles = await index.getService('upload').replace(fileId, {
106
129
  data,
107
130
  file: validFiles[0]
108
131
  });
@@ -1 +1 @@
1
- {"version":3,"file":"content-api.js","sources":["../../../server/src/controllers/content-api.ts"],"sourcesContent":["import _ from 'lodash';\nimport { async, errors } from '@strapi/utils';\n\nimport type { Context } from 'koa';\nimport type { Core } from '@strapi/types';\n\nimport { getService } from '../utils';\nimport { FILE_MODEL_UID } from '../constants';\nimport { validateUploadBody } from './validation/content-api/upload';\nimport { FileInfo } from '../types';\nimport { prepareUploadRequest } from '../utils/mime-validation';\n\nconst { ValidationError } = errors;\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const sanitizeOutput = async (data: unknown | unknown[], ctx: Context) => {\n const schema = strapi.getModel(FILE_MODEL_UID);\n const { auth } = ctx.state;\n\n return strapi.contentAPI.sanitize.output(data, schema, { auth });\n };\n\n const validateQuery = async (data: Record<string, unknown>, ctx: Context) => {\n const schema = strapi.getModel(FILE_MODEL_UID);\n const { auth, route } = ctx.state;\n\n return strapi.contentAPI.validate.query(data, schema, { auth, route });\n };\n\n const sanitizeQuery = async (data: Record<string, unknown>, ctx: Context) => {\n const schema = strapi.getModel(FILE_MODEL_UID);\n const { auth, route } = ctx.state;\n\n return strapi.contentAPI.sanitize.query(data, schema, { auth, route });\n };\n\n return {\n async find(ctx: Context) {\n await validateQuery(ctx.query, ctx);\n const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);\n\n const files = await getService('upload').findMany(sanitizedQuery);\n\n const signedFiles = await async.map(files, getService('file').signFileUrls);\n\n ctx.body = await sanitizeOutput(signedFiles, ctx);\n },\n\n async findPage(ctx: Context) {\n await validateQuery(ctx.query, ctx);\n const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);\n\n const { results, pagination } = await getService('upload').findAndCountPage(sanitizedQuery);\n\n const data = await sanitizeOutput(results, ctx);\n\n ctx.body = { data, meta: { pagination } };\n },\n\n async findOne(ctx: Context) {\n const {\n params: { id },\n } = ctx;\n\n await validateQuery(ctx.query, ctx);\n const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);\n\n const file = await getService('upload').findOne(id, sanitizedQuery.populate!);\n\n if (!file) {\n return ctx.notFound('file.notFound');\n }\n\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await sanitizeOutput(signedFile, ctx);\n },\n\n async destroy(ctx: Context) {\n const {\n params: { id },\n } = ctx;\n\n const file = await getService('upload').findOne(id);\n\n if (!file) {\n return ctx.notFound('file.notFound');\n }\n\n await getService('upload').remove(file);\n\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await sanitizeOutput(signedFile, ctx);\n },\n\n async updateFileInfo(ctx: Context) {\n const {\n query: { id },\n request: { body },\n } = ctx;\n const data = await validateUploadBody(body);\n\n if (!id || (typeof id !== 'string' && typeof id !== 'number')) {\n throw new ValidationError('File id is required and must be a single value');\n }\n\n const result = await getService('upload').updateFileInfo(id, data.fileInfo as any);\n\n const signedResult = await getService('file').signFileUrls(result);\n\n ctx.body = await sanitizeOutput(signedResult, ctx);\n },\n\n async replaceFile(ctx: Context) {\n const {\n query: { id },\n request: { body, files: { files: filesInput } = {} },\n } = ctx;\n\n // cannot replace with more than one file\n if (Array.isArray(filesInput) && filesInput.length > 1) {\n throw new ValidationError('Cannot replace a file with multiple ones');\n }\n\n const files = Array.isArray(filesInput) ? filesInput[0] : filesInput;\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n if (!id || (typeof id !== 'string' && typeof id !== 'number')) {\n throw new ValidationError('File id is required and must be a single value');\n }\n\n const data = (await validateUploadBody(filteredBody)) as { fileInfo: FileInfo };\n\n const replacedFiles = await getService('upload').replace(id, { data, file: validFiles[0] });\n\n const signedFiles = await getService('file').signFileUrls(replacedFiles);\n\n ctx.body = await sanitizeOutput(signedFiles, ctx);\n },\n\n async uploadFiles(ctx: Context) {\n const {\n request: { body, files: { files: filesInput } = {} },\n } = ctx;\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(filesInput, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const isMultipleFiles = validFiles.length > 1;\n const data: any = await validateUploadBody(filteredBody, isMultipleFiles);\n\n const apiUploadFolderService = getService('api-upload-folder');\n\n const apiUploadFolder = await apiUploadFolderService.getAPIUploadFolder();\n\n if (isMultipleFiles) {\n data.fileInfo = data.fileInfo || [];\n data.fileInfo = validFiles.map((_f, i) => ({\n ...data.fileInfo[i],\n folder: apiUploadFolder.id,\n }));\n } else {\n data.fileInfo = { ...data.fileInfo, folder: apiUploadFolder.id };\n }\n\n const uploadedFiles = await getService('upload').upload({\n data,\n files: validFiles,\n });\n\n const signedFiles = await async.map(uploadedFiles as any[], getService('file').signFileUrls);\n\n ctx.body = await sanitizeOutput(signedFiles, ctx);\n ctx.status = 201;\n },\n\n // TODO: split into multiple endpoints\n async upload(ctx: Context) {\n const {\n query: { id },\n request: { files: { files } = {} },\n } = ctx;\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n if (id) {\n return this.updateFileInfo(ctx);\n }\n\n throw new ValidationError('Files are empty');\n }\n\n await (id ? this.replaceFile : this.uploadFiles)(ctx);\n },\n };\n};\n"],"names":["ValidationError","errors","strapi","sanitizeOutput","data","ctx","schema","getModel","FILE_MODEL_UID","auth","state","contentAPI","sanitize","output","validateQuery","route","validate","query","sanitizeQuery","find","sanitizedQuery","files","getService","findMany","signedFiles","async","map","signFileUrls","body","findPage","results","pagination","findAndCountPage","meta","findOne","params","id","file","populate","notFound","signedFile","destroy","remove","updateFileInfo","request","validateUploadBody","result","fileInfo","signedResult","replaceFile","filesInput","Array","isArray","length","validFiles","filteredBody","validationErrors","prepareUploadRequest","message","replacedFiles","replace","uploadFiles","isMultipleFiles","apiUploadFolderService","apiUploadFolder","getAPIUploadFolder","_f","i","folder","uploadedFiles","upload","status","_","isEmpty","size"],"mappings":"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"}
1
+ {"version":3,"file":"content-api.js","sources":["../../../server/src/controllers/content-api.ts"],"sourcesContent":["import _ from 'lodash';\nimport { async, errors } from '@strapi/utils';\n\nimport type { Context } from 'koa';\nimport type { Core } from '@strapi/types';\n\nimport { getService } from '../utils';\nimport { FILE_MODEL_UID } from '../constants';\nimport { validateUploadBody } from './validation/content-api/upload';\nimport { FileInfo } from '../types';\nimport { prepareUploadRequest } from '../utils/mime-validation';\n\nconst { ValidationError, NotFoundError } = errors;\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n const sanitizeOutput = async (data: unknown | unknown[], ctx: Context) => {\n const schema = strapi.getModel(FILE_MODEL_UID);\n const { auth } = ctx.state;\n\n return strapi.contentAPI.sanitize.output(data, schema, { auth });\n };\n\n const validateQuery = async (data: Record<string, unknown>, ctx: Context) => {\n const schema = strapi.getModel(FILE_MODEL_UID);\n const { auth, route } = ctx.state;\n\n return strapi.contentAPI.validate.query(data, schema, { auth, route });\n };\n\n const sanitizeQuery = async (data: Record<string, unknown>, ctx: Context) => {\n const schema = strapi.getModel(FILE_MODEL_UID);\n const { auth, route } = ctx.state;\n\n return strapi.contentAPI.sanitize.query(data, schema, { auth, route });\n };\n\n // Files can be addressed by numeric id or documentId (1:1, files have no draft & publish)\n const resolveFileId = async (id: string | number) => {\n if (/^\\d+$/.test(String(id))) {\n return id;\n }\n\n const file = await strapi.db\n .query(FILE_MODEL_UID)\n .findOne({ where: { documentId: id }, select: ['id'] });\n\n return file?.id;\n };\n\n return {\n async find(ctx: Context) {\n await validateQuery(ctx.query, ctx);\n const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);\n\n const files = await getService('upload').findMany(sanitizedQuery);\n\n const signedFiles = await async.map(files, getService('file').signFileUrls);\n\n ctx.body = await sanitizeOutput(signedFiles, ctx);\n },\n\n async findPage(ctx: Context) {\n await validateQuery(ctx.query, ctx);\n const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);\n\n const { results, pagination } = await getService('upload').findAndCountPage(sanitizedQuery);\n\n const data = await sanitizeOutput(results, ctx);\n\n ctx.body = { data, meta: { pagination } };\n },\n\n async findOne(ctx: Context) {\n await validateQuery(ctx.query, ctx);\n const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);\n\n const id = await resolveFileId(ctx.params.id);\n const file = id ? await getService('upload').findOne(id, sanitizedQuery.populate!) : null;\n\n if (!file) {\n return ctx.notFound('file.notFound');\n }\n\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await sanitizeOutput(signedFile, ctx);\n },\n\n async destroy(ctx: Context) {\n const id = await resolveFileId(ctx.params.id);\n const file = id ? await getService('upload').findOne(id) : null;\n\n if (!file) {\n return ctx.notFound('file.notFound');\n }\n\n await getService('upload').remove(file);\n\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await sanitizeOutput(signedFile, ctx);\n },\n\n async updateFileInfo(ctx: Context) {\n const {\n query: { id },\n request: { body },\n } = ctx;\n const data = await validateUploadBody(body);\n\n if (!id || (typeof id !== 'string' && typeof id !== 'number')) {\n throw new ValidationError('File id is required and must be a single value');\n }\n\n const fileId = await resolveFileId(id);\n\n if (!fileId) {\n throw new NotFoundError();\n }\n\n const result = await getService('upload').updateFileInfo(fileId, data.fileInfo as any);\n\n const signedResult = await getService('file').signFileUrls(result);\n\n ctx.body = await sanitizeOutput(signedResult, ctx);\n },\n\n async replaceFile(ctx: Context) {\n const {\n query: { id },\n request: { body, files: { files: filesInput } = {} },\n } = ctx;\n\n // cannot replace with more than one file\n if (Array.isArray(filesInput) && filesInput.length > 1) {\n throw new ValidationError('Cannot replace a file with multiple ones');\n }\n\n const files = Array.isArray(filesInput) ? filesInput[0] : filesInput;\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n if (!id || (typeof id !== 'string' && typeof id !== 'number')) {\n throw new ValidationError('File id is required and must be a single value');\n }\n\n const fileId = await resolveFileId(id);\n\n if (!fileId) {\n throw new NotFoundError();\n }\n\n const data = (await validateUploadBody(filteredBody)) as { fileInfo: FileInfo };\n\n const replacedFiles = await getService('upload').replace(fileId, {\n data,\n file: validFiles[0],\n });\n\n const signedFiles = await getService('file').signFileUrls(replacedFiles);\n\n ctx.body = await sanitizeOutput(signedFiles, ctx);\n },\n\n async uploadFiles(ctx: Context) {\n const {\n request: { body, files: { files: filesInput } = {} },\n } = ctx;\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(filesInput, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const isMultipleFiles = validFiles.length > 1;\n const data: any = await validateUploadBody(filteredBody, isMultipleFiles);\n\n const apiUploadFolderService = getService('api-upload-folder');\n\n const apiUploadFolder = await apiUploadFolderService.getAPIUploadFolder();\n\n if (isMultipleFiles) {\n data.fileInfo = data.fileInfo || [];\n data.fileInfo = validFiles.map((_f, i) => ({\n ...data.fileInfo[i],\n folder: apiUploadFolder.id,\n }));\n } else {\n data.fileInfo = { ...data.fileInfo, folder: apiUploadFolder.id };\n }\n\n const uploadedFiles = await getService('upload').upload({\n data,\n files: validFiles,\n });\n\n const signedFiles = await async.map(uploadedFiles as any[], getService('file').signFileUrls);\n\n ctx.body = await sanitizeOutput(signedFiles, ctx);\n ctx.status = 201;\n },\n\n // TODO: split into multiple endpoints\n async upload(ctx: Context) {\n const {\n query: { id },\n request: { files: { files } = {} },\n } = ctx;\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n if (id) {\n return this.updateFileInfo(ctx);\n }\n\n throw new ValidationError('Files are empty');\n }\n\n await (id ? this.replaceFile : this.uploadFiles)(ctx);\n },\n };\n};\n"],"names":["ValidationError","NotFoundError","errors","strapi","sanitizeOutput","data","ctx","schema","getModel","FILE_MODEL_UID","auth","state","contentAPI","sanitize","output","validateQuery","route","validate","query","sanitizeQuery","resolveFileId","id","test","String","file","db","findOne","where","documentId","select","find","sanitizedQuery","files","getService","findMany","signedFiles","async","map","signFileUrls","body","findPage","results","pagination","findAndCountPage","meta","params","populate","notFound","signedFile","destroy","remove","updateFileInfo","request","validateUploadBody","fileId","result","fileInfo","signedResult","replaceFile","filesInput","Array","isArray","length","validFiles","filteredBody","validationErrors","prepareUploadRequest","message","replacedFiles","replace","uploadFiles","isMultipleFiles","apiUploadFolderService","apiUploadFolder","getAPIUploadFolder","_f","i","folder","uploadedFiles","upload","status","_","isEmpty","size"],"mappings":"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"}
@@ -5,7 +5,7 @@ import { FILE_MODEL_UID } from '../constants.mjs';
5
5
  import { validateUploadBody } from './validation/content-api/upload.mjs';
6
6
  import { prepareUploadRequest } from '../utils/mime-validation.mjs';
7
7
 
8
- const { ValidationError } = errors;
8
+ const { ValidationError, NotFoundError } = errors;
9
9
  var contentApi = (({ strapi })=>{
10
10
  const sanitizeOutput = async (data, ctx)=>{
11
11
  const schema = strapi.getModel(FILE_MODEL_UID);
@@ -30,6 +30,21 @@ var contentApi = (({ strapi })=>{
30
30
  route
31
31
  });
32
32
  };
33
+ // Files can be addressed by numeric id or documentId (1:1, files have no draft & publish)
34
+ const resolveFileId = async (id)=>{
35
+ if (/^\d+$/.test(String(id))) {
36
+ return id;
37
+ }
38
+ const file = await strapi.db.query(FILE_MODEL_UID).findOne({
39
+ where: {
40
+ documentId: id
41
+ },
42
+ select: [
43
+ 'id'
44
+ ]
45
+ });
46
+ return file?.id;
47
+ };
33
48
  return {
34
49
  async find (ctx) {
35
50
  await validateQuery(ctx.query, ctx);
@@ -51,10 +66,10 @@ var contentApi = (({ strapi })=>{
51
66
  };
52
67
  },
53
68
  async findOne (ctx) {
54
- const { params: { id } } = ctx;
55
69
  await validateQuery(ctx.query, ctx);
56
70
  const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);
57
- const file = await getService('upload').findOne(id, sanitizedQuery.populate);
71
+ const id = await resolveFileId(ctx.params.id);
72
+ const file = id ? await getService('upload').findOne(id, sanitizedQuery.populate) : null;
58
73
  if (!file) {
59
74
  return ctx.notFound('file.notFound');
60
75
  }
@@ -62,8 +77,8 @@ var contentApi = (({ strapi })=>{
62
77
  ctx.body = await sanitizeOutput(signedFile, ctx);
63
78
  },
64
79
  async destroy (ctx) {
65
- const { params: { id } } = ctx;
66
- const file = await getService('upload').findOne(id);
80
+ const id = await resolveFileId(ctx.params.id);
81
+ const file = id ? await getService('upload').findOne(id) : null;
67
82
  if (!file) {
68
83
  return ctx.notFound('file.notFound');
69
84
  }
@@ -77,7 +92,11 @@ var contentApi = (({ strapi })=>{
77
92
  if (!id || typeof id !== 'string' && typeof id !== 'number') {
78
93
  throw new ValidationError('File id is required and must be a single value');
79
94
  }
80
- const result = await getService('upload').updateFileInfo(id, data.fileInfo);
95
+ const fileId = await resolveFileId(id);
96
+ if (!fileId) {
97
+ throw new NotFoundError();
98
+ }
99
+ const result = await getService('upload').updateFileInfo(fileId, data.fileInfo);
81
100
  const signedResult = await getService('file').signFileUrls(result);
82
101
  ctx.body = await sanitizeOutput(signedResult, ctx);
83
102
  },
@@ -95,8 +114,12 @@ var contentApi = (({ strapi })=>{
95
114
  if (!id || typeof id !== 'string' && typeof id !== 'number') {
96
115
  throw new ValidationError('File id is required and must be a single value');
97
116
  }
117
+ const fileId = await resolveFileId(id);
118
+ if (!fileId) {
119
+ throw new NotFoundError();
120
+ }
98
121
  const data = await validateUploadBody(filteredBody);
99
- const replacedFiles = await getService('upload').replace(id, {
122
+ const replacedFiles = await getService('upload').replace(fileId, {
100
123
  data,
101
124
  file: validFiles[0]
102
125
  });