@strapi/upload 5.60.0 → 5.61.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 (91) hide show
  1. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.js +29 -0
  2. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.js.map +1 -0
  3. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.mjs +27 -0
  4. package/dist/admin/components/AssetPickerDialog/MediaLibraryPickerDialog.mjs.map +1 -0
  5. package/dist/admin/components/Drawer.js +12 -7
  6. package/dist/admin/components/Drawer.js.map +1 -1
  7. package/dist/admin/components/Drawer.mjs +12 -7
  8. package/dist/admin/components/Drawer.mjs.map +1 -1
  9. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.js +188 -0
  10. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.js.map +1 -0
  11. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.mjs +186 -0
  12. package/dist/admin/components/EditorFileDropZone/EditorFileDropZone.mjs.map +1 -0
  13. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.js +5 -1
  14. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.js.map +1 -1
  15. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs +5 -1
  16. package/dist/admin/components/MediaLibraryInput/AddAssetMenu.mjs.map +1 -1
  17. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js +37 -27
  18. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js.map +1 -1
  19. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs +37 -27
  20. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs.map +1 -1
  21. package/dist/admin/components/MediaLibraryInput/openAssetDetails.js +46 -0
  22. package/dist/admin/components/MediaLibraryInput/openAssetDetails.js.map +1 -0
  23. package/dist/admin/components/MediaLibraryInput/openAssetDetails.mjs +43 -0
  24. package/dist/admin/components/MediaLibraryInput/openAssetDetails.mjs.map +1 -0
  25. package/dist/admin/index.js +10 -1
  26. package/dist/admin/index.js.map +1 -1
  27. package/dist/admin/index.mjs +10 -1
  28. package/dist/admin/index.mjs.map +1 -1
  29. package/dist/admin/pages/Assets/AssetsPage.js +1 -1
  30. package/dist/admin/pages/Assets/AssetsPage.js.map +1 -1
  31. package/dist/admin/pages/Assets/AssetsPage.mjs +2 -2
  32. package/dist/admin/pages/Assets/AssetsPage.mjs.map +1 -1
  33. package/dist/admin/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +2 -2
  34. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +181 -65
  35. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  36. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +184 -69
  37. package/dist/admin/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  38. package/dist/admin/pages/Assets/components/AssetDetails/AssetPreview.mjs +1 -1
  39. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.js +2 -6
  40. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.js.map +1 -1
  41. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.mjs +2 -6
  42. package/dist/admin/pages/Assets/hooks/useIsAssetDetailsOpen.mjs.map +1 -1
  43. package/dist/admin/src/components/AssetPickerDialog/MediaLibraryPickerDialog.d.ts +19 -0
  44. package/dist/admin/src/components/Drawer.d.ts +8 -0
  45. package/dist/admin/src/components/EditorFileDropZone/EditorFileDropZone.d.ts +21 -0
  46. package/dist/admin/src/components/MediaLibraryInput/AddAssetMenu.d.ts +7 -1
  47. package/dist/admin/src/components/MediaLibraryInput/openAssetDetails.d.ts +10 -0
  48. package/dist/admin/src/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +41 -5
  49. package/dist/admin/src/pages/Assets/hooks/useIsAssetDetailsOpen.d.ts +2 -6
  50. package/dist/admin/translations/en.json.js +4 -0
  51. package/dist/admin/translations/en.json.js.map +1 -1
  52. package/dist/admin/translations/en.json.mjs +4 -0
  53. package/dist/admin/translations/en.json.mjs.map +1 -1
  54. package/dist/server/audit-logs.js +264 -0
  55. package/dist/server/audit-logs.js.map +1 -0
  56. package/dist/server/audit-logs.mjs +255 -0
  57. package/dist/server/audit-logs.mjs.map +1 -0
  58. package/dist/server/bootstrap.js +4 -0
  59. package/dist/server/bootstrap.js.map +1 -1
  60. package/dist/server/bootstrap.mjs +4 -0
  61. package/dist/server/bootstrap.mjs.map +1 -1
  62. package/dist/server/controllers/admin-folder-file.js +23 -1
  63. package/dist/server/controllers/admin-folder-file.js.map +1 -1
  64. package/dist/server/controllers/admin-folder-file.mjs +23 -1
  65. package/dist/server/controllers/admin-folder-file.mjs.map +1 -1
  66. package/dist/server/services/folder.js +48 -1
  67. package/dist/server/services/folder.js.map +1 -1
  68. package/dist/server/services/folder.mjs +48 -1
  69. package/dist/server/services/folder.mjs.map +1 -1
  70. package/dist/server/services/image-manipulation.js +12 -5
  71. package/dist/server/services/image-manipulation.js.map +1 -1
  72. package/dist/server/services/image-manipulation.mjs +12 -5
  73. package/dist/server/services/image-manipulation.mjs.map +1 -1
  74. package/dist/server/services/upload.js +100 -16
  75. package/dist/server/services/upload.js.map +1 -1
  76. package/dist/server/services/upload.mjs +102 -18
  77. package/dist/server/services/upload.mjs.map +1 -1
  78. package/dist/server/src/audit-logs.d.ts +142 -0
  79. package/dist/server/src/audit-logs.d.ts.map +1 -0
  80. package/dist/server/src/bootstrap.d.ts.map +1 -1
  81. package/dist/server/src/controllers/admin-folder-file.d.ts.map +1 -1
  82. package/dist/server/src/index.d.ts +3 -3
  83. package/dist/server/src/index.d.ts.map +1 -1
  84. package/dist/server/src/mcp/ambient-instance.d.ts.map +1 -1
  85. package/dist/server/src/services/folder.d.ts.map +1 -1
  86. package/dist/server/src/services/image-manipulation.d.ts +3 -3
  87. package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
  88. package/dist/server/src/services/index.d.ts +3 -3
  89. package/dist/server/src/services/index.d.ts.map +1 -1
  90. package/dist/server/src/services/upload.d.ts.map +1 -1
  91. package/package.json +9 -16
@@ -3,6 +3,7 @@ import { getService } from '../utils/index.mjs';
3
3
  import { FOLDER_MODEL_UID, FILE_MODEL_UID, ACTIONS } from '../constants.mjs';
4
4
  import { FolderContainsUnauthorizedAssetsError } from '../errors.mjs';
5
5
  import { validateMoveManyFoldersFiles, validateDeleteManyFoldersFiles } from './validation/admin/folder-file.mjs';
6
+ import { readMediaMoves, emitMediaMoves } from '../audit-logs.mjs';
6
7
 
7
8
  var adminFolderFile = {
8
9
  async deleteMany (ctx) {
@@ -101,11 +102,13 @@ var adminFolderFile = {
101
102
  const { folderIds = [], fileIds = [], destinationFolderId } = body;
102
103
  let totalFolderNumber = 0;
103
104
  let totalFileNumber = 0;
105
+ let moves = [];
104
106
  const trx = await strapi.db.transaction();
105
107
  try {
106
108
  // fetch folders
107
109
  const existingFolders = await strapi.db.queryBuilder(FOLDER_MODEL_UID).select([
108
110
  'id',
111
+ 'name',
109
112
  'pathId',
110
113
  'path'
111
114
  ]).where({
@@ -115,7 +118,8 @@ var adminFolderFile = {
115
118
  }).transacting(trx.get()).forUpdate().execute();
116
119
  // fetch files
117
120
  const existingFiles = await strapi.db.queryBuilder(FILE_MODEL_UID).select([
118
- 'id'
121
+ 'id',
122
+ 'name'
119
123
  ]).where({
120
124
  id: {
121
125
  $in: fileIds
@@ -135,6 +139,19 @@ var adminFolderFile = {
135
139
  strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;
136
140
  // @ts-expect-error - no dynamic typings for the models
137
141
  const pathColName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;
142
+ // Read before the write: the audit log records where each item was.
143
+ const fileFolderAttribute = strapi.db.metadata.get(FILE_MODEL_UID).attributes.folder;
144
+ const folderParentAttribute = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;
145
+ moves = await readMediaMoves((table)=>strapi.db.getConnection(table).transacting(trx.get()), {
146
+ files: existingFiles,
147
+ folders: existingFolders,
148
+ destinationFolderId,
149
+ // @ts-expect-error - no dynamic typings for the models
150
+ fileFolderJoinTable: fileFolderAttribute.joinTable,
151
+ // @ts-expect-error - no dynamic typings for the models
152
+ folderParentJoinTable: folderParentAttribute.joinTable,
153
+ folderTable
154
+ });
138
155
  if (existingFolders.length > 0) {
139
156
  // update folders' parent relation
140
157
  // @ts-expect-error - no dynamic typings for the models
@@ -199,6 +216,11 @@ var adminFolderFile = {
199
216
  await trx.rollback();
200
217
  throw e;
201
218
  }
219
+ emitMediaMoves({
220
+ strapi
221
+ }, moves).catch((error)=>{
222
+ strapi.log.error(`Could not record media moves in audit logs: ${error?.message ?? error}`);
223
+ });
202
224
  const updatedFolders = await strapi.db.query(FOLDER_MODEL_UID).findMany({
203
225
  where: {
204
226
  id: {
@@ -1 +1 @@
1
- {"version":3,"file":"admin-folder-file.mjs","sources":["../../../server/src/controllers/admin-folder-file.ts"],"sourcesContent":["import { errors, strings } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FOLDER_MODEL_UID, FILE_MODEL_UID } from '../constants';\nimport { FolderContainsUnauthorizedAssetsError } from '../errors';\nimport {\n validateDeleteManyFoldersFiles,\n validateMoveManyFoldersFiles,\n} from './validation/admin/folder-file';\n\nimport type { File, Folder } from '../types';\n\nexport default {\n async deleteMany(ctx: Context) {\n const { body } = ctx.request;\n const {\n state: { userAbility },\n } = ctx;\n\n const pmFolder = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n const pmFile = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n await validateDeleteManyFoldersFiles(body);\n\n const fileService = getService('file');\n const folderService = getService('folder');\n\n const { fileIds = [], folderIds = [] } = body;\n\n const canDeleteFiles = async (files: File[]) => {\n const ids = [...new Set(files.map(({ id }) => id))];\n\n if (ids.length === 0) {\n return true;\n }\n\n const query = pmFile.addPermissionsQueryTo({ filters: { id: { $in: ids } } });\n const permittedFiles = await strapi.db.query(FILE_MODEL_UID).findMany({\n select: ['id'],\n where: query.filters,\n });\n\n return permittedFiles.length === ids.length;\n };\n\n // https://github.com/strapi/strapi/issues/27649\n // Validate explicitly selected files before deleting a folder. Otherwise a mixed request\n // could delete permitted files first and only then discover a forbidden file in the folder.\n if (fileIds.length > 0) {\n const selectedFiles = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: { id: { $in: fileIds } },\n });\n\n if (!(await canDeleteFiles(selectedFiles))) {\n throw new errors.ForbiddenError();\n }\n }\n\n const {\n folders: deletedFolders,\n totalFolderNumber,\n totalFileNumber,\n } = await folderService.deleteByIds(folderIds, {\n async validateFiles(files) {\n if (!(await canDeleteFiles(files))) {\n throw new FolderContainsUnauthorizedAssetsError();\n }\n },\n });\n const deletedFiles = await fileService.deleteByIds(fileIds);\n\n if (deletedFiles.length + deletedFolders.length > 1) {\n await getService('metrics').trackUsage('didBulkDeleteMediaLibraryElements', {\n eventProperties: {\n rootFolderNumber: deletedFolders.length,\n rootAssetNumber: deletedFiles.length,\n totalFolderNumber,\n totalAssetNumber: totalFileNumber + deletedFiles.length,\n },\n });\n }\n\n ctx.body = {\n data: {\n files: await pmFile.sanitizeOutput(deletedFiles, { action: ACTIONS.read }),\n folders: await pmFolder.sanitizeOutput(deletedFolders),\n },\n };\n },\n async moveMany(ctx: Context) {\n const { body } = ctx.request;\n const {\n state: { userAbility },\n } = ctx;\n\n const pmFolder = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n const pmFile = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n await validateMoveManyFoldersFiles(body);\n const { folderIds = [], fileIds = [], destinationFolderId } = body;\n\n let totalFolderNumber = 0;\n let totalFileNumber = 0;\n\n const trx = await strapi.db.transaction();\n try {\n // fetch folders\n const existingFolders = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select(['id', 'pathId', 'path'])\n .where({ id: { $in: folderIds } })\n .transacting(trx.get())\n .forUpdate()\n .execute<Folder[]>();\n\n // fetch files\n const existingFiles = await strapi.db\n .queryBuilder(FILE_MODEL_UID)\n .select(['id'])\n .where({ id: { $in: fileIds } })\n .transacting(trx.get())\n .forUpdate()\n .execute<File[]>();\n\n // fetch destinationFolder path\n let destinationFolderPath = '/';\n if (destinationFolderId !== null) {\n const destinationFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select('path')\n .where({ id: destinationFolderId })\n .transacting(trx.get())\n .first()\n .execute<Folder>();\n destinationFolderPath = destinationFolder.path;\n }\n\n const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;\n const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;\n const folderPathColName =\n // @ts-expect-error - no dynamic typings for the models\n strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;\n // @ts-expect-error - no dynamic typings for the models\n const pathColName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;\n\n if (existingFolders.length > 0) {\n // update folders' parent relation\n // @ts-expect-error - no dynamic typings for the models\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [joinTable.joinColumn.name]: { $in: folderIds } })\n .execute();\n\n if (destinationFolderId !== null) {\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .insert(\n existingFolders.map((folder) => ({\n [joinTable.inverseJoinColumn.name]: destinationFolderId,\n [joinTable.joinColumn.name]: folder.id,\n }))\n )\n .execute();\n }\n\n for (const existingFolder of existingFolders) {\n let replaceQuery;\n switch (strapi.db.dialect.client) {\n case 'sqlite':\n replaceQuery = '? || SUBSTRING(??, ?)';\n break;\n case 'postgres':\n replaceQuery = 'CONCAT(?::TEXT, SUBSTRING(??, ?::INTEGER))';\n break;\n default:\n replaceQuery = 'CONCAT(?, SUBSTRING(??, ?))';\n }\n\n // update path for folders themselves & folders below\n totalFolderNumber = await strapi.db\n .getConnection(folderTable)\n .transacting(trx.get())\n .where(pathColName, existingFolder.path)\n .orWhere(pathColName, 'like', `${existingFolder.path}/%`)\n .update(\n pathColName,\n strapi.db.connection.raw(replaceQuery, [\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n pathColName,\n existingFolder.path.length + 1,\n ])\n );\n\n // update path of files below\n totalFileNumber = await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .where(folderPathColName, existingFolder.path)\n .orWhere(folderPathColName, 'like', `${existingFolder.path}/%`)\n .update(\n folderPathColName,\n strapi.db.connection.raw(replaceQuery, [\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n folderPathColName,\n existingFolder.path.length + 1,\n ])\n );\n }\n }\n\n if (existingFiles.length > 0) {\n // update files' folder relation (delete + insert; upsert not possible)\n // @ts-expect-error - no dynamic typings for the models\n const fileJoinTable = strapi.db.metadata.get(FILE_MODEL_UID).attributes.folder.joinTable;\n await strapi.db\n .queryBuilder(fileJoinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [fileJoinTable.joinColumn.name]: { $in: fileIds } })\n .execute();\n\n if (destinationFolderId !== null) {\n await strapi.db\n .queryBuilder(fileJoinTable.name)\n .transacting(trx.get())\n .insert(\n existingFiles.map((file) => ({\n [fileJoinTable.inverseJoinColumn.name]: destinationFolderId,\n [fileJoinTable.joinColumn.name]: file.id,\n }))\n )\n .execute();\n }\n\n // update files main fields (path + updatedBy)\n await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .whereIn('id', fileIds)\n .update(folderPathColName, destinationFolderPath);\n }\n\n await trx.commit();\n } catch (e) {\n await trx.rollback();\n throw e;\n }\n\n const updatedFolders = await strapi.db.query(FOLDER_MODEL_UID).findMany({\n where: { id: { $in: folderIds } },\n });\n\n const updatedFiles = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: { id: { $in: fileIds } },\n });\n\n await getService('metrics').trackUsage('didBulkMoveMediaLibraryElements', {\n eventProperties: {\n rootFolderNumber: updatedFolders.length,\n rootAssetNumber: updatedFiles.length,\n totalFolderNumber,\n totalAssetNumber: totalFileNumber + updatedFiles.length,\n },\n });\n\n ctx.body = {\n data: {\n files: await pmFile.sanitizeOutput(updatedFiles),\n folders: await pmFolder.sanitizeOutput(updatedFolders),\n },\n };\n },\n};\n"],"names":["deleteMany","ctx","body","request","state","userAbility","pmFolder","strapi","service","createPermissionsManager","ability","model","FOLDER_MODEL_UID","pmFile","action","ACTIONS","update","FILE_MODEL_UID","validateDeleteManyFoldersFiles","fileService","getService","folderService","fileIds","folderIds","canDeleteFiles","files","ids","Set","map","id","length","query","addPermissionsQueryTo","filters","$in","permittedFiles","db","findMany","select","where","selectedFiles","errors","ForbiddenError","folders","deletedFolders","totalFolderNumber","totalFileNumber","deleteByIds","validateFiles","FolderContainsUnauthorizedAssetsError","deletedFiles","trackUsage","eventProperties","rootFolderNumber","rootAssetNumber","totalAssetNumber","data","sanitizeOutput","read","moveMany","validateMoveManyFoldersFiles","destinationFolderId","trx","transaction","existingFolders","queryBuilder","transacting","get","forUpdate","execute","existingFiles","destinationFolderPath","destinationFolder","first","path","fileTable","getModel","collectionName","folderTable","folderPathColName","metadata","attributes","folderPath","columnName","pathColName","joinTable","parent","name","delete","joinColumn","insert","folder","inverseJoinColumn","existingFolder","replaceQuery","dialect","client","getConnection","orWhere","connection","raw","strings","joinBy","pathId","fileJoinTable","file","whereIn","commit","e","rollback","updatedFolders","updatedFiles"],"mappings":"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"}
1
+ {"version":3,"file":"admin-folder-file.mjs","sources":["../../../server/src/controllers/admin-folder-file.ts"],"sourcesContent":["import { errors, strings } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FOLDER_MODEL_UID, FILE_MODEL_UID } from '../constants';\nimport { FolderContainsUnauthorizedAssetsError } from '../errors';\nimport {\n validateDeleteManyFoldersFiles,\n validateMoveManyFoldersFiles,\n} from './validation/admin/folder-file';\nimport { emitMediaMoves, readMediaMoves, type MediaMoveEvent } from '../audit-logs';\n\nimport type { File, Folder } from '../types';\n\nexport default {\n async deleteMany(ctx: Context) {\n const { body } = ctx.request;\n const {\n state: { userAbility },\n } = ctx;\n\n const pmFolder = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n const pmFile = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.update,\n model: FILE_MODEL_UID,\n });\n\n await validateDeleteManyFoldersFiles(body);\n\n const fileService = getService('file');\n const folderService = getService('folder');\n\n const { fileIds = [], folderIds = [] } = body;\n\n const canDeleteFiles = async (files: File[]) => {\n const ids = [...new Set(files.map(({ id }) => id))];\n\n if (ids.length === 0) {\n return true;\n }\n\n const query = pmFile.addPermissionsQueryTo({ filters: { id: { $in: ids } } });\n const permittedFiles = await strapi.db.query(FILE_MODEL_UID).findMany({\n select: ['id'],\n where: query.filters,\n });\n\n return permittedFiles.length === ids.length;\n };\n\n // https://github.com/strapi/strapi/issues/27649\n // Validate explicitly selected files before deleting a folder. Otherwise a mixed request\n // could delete permitted files first and only then discover a forbidden file in the folder.\n if (fileIds.length > 0) {\n const selectedFiles = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: { id: { $in: fileIds } },\n });\n\n if (!(await canDeleteFiles(selectedFiles))) {\n throw new errors.ForbiddenError();\n }\n }\n\n const {\n folders: deletedFolders,\n totalFolderNumber,\n totalFileNumber,\n } = await folderService.deleteByIds(folderIds, {\n async validateFiles(files) {\n if (!(await canDeleteFiles(files))) {\n throw new FolderContainsUnauthorizedAssetsError();\n }\n },\n });\n const deletedFiles = await fileService.deleteByIds(fileIds);\n\n if (deletedFiles.length + deletedFolders.length > 1) {\n await getService('metrics').trackUsage('didBulkDeleteMediaLibraryElements', {\n eventProperties: {\n rootFolderNumber: deletedFolders.length,\n rootAssetNumber: deletedFiles.length,\n totalFolderNumber,\n totalAssetNumber: totalFileNumber + deletedFiles.length,\n },\n });\n }\n\n ctx.body = {\n data: {\n files: await pmFile.sanitizeOutput(deletedFiles, { action: ACTIONS.read }),\n folders: await pmFolder.sanitizeOutput(deletedFolders),\n },\n };\n },\n async moveMany(ctx: Context) {\n const { body } = ctx.request;\n const {\n state: { userAbility },\n } = ctx;\n\n const pmFolder = strapi.service('admin::permission').createPermissionsManager({\n ability: ctx.state.userAbility,\n model: FOLDER_MODEL_UID,\n });\n\n const pmFile = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.read,\n model: FILE_MODEL_UID,\n });\n\n await validateMoveManyFoldersFiles(body);\n const { folderIds = [], fileIds = [], destinationFolderId } = body;\n\n let totalFolderNumber = 0;\n let totalFileNumber = 0;\n let moves: MediaMoveEvent[] = [];\n\n const trx = await strapi.db.transaction();\n try {\n // fetch folders\n const existingFolders = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select(['id', 'name', 'pathId', 'path'])\n .where({ id: { $in: folderIds } })\n .transacting(trx.get())\n .forUpdate()\n .execute<Folder[]>();\n\n // fetch files\n const existingFiles = await strapi.db\n .queryBuilder(FILE_MODEL_UID)\n .select(['id', 'name'])\n .where({ id: { $in: fileIds } })\n .transacting(trx.get())\n .forUpdate()\n .execute<File[]>();\n\n // fetch destinationFolder path\n let destinationFolderPath = '/';\n if (destinationFolderId !== null) {\n const destinationFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select('path')\n .where({ id: destinationFolderId })\n .transacting(trx.get())\n .first()\n .execute<Folder>();\n destinationFolderPath = destinationFolder.path;\n }\n\n const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;\n const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;\n const folderPathColName =\n // @ts-expect-error - no dynamic typings for the models\n strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;\n // @ts-expect-error - no dynamic typings for the models\n const pathColName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;\n\n // Read before the write: the audit log records where each item was.\n const fileFolderAttribute = strapi.db.metadata.get(FILE_MODEL_UID).attributes.folder;\n const folderParentAttribute = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n moves = await readMediaMoves(\n (table) => strapi.db.getConnection(table).transacting(trx.get()),\n {\n files: existingFiles,\n folders: existingFolders,\n destinationFolderId,\n // @ts-expect-error - no dynamic typings for the models\n fileFolderJoinTable: fileFolderAttribute.joinTable,\n // @ts-expect-error - no dynamic typings for the models\n folderParentJoinTable: folderParentAttribute.joinTable,\n folderTable,\n }\n );\n\n if (existingFolders.length > 0) {\n // update folders' parent relation\n // @ts-expect-error - no dynamic typings for the models\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [joinTable.joinColumn.name]: { $in: folderIds } })\n .execute();\n\n if (destinationFolderId !== null) {\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .insert(\n existingFolders.map((folder) => ({\n [joinTable.inverseJoinColumn.name]: destinationFolderId,\n [joinTable.joinColumn.name]: folder.id,\n }))\n )\n .execute();\n }\n\n for (const existingFolder of existingFolders) {\n let replaceQuery;\n switch (strapi.db.dialect.client) {\n case 'sqlite':\n replaceQuery = '? || SUBSTRING(??, ?)';\n break;\n case 'postgres':\n replaceQuery = 'CONCAT(?::TEXT, SUBSTRING(??, ?::INTEGER))';\n break;\n default:\n replaceQuery = 'CONCAT(?, SUBSTRING(??, ?))';\n }\n\n // update path for folders themselves & folders below\n totalFolderNumber = await strapi.db\n .getConnection(folderTable)\n .transacting(trx.get())\n .where(pathColName, existingFolder.path)\n .orWhere(pathColName, 'like', `${existingFolder.path}/%`)\n .update(\n pathColName,\n strapi.db.connection.raw(replaceQuery, [\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n pathColName,\n existingFolder.path.length + 1,\n ])\n );\n\n // update path of files below\n totalFileNumber = await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .where(folderPathColName, existingFolder.path)\n .orWhere(folderPathColName, 'like', `${existingFolder.path}/%`)\n .update(\n folderPathColName,\n strapi.db.connection.raw(replaceQuery, [\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n folderPathColName,\n existingFolder.path.length + 1,\n ])\n );\n }\n }\n\n if (existingFiles.length > 0) {\n // update files' folder relation (delete + insert; upsert not possible)\n // @ts-expect-error - no dynamic typings for the models\n const fileJoinTable = strapi.db.metadata.get(FILE_MODEL_UID).attributes.folder.joinTable;\n await strapi.db\n .queryBuilder(fileJoinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [fileJoinTable.joinColumn.name]: { $in: fileIds } })\n .execute();\n\n if (destinationFolderId !== null) {\n await strapi.db\n .queryBuilder(fileJoinTable.name)\n .transacting(trx.get())\n .insert(\n existingFiles.map((file) => ({\n [fileJoinTable.inverseJoinColumn.name]: destinationFolderId,\n [fileJoinTable.joinColumn.name]: file.id,\n }))\n )\n .execute();\n }\n\n // update files main fields (path + updatedBy)\n await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .whereIn('id', fileIds)\n .update(folderPathColName, destinationFolderPath);\n }\n\n await trx.commit();\n } catch (e) {\n await trx.rollback();\n throw e;\n }\n\n emitMediaMoves({ strapi }, moves).catch((error) => {\n strapi.log.error(`Could not record media moves in audit logs: ${error?.message ?? error}`);\n });\n\n const updatedFolders = await strapi.db.query(FOLDER_MODEL_UID).findMany({\n where: { id: { $in: folderIds } },\n });\n\n const updatedFiles = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: { id: { $in: fileIds } },\n });\n\n await getService('metrics').trackUsage('didBulkMoveMediaLibraryElements', {\n eventProperties: {\n rootFolderNumber: updatedFolders.length,\n rootAssetNumber: updatedFiles.length,\n totalFolderNumber,\n totalAssetNumber: totalFileNumber + updatedFiles.length,\n },\n });\n\n ctx.body = {\n data: {\n files: await pmFile.sanitizeOutput(updatedFiles),\n folders: await pmFolder.sanitizeOutput(updatedFolders),\n },\n };\n },\n};\n"],"names":["deleteMany","ctx","body","request","state","userAbility","pmFolder","strapi","service","createPermissionsManager","ability","model","FOLDER_MODEL_UID","pmFile","action","ACTIONS","update","FILE_MODEL_UID","validateDeleteManyFoldersFiles","fileService","getService","folderService","fileIds","folderIds","canDeleteFiles","files","ids","Set","map","id","length","query","addPermissionsQueryTo","filters","$in","permittedFiles","db","findMany","select","where","selectedFiles","errors","ForbiddenError","folders","deletedFolders","totalFolderNumber","totalFileNumber","deleteByIds","validateFiles","FolderContainsUnauthorizedAssetsError","deletedFiles","trackUsage","eventProperties","rootFolderNumber","rootAssetNumber","totalAssetNumber","data","sanitizeOutput","read","moveMany","validateMoveManyFoldersFiles","destinationFolderId","moves","trx","transaction","existingFolders","queryBuilder","transacting","get","forUpdate","execute","existingFiles","destinationFolderPath","destinationFolder","first","path","fileTable","getModel","collectionName","folderTable","folderPathColName","metadata","attributes","folderPath","columnName","pathColName","fileFolderAttribute","folder","folderParentAttribute","parent","readMediaMoves","table","getConnection","fileFolderJoinTable","joinTable","folderParentJoinTable","name","delete","joinColumn","insert","inverseJoinColumn","existingFolder","replaceQuery","dialect","client","orWhere","connection","raw","strings","joinBy","pathId","fileJoinTable","file","whereIn","commit","e","rollback","emitMediaMoves","catch","error","log","message","updatedFolders","updatedFiles"],"mappings":"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"}
@@ -4,6 +4,7 @@ var _ = require('lodash');
4
4
  var utils = require('@strapi/utils');
5
5
  var constants = require('../constants.js');
6
6
  var index = require('../utils/index.js');
7
+ var auditLogs = require('../audit-logs.js');
7
8
 
8
9
  const setPathIdAndPath = async (folder)=>{
9
10
  const { max } = await strapi.db.queryBuilder(constants.FOLDER_MODEL_UID).max('pathId').first().execute();
@@ -100,6 +101,11 @@ const create = async (folderData, opts)=>{
100
101
  strapi.eventHub.emit('media-folder.delete', {
101
102
  folders
102
103
  });
104
+ folders.forEach((folder)=>{
105
+ strapi.eventHub.emit(auditLogs.AUDITED_EVENTS.FOLDER_DELETE_AUDIT, {
106
+ folder
107
+ });
108
+ });
103
109
  return {
104
110
  folders,
105
111
  totalFolderNumber,
@@ -114,6 +120,14 @@ const create = async (folderData, opts)=>{
114
120
  const existingFolder = await strapi.db.query(constants.FOLDER_MODEL_UID).findOne({
115
121
  where: {
116
122
  id
123
+ },
124
+ populate: {
125
+ parent: {
126
+ select: [
127
+ 'id',
128
+ 'name'
129
+ ]
130
+ }
117
131
  }
118
132
  });
119
133
  if (!existingFolder) {
@@ -133,10 +147,30 @@ const create = async (folderData, opts)=>{
133
147
  },
134
148
  data: newFolder
135
149
  });
150
+ strapi.eventHub.emit('media-folder.update', {
151
+ folder: {
152
+ ...folder,
153
+ parent: existingFolder.parent ?? null
154
+ },
155
+ previous: existingFolder
156
+ });
136
157
  return folder;
137
158
  }
138
159
  // location is updated => using transaction
139
160
  } else {
161
+ const previous = await strapi.db.query(constants.FOLDER_MODEL_UID).findOne({
162
+ where: {
163
+ id
164
+ },
165
+ populate: {
166
+ parent: {
167
+ select: [
168
+ 'id',
169
+ 'name'
170
+ ]
171
+ }
172
+ }
173
+ });
140
174
  const trx = await strapi.db.transaction();
141
175
  try {
142
176
  // fetch existing folder
@@ -204,8 +238,21 @@ const create = async (folderData, opts)=>{
204
238
  },
205
239
  data: newFolder
206
240
  });
241
+ const parentFolder = parent === null ? null : await strapi.db.query(constants.FOLDER_MODEL_UID).findOne({
242
+ where: {
243
+ id: parent
244
+ },
245
+ select: [
246
+ 'id',
247
+ 'name'
248
+ ]
249
+ });
207
250
  strapi.eventHub.emit('media-folder.update', {
208
- folder
251
+ folder: {
252
+ ...folder,
253
+ parent: parentFolder
254
+ },
255
+ previous
209
256
  });
210
257
  return folder;
211
258
  }
@@ -1 +1 @@
1
- {"version":3,"file":"folder.js","sources":["../../../server/src/services/folder.ts"],"sourcesContent":["import { map, sortBy } from 'lodash';\nimport { strings, setCreatorFields } from '@strapi/utils';\nimport { FOLDER_MODEL_UID, FILE_MODEL_UID } from '../constants';\nimport { getService } from '../utils';\n\nimport type { File, Folder } from '../types';\n\ntype FolderMap = {\n [key: string]: Partial<Folder> & {\n children: FolderNode[];\n };\n};\n\ntype FolderNode = Partial<Folder> & {\n children: FolderNode[];\n};\n\ntype DeleteByIdsOptions = {\n validateFiles?: (files: File[]) => Promise<void>;\n};\n\nconst setPathIdAndPath = async (folder: Pick<Folder, 'parent'>) => {\n const { max } = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .max('pathId')\n .first()\n .execute<{ max: number }>();\n\n const pathId = max + 1;\n let parentPath = '/';\n if (folder.parent) {\n const parentFolder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id: folder.parent } });\n\n parentPath = parentFolder.path;\n }\n\n return Object.assign(folder, {\n pathId,\n path: strings.joinBy('/', parentPath, `${pathId}`),\n });\n};\n\nconst create = async (\n folderData: Pick<Folder, 'name' | 'parent'>,\n opts?: { user: { id: string | number } }\n) => {\n const folderService = getService('folder');\n\n const { user } = opts || {};\n\n let enrichedFolder = await folderService.setPathIdAndPath(folderData);\n if (user) {\n enrichedFolder = await setCreatorFields({ user })(enrichedFolder);\n }\n\n const folder = await strapi.db.query(FOLDER_MODEL_UID).create({ data: enrichedFolder });\n\n strapi.eventHub.emit('media-folder.create', { folder });\n\n return folder;\n};\n\n/**\n * Recursively delete folders and included files\n * @param ids ids of the folders to delete\n * @returns {Promise<Object[]>}\n */\nconst deleteByIds = async (ids: number[] = [], { validateFiles }: DeleteByIdsOptions = {}) => {\n const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({ where: { id: { $in: ids } } });\n if (folders.length === 0) {\n return {\n folders: [],\n totalFolderNumber: 0,\n totalFileNumber: 0,\n };\n }\n\n const pathsToDelete = map(folders, 'path');\n\n // delete files\n const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { folderPath: { $eq: path } },\n { folderPath: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n // A folder deletion cascades to every file in its subtree. Let callers enforce\n // request-scoped permissions against the complete set before the first destructive action.\n await validateFiles?.(filesToDelete);\n\n await Promise.all(filesToDelete.map((file: File) => getService('upload').remove(file)));\n\n // delete folders and subfolders\n const { count: totalFolderNumber } = await strapi.db.query(FOLDER_MODEL_UID).deleteMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { path: { $eq: path } },\n { path: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n strapi.eventHub.emit('media-folder.delete', { folders });\n\n return {\n folders,\n totalFolderNumber,\n totalFileNumber: filesToDelete.length,\n };\n};\n\n/**\n * Update name and location of a folder and its belonging folders and files\n */\nconst update = async (\n id: number,\n {\n name,\n parent,\n }: {\n name: string;\n /**\n * Omit to rename in place: the name-only branch skips the transaction that rewrites\n * descendant paths. Pass a number to re-parent, or null to move to the root.\n */\n parent?: number | null;\n },\n { user }: { user: { id: string | number } }\n) => {\n // only name is updated\n if (parent === undefined) {\n const existingFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({ where: { id } });\n\n if (!existingFolder) {\n return undefined;\n }\n\n const newFolder = setCreatorFields({ user, isEdition: true })({ name, parent });\n\n if (parent === undefined) {\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n return folder;\n }\n // location is updated => using transaction\n } else {\n const trx = await strapi.db.transaction();\n try {\n // fetch existing folder\n const existingFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select(['pathId', 'path'])\n .where({ id })\n .transacting(trx.get())\n .forUpdate()\n .first()\n .execute<Folder>();\n\n // update parent folder (delete + insert; upsert not possible)\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n\n if (parent !== null) {\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .insert({ [joinTable.inverseJoinColumn.name]: parent, [joinTable.joinColumn.name]: id })\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n }\n\n // fetch destinationFolder path\n let destinationFolderPath = '/';\n if (parent !== null) {\n const destinationFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select('path')\n .where({ id: parent })\n .transacting(trx.get())\n .first()\n .execute<Folder>();\n destinationFolderPath = destinationFolder.path;\n }\n\n const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;\n const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;\n const folderPathColumnName =\n // @ts-expect-error - no dynamic types\n strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;\n // @ts-expect-error - no dynamic types\n const pathColumnName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;\n\n // update folders below\n await strapi.db\n .getConnection(folderTable)\n .transacting(trx.get())\n .where(pathColumnName, existingFolder.path)\n .orWhere(pathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n pathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n pathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n // update files below\n await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .where(folderPathColumnName, existingFolder.path)\n .orWhere(folderPathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n folderPathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n folderPathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n await trx.commit();\n } catch (e) {\n await trx.rollback();\n throw e;\n }\n\n // update less critical information (name + updatedBy)\n const newFolder = setCreatorFields({ user, isEdition: true })({ name });\n\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n strapi.eventHub.emit('media-folder.update', { folder });\n return folder;\n }\n};\n\n/**\n * Check if a folder exists in database\n * @param params query params to find the folder\n * @returns {Promise<boolean>}\n */\nconst exists = async (params = {}) => {\n const count = await strapi.db.query(FOLDER_MODEL_UID).count({ where: params });\n return count > 0;\n};\n\n/**\n * Returns the nested structure of folders\n * @returns {Promise<array>}\n */\nconst getStructure = async () => {\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n const qb = strapi.db.queryBuilder(FOLDER_MODEL_UID);\n const alias = qb.getAlias();\n const folders = (await qb\n .select(['id', 'name', `${alias}.${joinTable.inverseJoinColumn.name} as parent`])\n .join({\n alias,\n referencedTable: joinTable.name,\n referencedColumn: joinTable.joinColumn.name,\n rootColumn: joinTable.joinColumn.referencedColumn,\n rootTable: qb.alias,\n })\n .execute({ mapResults: false })) as Folder[];\n\n const folderMap: FolderMap = {\n null: { children: [] },\n };\n\n folders.forEach((f) => {\n folderMap[f.id] = { ...f, children: [] };\n });\n\n folders.forEach((f) => {\n const parentId = f.parent || 'null';\n\n if (!folderMap[parentId]) {\n folderMap[parentId] = { children: [] };\n }\n\n folderMap[parentId].children.push(folderMap[f.id]);\n folderMap[parentId].children = sortBy(folderMap[parentId].children, 'name');\n delete folderMap[f.id].parent;\n });\n\n return folderMap.null.children;\n};\n\nexport default {\n create,\n exists,\n deleteByIds,\n update,\n setPathIdAndPath,\n getStructure,\n};\n"],"names":["setPathIdAndPath","folder","max","strapi","db","queryBuilder","FOLDER_MODEL_UID","first","execute","pathId","parentPath","parent","parentFolder","query","findOne","where","id","path","Object","assign","strings","joinBy","create","folderData","opts","folderService","getService","user","enrichedFolder","setCreatorFields","data","eventHub","emit","deleteByIds","ids","validateFiles","folders","findMany","$in","length","totalFolderNumber","totalFileNumber","pathsToDelete","map","filesToDelete","FILE_MODEL_UID","$or","flatMap","folderPath","$eq","$startsWith","Promise","all","file","remove","count","deleteMany","update","name","undefined","existingFolder","newFolder","isEdition","trx","transaction","select","transacting","get","forUpdate","joinTable","metadata","attributes","delete","joinColumn","insert","inverseJoinColumn","destinationFolderPath","destinationFolder","folderTable","getModel","collectionName","fileTable","folderPathColumnName","columnName","pathColumnName","getConnection","orWhere","connection","raw","commit","e","rollback","exists","params","getStructure","qb","alias","getAlias","join","referencedTable","referencedColumn","rootColumn","rootTable","mapResults","folderMap","null","children","forEach","f","parentId","push","sortBy"],"mappings":"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"}
1
+ {"version":3,"file":"folder.js","sources":["../../../server/src/services/folder.ts"],"sourcesContent":["import { map, sortBy } from 'lodash';\nimport { strings, setCreatorFields } from '@strapi/utils';\nimport { FOLDER_MODEL_UID, FILE_MODEL_UID } from '../constants';\nimport { getService } from '../utils';\nimport { AUDITED_EVENTS } from '../audit-logs';\n\nimport type { File, Folder } from '../types';\n\ntype FolderMap = {\n [key: string]: Partial<Folder> & {\n children: FolderNode[];\n };\n};\n\ntype FolderNode = Partial<Folder> & {\n children: FolderNode[];\n};\n\ntype DeleteByIdsOptions = {\n validateFiles?: (files: File[]) => Promise<void>;\n};\n\nconst setPathIdAndPath = async (folder: Pick<Folder, 'parent'>) => {\n const { max } = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .max('pathId')\n .first()\n .execute<{ max: number }>();\n\n const pathId = max + 1;\n let parentPath = '/';\n if (folder.parent) {\n const parentFolder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id: folder.parent } });\n\n parentPath = parentFolder.path;\n }\n\n return Object.assign(folder, {\n pathId,\n path: strings.joinBy('/', parentPath, `${pathId}`),\n });\n};\n\nconst create = async (\n folderData: Pick<Folder, 'name' | 'parent'>,\n opts?: { user: { id: string | number } }\n) => {\n const folderService = getService('folder');\n\n const { user } = opts || {};\n\n let enrichedFolder = await folderService.setPathIdAndPath(folderData);\n if (user) {\n enrichedFolder = await setCreatorFields({ user })(enrichedFolder);\n }\n\n const folder = await strapi.db.query(FOLDER_MODEL_UID).create({ data: enrichedFolder });\n\n strapi.eventHub.emit('media-folder.create', { folder });\n\n return folder;\n};\n\n/**\n * Recursively delete folders and included files\n * @param ids ids of the folders to delete\n * @returns {Promise<Object[]>}\n */\nconst deleteByIds = async (ids: number[] = [], { validateFiles }: DeleteByIdsOptions = {}) => {\n const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({ where: { id: { $in: ids } } });\n if (folders.length === 0) {\n return {\n folders: [],\n totalFolderNumber: 0,\n totalFileNumber: 0,\n };\n }\n\n const pathsToDelete = map(folders, 'path');\n\n // delete files\n const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { folderPath: { $eq: path } },\n { folderPath: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n // A folder deletion cascades to every file in its subtree. Let callers enforce\n // request-scoped permissions against the complete set before the first destructive action.\n await validateFiles?.(filesToDelete);\n\n await Promise.all(filesToDelete.map((file: File) => getService('upload').remove(file)));\n\n // delete folders and subfolders\n const { count: totalFolderNumber } = await strapi.db.query(FOLDER_MODEL_UID).deleteMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { path: { $eq: path } },\n { path: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n strapi.eventHub.emit('media-folder.delete', { folders });\n folders.forEach((folder: Folder) => {\n strapi.eventHub.emit(AUDITED_EVENTS.FOLDER_DELETE_AUDIT, { folder });\n });\n\n return {\n folders,\n totalFolderNumber,\n totalFileNumber: filesToDelete.length,\n };\n};\n\n/**\n * Update name and location of a folder and its belonging folders and files\n */\nconst update = async (\n id: number,\n {\n name,\n parent,\n }: {\n name: string;\n /**\n * Omit to rename in place: the name-only branch skips the transaction that rewrites\n * descendant paths. Pass a number to re-parent, or null to move to the root.\n */\n parent?: number | null;\n },\n { user }: { user: { id: string | number } }\n) => {\n // only name is updated\n if (parent === undefined) {\n const existingFolder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id }, populate: { parent: { select: ['id', 'name'] } } });\n\n if (!existingFolder) {\n return undefined;\n }\n\n const newFolder = setCreatorFields({ user, isEdition: true })({ name, parent });\n\n if (parent === undefined) {\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n strapi.eventHub.emit('media-folder.update', {\n folder: { ...folder, parent: existingFolder.parent ?? null },\n previous: existingFolder,\n });\n\n return folder;\n }\n // location is updated => using transaction\n } else {\n const previous = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id }, populate: { parent: { select: ['id', 'name'] } } });\n\n const trx = await strapi.db.transaction();\n try {\n // fetch existing folder\n const existingFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select(['pathId', 'path'])\n .where({ id })\n .transacting(trx.get())\n .forUpdate()\n .first()\n .execute<Folder>();\n\n // update parent folder (delete + insert; upsert not possible)\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n\n if (parent !== null) {\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .insert({ [joinTable.inverseJoinColumn.name]: parent, [joinTable.joinColumn.name]: id })\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n }\n\n // fetch destinationFolder path\n let destinationFolderPath = '/';\n if (parent !== null) {\n const destinationFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select('path')\n .where({ id: parent })\n .transacting(trx.get())\n .first()\n .execute<Folder>();\n destinationFolderPath = destinationFolder.path;\n }\n\n const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;\n const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;\n const folderPathColumnName =\n // @ts-expect-error - no dynamic types\n strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;\n // @ts-expect-error - no dynamic types\n const pathColumnName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;\n\n // update folders below\n await strapi.db\n .getConnection(folderTable)\n .transacting(trx.get())\n .where(pathColumnName, existingFolder.path)\n .orWhere(pathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n pathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n pathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n // update files below\n await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .where(folderPathColumnName, existingFolder.path)\n .orWhere(folderPathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n folderPathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n folderPathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n await trx.commit();\n } catch (e) {\n await trx.rollback();\n throw e;\n }\n\n // update less critical information (name + updatedBy)\n const newFolder = setCreatorFields({ user, isEdition: true })({ name });\n\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n const parentFolder =\n parent === null\n ? null\n : await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id: parent }, select: ['id', 'name'] });\n\n strapi.eventHub.emit('media-folder.update', {\n folder: { ...folder, parent: parentFolder },\n previous,\n });\n return folder;\n }\n};\n\n/**\n * Check if a folder exists in database\n * @param params query params to find the folder\n * @returns {Promise<boolean>}\n */\nconst exists = async (params = {}) => {\n const count = await strapi.db.query(FOLDER_MODEL_UID).count({ where: params });\n return count > 0;\n};\n\n/**\n * Returns the nested structure of folders\n * @returns {Promise<array>}\n */\nconst getStructure = async () => {\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n const qb = strapi.db.queryBuilder(FOLDER_MODEL_UID);\n const alias = qb.getAlias();\n const folders = (await qb\n .select(['id', 'name', `${alias}.${joinTable.inverseJoinColumn.name} as parent`])\n .join({\n alias,\n referencedTable: joinTable.name,\n referencedColumn: joinTable.joinColumn.name,\n rootColumn: joinTable.joinColumn.referencedColumn,\n rootTable: qb.alias,\n })\n .execute({ mapResults: false })) as Folder[];\n\n const folderMap: FolderMap = {\n null: { children: [] },\n };\n\n folders.forEach((f) => {\n folderMap[f.id] = { ...f, children: [] };\n });\n\n folders.forEach((f) => {\n const parentId = f.parent || 'null';\n\n if (!folderMap[parentId]) {\n folderMap[parentId] = { children: [] };\n }\n\n folderMap[parentId].children.push(folderMap[f.id]);\n folderMap[parentId].children = sortBy(folderMap[parentId].children, 'name');\n delete folderMap[f.id].parent;\n });\n\n return folderMap.null.children;\n};\n\nexport default {\n create,\n exists,\n deleteByIds,\n update,\n setPathIdAndPath,\n getStructure,\n};\n"],"names":["setPathIdAndPath","folder","max","strapi","db","queryBuilder","FOLDER_MODEL_UID","first","execute","pathId","parentPath","parent","parentFolder","query","findOne","where","id","path","Object","assign","strings","joinBy","create","folderData","opts","folderService","getService","user","enrichedFolder","setCreatorFields","data","eventHub","emit","deleteByIds","ids","validateFiles","folders","findMany","$in","length","totalFolderNumber","totalFileNumber","pathsToDelete","map","filesToDelete","FILE_MODEL_UID","$or","flatMap","folderPath","$eq","$startsWith","Promise","all","file","remove","count","deleteMany","forEach","AUDITED_EVENTS","FOLDER_DELETE_AUDIT","update","name","undefined","existingFolder","populate","select","newFolder","isEdition","previous","trx","transaction","transacting","get","forUpdate","joinTable","metadata","attributes","delete","joinColumn","insert","inverseJoinColumn","destinationFolderPath","destinationFolder","folderTable","getModel","collectionName","fileTable","folderPathColumnName","columnName","pathColumnName","getConnection","orWhere","connection","raw","commit","e","rollback","exists","params","getStructure","qb","alias","getAlias","join","referencedTable","referencedColumn","rootColumn","rootTable","mapResults","folderMap","null","children","f","parentId","push","sortBy"],"mappings":"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"}
@@ -2,6 +2,7 @@ import { sortBy, map } from 'lodash';
2
2
  import { strings, setCreatorFields } from '@strapi/utils';
3
3
  import { FOLDER_MODEL_UID, FILE_MODEL_UID } from '../constants.mjs';
4
4
  import { getService } from '../utils/index.mjs';
5
+ import { AUDITED_EVENTS } from '../audit-logs.mjs';
5
6
 
6
7
  const setPathIdAndPath = async (folder)=>{
7
8
  const { max } = await strapi.db.queryBuilder(FOLDER_MODEL_UID).max('pathId').first().execute();
@@ -98,6 +99,11 @@ const create = async (folderData, opts)=>{
98
99
  strapi.eventHub.emit('media-folder.delete', {
99
100
  folders
100
101
  });
102
+ folders.forEach((folder)=>{
103
+ strapi.eventHub.emit(AUDITED_EVENTS.FOLDER_DELETE_AUDIT, {
104
+ folder
105
+ });
106
+ });
101
107
  return {
102
108
  folders,
103
109
  totalFolderNumber,
@@ -112,6 +118,14 @@ const create = async (folderData, opts)=>{
112
118
  const existingFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
113
119
  where: {
114
120
  id
121
+ },
122
+ populate: {
123
+ parent: {
124
+ select: [
125
+ 'id',
126
+ 'name'
127
+ ]
128
+ }
115
129
  }
116
130
  });
117
131
  if (!existingFolder) {
@@ -131,10 +145,30 @@ const create = async (folderData, opts)=>{
131
145
  },
132
146
  data: newFolder
133
147
  });
148
+ strapi.eventHub.emit('media-folder.update', {
149
+ folder: {
150
+ ...folder,
151
+ parent: existingFolder.parent ?? null
152
+ },
153
+ previous: existingFolder
154
+ });
134
155
  return folder;
135
156
  }
136
157
  // location is updated => using transaction
137
158
  } else {
159
+ const previous = await strapi.db.query(FOLDER_MODEL_UID).findOne({
160
+ where: {
161
+ id
162
+ },
163
+ populate: {
164
+ parent: {
165
+ select: [
166
+ 'id',
167
+ 'name'
168
+ ]
169
+ }
170
+ }
171
+ });
138
172
  const trx = await strapi.db.transaction();
139
173
  try {
140
174
  // fetch existing folder
@@ -202,8 +236,21 @@ const create = async (folderData, opts)=>{
202
236
  },
203
237
  data: newFolder
204
238
  });
239
+ const parentFolder = parent === null ? null : await strapi.db.query(FOLDER_MODEL_UID).findOne({
240
+ where: {
241
+ id: parent
242
+ },
243
+ select: [
244
+ 'id',
245
+ 'name'
246
+ ]
247
+ });
205
248
  strapi.eventHub.emit('media-folder.update', {
206
- folder
249
+ folder: {
250
+ ...folder,
251
+ parent: parentFolder
252
+ },
253
+ previous
207
254
  });
208
255
  return folder;
209
256
  }
@@ -1 +1 @@
1
- {"version":3,"file":"folder.mjs","sources":["../../../server/src/services/folder.ts"],"sourcesContent":["import { map, sortBy } from 'lodash';\nimport { strings, setCreatorFields } from '@strapi/utils';\nimport { FOLDER_MODEL_UID, FILE_MODEL_UID } from '../constants';\nimport { getService } from '../utils';\n\nimport type { File, Folder } from '../types';\n\ntype FolderMap = {\n [key: string]: Partial<Folder> & {\n children: FolderNode[];\n };\n};\n\ntype FolderNode = Partial<Folder> & {\n children: FolderNode[];\n};\n\ntype DeleteByIdsOptions = {\n validateFiles?: (files: File[]) => Promise<void>;\n};\n\nconst setPathIdAndPath = async (folder: Pick<Folder, 'parent'>) => {\n const { max } = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .max('pathId')\n .first()\n .execute<{ max: number }>();\n\n const pathId = max + 1;\n let parentPath = '/';\n if (folder.parent) {\n const parentFolder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id: folder.parent } });\n\n parentPath = parentFolder.path;\n }\n\n return Object.assign(folder, {\n pathId,\n path: strings.joinBy('/', parentPath, `${pathId}`),\n });\n};\n\nconst create = async (\n folderData: Pick<Folder, 'name' | 'parent'>,\n opts?: { user: { id: string | number } }\n) => {\n const folderService = getService('folder');\n\n const { user } = opts || {};\n\n let enrichedFolder = await folderService.setPathIdAndPath(folderData);\n if (user) {\n enrichedFolder = await setCreatorFields({ user })(enrichedFolder);\n }\n\n const folder = await strapi.db.query(FOLDER_MODEL_UID).create({ data: enrichedFolder });\n\n strapi.eventHub.emit('media-folder.create', { folder });\n\n return folder;\n};\n\n/**\n * Recursively delete folders and included files\n * @param ids ids of the folders to delete\n * @returns {Promise<Object[]>}\n */\nconst deleteByIds = async (ids: number[] = [], { validateFiles }: DeleteByIdsOptions = {}) => {\n const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({ where: { id: { $in: ids } } });\n if (folders.length === 0) {\n return {\n folders: [],\n totalFolderNumber: 0,\n totalFileNumber: 0,\n };\n }\n\n const pathsToDelete = map(folders, 'path');\n\n // delete files\n const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { folderPath: { $eq: path } },\n { folderPath: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n // A folder deletion cascades to every file in its subtree. Let callers enforce\n // request-scoped permissions against the complete set before the first destructive action.\n await validateFiles?.(filesToDelete);\n\n await Promise.all(filesToDelete.map((file: File) => getService('upload').remove(file)));\n\n // delete folders and subfolders\n const { count: totalFolderNumber } = await strapi.db.query(FOLDER_MODEL_UID).deleteMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { path: { $eq: path } },\n { path: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n strapi.eventHub.emit('media-folder.delete', { folders });\n\n return {\n folders,\n totalFolderNumber,\n totalFileNumber: filesToDelete.length,\n };\n};\n\n/**\n * Update name and location of a folder and its belonging folders and files\n */\nconst update = async (\n id: number,\n {\n name,\n parent,\n }: {\n name: string;\n /**\n * Omit to rename in place: the name-only branch skips the transaction that rewrites\n * descendant paths. Pass a number to re-parent, or null to move to the root.\n */\n parent?: number | null;\n },\n { user }: { user: { id: string | number } }\n) => {\n // only name is updated\n if (parent === undefined) {\n const existingFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({ where: { id } });\n\n if (!existingFolder) {\n return undefined;\n }\n\n const newFolder = setCreatorFields({ user, isEdition: true })({ name, parent });\n\n if (parent === undefined) {\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n return folder;\n }\n // location is updated => using transaction\n } else {\n const trx = await strapi.db.transaction();\n try {\n // fetch existing folder\n const existingFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select(['pathId', 'path'])\n .where({ id })\n .transacting(trx.get())\n .forUpdate()\n .first()\n .execute<Folder>();\n\n // update parent folder (delete + insert; upsert not possible)\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n\n if (parent !== null) {\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .insert({ [joinTable.inverseJoinColumn.name]: parent, [joinTable.joinColumn.name]: id })\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n }\n\n // fetch destinationFolder path\n let destinationFolderPath = '/';\n if (parent !== null) {\n const destinationFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select('path')\n .where({ id: parent })\n .transacting(trx.get())\n .first()\n .execute<Folder>();\n destinationFolderPath = destinationFolder.path;\n }\n\n const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;\n const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;\n const folderPathColumnName =\n // @ts-expect-error - no dynamic types\n strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;\n // @ts-expect-error - no dynamic types\n const pathColumnName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;\n\n // update folders below\n await strapi.db\n .getConnection(folderTable)\n .transacting(trx.get())\n .where(pathColumnName, existingFolder.path)\n .orWhere(pathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n pathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n pathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n // update files below\n await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .where(folderPathColumnName, existingFolder.path)\n .orWhere(folderPathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n folderPathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n folderPathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n await trx.commit();\n } catch (e) {\n await trx.rollback();\n throw e;\n }\n\n // update less critical information (name + updatedBy)\n const newFolder = setCreatorFields({ user, isEdition: true })({ name });\n\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n strapi.eventHub.emit('media-folder.update', { folder });\n return folder;\n }\n};\n\n/**\n * Check if a folder exists in database\n * @param params query params to find the folder\n * @returns {Promise<boolean>}\n */\nconst exists = async (params = {}) => {\n const count = await strapi.db.query(FOLDER_MODEL_UID).count({ where: params });\n return count > 0;\n};\n\n/**\n * Returns the nested structure of folders\n * @returns {Promise<array>}\n */\nconst getStructure = async () => {\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n const qb = strapi.db.queryBuilder(FOLDER_MODEL_UID);\n const alias = qb.getAlias();\n const folders = (await qb\n .select(['id', 'name', `${alias}.${joinTable.inverseJoinColumn.name} as parent`])\n .join({\n alias,\n referencedTable: joinTable.name,\n referencedColumn: joinTable.joinColumn.name,\n rootColumn: joinTable.joinColumn.referencedColumn,\n rootTable: qb.alias,\n })\n .execute({ mapResults: false })) as Folder[];\n\n const folderMap: FolderMap = {\n null: { children: [] },\n };\n\n folders.forEach((f) => {\n folderMap[f.id] = { ...f, children: [] };\n });\n\n folders.forEach((f) => {\n const parentId = f.parent || 'null';\n\n if (!folderMap[parentId]) {\n folderMap[parentId] = { children: [] };\n }\n\n folderMap[parentId].children.push(folderMap[f.id]);\n folderMap[parentId].children = sortBy(folderMap[parentId].children, 'name');\n delete folderMap[f.id].parent;\n });\n\n return folderMap.null.children;\n};\n\nexport default {\n create,\n exists,\n deleteByIds,\n update,\n setPathIdAndPath,\n getStructure,\n};\n"],"names":["setPathIdAndPath","folder","max","strapi","db","queryBuilder","FOLDER_MODEL_UID","first","execute","pathId","parentPath","parent","parentFolder","query","findOne","where","id","path","Object","assign","strings","joinBy","create","folderData","opts","folderService","getService","user","enrichedFolder","setCreatorFields","data","eventHub","emit","deleteByIds","ids","validateFiles","folders","findMany","$in","length","totalFolderNumber","totalFileNumber","pathsToDelete","map","filesToDelete","FILE_MODEL_UID","$or","flatMap","folderPath","$eq","$startsWith","Promise","all","file","remove","count","deleteMany","update","name","undefined","existingFolder","newFolder","isEdition","trx","transaction","select","transacting","get","forUpdate","joinTable","metadata","attributes","delete","joinColumn","insert","inverseJoinColumn","destinationFolderPath","destinationFolder","folderTable","getModel","collectionName","fileTable","folderPathColumnName","columnName","pathColumnName","getConnection","orWhere","connection","raw","commit","e","rollback","exists","params","getStructure","qb","alias","getAlias","join","referencedTable","referencedColumn","rootColumn","rootTable","mapResults","folderMap","null","children","forEach","f","parentId","push","sortBy"],"mappings":";;;;;AAqBA,MAAMA,mBAAmB,OAAOC,MAAAA,GAAAA;AAC9B,IAAA,MAAM,EAAEC,GAAG,EAAE,GAAG,MAAMC,OAAOC,EAAE,CAC5BC,YAAY,CAACC,kBACbJ,GAAG,CAAC,QAAA,CAAA,CACJK,KAAK,GACLC,OAAO,EAAA;AAEV,IAAA,MAAMC,SAASP,GAAAA,GAAM,CAAA;AACrB,IAAA,IAAIQ,UAAAA,GAAa,GAAA;IACjB,IAAIT,MAAAA,CAAOU,MAAM,EAAE;QACjB,MAAMC,YAAAA,GAAe,MAAMT,MAAAA,CAAOC,EAAE,CACjCS,KAAK,CAACP,gBAAAA,CAAAA,CACNQ,OAAO,CAAC;YAAEC,KAAAA,EAAO;AAAEC,gBAAAA,EAAAA,EAAIf,OAAOU;AAAO;AAAE,SAAA,CAAA;AAE1CD,QAAAA,UAAAA,GAAaE,aAAaK,IAAI;AAChC,IAAA;IAEA,OAAOC,MAAAA,CAAOC,MAAM,CAAClB,MAAAA,EAAQ;AAC3BQ,QAAAA,MAAAA;AACAQ,QAAAA,IAAAA,EAAMG,QAAQC,MAAM,CAAC,GAAA,EAAKX,UAAAA,EAAY,GAAGD,MAAAA,CAAAA,CAAQ;AACnD,KAAA,CAAA;AACF,CAAA;AAEA,MAAMa,MAAAA,GAAS,OACbC,UAAAA,EACAC,IAAAA,GAAAA;AAEA,IAAA,MAAMC,gBAAgBC,UAAAA,CAAW,QAAA,CAAA;AAEjC,IAAA,MAAM,EAAEC,IAAI,EAAE,GAAGH,QAAQ,EAAC;AAE1B,IAAA,IAAII,cAAAA,GAAiB,MAAMH,aAAAA,CAAczB,gBAAgB,CAACuB,UAAAA,CAAAA;AAC1D,IAAA,IAAII,IAAAA,EAAM;AACRC,QAAAA,cAAAA,GAAiB,MAAMC,gBAAAA,CAAiB;AAAEF,YAAAA;SAAK,CAAA,CAAGC,cAAAA,CAAAA;AACpD,IAAA;IAEA,MAAM3B,MAAAA,GAAS,MAAME,MAAAA,CAAOC,EAAE,CAACS,KAAK,CAACP,gBAAAA,CAAAA,CAAkBgB,MAAM,CAAC;QAAEQ,IAAAA,EAAMF;AAAe,KAAA,CAAA;AAErFzB,IAAAA,MAAAA,CAAO4B,QAAQ,CAACC,IAAI,CAAC,qBAAA,EAAuB;AAAE/B,QAAAA;AAAO,KAAA,CAAA;IAErD,OAAOA,MAAAA;AACT,CAAA;AAEA;;;;IAKA,MAAMgC,WAAAA,GAAc,OAAOC,GAAAA,GAAgB,EAAE,EAAE,EAAEC,aAAa,EAAsB,GAAG,EAAE,GAAA;IACvF,MAAMC,OAAAA,GAAU,MAAMjC,MAAAA,CAAOC,EAAE,CAACS,KAAK,CAACP,gBAAAA,CAAAA,CAAkB+B,QAAQ,CAAC;QAAEtB,KAAAA,EAAO;YAAEC,EAAAA,EAAI;gBAAEsB,GAAAA,EAAKJ;AAAI;AAAE;AAAE,KAAA,CAAA;IAC/F,IAAIE,OAAAA,CAAQG,MAAM,KAAK,CAAA,EAAG;QACxB,OAAO;AACLH,YAAAA,OAAAA,EAAS,EAAE;YACXI,iBAAAA,EAAmB,CAAA;YACnBC,eAAAA,EAAiB;AACnB,SAAA;AACF,IAAA;IAEA,MAAMC,aAAAA,GAAgBC,IAAIP,OAAAA,EAAS,MAAA,CAAA;;IAGnC,MAAMQ,aAAAA,GAAgB,MAAMzC,MAAAA,CAAOC,EAAE,CAACS,KAAK,CAACgC,cAAAA,CAAAA,CAAgBR,QAAQ,CAAC;QACnEtB,KAAAA,EAAO;AACL+B,YAAAA,GAAAA,EAAKJ,aAAAA,CAAcK,OAAO,CAAC,CAAC9B,IAAAA,GAAS;AACnC,oBAAA;wBAAE+B,UAAAA,EAAY;4BAAEC,GAAAA,EAAKhC;AAAK;AAAE,qBAAA;AAC5B,oBAAA;wBAAE+B,UAAAA,EAAY;4BAAEE,WAAAA,EAAa,CAAA,EAAGjC,IAAAA,CAAK,CAAC;AAAE;AAAE;AAC3C,iBAAA;AACH;AACF,KAAA,CAAA;;;AAIA,IAAA,MAAMkB,aAAAA,GAAgBS,aAAAA,CAAAA;IAEtB,MAAMO,OAAAA,CAAQC,GAAG,CAACR,aAAAA,CAAcD,GAAG,CAAC,CAACU,IAAAA,GAAe3B,UAAAA,CAAW,QAAA,CAAA,CAAU4B,MAAM,CAACD,IAAAA,CAAAA,CAAAA,CAAAA;;AAGhF,IAAA,MAAM,EAAEE,KAAAA,EAAOf,iBAAiB,EAAE,GAAG,MAAMrC,MAAAA,CAAOC,EAAE,CAACS,KAAK,CAACP,gBAAAA,CAAAA,CAAkBkD,UAAU,CAAC;QACtFzC,KAAAA,EAAO;AACL+B,YAAAA,GAAAA,EAAKJ,aAAAA,CAAcK,OAAO,CAAC,CAAC9B,IAAAA,GAAS;AACnC,oBAAA;wBAAEA,IAAAA,EAAM;4BAAEgC,GAAAA,EAAKhC;AAAK;AAAE,qBAAA;AACtB,oBAAA;wBAAEA,IAAAA,EAAM;4BAAEiC,WAAAA,EAAa,CAAA,EAAGjC,IAAAA,CAAK,CAAC;AAAE;AAAE;AACrC,iBAAA;AACH;AACF,KAAA,CAAA;AAEAd,IAAAA,MAAAA,CAAO4B,QAAQ,CAACC,IAAI,CAAC,qBAAA,EAAuB;AAAEI,QAAAA;AAAQ,KAAA,CAAA;IAEtD,OAAO;AACLA,QAAAA,OAAAA;AACAI,QAAAA,iBAAAA;AACAC,QAAAA,eAAAA,EAAiBG,cAAcL;AACjC,KAAA;AACF,CAAA;AAEA;;AAEC,IACD,MAAMkB,MAAAA,GAAS,OACbzC,EAAAA,EACA,EACE0C,IAAI,EACJ/C,MAAM,EAQP,EACD,EAAEgB,IAAI,EAAqC,GAAA;;AAG3C,IAAA,IAAIhB,WAAWgD,SAAAA,EAAW;QACxB,MAAMC,cAAAA,GAAiB,MAAMzD,MAAAA,CAAOC,EAAE,CAACS,KAAK,CAACP,gBAAAA,CAAAA,CAAkBQ,OAAO,CAAC;YAAEC,KAAAA,EAAO;AAAEC,gBAAAA;AAAG;AAAE,SAAA,CAAA;AAEvF,QAAA,IAAI,CAAC4C,cAAAA,EAAgB;YACnB,OAAOD,SAAAA;AACT,QAAA;AAEA,QAAA,MAAME,YAAYhC,gBAAAA,CAAiB;AAAEF,YAAAA,IAAAA;YAAMmC,SAAAA,EAAW;SAAK,CAAA,CAAG;AAAEJ,YAAAA,IAAAA;AAAM/C,YAAAA;AAAO,SAAA,CAAA;AAE7E,QAAA,IAAIA,WAAWgD,SAAAA,EAAW;YACxB,MAAM1D,MAAAA,GAAS,MAAME,MAAAA,CAAOC,EAAE,CAC3BS,KAAK,CAACP,gBAAAA,CAAAA,CACNmD,MAAM,CAAC;gBAAE1C,KAAAA,EAAO;AAAEC,oBAAAA;AAAG,iBAAA;gBAAGc,IAAAA,EAAM+B;AAAU,aAAA,CAAA;YAE3C,OAAO5D,MAAAA;AACT,QAAA;;IAEF,CAAA,MAAO;AACL,QAAA,MAAM8D,GAAAA,GAAM,MAAM5D,MAAAA,CAAOC,EAAE,CAAC4D,WAAW,EAAA;QACvC,IAAI;;YAEF,MAAMJ,cAAAA,GAAiB,MAAMzD,MAAAA,CAAOC,EAAE,CACnCC,YAAY,CAACC,gBAAAA,CAAAA,CACb2D,MAAM,CAAC;AAAC,gBAAA,QAAA;AAAU,gBAAA;AAAO,aAAA,CAAA,CACzBlD,KAAK,CAAC;AAAEC,gBAAAA;aAAG,CAAA,CACXkD,WAAW,CAACH,GAAAA,CAAII,GAAG,IACnBC,SAAS,EAAA,CACT7D,KAAK,EAAA,CACLC,OAAO,EAAA;;;AAIV,YAAA,MAAM,EAAE6D,SAAS,EAAE,GAAGlE,OAAOC,EAAE,CAACkE,QAAQ,CAACH,GAAG,CAAC7D,gBAAAA,CAAAA,CAAkBiE,UAAU,CAAC5D,MAAM;AAChF,YAAA,MAAMR,OAAOC,EAAE,CACZC,YAAY,CAACgE,UAAUX,IAAI,CAAA,CAC3BQ,WAAW,CAACH,IAAII,GAAG,EAAA,CAAA,CACnBK,MAAM,EAAA,CACNzD,KAAK,CAAC;AAAE,gBAAA,CAACsD,SAAAA,CAAUI,UAAU,CAACf,IAAI,GAAG1C;AAAG,aAAA,CAAA,CACxCR,OAAO,EAAA;AAEV,YAAA,IAAIG,WAAW,IAAA,EAAM;AACnB,gBAAA,MAAMR,MAAAA,CAAOC,EAAE,CACZC,YAAY,CAACgE,SAAAA,CAAUX,IAAI,CAAA,CAC3BQ,WAAW,CAACH,GAAAA,CAAII,GAAG,EAAA,CAAA,CACnBO,MAAM,CAAC;AAAE,oBAAA,CAACL,SAAAA,CAAUM,iBAAiB,CAACjB,IAAI,GAAG/C,MAAAA;AAAQ,oBAAA,CAAC0D,SAAAA,CAAUI,UAAU,CAACf,IAAI,GAAG1C;AAAG,iBAAA,CAAA,CACrFD,KAAK,CAAC;AAAE,oBAAA,CAACsD,SAAAA,CAAUI,UAAU,CAACf,IAAI,GAAG1C;AAAG,iBAAA,CAAA,CACxCR,OAAO,EAAA;AACZ,YAAA;;AAGA,YAAA,IAAIoE,qBAAAA,GAAwB,GAAA;AAC5B,YAAA,IAAIjE,WAAW,IAAA,EAAM;AACnB,gBAAA,MAAMkE,iBAAAA,GAAoB,MAAM1E,MAAAA,CAAOC,EAAE,CACtCC,YAAY,CAACC,gBAAAA,CAAAA,CACb2D,MAAM,CAAC,MAAA,CAAA,CACPlD,KAAK,CAAC;oBAAEC,EAAAA,EAAIL;AAAO,iBAAA,CAAA,CACnBuD,WAAW,CAACH,GAAAA,CAAII,GAAG,EAAA,CAAA,CACnB5D,KAAK,GACLC,OAAO,EAAA;AACVoE,gBAAAA,qBAAAA,GAAwBC,kBAAkB5D,IAAI;AAChD,YAAA;AAEA,YAAA,MAAM6D,WAAAA,GAAc3E,MAAAA,CAAO4E,QAAQ,CAACzE,kBAAkB0E,cAAc;AACpE,YAAA,MAAMC,SAAAA,GAAY9E,MAAAA,CAAO4E,QAAQ,CAAClC,gBAAgBmC,cAAc;AAChE,YAAA,MAAME;YAEJ/E,MAAAA,CAAOC,EAAE,CAACkE,QAAQ,CAACH,GAAG,CAACtB,cAAAA,CAAAA,CAAgB0B,UAAU,CAACvB,UAAU,CAACmC,UAAU;;AAEzE,YAAA,MAAMC,cAAAA,GAAiBjF,MAAAA,CAAOC,EAAE,CAACkE,QAAQ,CAACH,GAAG,CAAC7D,gBAAAA,CAAAA,CAAkBiE,UAAU,CAACtD,IAAI,CAACkE,UAAU;;AAG1F,YAAA,MAAMhF,OAAOC,EAAE,CACZiF,aAAa,CAACP,aACdZ,WAAW,CAACH,GAAAA,CAAII,GAAG,IACnBpD,KAAK,CAACqE,gBAAgBxB,cAAAA,CAAe3C,IAAI,EACzCqE,OAAO,CAACF,cAAAA,EAAgB,MAAA,EAAQ,GAAGxB,cAAAA,CAAe3C,IAAI,CAAC,EAAE,CAAC,CAAA,CAC1DwC,MAAM,CACL2B,cAAAA,EACAjF,OAAOC,EAAE,CAACmF,UAAU,CAACC,GAAG,CAAC,mBAAA,EAAqB;AAC5CJ,gBAAAA,cAAAA;AACAxB,gBAAAA,cAAAA,CAAe3C,IAAI;AACnBG,gBAAAA,OAAAA,CAAQC,MAAM,CAAC,GAAA,EAAKuD,uBAAuB,CAAA,EAAGhB,cAAAA,CAAenD,MAAM,CAAA,CAAE;AACtE,aAAA,CAAA,CAAA;;AAIL,YAAA,MAAMN,OAAOC,EAAE,CACZiF,aAAa,CAACJ,WACdf,WAAW,CAACH,GAAAA,CAAII,GAAG,IACnBpD,KAAK,CAACmE,sBAAsBtB,cAAAA,CAAe3C,IAAI,EAC/CqE,OAAO,CAACJ,oBAAAA,EAAsB,MAAA,EAAQ,GAAGtB,cAAAA,CAAe3C,IAAI,CAAC,EAAE,CAAC,CAAA,CAChEwC,MAAM,CACLyB,oBAAAA,EACA/E,OAAOC,EAAE,CAACmF,UAAU,CAACC,GAAG,CAAC,mBAAA,EAAqB;AAC5CN,gBAAAA,oBAAAA;AACAtB,gBAAAA,cAAAA,CAAe3C,IAAI;AACnBG,gBAAAA,OAAAA,CAAQC,MAAM,CAAC,GAAA,EAAKuD,uBAAuB,CAAA,EAAGhB,cAAAA,CAAenD,MAAM,CAAA,CAAE;AACtE,aAAA,CAAA,CAAA;AAGL,YAAA,MAAMsD,IAAI0B,MAAM,EAAA;AAClB,QAAA,CAAA,CAAE,OAAOC,CAAAA,EAAG;AACV,YAAA,MAAM3B,IAAI4B,QAAQ,EAAA;YAClB,MAAMD,CAAAA;AACR,QAAA;;AAGA,QAAA,MAAM7B,YAAYhC,gBAAAA,CAAiB;AAAEF,YAAAA,IAAAA;YAAMmC,SAAAA,EAAW;SAAK,CAAA,CAAG;AAAEJ,YAAAA;AAAK,SAAA,CAAA;QAErE,MAAMzD,MAAAA,GAAS,MAAME,MAAAA,CAAOC,EAAE,CAC3BS,KAAK,CAACP,gBAAAA,CAAAA,CACNmD,MAAM,CAAC;YAAE1C,KAAAA,EAAO;AAAEC,gBAAAA;AAAG,aAAA;YAAGc,IAAAA,EAAM+B;AAAU,SAAA,CAAA;AAE3C1D,QAAAA,MAAAA,CAAO4B,QAAQ,CAACC,IAAI,CAAC,qBAAA,EAAuB;AAAE/B,YAAAA;AAAO,SAAA,CAAA;QACrD,OAAOA,MAAAA;AACT,IAAA;AACF,CAAA;AAEA;;;;AAIC,IACD,MAAM2F,MAAAA,GAAS,OAAOC,MAAAA,GAAS,EAAE,GAAA;IAC/B,MAAMtC,KAAAA,GAAQ,MAAMpD,MAAAA,CAAOC,EAAE,CAACS,KAAK,CAACP,gBAAAA,CAAAA,CAAkBiD,KAAK,CAAC;QAAExC,KAAAA,EAAO8E;AAAO,KAAA,CAAA;AAC5E,IAAA,OAAOtC,KAAAA,GAAQ,CAAA;AACjB,CAAA;AAEA;;;AAGC,IACD,MAAMuC,YAAAA,GAAe,UAAA;;AAEnB,IAAA,MAAM,EAAEzB,SAAS,EAAE,GAAGlE,OAAOC,EAAE,CAACkE,QAAQ,CAACH,GAAG,CAAC7D,gBAAAA,CAAAA,CAAkBiE,UAAU,CAAC5D,MAAM;AAChF,IAAA,MAAMoF,EAAAA,GAAK5F,MAAAA,CAAOC,EAAE,CAACC,YAAY,CAACC,gBAAAA,CAAAA;IAClC,MAAM0F,KAAAA,GAAQD,GAAGE,QAAQ,EAAA;AACzB,IAAA,MAAM7D,OAAAA,GAAW,MAAM2D,EAAAA,CACpB9B,MAAM,CAAC;AAAC,QAAA,IAAA;AAAM,QAAA,MAAA;QAAQ,CAAA,EAAG+B,KAAAA,CAAM,CAAC,EAAE3B,SAAAA,CAAUM,iBAAiB,CAACjB,IAAI,CAAC,UAAU;AAAE,KAAA,CAAA,CAC/EwC,IAAI,CAAC;AACJF,QAAAA,KAAAA;AACAG,QAAAA,eAAAA,EAAiB9B,UAAUX,IAAI;QAC/B0C,gBAAAA,EAAkB/B,SAAAA,CAAUI,UAAU,CAACf,IAAI;QAC3C2C,UAAAA,EAAYhC,SAAAA,CAAUI,UAAU,CAAC2B,gBAAgB;AACjDE,QAAAA,SAAAA,EAAWP,GAAGC;AAChB,KAAA,CAAA,CACCxF,OAAO,CAAC;QAAE+F,UAAAA,EAAY;AAAM,KAAA,CAAA;AAE/B,IAAA,MAAMC,SAAAA,GAAuB;QAC3BC,IAAAA,EAAM;AAAEC,YAAAA,QAAAA,EAAU;AAAG;AACvB,KAAA;IAEAtE,OAAAA,CAAQuE,OAAO,CAAC,CAACC,CAAAA,GAAAA;AACfJ,QAAAA,SAAS,CAACI,CAAAA,CAAE5F,EAAE,CAAC,GAAG;AAAE,YAAA,GAAG4F,CAAC;AAAEF,YAAAA,QAAAA,EAAU;AAAG,SAAA;AACzC,IAAA,CAAA,CAAA;IAEAtE,OAAAA,CAAQuE,OAAO,CAAC,CAACC,CAAAA,GAAAA;QACf,MAAMC,QAAAA,GAAWD,CAAAA,CAAEjG,MAAM,IAAI,MAAA;AAE7B,QAAA,IAAI,CAAC6F,SAAS,CAACK,QAAAA,CAAS,EAAE;YACxBL,SAAS,CAACK,SAAS,GAAG;AAAEH,gBAAAA,QAAAA,EAAU;AAAG,aAAA;AACvC,QAAA;QAEAF,SAAS,CAACK,QAAAA,CAAS,CAACH,QAAQ,CAACI,IAAI,CAACN,SAAS,CAACI,CAAAA,CAAE5F,EAAE,CAAC,CAAA;QACjDwF,SAAS,CAACK,QAAAA,CAAS,CAACH,QAAQ,GAAGK,MAAAA,CAAOP,SAAS,CAACK,QAAAA,CAAS,CAACH,QAAQ,EAAE,MAAA,CAAA;AACpE,QAAA,OAAOF,SAAS,CAACI,CAAAA,CAAE5F,EAAE,CAAC,CAACL,MAAM;AAC/B,IAAA,CAAA,CAAA;IAEA,OAAO6F,SAAAA,CAAUC,IAAI,CAACC,QAAQ;AAChC,CAAA;AAEA,aAAe;AACbpF,IAAAA,MAAAA;AACAsE,IAAAA,MAAAA;AACA3D,IAAAA,WAAAA;AACAwB,IAAAA,MAAAA;AACAzD,IAAAA,gBAAAA;AACA8F,IAAAA;AACF,CAAA;;;;"}
1
+ {"version":3,"file":"folder.mjs","sources":["../../../server/src/services/folder.ts"],"sourcesContent":["import { map, sortBy } from 'lodash';\nimport { strings, setCreatorFields } from '@strapi/utils';\nimport { FOLDER_MODEL_UID, FILE_MODEL_UID } from '../constants';\nimport { getService } from '../utils';\nimport { AUDITED_EVENTS } from '../audit-logs';\n\nimport type { File, Folder } from '../types';\n\ntype FolderMap = {\n [key: string]: Partial<Folder> & {\n children: FolderNode[];\n };\n};\n\ntype FolderNode = Partial<Folder> & {\n children: FolderNode[];\n};\n\ntype DeleteByIdsOptions = {\n validateFiles?: (files: File[]) => Promise<void>;\n};\n\nconst setPathIdAndPath = async (folder: Pick<Folder, 'parent'>) => {\n const { max } = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .max('pathId')\n .first()\n .execute<{ max: number }>();\n\n const pathId = max + 1;\n let parentPath = '/';\n if (folder.parent) {\n const parentFolder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id: folder.parent } });\n\n parentPath = parentFolder.path;\n }\n\n return Object.assign(folder, {\n pathId,\n path: strings.joinBy('/', parentPath, `${pathId}`),\n });\n};\n\nconst create = async (\n folderData: Pick<Folder, 'name' | 'parent'>,\n opts?: { user: { id: string | number } }\n) => {\n const folderService = getService('folder');\n\n const { user } = opts || {};\n\n let enrichedFolder = await folderService.setPathIdAndPath(folderData);\n if (user) {\n enrichedFolder = await setCreatorFields({ user })(enrichedFolder);\n }\n\n const folder = await strapi.db.query(FOLDER_MODEL_UID).create({ data: enrichedFolder });\n\n strapi.eventHub.emit('media-folder.create', { folder });\n\n return folder;\n};\n\n/**\n * Recursively delete folders and included files\n * @param ids ids of the folders to delete\n * @returns {Promise<Object[]>}\n */\nconst deleteByIds = async (ids: number[] = [], { validateFiles }: DeleteByIdsOptions = {}) => {\n const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({ where: { id: { $in: ids } } });\n if (folders.length === 0) {\n return {\n folders: [],\n totalFolderNumber: 0,\n totalFileNumber: 0,\n };\n }\n\n const pathsToDelete = map(folders, 'path');\n\n // delete files\n const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { folderPath: { $eq: path } },\n { folderPath: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n // A folder deletion cascades to every file in its subtree. Let callers enforce\n // request-scoped permissions against the complete set before the first destructive action.\n await validateFiles?.(filesToDelete);\n\n await Promise.all(filesToDelete.map((file: File) => getService('upload').remove(file)));\n\n // delete folders and subfolders\n const { count: totalFolderNumber } = await strapi.db.query(FOLDER_MODEL_UID).deleteMany({\n where: {\n $or: pathsToDelete.flatMap((path) => [\n { path: { $eq: path } },\n { path: { $startsWith: `${path}/` } },\n ]),\n },\n });\n\n strapi.eventHub.emit('media-folder.delete', { folders });\n folders.forEach((folder: Folder) => {\n strapi.eventHub.emit(AUDITED_EVENTS.FOLDER_DELETE_AUDIT, { folder });\n });\n\n return {\n folders,\n totalFolderNumber,\n totalFileNumber: filesToDelete.length,\n };\n};\n\n/**\n * Update name and location of a folder and its belonging folders and files\n */\nconst update = async (\n id: number,\n {\n name,\n parent,\n }: {\n name: string;\n /**\n * Omit to rename in place: the name-only branch skips the transaction that rewrites\n * descendant paths. Pass a number to re-parent, or null to move to the root.\n */\n parent?: number | null;\n },\n { user }: { user: { id: string | number } }\n) => {\n // only name is updated\n if (parent === undefined) {\n const existingFolder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id }, populate: { parent: { select: ['id', 'name'] } } });\n\n if (!existingFolder) {\n return undefined;\n }\n\n const newFolder = setCreatorFields({ user, isEdition: true })({ name, parent });\n\n if (parent === undefined) {\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n strapi.eventHub.emit('media-folder.update', {\n folder: { ...folder, parent: existingFolder.parent ?? null },\n previous: existingFolder,\n });\n\n return folder;\n }\n // location is updated => using transaction\n } else {\n const previous = await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id }, populate: { parent: { select: ['id', 'name'] } } });\n\n const trx = await strapi.db.transaction();\n try {\n // fetch existing folder\n const existingFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select(['pathId', 'path'])\n .where({ id })\n .transacting(trx.get())\n .forUpdate()\n .first()\n .execute<Folder>();\n\n // update parent folder (delete + insert; upsert not possible)\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .delete()\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n\n if (parent !== null) {\n await strapi.db\n .queryBuilder(joinTable.name)\n .transacting(trx.get())\n .insert({ [joinTable.inverseJoinColumn.name]: parent, [joinTable.joinColumn.name]: id })\n .where({ [joinTable.joinColumn.name]: id })\n .execute();\n }\n\n // fetch destinationFolder path\n let destinationFolderPath = '/';\n if (parent !== null) {\n const destinationFolder = await strapi.db\n .queryBuilder(FOLDER_MODEL_UID)\n .select('path')\n .where({ id: parent })\n .transacting(trx.get())\n .first()\n .execute<Folder>();\n destinationFolderPath = destinationFolder.path;\n }\n\n const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;\n const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;\n const folderPathColumnName =\n // @ts-expect-error - no dynamic types\n strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;\n // @ts-expect-error - no dynamic types\n const pathColumnName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;\n\n // update folders below\n await strapi.db\n .getConnection(folderTable)\n .transacting(trx.get())\n .where(pathColumnName, existingFolder.path)\n .orWhere(pathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n pathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n pathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n // update files below\n await strapi.db\n .getConnection(fileTable)\n .transacting(trx.get())\n .where(folderPathColumnName, existingFolder.path)\n .orWhere(folderPathColumnName, 'like', `${existingFolder.path}/%`)\n .update(\n folderPathColumnName,\n strapi.db.connection.raw('REPLACE(??, ?, ?)', [\n folderPathColumnName,\n existingFolder.path,\n strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),\n ])\n );\n\n await trx.commit();\n } catch (e) {\n await trx.rollback();\n throw e;\n }\n\n // update less critical information (name + updatedBy)\n const newFolder = setCreatorFields({ user, isEdition: true })({ name });\n\n const folder = await strapi.db\n .query(FOLDER_MODEL_UID)\n .update({ where: { id }, data: newFolder });\n\n const parentFolder =\n parent === null\n ? null\n : await strapi.db\n .query(FOLDER_MODEL_UID)\n .findOne({ where: { id: parent }, select: ['id', 'name'] });\n\n strapi.eventHub.emit('media-folder.update', {\n folder: { ...folder, parent: parentFolder },\n previous,\n });\n return folder;\n }\n};\n\n/**\n * Check if a folder exists in database\n * @param params query params to find the folder\n * @returns {Promise<boolean>}\n */\nconst exists = async (params = {}) => {\n const count = await strapi.db.query(FOLDER_MODEL_UID).count({ where: params });\n return count > 0;\n};\n\n/**\n * Returns the nested structure of folders\n * @returns {Promise<array>}\n */\nconst getStructure = async () => {\n // @ts-expect-error - no dynamic types\n const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;\n const qb = strapi.db.queryBuilder(FOLDER_MODEL_UID);\n const alias = qb.getAlias();\n const folders = (await qb\n .select(['id', 'name', `${alias}.${joinTable.inverseJoinColumn.name} as parent`])\n .join({\n alias,\n referencedTable: joinTable.name,\n referencedColumn: joinTable.joinColumn.name,\n rootColumn: joinTable.joinColumn.referencedColumn,\n rootTable: qb.alias,\n })\n .execute({ mapResults: false })) as Folder[];\n\n const folderMap: FolderMap = {\n null: { children: [] },\n };\n\n folders.forEach((f) => {\n folderMap[f.id] = { ...f, children: [] };\n });\n\n folders.forEach((f) => {\n const parentId = f.parent || 'null';\n\n if (!folderMap[parentId]) {\n folderMap[parentId] = { children: [] };\n }\n\n folderMap[parentId].children.push(folderMap[f.id]);\n folderMap[parentId].children = sortBy(folderMap[parentId].children, 'name');\n delete folderMap[f.id].parent;\n });\n\n return folderMap.null.children;\n};\n\nexport default {\n create,\n exists,\n deleteByIds,\n update,\n setPathIdAndPath,\n getStructure,\n};\n"],"names":["setPathIdAndPath","folder","max","strapi","db","queryBuilder","FOLDER_MODEL_UID","first","execute","pathId","parentPath","parent","parentFolder","query","findOne","where","id","path","Object","assign","strings","joinBy","create","folderData","opts","folderService","getService","user","enrichedFolder","setCreatorFields","data","eventHub","emit","deleteByIds","ids","validateFiles","folders","findMany","$in","length","totalFolderNumber","totalFileNumber","pathsToDelete","map","filesToDelete","FILE_MODEL_UID","$or","flatMap","folderPath","$eq","$startsWith","Promise","all","file","remove","count","deleteMany","forEach","AUDITED_EVENTS","FOLDER_DELETE_AUDIT","update","name","undefined","existingFolder","populate","select","newFolder","isEdition","previous","trx","transaction","transacting","get","forUpdate","joinTable","metadata","attributes","delete","joinColumn","insert","inverseJoinColumn","destinationFolderPath","destinationFolder","folderTable","getModel","collectionName","fileTable","folderPathColumnName","columnName","pathColumnName","getConnection","orWhere","connection","raw","commit","e","rollback","exists","params","getStructure","qb","alias","getAlias","join","referencedTable","referencedColumn","rootColumn","rootTable","mapResults","folderMap","null","children","f","parentId","push","sortBy"],"mappings":"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"}
@@ -32,7 +32,8 @@ const FORMATS_TO_RESIZE = new Set([
32
32
  'png',
33
33
  'webp',
34
34
  'tiff',
35
- 'gif'
35
+ 'gif',
36
+ 'avif'
36
37
  ]);
37
38
  const FORMATS_TO_PROCESS = new Set([
38
39
  'jpeg',
@@ -51,6 +52,10 @@ const FORMATS_TO_OPTIMIZE = new Set([
51
52
  'avif'
52
53
  ]);
53
54
  const isOptimizableFormat = (format)=>format !== undefined && FORMATS_TO_OPTIMIZE.has(format);
55
+ /**
56
+ * sharp reports AVIF files as `heif` with `av1` compression. Normalize them to `avif`;
57
+ * other HEIF files (e.g. HEIC, `hevc` compression) keep the `heif` format and stay unprocessed.
58
+ */ const getFormat = ({ format, compression })=>format === 'heif' && compression === 'av1' ? 'avif' : format;
54
59
  const writeStreamToFile = (stream, path)=>new Promise((resolve, reject)=>{
55
60
  const writeStream = fs__default.default.createWriteStream(path);
56
61
  // Reject promise if there is an error with the provided stream
@@ -133,7 +138,9 @@ const generateThumbnail = async (file)=>{
133
138
  *
134
139
  */ const optimize = async (file)=>{
135
140
  const { sizeOptimization = false, autoOrientation = false } = await index.getService('upload').getSettings() ?? {};
136
- const { format, size } = await getMetadata(file);
141
+ const metadata = await getMetadata(file);
142
+ const format = getFormat(metadata);
143
+ const { size } = metadata;
137
144
  if ((sizeOptimization || autoOrientation) && isOptimizableFormat(format)) {
138
145
  let transformer;
139
146
  if (!file.filepath) {
@@ -246,7 +253,7 @@ const isOptimizableImage = async (file)=>{
246
253
  let format;
247
254
  try {
248
255
  const metadata = await getMetadata(file);
249
- format = metadata.format;
256
+ format = getFormat(metadata);
250
257
  } catch {
251
258
  // throw when the file is not a supported image
252
259
  return false;
@@ -257,7 +264,7 @@ const isResizableImage = async (file)=>{
257
264
  let format;
258
265
  try {
259
266
  const metadata = await getMetadata(file);
260
- format = metadata.format;
267
+ format = getFormat(metadata);
261
268
  } catch {
262
269
  // throw when the file is not a supported image
263
270
  return false;
@@ -268,7 +275,7 @@ const isImage = async (file)=>{
268
275
  let format;
269
276
  try {
270
277
  const metadata = await getMetadata(file);
271
- format = metadata.format;
278
+ format = getFormat(metadata);
272
279
  } catch {
273
280
  // throw when the file is not a supported image
274
281
  return false;