@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,15 @@
1
+ import { get } from 'lodash';
2
+ import pluginId from '../pluginId';
3
+
4
+ const getFileModelTimestamps = plugins => {
5
+ const timestamps = get(plugins, [pluginId, 'fileModel', 'options', 'timestamps']);
6
+
7
+ // All connectors must initialise the "timestamps" option as a tuple
8
+ if (!Array.isArray(timestamps) || timestamps.length !== 2) {
9
+ throw new Error('Unexpected timestamp field configuration.');
10
+ }
11
+
12
+ return timestamps;
13
+ };
14
+
15
+ export default getFileModelTimestamps;
@@ -0,0 +1,5 @@
1
+ const getFilesToDownload = files => {
2
+ return files.filter(file => file.isDownloading === true);
3
+ };
4
+
5
+ export default getFilesToDownload;
@@ -0,0 +1,5 @@
1
+ import pluginId from '../pluginId';
2
+
3
+ const getRequestUrl = path => `/${pluginId}/${path}`;
4
+
5
+ export default getRequestUrl;
@@ -0,0 +1,5 @@
1
+ import pluginId from '../pluginId';
2
+
3
+ const getTrad = id => `${pluginId}.${id}`;
4
+
5
+ export default getTrad;
@@ -0,0 +1,15 @@
1
+ const getType = mime => {
2
+ if (!mime) {
3
+ return 'file';
4
+ }
5
+
6
+ const type = mime.split(/[\s/]+/)[0];
7
+
8
+ if (type === 'image' || type === 'video') {
9
+ return type;
10
+ }
11
+
12
+ return 'file';
13
+ };
14
+
15
+ export default getType;
@@ -0,0 +1,17 @@
1
+ import { get } from 'lodash';
2
+
3
+ const getYupError = error => {
4
+ return get(error, 'inner', []).reduce((acc, curr) => {
5
+ acc[
6
+ curr.path
7
+ .split('[')
8
+ .join('.')
9
+ .split(']')
10
+ .join('')
11
+ ] = { id: curr.message, number: curr.params.wrongURLsNumber };
12
+
13
+ return acc;
14
+ }, {});
15
+ };
16
+
17
+ export default getYupError;
@@ -0,0 +1,20 @@
1
+ export { default as canDownloadFile } from './canDownloadFile';
2
+ export { default as compactParams } from './compactParams';
3
+ export { default as createFileToDownloadName } from './createFileToDownloadName';
4
+ export { default as createMatrix } from './createMatrix';
5
+ export { default as createNewFilesToDownloadArray } from './createNewFilesToDownloadArray';
6
+ export { default as createNewFilesToUploadArray } from './createNewFilesToUploadArray';
7
+ export { default as formatBytes } from './formatBytes';
8
+ export { default as formatFileForEditing } from './formatFileForEditing';
9
+ export { default as formatFilters } from './formatFilters';
10
+ export { default as generatePageFromStart } from './generatePageFromStart';
11
+ export { default as generateStartFromPage } from './generateStartFromPage';
12
+ export { default as getFileModelTimestamps } from './getFileModelTimestamps';
13
+ export { default as getFilesToDownload } from './getFilesToDownload';
14
+ export { default as getRequestUrl } from './getRequestUrl';
15
+ export { default as getTrad } from './getTrad';
16
+ export { default as getType } from './getType';
17
+ export { default as getYupError } from './getYupError';
18
+ export { default as ItemTypes } from './ItemTypes';
19
+ export { default as unformatBytes } from './unformatBytes';
20
+ export { default as urlSchema } from './urlYupSchema';
@@ -0,0 +1,16 @@
1
+ function unformatBytes(value) {
2
+ const sizes = ['B', 'KB', 'MB', 'GB'];
3
+ const k = 1000;
4
+
5
+ const number = value.split(/KB|MB|GB/)[0];
6
+ const unit = value.split(number)[1];
7
+
8
+ const i = sizes.findIndex(size => size === unit);
9
+
10
+ const multiplicator = k ** i;
11
+ const newValue = number * multiplicator;
12
+
13
+ return newValue / 1000;
14
+ }
15
+
16
+ export default unformatBytes;
@@ -0,0 +1,49 @@
1
+ /* eslint-disable no-template-curly-in-string */
2
+ import * as yup from 'yup';
3
+ import { translatedErrors as errorsTrads } from 'strapi-helper-plugin';
4
+ import getTrad from './getTrad';
5
+
6
+ const urlSchema = yup.object().shape({
7
+ filesToDownload: yup
8
+ .array()
9
+ .of(yup.string())
10
+
11
+ .test({
12
+ name: 'isUrlValid',
13
+ message: '${path}',
14
+ test(values) {
15
+ const filtered = values.filter(val => {
16
+ try {
17
+ // eslint-disable-next-line no-new
18
+ new URL(val);
19
+
20
+ return false;
21
+ } catch (err) {
22
+ // invalid url
23
+ return true;
24
+ }
25
+ });
26
+
27
+ const filteredLength = filtered.length;
28
+
29
+ if (filteredLength === 0) {
30
+ return true;
31
+ }
32
+
33
+ const errorMessage =
34
+ filteredLength > 1
35
+ ? 'form.upload-url.error.url.invalids'
36
+ : 'form.upload-url.error.url.invalid';
37
+
38
+ return this.createError({
39
+ path: this.path,
40
+ message: getTrad(errorMessage),
41
+ params: { wrongURLsNumber: filtered.length },
42
+ });
43
+ },
44
+ })
45
+ .min(0, errorsTrads.min)
46
+ .max(20, errorsTrads.max),
47
+ });
48
+
49
+ export default urlSchema;
@@ -0,0 +1,8 @@
1
+ {
2
+ "enabled": true,
3
+ "provider": "local",
4
+ "providerOptions": {
5
+ "sizeLimit": 1000000
6
+ },
7
+ "actionOptions": {}
8
+ }
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+
3
+ const { convertToStrapiError } = require('../../errors');
4
+
5
+ module.exports = async () => {
6
+ // set plugin store
7
+ const configurator = strapi.store({
8
+ type: 'plugin',
9
+ name: 'upload',
10
+ key: 'settings',
11
+ });
12
+
13
+ strapi.plugins.upload.provider = createProvider(strapi.plugins.upload.config || {});
14
+
15
+ // if provider config does not exist set one by default
16
+ const config = await configurator.get();
17
+
18
+ if (!config) {
19
+ await configurator.set({
20
+ value: {
21
+ sizeOptimization: true,
22
+ responsiveDimensions: true,
23
+ },
24
+ });
25
+ }
26
+
27
+ await pruneObsoleteRelations();
28
+ await registerPermissionActions();
29
+ };
30
+
31
+ const wrapFunctionForErrors = fn => async (...args) => {
32
+ try {
33
+ return await fn(...args);
34
+ } catch (err) {
35
+ throw convertToStrapiError(err);
36
+ }
37
+ };
38
+
39
+ const createProvider = ({ provider, providerOptions, actionOptions = {} }) => {
40
+ try {
41
+ const providerInstance = require(`strapi-provider-upload-${provider}`).init(providerOptions);
42
+
43
+ return Object.assign(Object.create(baseProvider), {
44
+ ...providerInstance,
45
+ upload: wrapFunctionForErrors((file, options = actionOptions.upload) => {
46
+ return providerInstance.upload(file, options);
47
+ }),
48
+ delete: wrapFunctionForErrors((file, options = actionOptions.delete) => {
49
+ return providerInstance.delete(file, options);
50
+ }),
51
+ });
52
+ } catch (err) {
53
+ strapi.log.error(err);
54
+ throw new Error(
55
+ `The provider package isn't installed. Please run \`npm install strapi-provider-upload-${provider}\``
56
+ );
57
+ }
58
+ };
59
+
60
+ const baseProvider = {
61
+ extend(obj) {
62
+ Object.assign(this, obj);
63
+ },
64
+ upload() {
65
+ throw new Error('Provider upload method is not implemented');
66
+ },
67
+ delete() {
68
+ throw new Error('Provider delete method is not implemented');
69
+ },
70
+ };
71
+
72
+ const pruneObsoleteRelations = async () => {
73
+ const { upload: plugin } = strapi.plugins;
74
+ const modelIsNotDefined = !plugin || !plugin.models || !plugin.models.file;
75
+
76
+ if (modelIsNotDefined) {
77
+ return Promise.resolve();
78
+ }
79
+
80
+ await strapi.query('file', 'upload').custom(pruneObsoleteRelationsQuery)();
81
+ };
82
+
83
+ const pruneObsoleteRelationsQuery = ({ model }) => {
84
+ if (model.orm !== 'mongoose') {
85
+ return Promise.resolve();
86
+ }
87
+
88
+ const models = Array.from(strapi.db.models.values());
89
+ const modelsId = models.map(model => model.globalId);
90
+
91
+ return model.updateMany(
92
+ { related: { $elemMatch: { kind: { $nin: modelsId } } } },
93
+ { $pull: { related: { kind: { $nin: modelsId } } } }
94
+ );
95
+ };
96
+
97
+ const registerPermissionActions = async () => {
98
+ const actions = [
99
+ {
100
+ section: 'plugins',
101
+ displayName: 'Access the Media Library',
102
+ uid: 'read',
103
+ pluginName: 'upload',
104
+ },
105
+ {
106
+ section: 'plugins',
107
+ displayName: 'Create (upload)',
108
+ uid: 'assets.create',
109
+ subCategory: 'assets',
110
+ pluginName: 'upload',
111
+ },
112
+ {
113
+ section: 'plugins',
114
+ displayName: 'Update (crop, details, replace) + delete',
115
+ uid: 'assets.update',
116
+ subCategory: 'assets',
117
+ pluginName: 'upload',
118
+ },
119
+ {
120
+ section: 'plugins',
121
+ displayName: 'Download',
122
+ uid: 'assets.download',
123
+ subCategory: 'assets',
124
+ pluginName: 'upload',
125
+ },
126
+ {
127
+ section: 'plugins',
128
+ displayName: 'Copy link',
129
+ uid: 'assets.copy-link',
130
+ subCategory: 'assets',
131
+ pluginName: 'upload',
132
+ },
133
+ {
134
+ section: 'settings',
135
+ displayName: 'Access the Media Library settings page',
136
+ uid: 'settings.read',
137
+ category: 'media library',
138
+ pluginName: 'upload',
139
+ },
140
+ ];
141
+
142
+ await strapi.admin.services.permission.actionProvider.registerMany(actions);
143
+ };
@@ -0,0 +1,98 @@
1
+ {
2
+ "routes": [
3
+ {
4
+ "method": "GET",
5
+ "path": "/settings",
6
+ "handler": "Upload.getSettings",
7
+ "config": {
8
+ "policies": []
9
+ }
10
+ },
11
+ {
12
+ "method": "PUT",
13
+ "path": "/settings",
14
+ "handler": "Upload.updateSettings",
15
+ "config": {
16
+ "policies": []
17
+ }
18
+ },
19
+ {
20
+ "method": "POST",
21
+ "path": "/",
22
+ "handler": "Upload.upload",
23
+ "config": {
24
+ "policies": [],
25
+ "description": "Upload a file",
26
+ "tag": {
27
+ "plugin": "upload",
28
+ "name": "File"
29
+ }
30
+ }
31
+ },
32
+ {
33
+ "method": "GET",
34
+ "path": "/files/count",
35
+ "handler": "Upload.count",
36
+ "config": {
37
+ "policies": [],
38
+ "description": "Retrieve the total number of uploaded files",
39
+ "tag": {
40
+ "plugin": "upload",
41
+ "name": "File"
42
+ }
43
+ }
44
+ },
45
+ {
46
+ "method": "GET",
47
+ "path": "/files",
48
+ "handler": "Upload.find",
49
+ "config": {
50
+ "policies": [],
51
+ "description": "Retrieve all file documents",
52
+ "tag": {
53
+ "plugin": "upload",
54
+ "name": "File"
55
+ }
56
+ }
57
+ },
58
+ {
59
+ "method": "GET",
60
+ "path": "/files/:id",
61
+ "handler": "Upload.findOne",
62
+ "config": {
63
+ "policies": [],
64
+ "description": "Retrieve a single file depending on its id",
65
+ "tag": {
66
+ "plugin": "upload",
67
+ "name": "File"
68
+ }
69
+ }
70
+ },
71
+ {
72
+ "method": "GET",
73
+ "path": "/search/:id",
74
+ "handler": "Upload.search",
75
+ "config": {
76
+ "policies": [],
77
+ "description": "Search for an uploaded file",
78
+ "tag": {
79
+ "plugin": "upload",
80
+ "name": "File"
81
+ }
82
+ }
83
+ },
84
+ {
85
+ "method": "DELETE",
86
+ "path": "/files/:id",
87
+ "handler": "Upload.destroy",
88
+ "config": {
89
+ "policies": [],
90
+ "description": "Delete an uploaded file",
91
+ "tag": {
92
+ "plugin": "upload",
93
+ "name": "File"
94
+ }
95
+ }
96
+ }
97
+ ]
98
+ }
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+ const { streamToBuffer } = require('../utils/file');
5
+
6
+ module.exports = {
7
+ definition: `
8
+ input FileInfoInput {
9
+ name: String
10
+ alternativeText: String
11
+ caption: String
12
+ }
13
+ `,
14
+ mutation: `
15
+ upload(refId: ID, ref: String, field: String, source: String, info: FileInfoInput, file: Upload!): UploadFile!
16
+ multipleUpload(refId: ID, ref: String, field: String, source: String, files: [Upload]!): [UploadFile]!
17
+ updateFileInfo(id: ID!, info: FileInfoInput!): UploadFile!
18
+ `,
19
+ resolver: {
20
+ Query: {
21
+ file: false,
22
+ files: {
23
+ resolver: 'plugins::upload.upload.find',
24
+ },
25
+ },
26
+ Mutation: {
27
+ createFile: false,
28
+ updateFile: false,
29
+ upload: {
30
+ description: 'Upload one file',
31
+ resolverOf: 'plugins::upload.upload.upload',
32
+ resolver: async (obj, { file: upload, info, ...fields }) => {
33
+ const file = await formatFile(upload, info, fields);
34
+
35
+ const uploadedFiles = await strapi.plugins.upload.services.upload.uploadFileAndPersist(
36
+ file
37
+ );
38
+
39
+ // Return response.
40
+ return uploadedFiles.length === 1 ? uploadedFiles[0] : uploadedFiles;
41
+ },
42
+ },
43
+ multipleUpload: {
44
+ description: 'Upload one file',
45
+ resolverOf: 'plugins::upload.upload.upload',
46
+ resolver: async (obj, { files: uploads, ...fields }) => {
47
+ const files = await Promise.all(uploads.map(upload => formatFile(upload, {}, fields)));
48
+
49
+ const uploadService = strapi.plugins.upload.services.upload;
50
+
51
+ return Promise.all(files.map(file => uploadService.uploadFileAndPersist(file)));
52
+ },
53
+ },
54
+ updateFileInfo: {
55
+ description: 'Update file information',
56
+ resolverOf: 'plugins::upload.upload.upload',
57
+ resolver: async (obj, { id, info }) => {
58
+ return await strapi.plugins.upload.services.upload.updateFileInfo(id, info);
59
+ },
60
+ },
61
+ deleteFile: {
62
+ description: 'Delete one file',
63
+ resolverOf: 'plugins::upload.upload.destroy',
64
+ resolver: async (obj, options, { context }) => {
65
+ const file = await strapi.plugins.upload.services.upload.fetch({ id: context.params.id });
66
+ if (file) {
67
+ const fileResult = await strapi.plugins.upload.services.upload.remove(file);
68
+ return { file: fileResult };
69
+ }
70
+ },
71
+ },
72
+ },
73
+ },
74
+ };
75
+
76
+ const formatFile = async (upload, extraInfo, metas) => {
77
+ const { filename, mimetype, createReadStream } = await upload;
78
+
79
+ const { optimize } = strapi.plugins.upload.services['image-manipulation'];
80
+ const readBuffer = await streamToBuffer(createReadStream());
81
+
82
+ const { buffer, info } = await optimize(readBuffer);
83
+
84
+ const uploadService = strapi.plugins.upload.services.upload;
85
+ const fileInfo = uploadService.formatFileInfo(
86
+ {
87
+ filename,
88
+ type: mimetype,
89
+ size: buffer.length,
90
+ },
91
+ extraInfo || {},
92
+ metas
93
+ );
94
+
95
+ return _.assign(fileInfo, info, { buffer });
96
+ };
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Upload.js controller
5
+ *
6
+ */
7
+
8
+ const _ = require('lodash');
9
+ const { sanitizeEntity } = require('@akemona-org/strapi-utils');
10
+ const apiUploadController = require('./upload/api');
11
+ const adminUploadController = require('./upload/admin');
12
+
13
+ const resolveController = (ctx) => {
14
+ const {
15
+ state: { isAuthenticatedAdmin },
16
+ } = ctx;
17
+
18
+ return isAuthenticatedAdmin ? adminUploadController : apiUploadController;
19
+ };
20
+
21
+ const resolveControllerMethod = (method) => (ctx) => {
22
+ const controller = resolveController(ctx);
23
+ const callbackFn = controller[method];
24
+
25
+ if (!_.isFunction(callbackFn)) {
26
+ return ctx.notFound();
27
+ }
28
+
29
+ return callbackFn(ctx);
30
+ };
31
+
32
+ module.exports = {
33
+ find: resolveControllerMethod('find'),
34
+ findOne: resolveControllerMethod('findOne'),
35
+ count: resolveControllerMethod('count'),
36
+ destroy: resolveControllerMethod('destroy'),
37
+ updateSettings: resolveControllerMethod('updateSettings'),
38
+ getSettings: resolveControllerMethod('getSettings'),
39
+
40
+ async upload(ctx) {
41
+ const isUploadDisabled = _.get(strapi.plugins, 'upload.config.enabled', true) === false;
42
+
43
+ if (isUploadDisabled) {
44
+ throw strapi.errors.badRequest(null, {
45
+ errors: [{ id: 'Upload.status.disabled', message: 'File upload is disabled' }],
46
+ });
47
+ }
48
+
49
+ const {
50
+ query: { id },
51
+ request: { files: { files } = {} },
52
+ } = ctx;
53
+ const controller = resolveController(ctx);
54
+
55
+ if (id && (_.isEmpty(files) || files.size === 0)) {
56
+ return controller.updateFileInfo(ctx);
57
+ }
58
+
59
+ if (_.isEmpty(files) || files.size === 0) {
60
+ throw strapi.errors.badRequest(null, {
61
+ errors: [{ id: 'Upload.status.empty', message: 'Files are empty' }],
62
+ });
63
+ }
64
+
65
+ await (id ? controller.replaceFile : controller.uploadFiles)(ctx);
66
+ },
67
+
68
+ async search(ctx) {
69
+ const { id } = ctx.params;
70
+ const model = strapi.getModel('file', 'upload');
71
+ const entries = await strapi.query('file', 'upload').custom(searchQueries)({
72
+ id,
73
+ });
74
+
75
+ ctx.body = sanitizeEntity(entries, { model });
76
+ },
77
+ };
78
+
79
+ const searchQueries = {
80
+ bookshelf({ model }) {
81
+ return ({ id }) => {
82
+ return model
83
+ .query((qb) => {
84
+ qb.whereRaw('LOWER(hash) LIKE ?', [`%${id}%`]).orWhereRaw('LOWER(name) LIKE ?', [
85
+ `%${id}%`,
86
+ ]);
87
+ })
88
+ .fetchAll()
89
+ .then((results) => results.toJSON());
90
+ };
91
+ },
92
+ mongoose({ model }) {
93
+ return ({ id }) => {
94
+ const re = new RegExp(id, 'i');
95
+
96
+ return model
97
+ .find({
98
+ $or: [{ hash: re }, { name: re }],
99
+ })
100
+ .lean();
101
+ };
102
+ },
103
+ };