@akemona-org/strapi-plugin-upload 3.7.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 (246) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +19 -0
  3. package/admin/src/assets/images/logo.svg +1 -0
  4. package/admin/src/components/BrowseAssets/Wrapper.js +8 -0
  5. package/admin/src/components/BrowseAssets/index.js +182 -0
  6. package/admin/src/components/Card/index.js +146 -0
  7. package/admin/src/components/CardBorder/index.js +28 -0
  8. package/admin/src/components/CardControl/Wrapper.js +89 -0
  9. package/admin/src/components/CardControl/index.js +61 -0
  10. package/admin/src/components/CardControlsWrapper/index.js +22 -0
  11. package/admin/src/components/CardEmpty/Bar.js +19 -0
  12. package/admin/src/components/CardEmpty/Wrapper.js +7 -0
  13. package/admin/src/components/CardEmpty/index.js +16 -0
  14. package/admin/src/components/CardErrorMessage/index.js +9 -0
  15. package/admin/src/components/CardImgWrapper/index.js +52 -0
  16. package/admin/src/components/CardPreview/Image.js +12 -0
  17. package/admin/src/components/CardPreview/Wrapper.js +25 -0
  18. package/admin/src/components/CardPreview/index.js +66 -0
  19. package/admin/src/components/CardTitle/index.js +14 -0
  20. package/admin/src/components/CardWrapper/index.js +23 -0
  21. package/admin/src/components/CheckControl/Button.js +49 -0
  22. package/admin/src/components/CheckControl/CustomDropdownSection.js +9 -0
  23. package/admin/src/components/CheckControl/Spacer.js +7 -0
  24. package/admin/src/components/CheckControl/index.js +74 -0
  25. package/admin/src/components/Container/index.js +7 -0
  26. package/admin/src/components/ContainerFluid/index.js +12 -0
  27. package/admin/src/components/ControlsWrapper/index.js +9 -0
  28. package/admin/src/components/DragLayer/Wrapper.js +13 -0
  29. package/admin/src/components/DragLayer/index.js +68 -0
  30. package/admin/src/components/DropdownButton/index.js +63 -0
  31. package/admin/src/components/DropdownSection/index.js +27 -0
  32. package/admin/src/components/Duration/index.js +25 -0
  33. package/admin/src/components/Duration/utils/formatDuration.js +13 -0
  34. package/admin/src/components/EditForm/CropWrapper.js +21 -0
  35. package/admin/src/components/EditForm/ErrorMessage.js +10 -0
  36. package/admin/src/components/EditForm/FileDetailsBox.js +95 -0
  37. package/admin/src/components/EditForm/FileDetailsBoxWrapper.js +14 -0
  38. package/admin/src/components/EditForm/FileWrapper.js +41 -0
  39. package/admin/src/components/EditForm/FormWrapper.js +7 -0
  40. package/admin/src/components/EditForm/SizeBox.js +13 -0
  41. package/admin/src/components/EditForm/Wrapper.js +8 -0
  42. package/admin/src/components/EditForm/index.js +425 -0
  43. package/admin/src/components/EditForm/utils/form.js +34 -0
  44. package/admin/src/components/EditForm/utils/isImageType.js +3 -0
  45. package/admin/src/components/EditForm/utils/isVideoType.js +3 -0
  46. package/admin/src/components/FileIcon/Wrapper.js +20 -0
  47. package/admin/src/components/FileIcon/index.js +33 -0
  48. package/admin/src/components/FileIcon/utils/extensions.json +4 -0
  49. package/admin/src/components/FileInfos/index.js +32 -0
  50. package/admin/src/components/Filters/index.js +30 -0
  51. package/admin/src/components/FiltersList/index.js +34 -0
  52. package/admin/src/components/FiltersList/utils/formatFilter.js +36 -0
  53. package/admin/src/components/FiltersPicker/FiltersCard/FilterButton.js +8 -0
  54. package/admin/src/components/FiltersPicker/FiltersCard/FilterInput.js +35 -0
  55. package/admin/src/components/FiltersPicker/FiltersCard/InputWrapper.js +10 -0
  56. package/admin/src/components/FiltersPicker/FiltersCard/SizeInput.js +57 -0
  57. package/admin/src/components/FiltersPicker/FiltersCard/Wrapper.js +8 -0
  58. package/admin/src/components/FiltersPicker/FiltersCard/index.js +97 -0
  59. package/admin/src/components/FiltersPicker/FiltersCard/init.js +21 -0
  60. package/admin/src/components/FiltersPicker/FiltersCard/reducer.js +47 -0
  61. package/admin/src/components/FiltersPicker/FiltersCard/utils/filtersForm.js +27 -0
  62. package/admin/src/components/FiltersPicker/index.js +43 -0
  63. package/admin/src/components/FiltersPicker/utils/formatFilter.js +18 -0
  64. package/admin/src/components/InfiniteLoadingIndicator/Button.js +20 -0
  65. package/admin/src/components/InfiniteLoadingIndicator/Container.js +12 -0
  66. package/admin/src/components/InfiniteLoadingIndicator/Wrapper.js +18 -0
  67. package/admin/src/components/InfiniteLoadingIndicator/index.js +39 -0
  68. package/admin/src/components/Input/index.js +7 -0
  69. package/admin/src/components/InputFileModal/Label.js +47 -0
  70. package/admin/src/components/InputFileModal/P.js +15 -0
  71. package/admin/src/components/InputFileModal/index.js +73 -0
  72. package/admin/src/components/InputMedia/CardControlWrapper.js +12 -0
  73. package/admin/src/components/InputMedia/CardPreviewWrapper.js +13 -0
  74. package/admin/src/components/InputMedia/Chevron/Wrapper.js +10 -0
  75. package/admin/src/components/InputMedia/Chevron/index.js +21 -0
  76. package/admin/src/components/InputMedia/EmptyInputMedia.js +60 -0
  77. package/admin/src/components/InputMedia/EmptyText.js +13 -0
  78. package/admin/src/components/InputMedia/ErrorMessage.js +12 -0
  79. package/admin/src/components/InputMedia/IconUpload.js +48 -0
  80. package/admin/src/components/InputMedia/InputFilePreview.js +37 -0
  81. package/admin/src/components/InputMedia/Name.js +10 -0
  82. package/admin/src/components/InputMedia/Wrapper.js +11 -0
  83. package/admin/src/components/InputMedia/index.js +238 -0
  84. package/admin/src/components/InputUploadURL/Wrapper.js +13 -0
  85. package/admin/src/components/InputUploadURL/index.js +46 -0
  86. package/admin/src/components/IntlText/index.js +26 -0
  87. package/admin/src/components/List/ListCell.js +19 -0
  88. package/admin/src/components/List/ListRow.js +8 -0
  89. package/admin/src/components/List/index.js +114 -0
  90. package/admin/src/components/ListEmpty/Wrapper.js +15 -0
  91. package/admin/src/components/ListEmpty/index.js +70 -0
  92. package/admin/src/components/ListEmpty/utils/generateRows.js +12 -0
  93. package/admin/src/components/ListModal/BaselineAlignmentWrapper.js +12 -0
  94. package/admin/src/components/ListModal/index.js +66 -0
  95. package/admin/src/components/ListWrapper/index.js +16 -0
  96. package/admin/src/components/LoadingIndicator/index.js +44 -0
  97. package/admin/src/components/ModalHeader/BackButton.js +33 -0
  98. package/admin/src/components/ModalHeader/Wrapper.js +24 -0
  99. package/admin/src/components/ModalHeader/index.js +47 -0
  100. package/admin/src/components/ModalNavWrapper/BaselineAlignment.js +12 -0
  101. package/admin/src/components/ModalNavWrapper/Hr.js +14 -0
  102. package/admin/src/components/ModalNavWrapper/Wrapper.js +8 -0
  103. package/admin/src/components/ModalNavWrapper/index.js +70 -0
  104. package/admin/src/components/ModalSection/index.js +20 -0
  105. package/admin/src/components/ModalTab/Count/Wrapper.js +16 -0
  106. package/admin/src/components/ModalTab/Count/index.js +30 -0
  107. package/admin/src/components/ModalTab/Wrapper.js +37 -0
  108. package/admin/src/components/ModalTab/index.js +60 -0
  109. package/admin/src/components/PlayIcon/Play.js +65 -0
  110. package/admin/src/components/PlayIcon/Wrapper.js +24 -0
  111. package/admin/src/components/PlayIcon/index.js +23 -0
  112. package/admin/src/components/SelectAll/Wrapper.js +19 -0
  113. package/admin/src/components/SelectAll/index.js +26 -0
  114. package/admin/src/components/SelectedAssets/DraggableCard.js +149 -0
  115. package/admin/src/components/SelectedAssets/ListTitleWrapper.js +7 -0
  116. package/admin/src/components/SelectedAssets/ListWrapper.js +7 -0
  117. package/admin/src/components/SelectedAssets/SortableList.js +102 -0
  118. package/admin/src/components/SelectedAssets/Wrapper.js +7 -0
  119. package/admin/src/components/SelectedAssets/index.js +56 -0
  120. package/admin/src/components/SortList/Wrapper.js +19 -0
  121. package/admin/src/components/SortList/index.js +37 -0
  122. package/admin/src/components/SortListItem/Wrapper.js +28 -0
  123. package/admin/src/components/SortListItem/index.js +35 -0
  124. package/admin/src/components/SortPicker/index.js +54 -0
  125. package/admin/src/components/Tag/Wrapper.js +16 -0
  126. package/admin/src/components/Tag/index.js +25 -0
  127. package/admin/src/components/UploadForm/index.js +61 -0
  128. package/admin/src/components/UploadList/ButtonWrapper.js +7 -0
  129. package/admin/src/components/UploadList/Container.js +10 -0
  130. package/admin/src/components/UploadList/CustomModalSection.js +9 -0
  131. package/admin/src/components/UploadList/ListTitle.js +10 -0
  132. package/admin/src/components/UploadList/ListTitleWrapper.js +7 -0
  133. package/admin/src/components/UploadList/RowItem.js +98 -0
  134. package/admin/src/components/UploadList/index.js +90 -0
  135. package/admin/src/components/VideoPlayer/Wrapper.js +24 -0
  136. package/admin/src/components/VideoPlayer/index.js +57 -0
  137. package/admin/src/components/VideoPreview/CanvasWrapper.js +22 -0
  138. package/admin/src/components/VideoPreview/Thumbnail.js +12 -0
  139. package/admin/src/components/VideoPreview/Wrapper.js +15 -0
  140. package/admin/src/components/VideoPreview/index.js +165 -0
  141. package/admin/src/components/VideoPreview/reducer.js +33 -0
  142. package/admin/src/containers/App/index.js +31 -0
  143. package/admin/src/containers/HomePage/HomePageContent/HomePageList.js +98 -0
  144. package/admin/src/containers/HomePage/HomePageContent/HomePageSettings.js +103 -0
  145. package/admin/src/containers/HomePage/HomePageContent/index.js +90 -0
  146. package/admin/src/containers/HomePage/components.js +18 -0
  147. package/admin/src/containers/HomePage/index.js +373 -0
  148. package/admin/src/containers/HomePage/init.js +5 -0
  149. package/admin/src/containers/HomePage/reducer.js +88 -0
  150. package/admin/src/containers/HomePage/utils/generateParamsFromQuery.js +14 -0
  151. package/admin/src/containers/HomePage/utils/generateStringFromParams.js +27 -0
  152. package/admin/src/containers/HomePage/utils/getHeaderLabel.js +13 -0
  153. package/admin/src/containers/HomePage/utils/index.js +2 -0
  154. package/admin/src/containers/Initializer/index.js +44 -0
  155. package/admin/src/containers/InputModalStepper/HeaderSearch.js +12 -0
  156. package/admin/src/containers/InputModalStepper/InputModalStepper.js +480 -0
  157. package/admin/src/containers/InputModalStepper/Search.js +48 -0
  158. package/admin/src/containers/InputModalStepper/index.js +86 -0
  159. package/admin/src/containers/InputModalStepper/stepper.js +52 -0
  160. package/admin/src/containers/InputModalStepperProvider/index.js +564 -0
  161. package/admin/src/containers/InputModalStepperProvider/init.js +5 -0
  162. package/admin/src/containers/InputModalStepperProvider/reducer.js +301 -0
  163. package/admin/src/containers/ModalStepper/index.js +629 -0
  164. package/admin/src/containers/ModalStepper/init.js +5 -0
  165. package/admin/src/containers/ModalStepper/reducer.js +132 -0
  166. package/admin/src/containers/ModalStepper/stepper.js +46 -0
  167. package/admin/src/containers/SettingsPage/Divider.js +11 -0
  168. package/admin/src/containers/SettingsPage/SectionTitleWrapper.js +7 -0
  169. package/admin/src/containers/SettingsPage/Wrapper.js +17 -0
  170. package/admin/src/containers/SettingsPage/index.js +198 -0
  171. package/admin/src/containers/SettingsPage/init.js +5 -0
  172. package/admin/src/containers/SettingsPage/reducer.js +38 -0
  173. package/admin/src/contexts/AppContext/index.js +5 -0
  174. package/admin/src/contexts/InputModal/InputModalDataManager.js +5 -0
  175. package/admin/src/contexts/index.js +2 -0
  176. package/admin/src/hooks/index.js +2 -0
  177. package/admin/src/hooks/useAppContext/index.js +6 -0
  178. package/admin/src/hooks/useModalContext.js +6 -0
  179. package/admin/src/icons/BrokenFile/index.js +91 -0
  180. package/admin/src/icons/Cloud/index.js +35 -0
  181. package/admin/src/icons/DoubleFile/index.js +35 -0
  182. package/admin/src/icons/Download/index.js +36 -0
  183. package/admin/src/icons/File/index.js +35 -0
  184. package/admin/src/index.js +85 -0
  185. package/admin/src/lifecycles.js +13 -0
  186. package/admin/src/permissions.js +40 -0
  187. package/admin/src/pluginId.js +5 -0
  188. package/admin/src/translations/de.json +81 -0
  189. package/admin/src/translations/dk.json +81 -0
  190. package/admin/src/translations/en.json +86 -0
  191. package/admin/src/translations/es.json +81 -0
  192. package/admin/src/translations/fr.json +85 -0
  193. package/admin/src/translations/he.json +81 -0
  194. package/admin/src/translations/index.js +39 -0
  195. package/admin/src/translations/it.json +82 -0
  196. package/admin/src/translations/ja.json +81 -0
  197. package/admin/src/translations/ms.json +73 -0
  198. package/admin/src/translations/pl.json +81 -0
  199. package/admin/src/translations/pt-BR.json +81 -0
  200. package/admin/src/translations/ru.json +81 -0
  201. package/admin/src/translations/sk.json +81 -0
  202. package/admin/src/translations/th.json +81 -0
  203. package/admin/src/translations/uk.json +78 -0
  204. package/admin/src/translations/zh-Hans.json +86 -0
  205. package/admin/src/translations/zh.json +81 -0
  206. package/admin/src/utils/ItemTypes.js +3 -0
  207. package/admin/src/utils/canDownloadFile.js +3 -0
  208. package/admin/src/utils/compactParams.js +13 -0
  209. package/admin/src/utils/createFileToDownloadName.js +9 -0
  210. package/admin/src/utils/createMatrix.js +32 -0
  211. package/admin/src/utils/createNewFilesToDownloadArray.js +57 -0
  212. package/admin/src/utils/createNewFilesToUploadArray.js +25 -0
  213. package/admin/src/utils/formatBytes.js +13 -0
  214. package/admin/src/utils/formatFileForEditing.js +20 -0
  215. package/admin/src/utils/formatFilters.js +23 -0
  216. package/admin/src/utils/generatePageFromStart.js +5 -0
  217. package/admin/src/utils/generateStartFromPage.js +5 -0
  218. package/admin/src/utils/getFileModelTimestamps.js +15 -0
  219. package/admin/src/utils/getFilesToDownload.js +5 -0
  220. package/admin/src/utils/getRequestUrl.js +5 -0
  221. package/admin/src/utils/getTrad.js +5 -0
  222. package/admin/src/utils/getType.js +15 -0
  223. package/admin/src/utils/getYupError.js +17 -0
  224. package/admin/src/utils/index.js +20 -0
  225. package/admin/src/utils/unformatBytes.js +16 -0
  226. package/admin/src/utils/urlYupSchema.js +49 -0
  227. package/config/config.json +8 -0
  228. package/config/functions/bootstrap.js +143 -0
  229. package/config/routes.json +98 -0
  230. package/config/schema.graphql.js +96 -0
  231. package/controllers/Upload.js +103 -0
  232. package/controllers/upload/admin.js +213 -0
  233. package/controllers/upload/api.js +125 -0
  234. package/controllers/validation/settings.js +22 -0
  235. package/controllers/validation/upload.js +27 -0
  236. package/documentation/1.0.0/overrides/upload-File.json +263 -0
  237. package/errors.js +48 -0
  238. package/index.js +7 -0
  239. package/middlewares/upload/defaults.json +5 -0
  240. package/middlewares/upload/index.js +35 -0
  241. package/models/File.js +7 -0
  242. package/models/File.settings.json +86 -0
  243. package/package.json +71 -0
  244. package/services/Upload.js +397 -0
  245. package/services/image-manipulation.js +167 -0
  246. package/utils/file.js +23 -0
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ const { resolve } = require('path');
4
+ const range = require('koa-range');
5
+ const koaStatic = require('koa-static');
6
+ const _ = require('lodash');
7
+
8
+ module.exports = strapi => ({
9
+ initialize() {
10
+ const configPublicPath = strapi.config.get(
11
+ 'middleware.settings.public.path',
12
+ strapi.config.paths.static
13
+ );
14
+ const staticDir = resolve(strapi.dir, configPublicPath);
15
+
16
+ strapi.app.on('error', err => {
17
+ if (err.code === 'EPIPE') {
18
+ // when serving audio or video the browsers sometimes close the connection to go to range requests instead.
19
+ // This causes koa to emit a write EPIPE error. We can ignore it.
20
+ // Right now this ignores it globally and we cannot do much more because it is how koa handles it.
21
+ return;
22
+ }
23
+
24
+ strapi.app.onerror(err);
25
+ });
26
+
27
+ const localServerConfig =
28
+ _.get(strapi, 'plugins.upload.config.providerOptions.localServer') || {};
29
+ strapi.router.get(
30
+ '/uploads/(.*)',
31
+ range,
32
+ koaStatic(staticDir, { defer: true, ...localServerConfig })
33
+ );
34
+ },
35
+ });
package/models/File.js ADDED
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Lifecycle callbacks for the `File` model.
5
+ */
6
+
7
+ module.exports = {};
@@ -0,0 +1,86 @@
1
+ {
2
+ "info": {
3
+ "name": "file",
4
+ "description": ""
5
+ },
6
+ "options": {
7
+ "timestamps": true
8
+ },
9
+ "pluginOptions": {
10
+ "content-manager": {
11
+ "visible": false
12
+ },
13
+ "content-type-builder": {
14
+ "visible": false
15
+ }
16
+ },
17
+ "attributes": {
18
+ "name": {
19
+ "type": "string",
20
+ "configurable": false,
21
+ "required": true
22
+ },
23
+ "alternativeText": {
24
+ "type": "string",
25
+ "configurable": false
26
+ },
27
+ "caption": {
28
+ "type": "string",
29
+ "configurable": false
30
+ },
31
+ "width": {
32
+ "type": "integer",
33
+ "configurable": false
34
+ },
35
+ "height": {
36
+ "type": "integer",
37
+ "configurable": false
38
+ },
39
+ "formats": {
40
+ "type": "json",
41
+ "configurable": false
42
+ },
43
+ "hash": {
44
+ "type": "string",
45
+ "configurable": false,
46
+ "required": true
47
+ },
48
+ "ext": {
49
+ "type": "string",
50
+ "configurable": false
51
+ },
52
+ "mime": {
53
+ "type": "string",
54
+ "configurable": false,
55
+ "required": true
56
+ },
57
+ "size": {
58
+ "type": "decimal",
59
+ "configurable": false,
60
+ "required": true
61
+ },
62
+ "url": {
63
+ "type": "string",
64
+ "configurable": false,
65
+ "required": true
66
+ },
67
+ "previewUrl": {
68
+ "type": "string",
69
+ "configurable": false
70
+ },
71
+ "provider": {
72
+ "type": "string",
73
+ "configurable": false,
74
+ "required": true
75
+ },
76
+ "provider_metadata": {
77
+ "type": "json",
78
+ "configurable": false
79
+ },
80
+ "related": {
81
+ "collection": "*",
82
+ "filter": "field",
83
+ "configurable": false
84
+ }
85
+ }
86
+ }
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@akemona-org/strapi-plugin-upload",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "3.7.0",
7
+ "description": "Makes it easy to upload images and files to your Strapi Application.",
8
+ "strapi": {
9
+ "name": "Media Library",
10
+ "icon": "cloud-upload-alt",
11
+ "description": "upload.plugin.description",
12
+ "required": true
13
+ },
14
+ "scripts": {
15
+ "test": "echo \"no tests yet\""
16
+ },
17
+ "dependencies": {
18
+ "@akemona-org/strapi-helper-plugin": "3.7.0",
19
+ "@akemona-org/strapi-provider-upload-local": "3.7.0",
20
+ "@akemona-org/strapi-utils": "3.7.0",
21
+ "@buffetjs/core": "3.3.8",
22
+ "@buffetjs/custom": "3.3.8",
23
+ "@buffetjs/hooks": "3.3.8",
24
+ "@buffetjs/icons": "3.3.8",
25
+ "@buffetjs/styles": "3.3.8",
26
+ "@buffetjs/utils": "3.3.8",
27
+ "byte-size": "^7.0.1",
28
+ "cropperjs": "^1.5.11",
29
+ "immer": "9.0.16",
30
+ "immutable": "^3.8.2",
31
+ "is-valid-domain": "0.0.17",
32
+ "koa-range": "0.3.0",
33
+ "koa-static": "^5.0.0",
34
+ "lodash": "4.17.21",
35
+ "node-fetch": "2.6.1",
36
+ "react": "^16.14.0",
37
+ "react-copy-to-clipboard": "^5.0.3",
38
+ "react-dom": "^16.9.0",
39
+ "react-intl": "4.5.0",
40
+ "react-redux": "7.2.3",
41
+ "react-router": "^5.2.0",
42
+ "react-router-dom": "^5.0.0",
43
+ "reactstrap": "8.4.1",
44
+ "sharp": "0.31.1",
45
+ "stream-to-array": "^2.3.0",
46
+ "uuid": "^3.2.1"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/akemona/strapi.git",
51
+ "directory": "packages/strapi-plugin-upload"
52
+ },
53
+ "author": {
54
+ "name": "Akemona team",
55
+ "email": "strapi@akemona.com",
56
+ "url": "https://strapi.akemona.com"
57
+ },
58
+ "maintainers": [
59
+ {
60
+ "name": "Akemona team",
61
+ "email": "strapi@akemona.com",
62
+ "url": "https://strapi.akemona.com"
63
+ }
64
+ ],
65
+ "engines": {
66
+ "node": ">=10.16.0 <=14.x.x",
67
+ "npm": ">=6.0.0"
68
+ },
69
+ "license": "SEE LICENSE IN LICENSE",
70
+ "gitHead": "129a8d6191b55810fd66448dcc47fee829df986c"
71
+ }
@@ -0,0 +1,397 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Upload.js service
5
+ *
6
+ * @description: A set of functions similar to controller's actions to avoid code duplication.
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const crypto = require('crypto');
12
+ const util = require('util');
13
+ const _ = require('lodash');
14
+ const {
15
+ nameToSlug,
16
+ contentTypes: contentTypesUtils,
17
+ sanitizeEntity,
18
+ webhook: webhookUtils,
19
+ } = require('@akemona-org/strapi-utils');
20
+
21
+ const { MEDIA_UPDATE, MEDIA_CREATE, MEDIA_DELETE } = webhookUtils.webhookEvents;
22
+
23
+ const { bytesToKbytes } = require('../utils/file');
24
+
25
+ const { UPDATED_BY_ATTRIBUTE, CREATED_BY_ATTRIBUTE } = contentTypesUtils.constants;
26
+
27
+ const randomSuffix = () => crypto.randomBytes(5).toString('hex');
28
+
29
+ const generateFileName = (name) => {
30
+ const baseName = nameToSlug(name, { separator: '_', lowercase: false });
31
+
32
+ return `${baseName}_${randomSuffix()}`;
33
+ };
34
+
35
+ const sendMediaMetrics = (/* data */) => {
36
+ /* if (_.has(data, 'caption') && !_.isEmpty(data.caption)) {
37
+ strapi.telemetry.send('didSaveMediaWithCaption');
38
+ }
39
+
40
+ if (_.has(data, 'alternativeText') && !_.isEmpty(data.alternativeText)) {
41
+ strapi.telemetry.send('didSaveMediaWithAlternativeText');
42
+ } */
43
+ };
44
+
45
+ const combineFilters = (params) => {
46
+ // FIXME: until we support boolean operators for querying we need to make mime_ncontains use AND instead of OR
47
+ if (_.has(params, 'mime_ncontains') && Array.isArray(params.mime_ncontains)) {
48
+ params._where = params.mime_ncontains.map((val) => ({ mime_ncontains: val }));
49
+ delete params.mime_ncontains;
50
+ }
51
+ };
52
+
53
+ module.exports = {
54
+ formatFileInfo({ filename, type, size }, fileInfo = {}, metas = {}) {
55
+ const ext = path.extname(filename);
56
+ const basename = path.basename(fileInfo.name || filename, ext);
57
+
58
+ const usedName = fileInfo.name || filename;
59
+
60
+ const entity = {
61
+ name: usedName,
62
+ alternativeText: fileInfo.alternativeText,
63
+ caption: fileInfo.caption,
64
+ hash: generateFileName(basename),
65
+ ext,
66
+ mime: type,
67
+ size: bytesToKbytes(size),
68
+ };
69
+
70
+ const { refId, ref, source, field } = metas;
71
+
72
+ if (refId && ref && field) {
73
+ entity.related = [
74
+ {
75
+ refId,
76
+ ref,
77
+ source,
78
+ field,
79
+ },
80
+ ];
81
+ }
82
+
83
+ if (metas.path) {
84
+ entity.path = metas.path;
85
+ }
86
+
87
+ return entity;
88
+ },
89
+
90
+ async enhanceFile(file, fileInfo = {}, metas = {}) {
91
+ let readBuffer;
92
+ try {
93
+ readBuffer = await util.promisify(fs.readFile)(file.path);
94
+ } catch (e) {
95
+ if (e.code === 'ERR_FS_FILE_TOO_LARGE') {
96
+ throw strapi.errors.entityTooLarge('FileTooBig', {
97
+ errors: [
98
+ {
99
+ id: 'Upload.status.sizeLimit',
100
+ message: `${file.name} file is bigger than the limit size!`,
101
+ values: { file: file.name },
102
+ },
103
+ ],
104
+ });
105
+ }
106
+ throw e;
107
+ }
108
+
109
+ const { optimize } = strapi.plugins.upload.services['image-manipulation'];
110
+
111
+ const { buffer, info } = await optimize(readBuffer);
112
+
113
+ const formattedFile = this.formatFileInfo(
114
+ {
115
+ filename: file.name,
116
+ type: file.type,
117
+ size: file.size,
118
+ },
119
+ fileInfo,
120
+ metas
121
+ );
122
+
123
+ return _.assign(formattedFile, info, {
124
+ buffer,
125
+ });
126
+ },
127
+
128
+ async upload({ data, files }, { user } = {}) {
129
+ const { fileInfo, ...metas } = data;
130
+
131
+ const fileArray = Array.isArray(files) ? files : [files];
132
+ const fileInfoArray = Array.isArray(fileInfo) ? fileInfo : [fileInfo];
133
+
134
+ const doUpload = async (file, fileInfo) => {
135
+ const fileData = await this.enhanceFile(file, fileInfo, metas);
136
+
137
+ return this.uploadFileAndPersist(fileData, { user });
138
+ };
139
+
140
+ return await Promise.all(
141
+ fileArray.map((file, idx) => doUpload(file, fileInfoArray[idx] || {}))
142
+ );
143
+ },
144
+
145
+ async uploadFileAndPersist(fileData, { user } = {}) {
146
+ const config = strapi.plugins.upload.config;
147
+
148
+ const { getDimensions, generateThumbnail, generateResponsiveFormats } =
149
+ strapi.plugins.upload.services['image-manipulation'];
150
+
151
+ await strapi.plugins.upload.provider.upload(fileData);
152
+
153
+ const thumbnailFile = await generateThumbnail(fileData);
154
+ if (thumbnailFile) {
155
+ await strapi.plugins.upload.provider.upload(thumbnailFile);
156
+ delete thumbnailFile.buffer;
157
+ _.set(fileData, 'formats.thumbnail', thumbnailFile);
158
+ }
159
+
160
+ const formats = await generateResponsiveFormats(fileData);
161
+ if (Array.isArray(formats) && formats.length > 0) {
162
+ for (const format of formats) {
163
+ if (!format) continue;
164
+
165
+ const { key, file } = format;
166
+
167
+ await strapi.plugins.upload.provider.upload(file);
168
+ delete file.buffer;
169
+
170
+ _.set(fileData, ['formats', key], file);
171
+ }
172
+ }
173
+
174
+ const { width, height } = await getDimensions(fileData.buffer);
175
+
176
+ delete fileData.buffer;
177
+
178
+ _.assign(fileData, {
179
+ provider: config.provider,
180
+ width,
181
+ height,
182
+ });
183
+
184
+ return this.add(fileData, { user });
185
+ },
186
+
187
+ async updateFileInfo(id, { name, alternativeText, caption }, { user } = {}) {
188
+ const dbFile = await this.fetch({ id });
189
+
190
+ if (!dbFile) {
191
+ throw strapi.errors.notFound('file not found');
192
+ }
193
+
194
+ const newInfos = {
195
+ name: _.isNil(name) ? dbFile.name : name,
196
+ alternativeText: _.isNil(alternativeText) ? dbFile.alternativeText : alternativeText,
197
+ caption: _.isNil(caption) ? dbFile.caption : caption,
198
+ };
199
+
200
+ return this.update({ id }, newInfos, { user });
201
+ },
202
+
203
+ async replace(id, { data, file }, { user } = {}) {
204
+ const config = strapi.plugins.upload.config;
205
+
206
+ const { getDimensions, generateThumbnail, generateResponsiveFormats } =
207
+ strapi.plugins.upload.services['image-manipulation'];
208
+
209
+ const dbFile = await this.fetch({ id });
210
+
211
+ if (!dbFile) {
212
+ throw strapi.errors.notFound('file not found');
213
+ }
214
+
215
+ const { fileInfo } = data;
216
+ const fileData = await this.enhanceFile(file, fileInfo);
217
+
218
+ // keep a constant hash
219
+ _.assign(fileData, {
220
+ hash: dbFile.hash,
221
+ ext: dbFile.ext,
222
+ });
223
+
224
+ // execute delete function of the provider
225
+ if (dbFile.provider === config.provider) {
226
+ await strapi.plugins.upload.provider.delete(dbFile);
227
+
228
+ if (dbFile.formats) {
229
+ await Promise.all(
230
+ Object.keys(dbFile.formats).map((key) => {
231
+ return strapi.plugins.upload.provider.delete(dbFile.formats[key]);
232
+ })
233
+ );
234
+ }
235
+ }
236
+
237
+ await strapi.plugins.upload.provider.upload(fileData);
238
+
239
+ // clear old formats
240
+ _.set(fileData, 'formats', {});
241
+
242
+ const thumbnailFile = await generateThumbnail(fileData);
243
+ if (thumbnailFile) {
244
+ await strapi.plugins.upload.provider.upload(thumbnailFile);
245
+ delete thumbnailFile.buffer;
246
+ _.set(fileData, 'formats.thumbnail', thumbnailFile);
247
+ }
248
+
249
+ const formats = await generateResponsiveFormats(fileData);
250
+ if (Array.isArray(formats) && formats.length > 0) {
251
+ for (const format of formats) {
252
+ if (!format) continue;
253
+
254
+ const { key, file } = format;
255
+
256
+ await strapi.plugins.upload.provider.upload(file);
257
+ delete file.buffer;
258
+
259
+ _.set(fileData, ['formats', key], file);
260
+ }
261
+ }
262
+
263
+ const { width, height } = await getDimensions(fileData.buffer);
264
+ delete fileData.buffer;
265
+
266
+ _.assign(fileData, {
267
+ provider: config.provider,
268
+ width,
269
+ height,
270
+ });
271
+
272
+ return this.update({ id }, fileData, { user });
273
+ },
274
+
275
+ async update(params, values, { user } = {}) {
276
+ const fileValues = { ...values };
277
+ if (user) {
278
+ fileValues[UPDATED_BY_ATTRIBUTE] = user.id;
279
+ }
280
+ sendMediaMetrics(fileValues);
281
+
282
+ const res = await strapi.query('file', 'upload').update(params, fileValues);
283
+ const modelDef = strapi.getModel('file', 'upload');
284
+ strapi.eventHub.emit(MEDIA_UPDATE, { media: sanitizeEntity(res, { model: modelDef }) });
285
+ return res;
286
+ },
287
+
288
+ async add(values, { user } = {}) {
289
+ const fileValues = { ...values };
290
+ if (user) {
291
+ fileValues[UPDATED_BY_ATTRIBUTE] = user.id;
292
+ fileValues[CREATED_BY_ATTRIBUTE] = user.id;
293
+ }
294
+ sendMediaMetrics(fileValues);
295
+
296
+ const res = await strapi.query('file', 'upload').create(fileValues);
297
+ const modelDef = strapi.getModel('file', 'upload');
298
+ strapi.eventHub.emit(MEDIA_CREATE, { media: sanitizeEntity(res, { model: modelDef }) });
299
+ return res;
300
+ },
301
+
302
+ fetch(params, populate) {
303
+ return strapi.query('file', 'upload').findOne(params, populate);
304
+ },
305
+
306
+ fetchAll(params, populate) {
307
+ combineFilters(params);
308
+ return strapi.query('file', 'upload').find(params, populate);
309
+ },
310
+
311
+ search(params, populate) {
312
+ return strapi.query('file', 'upload').search(params, populate);
313
+ },
314
+
315
+ countSearch(params) {
316
+ return strapi.query('file', 'upload').countSearch(params);
317
+ },
318
+
319
+ count(params) {
320
+ combineFilters(params);
321
+ return strapi.query('file', 'upload').count(params);
322
+ },
323
+
324
+ async remove(file) {
325
+ const config = strapi.plugins.upload.config;
326
+
327
+ // execute delete function of the provider
328
+ if (file.provider === config.provider) {
329
+ await strapi.plugins.upload.provider.delete(file);
330
+
331
+ if (file.formats) {
332
+ await Promise.all(
333
+ Object.keys(file.formats).map((key) => {
334
+ return strapi.plugins.upload.provider.delete(file.formats[key]);
335
+ })
336
+ );
337
+ }
338
+ }
339
+
340
+ const media = await strapi.query('file', 'upload').findOne({
341
+ id: file.id,
342
+ });
343
+
344
+ const modelDef = strapi.getModel('file', 'upload');
345
+ strapi.eventHub.emit(MEDIA_DELETE, { media: sanitizeEntity(media, { model: modelDef }) });
346
+
347
+ return strapi.query('file', 'upload').delete({ id: file.id });
348
+ },
349
+
350
+ async uploadToEntity(params, files, source) {
351
+ const { id, model, field } = params;
352
+
353
+ const arr = Array.isArray(files) ? files : [files];
354
+ const enhancedFiles = await Promise.all(
355
+ arr.map((file) => {
356
+ return this.enhanceFile(
357
+ file,
358
+ {},
359
+ {
360
+ refId: id,
361
+ ref: model,
362
+ source,
363
+ field,
364
+ }
365
+ );
366
+ })
367
+ );
368
+
369
+ await Promise.all(enhancedFiles.map((file) => this.uploadFileAndPersist(file)));
370
+ },
371
+
372
+ getSettings() {
373
+ return strapi
374
+ .store({
375
+ type: 'plugin',
376
+ name: 'upload',
377
+ key: 'settings',
378
+ })
379
+ .get();
380
+ },
381
+
382
+ setSettings(value) {
383
+ /* if (value.responsiveDimensions === true) {
384
+ strapi.telemetry.send('didEnableResponsiveDimensions');
385
+ } else {
386
+ strapi.telemetry.send('didDisableResponsiveDimensions');
387
+ } */
388
+
389
+ return strapi
390
+ .store({
391
+ type: 'plugin',
392
+ name: 'upload',
393
+ key: 'settings',
394
+ })
395
+ .set({ value });
396
+ },
397
+ };