@strapi/upload 5.12.0 → 5.12.2
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.
- package/dist/admin/components/AssetCard/AssetCard.js +59 -0
- package/dist/admin/components/AssetCard/AssetCard.js.map +1 -0
- package/dist/admin/components/AssetCard/AssetCard.mjs +57 -0
- package/dist/admin/components/AssetCard/AssetCard.mjs.map +1 -0
- package/dist/admin/components/AssetCard/AssetCardBase.js +130 -0
- package/dist/admin/components/AssetCard/AssetCardBase.js.map +1 -0
- package/dist/admin/components/AssetCard/AssetCardBase.mjs +128 -0
- package/dist/admin/components/AssetCard/AssetCardBase.mjs.map +1 -0
- package/dist/admin/components/AssetCard/AudioAssetCard.js +40 -0
- package/dist/admin/components/AssetCard/AudioAssetCard.js.map +1 -0
- package/dist/admin/components/AssetCard/AudioAssetCard.mjs +38 -0
- package/dist/admin/components/AssetCard/AudioAssetCard.mjs.map +1 -0
- package/dist/admin/components/AssetCard/AudioPreview.js +17 -0
- package/dist/admin/components/AssetCard/AudioPreview.js.map +1 -0
- package/dist/admin/components/AssetCard/AudioPreview.mjs +15 -0
- package/dist/admin/components/AssetCard/AudioPreview.mjs.map +1 -0
- package/dist/admin/components/AssetCard/DocAssetCard.js +61 -0
- package/dist/admin/components/AssetCard/DocAssetCard.js.map +1 -0
- package/dist/admin/components/AssetCard/DocAssetCard.mjs +59 -0
- package/dist/admin/components/AssetCard/DocAssetCard.mjs.map +1 -0
- package/dist/admin/components/AssetCard/ImageAssetCard.js +37 -0
- package/dist/admin/components/AssetCard/ImageAssetCard.js.map +1 -0
- package/dist/admin/components/AssetCard/ImageAssetCard.mjs +35 -0
- package/dist/admin/components/AssetCard/ImageAssetCard.mjs.map +1 -0
- package/dist/admin/components/AssetCard/UploadingAssetCard.js +152 -0
- package/dist/admin/components/AssetCard/UploadingAssetCard.js.map +1 -0
- package/dist/admin/components/AssetCard/UploadingAssetCard.mjs +131 -0
- package/dist/admin/components/AssetCard/UploadingAssetCard.mjs.map +1 -0
- package/dist/admin/components/AssetCard/VideoAssetCard.js +72 -0
- package/dist/admin/components/AssetCard/VideoAssetCard.js.map +1 -0
- package/dist/admin/components/AssetCard/VideoAssetCard.mjs +51 -0
- package/dist/admin/components/AssetCard/VideoAssetCard.mjs.map +1 -0
- package/dist/admin/components/AssetCard/VideoPreview.js +50 -0
- package/dist/admin/components/AssetCard/VideoPreview.js.map +1 -0
- package/dist/admin/components/AssetCard/VideoPreview.mjs +48 -0
- package/dist/admin/components/AssetCard/VideoPreview.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/AssetDialog.js +321 -0
- package/dist/admin/components/AssetDialog/AssetDialog.js.map +1 -0
- package/dist/admin/components/AssetDialog/AssetDialog.mjs +299 -0
- package/dist/admin/components/AssetDialog/AssetDialog.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/BrowseStep.js +313 -0
- package/dist/admin/components/AssetDialog/BrowseStep/BrowseStep.js.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/BrowseStep.mjs +311 -0
- package/dist/admin/components/AssetDialog/BrowseStep/BrowseStep.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/Filters.js +70 -0
- package/dist/admin/components/AssetDialog/BrowseStep/Filters.js.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/Filters.mjs +49 -0
- package/dist/admin/components/AssetDialog/BrowseStep/Filters.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PageSize.js +58 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PageSize.js.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PageSize.mjs +56 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PageSize.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/Pagination.js +55 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/Pagination.js.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/Pagination.mjs +33 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/Pagination.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/PaginationFooter.js +378 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/PaginationFooter.js.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/PaginationFooter.mjs +376 -0
- package/dist/admin/components/AssetDialog/BrowseStep/PaginationFooter/PaginationFooter.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/SearchAsset/SearchAsset.js +102 -0
- package/dist/admin/components/AssetDialog/BrowseStep/SearchAsset/SearchAsset.js.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/SearchAsset/SearchAsset.mjs +81 -0
- package/dist/admin/components/AssetDialog/BrowseStep/SearchAsset/SearchAsset.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/utils/isSelectable.js +14 -0
- package/dist/admin/components/AssetDialog/BrowseStep/utils/isSelectable.js.map +1 -0
- package/dist/admin/components/AssetDialog/BrowseStep/utils/isSelectable.mjs +12 -0
- package/dist/admin/components/AssetDialog/BrowseStep/utils/isSelectable.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/DialogFooter.js +31 -0
- package/dist/admin/components/AssetDialog/DialogFooter.js.map +1 -0
- package/dist/admin/components/AssetDialog/DialogFooter.mjs +29 -0
- package/dist/admin/components/AssetDialog/DialogFooter.mjs.map +1 -0
- package/dist/admin/components/AssetDialog/SelectedStep/SelectedStep.js +60 -0
- package/dist/admin/components/AssetDialog/SelectedStep/SelectedStep.js.map +1 -0
- package/dist/admin/components/AssetDialog/SelectedStep/SelectedStep.mjs +58 -0
- package/dist/admin/components/AssetDialog/SelectedStep/SelectedStep.mjs.map +1 -0
- package/dist/admin/components/AssetGridList/AssetGridList.js +72 -0
- package/dist/admin/components/AssetGridList/AssetGridList.js.map +1 -0
- package/dist/admin/components/AssetGridList/AssetGridList.mjs +70 -0
- package/dist/admin/components/AssetGridList/AssetGridList.mjs.map +1 -0
- package/dist/admin/components/AssetGridList/Draggable.js +65 -0
- package/dist/admin/components/AssetGridList/Draggable.js.map +1 -0
- package/dist/admin/components/AssetGridList/Draggable.mjs +44 -0
- package/dist/admin/components/AssetGridList/Draggable.mjs.map +1 -0
- package/dist/admin/components/Breadcrumbs/Breadcrumbs.js +49 -0
- package/dist/admin/components/Breadcrumbs/Breadcrumbs.js.map +1 -0
- package/dist/admin/components/Breadcrumbs/Breadcrumbs.mjs +47 -0
- package/dist/admin/components/Breadcrumbs/Breadcrumbs.mjs.map +1 -0
- package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.js +89 -0
- package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.js.map +1 -0
- package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.mjs +68 -0
- package/dist/admin/components/Breadcrumbs/CrumbSimpleMenuAsync.mjs.map +1 -0
- package/dist/admin/components/BulkMoveDialog/BulkMoveDialog.js +154 -0
- package/dist/admin/components/BulkMoveDialog/BulkMoveDialog.js.map +1 -0
- package/dist/admin/components/BulkMoveDialog/BulkMoveDialog.mjs +152 -0
- package/dist/admin/components/BulkMoveDialog/BulkMoveDialog.mjs.map +1 -0
- package/dist/admin/components/ContextInfo/ContextInfo.js +44 -0
- package/dist/admin/components/ContextInfo/ContextInfo.js.map +1 -0
- package/dist/admin/components/ContextInfo/ContextInfo.mjs +42 -0
- package/dist/admin/components/ContextInfo/ContextInfo.mjs.map +1 -0
- package/dist/admin/components/CopyLinkButton/CopyLinkButton.js +43 -0
- package/dist/admin/components/CopyLinkButton/CopyLinkButton.js.map +1 -0
- package/dist/admin/components/CopyLinkButton/CopyLinkButton.mjs +41 -0
- package/dist/admin/components/CopyLinkButton/CopyLinkButton.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/DialogHeader.js +20 -0
- package/dist/admin/components/EditAssetDialog/DialogHeader.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/DialogHeader.mjs +18 -0
- package/dist/admin/components/EditAssetDialog/DialogHeader.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/EditAssetContent.js +403 -0
- package/dist/admin/components/EditAssetDialog/EditAssetContent.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs +380 -0
- package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/AssetPreview.js +127 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/AssetPreview.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/AssetPreview.mjs +106 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/AssetPreview.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/CroppingActions.js +111 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/CroppingActions.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/CroppingActions.mjs +109 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/CroppingActions.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewBox.js +260 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewBox.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewBox.mjs +239 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewBox.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewComponents.js +75 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewComponents.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewComponents.mjs +68 -0
- package/dist/admin/components/EditAssetDialog/PreviewBox/PreviewComponents.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/RemoveAssetDialog.js +27 -0
- package/dist/admin/components/EditAssetDialog/RemoveAssetDialog.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/RemoveAssetDialog.mjs +25 -0
- package/dist/admin/components/EditAssetDialog/RemoveAssetDialog.mjs.map +1 -0
- package/dist/admin/components/EditAssetDialog/ReplaceMediaButton.js +79 -0
- package/dist/admin/components/EditAssetDialog/ReplaceMediaButton.js.map +1 -0
- package/dist/admin/components/EditAssetDialog/ReplaceMediaButton.mjs +58 -0
- package/dist/admin/components/EditAssetDialog/ReplaceMediaButton.mjs.map +1 -0
- package/dist/admin/components/EditFolderDialog/EditFolderDialog.js +336 -0
- package/dist/admin/components/EditFolderDialog/EditFolderDialog.js.map +1 -0
- package/dist/admin/components/EditFolderDialog/EditFolderDialog.mjs +313 -0
- package/dist/admin/components/EditFolderDialog/EditFolderDialog.mjs.map +1 -0
- package/dist/admin/components/EditFolderDialog/ModalHeader/ModalHeader.js +29 -0
- package/dist/admin/components/EditFolderDialog/ModalHeader/ModalHeader.js.map +1 -0
- package/dist/admin/components/EditFolderDialog/ModalHeader/ModalHeader.mjs +27 -0
- package/dist/admin/components/EditFolderDialog/ModalHeader/ModalHeader.mjs.map +1 -0
- package/dist/admin/components/EditFolderDialog/RemoveFolderDialog.js +18 -0
- package/dist/admin/components/EditFolderDialog/RemoveFolderDialog.js.map +1 -0
- package/dist/admin/components/EditFolderDialog/RemoveFolderDialog.mjs +16 -0
- package/dist/admin/components/EditFolderDialog/RemoveFolderDialog.mjs.map +1 -0
- package/dist/admin/components/EmptyAssets/EmptyAssetGrid.js +31 -0
- package/dist/admin/components/EmptyAssets/EmptyAssetGrid.js.map +1 -0
- package/dist/admin/components/EmptyAssets/EmptyAssetGrid.mjs +29 -0
- package/dist/admin/components/EmptyAssets/EmptyAssetGrid.mjs.map +1 -0
- package/dist/admin/components/EmptyAssets/EmptyAssets.js +53 -0
- package/dist/admin/components/EmptyAssets/EmptyAssets.js.map +1 -0
- package/dist/admin/components/EmptyAssets/EmptyAssets.mjs +51 -0
- package/dist/admin/components/EmptyAssets/EmptyAssets.mjs.map +1 -0
- package/dist/admin/components/FilterList/FilterList.js +74 -0
- package/dist/admin/components/FilterList/FilterList.js.map +1 -0
- package/dist/admin/components/FilterList/FilterList.mjs +72 -0
- package/dist/admin/components/FilterList/FilterList.mjs.map +1 -0
- package/dist/admin/components/FilterList/FilterTag.js +50 -0
- package/dist/admin/components/FilterList/FilterTag.js.map +1 -0
- package/dist/admin/components/FilterList/FilterTag.mjs +48 -0
- package/dist/admin/components/FilterList/FilterTag.mjs.map +1 -0
- package/dist/admin/components/FilterPopover/FilterPopover.js +275 -0
- package/dist/admin/components/FilterPopover/FilterPopover.js.map +1 -0
- package/dist/admin/components/FilterPopover/FilterPopover.mjs +254 -0
- package/dist/admin/components/FilterPopover/FilterPopover.mjs.map +1 -0
- package/dist/admin/components/FilterPopover/FilterValueInput.js +39 -0
- package/dist/admin/components/FilterPopover/FilterValueInput.js.map +1 -0
- package/dist/admin/components/FilterPopover/FilterValueInput.mjs +37 -0
- package/dist/admin/components/FilterPopover/FilterValueInput.mjs.map +1 -0
- package/dist/admin/components/FilterPopover/utils/getFilterList.js +114 -0
- package/dist/admin/components/FilterPopover/utils/getFilterList.js.map +1 -0
- package/dist/admin/components/FilterPopover/utils/getFilterList.mjs +112 -0
- package/dist/admin/components/FilterPopover/utils/getFilterList.mjs.map +1 -0
- package/dist/admin/components/FolderCard/FolderCard/FolderCard.js +125 -0
- package/dist/admin/components/FolderCard/FolderCard/FolderCard.js.map +1 -0
- package/dist/admin/components/FolderCard/FolderCard/FolderCard.mjs +104 -0
- package/dist/admin/components/FolderCard/FolderCard/FolderCard.mjs.map +1 -0
- package/dist/admin/components/FolderCard/FolderCardBody/FolderCardBody.js +26 -0
- package/dist/admin/components/FolderCard/FolderCardBody/FolderCardBody.js.map +1 -0
- package/dist/admin/components/FolderCard/FolderCardBody/FolderCardBody.mjs +24 -0
- package/dist/admin/components/FolderCard/FolderCardBody/FolderCardBody.mjs.map +1 -0
- package/dist/admin/components/FolderCard/FolderCardBodyAction/FolderCardBodyAction.js +40 -0
- package/dist/admin/components/FolderCard/FolderCardBodyAction/FolderCardBodyAction.js.map +1 -0
- package/dist/admin/components/FolderCard/FolderCardBodyAction/FolderCardBodyAction.mjs +38 -0
- package/dist/admin/components/FolderCard/FolderCardBodyAction/FolderCardBodyAction.mjs.map +1 -0
- package/dist/admin/components/FolderCard/FolderCardCheckbox/FolderCardCheckbox.js +20 -0
- package/dist/admin/components/FolderCard/FolderCardCheckbox/FolderCardCheckbox.js.map +1 -0
- package/dist/admin/components/FolderCard/FolderCardCheckbox/FolderCardCheckbox.mjs +18 -0
- package/dist/admin/components/FolderCard/FolderCardCheckbox/FolderCardCheckbox.mjs.map +1 -0
- package/dist/admin/components/FolderCard/contexts/FolderCard.js +12 -0
- package/dist/admin/components/FolderCard/contexts/FolderCard.js.map +1 -0
- package/dist/admin/components/FolderCard/contexts/FolderCard.mjs +9 -0
- package/dist/admin/components/FolderCard/contexts/FolderCard.mjs.map +1 -0
- package/dist/admin/components/FolderGridList/FolderGridList.js +29 -0
- package/dist/admin/components/FolderGridList/FolderGridList.js.map +1 -0
- package/dist/admin/components/FolderGridList/FolderGridList.mjs +27 -0
- package/dist/admin/components/FolderGridList/FolderGridList.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryDialog/MediaLibraryDialog.js +71 -0
- package/dist/admin/components/MediaLibraryDialog/MediaLibraryDialog.js.map +1 -0
- package/dist/admin/components/MediaLibraryDialog/MediaLibraryDialog.mjs +50 -0
- package/dist/admin/components/MediaLibraryDialog/MediaLibraryDialog.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAsset.js +78 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAsset.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAsset.mjs +76 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAsset.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssetActions.js +52 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssetActions.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssetActions.mjs +50 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssetActions.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.js +112 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.mjs +91 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/CarouselAssets.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/EmptyStateAsset.js +116 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/EmptyStateAsset.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/EmptyStateAsset.mjs +95 -0
- package/dist/admin/components/MediaLibraryInput/Carousel/EmptyStateAsset.mjs.map +1 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js +216 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js.map +1 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs +195 -0
- package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs.map +1 -0
- package/dist/admin/components/SelectTree/Option.js +70 -0
- package/dist/admin/components/SelectTree/Option.js.map +1 -0
- package/dist/admin/components/SelectTree/Option.mjs +68 -0
- package/dist/admin/components/SelectTree/Option.mjs.map +1 -0
- package/dist/admin/components/SelectTree/SelectTree.js +276 -0
- package/dist/admin/components/SelectTree/SelectTree.js.map +1 -0
- package/dist/admin/components/SelectTree/SelectTree.mjs +255 -0
- package/dist/admin/components/SelectTree/SelectTree.mjs.map +1 -0
- package/dist/admin/components/SelectTree/utils/flattenTree.js +19 -0
- package/dist/admin/components/SelectTree/utils/flattenTree.js.map +1 -0
- package/dist/admin/components/SelectTree/utils/flattenTree.mjs +17 -0
- package/dist/admin/components/SelectTree/utils/flattenTree.mjs.map +1 -0
- package/dist/admin/components/SelectTree/utils/getOpenValues.js +24 -0
- package/dist/admin/components/SelectTree/utils/getOpenValues.js.map +1 -0
- package/dist/admin/components/SelectTree/utils/getOpenValues.mjs +22 -0
- package/dist/admin/components/SelectTree/utils/getOpenValues.mjs.map +1 -0
- package/dist/admin/components/SelectTree/utils/getValuesToClose.js +12 -0
- package/dist/admin/components/SelectTree/utils/getValuesToClose.js.map +1 -0
- package/dist/admin/components/SelectTree/utils/getValuesToClose.mjs +10 -0
- package/dist/admin/components/SelectTree/utils/getValuesToClose.mjs.map +1 -0
- package/dist/admin/components/SortPicker/SortPicker.js +39 -0
- package/dist/admin/components/SortPicker/SortPicker.js.map +1 -0
- package/dist/admin/components/SortPicker/SortPicker.mjs +37 -0
- package/dist/admin/components/SortPicker/SortPicker.mjs.map +1 -0
- package/dist/admin/components/TableList/CellContent.js +76 -0
- package/dist/admin/components/TableList/CellContent.js.map +1 -0
- package/dist/admin/components/TableList/CellContent.mjs +74 -0
- package/dist/admin/components/TableList/CellContent.mjs.map +1 -0
- package/dist/admin/components/TableList/PreviewCell.js +82 -0
- package/dist/admin/components/TableList/PreviewCell.js.map +1 -0
- package/dist/admin/components/TableList/PreviewCell.mjs +80 -0
- package/dist/admin/components/TableList/PreviewCell.mjs.map +1 -0
- package/dist/admin/components/TableList/TableList.js +99 -0
- package/dist/admin/components/TableList/TableList.js.map +1 -0
- package/dist/admin/components/TableList/TableList.mjs +97 -0
- package/dist/admin/components/TableList/TableList.mjs.map +1 -0
- package/dist/admin/components/TableList/TableRows.js +101 -0
- package/dist/admin/components/TableList/TableRows.js.map +1 -0
- package/dist/admin/components/TableList/TableRows.mjs +99 -0
- package/dist/admin/components/TableList/TableRows.mjs.map +1 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/AddAssetStep.js +84 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/AddAssetStep.js.map +1 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/AddAssetStep.mjs +82 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/AddAssetStep.mjs.map +1 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromComputerForm.js +203 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromComputerForm.js.map +1 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromComputerForm.mjs +182 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromComputerForm.mjs.map +1 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js +127 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.js.map +1 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs +106 -0
- package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromUrlForm.mjs.map +1 -0
- package/dist/admin/components/UploadAssetDialog/PendingAssetStep/PendingAssetStep.js +206 -0
- package/dist/admin/components/UploadAssetDialog/PendingAssetStep/PendingAssetStep.js.map +1 -0
- package/dist/admin/components/UploadAssetDialog/PendingAssetStep/PendingAssetStep.mjs +185 -0
- package/dist/admin/components/UploadAssetDialog/PendingAssetStep/PendingAssetStep.mjs.map +1 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js +129 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js.map +1 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs +108 -0
- package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs.map +1 -0
- package/dist/admin/components/UploadProgress/UploadProgress.js +88 -0
- package/dist/admin/components/UploadProgress/UploadProgress.js.map +1 -0
- package/dist/admin/components/UploadProgress/UploadProgress.mjs +86 -0
- package/dist/admin/components/UploadProgress/UploadProgress.mjs.map +1 -0
- package/dist/admin/constants.js +205 -0
- package/dist/admin/constants.js.map +1 -0
- package/dist/admin/constants.mjs +198 -0
- package/dist/admin/constants.mjs.map +1 -0
- package/dist/admin/hooks/useAssets.js +124 -0
- package/dist/admin/hooks/useAssets.js.map +1 -0
- package/dist/admin/hooks/useAssets.mjs +103 -0
- package/dist/admin/hooks/useAssets.mjs.map +1 -0
- package/dist/admin/hooks/useBulkMove.js +79 -0
- package/dist/admin/hooks/useBulkMove.js.map +1 -0
- package/dist/admin/hooks/useBulkMove.mjs +77 -0
- package/dist/admin/hooks/useBulkMove.mjs.map +1 -0
- package/dist/admin/hooks/useBulkRemove.js +79 -0
- package/dist/admin/hooks/useBulkRemove.js.map +1 -0
- package/dist/admin/hooks/useBulkRemove.mjs +77 -0
- package/dist/admin/hooks/useBulkRemove.mjs.map +1 -0
- package/dist/admin/hooks/useConfig.js +57 -0
- package/dist/admin/hooks/useConfig.js.map +1 -0
- package/dist/admin/hooks/useConfig.mjs +55 -0
- package/dist/admin/hooks/useConfig.mjs.map +1 -0
- package/dist/admin/hooks/useCropImg.js +96 -0
- package/dist/admin/hooks/useCropImg.js.map +1 -0
- package/dist/admin/hooks/useCropImg.mjs +75 -0
- package/dist/admin/hooks/useCropImg.mjs.map +1 -0
- package/dist/admin/hooks/useEditAsset.js +114 -0
- package/dist/admin/hooks/useEditAsset.js.map +1 -0
- package/dist/admin/hooks/useEditAsset.mjs +93 -0
- package/dist/admin/hooks/useEditAsset.mjs.map +1 -0
- package/dist/admin/hooks/useEditFolder.js +44 -0
- package/dist/admin/hooks/useEditFolder.js.map +1 -0
- package/dist/admin/hooks/useEditFolder.mjs +42 -0
- package/dist/admin/hooks/useEditFolder.mjs.map +1 -0
- package/dist/admin/hooks/useFolder.js +58 -0
- package/dist/admin/hooks/useFolder.js.map +1 -0
- package/dist/admin/hooks/useFolder.mjs +56 -0
- package/dist/admin/hooks/useFolder.mjs.map +1 -0
- package/dist/admin/hooks/useFolderStructure.js +53 -0
- package/dist/admin/hooks/useFolderStructure.js.map +1 -0
- package/dist/admin/hooks/useFolderStructure.mjs +51 -0
- package/dist/admin/hooks/useFolderStructure.mjs.map +1 -0
- package/dist/admin/hooks/useFolders.js +107 -0
- package/dist/admin/hooks/useFolders.js.map +1 -0
- package/dist/admin/hooks/useFolders.mjs +86 -0
- package/dist/admin/hooks/useFolders.mjs.map +1 -0
- package/dist/admin/hooks/useMediaLibraryPermissions.js +16 -0
- package/dist/admin/hooks/useMediaLibraryPermissions.js.map +1 -0
- package/dist/admin/hooks/useMediaLibraryPermissions.mjs +14 -0
- package/dist/admin/hooks/useMediaLibraryPermissions.mjs.map +1 -0
- package/dist/admin/hooks/useModalQueryParams.js +138 -0
- package/dist/admin/hooks/useModalQueryParams.js.map +1 -0
- package/dist/admin/hooks/useModalQueryParams.mjs +117 -0
- package/dist/admin/hooks/useModalQueryParams.mjs.map +1 -0
- package/dist/admin/hooks/usePersistentState.js +31 -0
- package/dist/admin/hooks/usePersistentState.js.map +1 -0
- package/dist/admin/hooks/usePersistentState.mjs +29 -0
- package/dist/admin/hooks/usePersistentState.mjs.map +1 -0
- package/dist/admin/hooks/useRemoveAsset.js +53 -0
- package/dist/admin/hooks/useRemoveAsset.js.map +1 -0
- package/dist/admin/hooks/useRemoveAsset.mjs +51 -0
- package/dist/admin/hooks/useRemoveAsset.mjs.map +1 -0
- package/dist/admin/hooks/useSelectionState.js +85 -0
- package/dist/admin/hooks/useSelectionState.js.map +1 -0
- package/dist/admin/hooks/useSelectionState.mjs +64 -0
- package/dist/admin/hooks/useSelectionState.mjs.map +1 -0
- package/dist/admin/hooks/useUpload.js +86 -0
- package/dist/admin/hooks/useUpload.js.map +1 -0
- package/dist/admin/hooks/useUpload.mjs +65 -0
- package/dist/admin/hooks/useUpload.mjs.map +1 -0
- package/dist/admin/hooks/utils/renameKeys.js +12 -0
- package/dist/admin/hooks/utils/renameKeys.js.map +1 -0
- package/dist/admin/hooks/utils/renameKeys.mjs +10 -0
- package/dist/admin/hooks/utils/renameKeys.mjs.map +1 -0
- package/dist/admin/index.js +104 -22
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +105 -21
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/package.json.js +161 -0
- package/dist/admin/package.json.js.map +1 -0
- package/dist/admin/package.json.mjs +143 -0
- package/dist/admin/package.json.mjs.map +1 -0
- package/dist/admin/pages/App/App.js +94 -0
- package/dist/admin/pages/App/App.js.map +1 -0
- package/dist/admin/pages/App/App.mjs +73 -0
- package/dist/admin/pages/App/App.mjs.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.js +142 -0
- package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.js.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.mjs +121 -0
- package/dist/admin/pages/App/ConfigureTheView/ConfigureTheView.mjs.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/components/Settings.js +108 -0
- package/dist/admin/pages/App/ConfigureTheView/components/Settings.js.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/components/Settings.mjs +106 -0
- package/dist/admin/pages/App/ConfigureTheView/components/Settings.mjs.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actionTypes.js +10 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actionTypes.js.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actionTypes.mjs +7 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actionTypes.mjs.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actions.js +16 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actions.js.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actions.mjs +13 -0
- package/dist/admin/pages/App/ConfigureTheView/state/actions.mjs.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/init.js +17 -0
- package/dist/admin/pages/App/ConfigureTheView/state/init.js.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/init.mjs +14 -0
- package/dist/admin/pages/App/ConfigureTheView/state/init.mjs.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/reducer.js +40 -0
- package/dist/admin/pages/App/ConfigureTheView/state/reducer.js.map +1 -0
- package/dist/admin/pages/App/ConfigureTheView/state/reducer.mjs +38 -0
- package/dist/admin/pages/App/ConfigureTheView/state/reducer.mjs.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/MediaLibrary.js +453 -0
- package/dist/admin/pages/App/MediaLibrary/MediaLibrary.js.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/MediaLibrary.mjs +432 -0
- package/dist/admin/pages/App/MediaLibrary/MediaLibrary.mjs.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkActions.js +49 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkActions.js.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkActions.mjs +47 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkActions.mjs.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkDeleteButton.js +38 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkDeleteButton.js.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkDeleteButton.mjs +36 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkDeleteButton.mjs.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkMoveButton.js +61 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkMoveButton.js.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkMoveButton.mjs +40 -0
- package/dist/admin/pages/App/MediaLibrary/components/BulkMoveButton.mjs.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/EmptyOrNoPermissions.js +66 -0
- package/dist/admin/pages/App/MediaLibrary/components/EmptyOrNoPermissions.js.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/EmptyOrNoPermissions.mjs +64 -0
- package/dist/admin/pages/App/MediaLibrary/components/EmptyOrNoPermissions.mjs.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/Filters.js +94 -0
- package/dist/admin/pages/App/MediaLibrary/components/Filters.js.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/Filters.mjs +73 -0
- package/dist/admin/pages/App/MediaLibrary/components/Filters.mjs.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/Header.js +76 -0
- package/dist/admin/pages/App/MediaLibrary/components/Header.js.map +1 -0
- package/dist/admin/pages/App/MediaLibrary/components/Header.mjs +74 -0
- package/dist/admin/pages/App/MediaLibrary/components/Header.mjs.map +1 -0
- package/dist/admin/{chunks/SettingsPage-5TS6R8ax.js → pages/SettingsPage/SettingsPage.js} +18 -67
- package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -0
- package/dist/admin/{chunks/SettingsPage-B7xS0X0V.mjs → pages/SettingsPage/SettingsPage.mjs} +6 -55
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -0
- package/dist/admin/pages/SettingsPage/init.js +8 -0
- package/dist/admin/pages/SettingsPage/init.js.map +1 -0
- package/dist/admin/pages/SettingsPage/init.mjs +6 -0
- package/dist/admin/pages/SettingsPage/init.mjs.map +1 -0
- package/dist/admin/pages/SettingsPage/reducer.js +43 -0
- package/dist/admin/pages/SettingsPage/reducer.js.map +1 -0
- package/dist/admin/pages/SettingsPage/reducer.mjs +40 -0
- package/dist/admin/pages/SettingsPage/reducer.mjs.map +1 -0
- package/dist/admin/pluginId.js +8 -0
- package/dist/admin/pluginId.js.map +1 -0
- package/dist/admin/pluginId.mjs +6 -0
- package/dist/admin/pluginId.mjs.map +1 -0
- package/dist/admin/{chunks/ca-pCOhKIn8.js → translations/ca.json.js} +2 -2
- package/dist/admin/translations/ca.json.js.map +1 -0
- package/dist/admin/{chunks/ca-Bi4qskZD.mjs → translations/ca.json.mjs} +1 -1
- package/dist/admin/translations/ca.json.mjs.map +1 -0
- package/dist/admin/{chunks/de-DUjKLmOP.js → translations/de.json.js} +2 -2
- package/dist/admin/translations/de.json.js.map +1 -0
- package/dist/admin/{chunks/de-BlbX8Dl_.mjs → translations/de.json.mjs} +1 -1
- package/dist/admin/translations/de.json.mjs.map +1 -0
- package/dist/admin/{chunks/dk-DSsspA0e.js → translations/dk.json.js} +2 -2
- package/dist/admin/translations/dk.json.js.map +1 -0
- package/dist/admin/{chunks/dk-C2ydE6A7.mjs → translations/dk.json.mjs} +1 -1
- package/dist/admin/translations/dk.json.mjs.map +1 -0
- package/dist/admin/{chunks/en-UjETkewz.js → translations/en.json.js} +2 -2
- package/dist/admin/translations/en.json.js.map +1 -0
- package/dist/admin/{chunks/en-Bw_Cb2IV.mjs → translations/en.json.mjs} +1 -1
- package/dist/admin/translations/en.json.mjs.map +1 -0
- package/dist/admin/{chunks/es-qAL8YcZz.js → translations/es.json.js} +2 -2
- package/dist/admin/translations/es.json.js.map +1 -0
- package/dist/admin/{chunks/es-CiEgbw0k.mjs → translations/es.json.mjs} +1 -1
- package/dist/admin/translations/es.json.mjs.map +1 -0
- package/dist/admin/{chunks/fr-BL0Uyj6j.js → translations/fr.json.js} +2 -2
- package/dist/admin/translations/fr.json.js.map +1 -0
- package/dist/admin/{chunks/fr-CwRt2FJu.mjs → translations/fr.json.mjs} +1 -1
- package/dist/admin/translations/fr.json.mjs.map +1 -0
- package/dist/admin/{chunks/he-BAmhVpfZ.js → translations/he.json.js} +2 -2
- package/dist/admin/translations/he.json.js.map +1 -0
- package/dist/admin/{chunks/he-DdpYNQdt.mjs → translations/he.json.mjs} +1 -1
- package/dist/admin/translations/he.json.mjs.map +1 -0
- package/dist/admin/{chunks/it-_NQZYepl.js → translations/it.json.js} +2 -2
- package/dist/admin/translations/it.json.js.map +1 -0
- package/dist/admin/{chunks/it-Be4kgSNB.mjs → translations/it.json.mjs} +1 -1
- package/dist/admin/translations/it.json.mjs.map +1 -0
- package/dist/admin/{chunks/ja-B75QiyXf.js → translations/ja.json.js} +2 -2
- package/dist/admin/translations/ja.json.js.map +1 -0
- package/dist/admin/{chunks/ja-U1NhT0bU.mjs → translations/ja.json.mjs} +1 -1
- package/dist/admin/translations/ja.json.mjs.map +1 -0
- package/dist/admin/{chunks/ko-BOvUcJqv.js → translations/ko.json.js} +2 -2
- package/dist/admin/translations/ko.json.js.map +1 -0
- package/dist/admin/{chunks/ko-BciqXefq.mjs → translations/ko.json.mjs} +1 -1
- package/dist/admin/translations/ko.json.mjs.map +1 -0
- package/dist/admin/{chunks/ms-B7Zl6Lm9.js → translations/ms.json.js} +2 -2
- package/dist/admin/translations/ms.json.js.map +1 -0
- package/dist/admin/{chunks/ms-D-8McNeg.mjs → translations/ms.json.mjs} +1 -1
- package/dist/admin/translations/ms.json.mjs.map +1 -0
- package/dist/admin/{chunks/pl-cYDYHOEf.js → translations/pl.json.js} +2 -2
- package/dist/admin/translations/pl.json.js.map +1 -0
- package/dist/admin/{chunks/pl-DdUYocl5.mjs → translations/pl.json.mjs} +1 -1
- package/dist/admin/translations/pl.json.mjs.map +1 -0
- package/dist/admin/{chunks/pt-BR-D1u_azCM.js → translations/pt-BR.json.js} +2 -2
- package/dist/admin/translations/pt-BR.json.js.map +1 -0
- package/dist/admin/{chunks/pt-BR-Demjoq41.mjs → translations/pt-BR.json.mjs} +1 -1
- package/dist/admin/translations/pt-BR.json.mjs.map +1 -0
- package/dist/admin/{chunks/pt-L2DZeTPL.js → translations/pt.json.js} +2 -2
- package/dist/admin/translations/pt.json.js.map +1 -0
- package/dist/admin/{chunks/pt-D8is2LpS.mjs → translations/pt.json.mjs} +1 -1
- package/dist/admin/translations/pt.json.mjs.map +1 -0
- package/dist/admin/{chunks/ru-Uxbk_WWv.js → translations/ru.json.js} +2 -2
- package/dist/admin/translations/ru.json.js.map +1 -0
- package/dist/admin/{chunks/ru-CGgHRTey.mjs → translations/ru.json.mjs} +1 -1
- package/dist/admin/translations/ru.json.mjs.map +1 -0
- package/dist/admin/{chunks/sk-BlLP5HAX.js → translations/sk.json.js} +2 -2
- package/dist/admin/translations/sk.json.js.map +1 -0
- package/dist/admin/{chunks/sk-xtSwaPXq.mjs → translations/sk.json.mjs} +1 -1
- package/dist/admin/translations/sk.json.mjs.map +1 -0
- package/dist/admin/{chunks/th-DNxPLegS.js → translations/th.json.js} +2 -2
- package/dist/admin/translations/th.json.js.map +1 -0
- package/dist/admin/{chunks/th-BOpLVfmg.mjs → translations/th.json.mjs} +1 -1
- package/dist/admin/translations/th.json.mjs.map +1 -0
- package/dist/admin/{chunks/tr-DWgXG75k.js → translations/tr.json.js} +2 -2
- package/dist/admin/translations/tr.json.js.map +1 -0
- package/dist/admin/{chunks/tr-BmAPh-f1.mjs → translations/tr.json.mjs} +1 -1
- package/dist/admin/translations/tr.json.mjs.map +1 -0
- package/dist/admin/{chunks/uk-Cfm1dM3v.js → translations/uk.json.js} +2 -2
- package/dist/admin/translations/uk.json.js.map +1 -0
- package/dist/admin/{chunks/uk-DPZD6U8g.mjs → translations/uk.json.mjs} +1 -1
- package/dist/admin/translations/uk.json.mjs.map +1 -0
- package/dist/admin/{chunks/zh-Hans-B8qxMQIl.js → translations/zh-Hans.json.js} +2 -2
- package/dist/admin/{chunks/ca-Bi4qskZD.mjs.map → translations/zh-Hans.json.js.map} +1 -1
- package/dist/admin/{chunks/zh-Hans-B1GabBRx.mjs → translations/zh-Hans.json.mjs} +1 -1
- package/dist/admin/translations/zh-Hans.json.mjs.map +1 -0
- package/dist/admin/{chunks/zh-MemsyMV6.js → translations/zh.json.js} +2 -2
- package/dist/admin/translations/zh.json.js.map +1 -0
- package/dist/admin/{chunks/zh-BIl0qgBy.mjs → translations/zh.json.mjs} +1 -1
- package/dist/admin/translations/zh.json.mjs.map +1 -0
- package/dist/admin/utils/appendSearchParamsToUrl.js +17 -0
- package/dist/admin/utils/appendSearchParamsToUrl.js.map +1 -0
- package/dist/admin/utils/appendSearchParamsToUrl.mjs +15 -0
- package/dist/admin/utils/appendSearchParamsToUrl.mjs.map +1 -0
- package/dist/admin/utils/containsAssetFilter.js +18 -0
- package/dist/admin/utils/containsAssetFilter.js.map +1 -0
- package/dist/admin/utils/containsAssetFilter.mjs +16 -0
- package/dist/admin/utils/containsAssetFilter.mjs.map +1 -0
- package/dist/admin/utils/createAssetUrl.js +14 -0
- package/dist/admin/utils/createAssetUrl.js.map +1 -0
- package/dist/admin/utils/createAssetUrl.mjs +12 -0
- package/dist/admin/utils/createAssetUrl.mjs.map +1 -0
- package/dist/admin/utils/displayedFilters.js +52 -0
- package/dist/admin/utils/displayedFilters.js.map +1 -0
- package/dist/admin/utils/displayedFilters.mjs +50 -0
- package/dist/admin/utils/displayedFilters.mjs.map +1 -0
- package/dist/admin/utils/downloadFile.js +13 -0
- package/dist/admin/utils/downloadFile.js.map +1 -0
- package/dist/admin/utils/downloadFile.mjs +11 -0
- package/dist/admin/utils/downloadFile.mjs.map +1 -0
- package/dist/admin/utils/findRecursiveFolderByValue.js +17 -0
- package/dist/admin/utils/findRecursiveFolderByValue.js.map +1 -0
- package/dist/admin/utils/findRecursiveFolderByValue.mjs +15 -0
- package/dist/admin/utils/findRecursiveFolderByValue.mjs.map +1 -0
- package/dist/admin/utils/formatBytes.js +17 -0
- package/dist/admin/utils/formatBytes.js.map +1 -0
- package/dist/admin/utils/formatBytes.mjs +15 -0
- package/dist/admin/utils/formatBytes.mjs.map +1 -0
- package/dist/admin/utils/formatDuration.js +15 -0
- package/dist/admin/utils/formatDuration.js.map +1 -0
- package/dist/admin/utils/formatDuration.mjs +13 -0
- package/dist/admin/utils/formatDuration.mjs.map +1 -0
- package/dist/admin/utils/getAPIInnerErrors.js +26 -0
- package/dist/admin/utils/getAPIInnerErrors.js.map +1 -0
- package/dist/admin/utils/getAPIInnerErrors.mjs +24 -0
- package/dist/admin/utils/getAPIInnerErrors.mjs.map +1 -0
- package/dist/admin/utils/getAllowedFiles.js +25 -0
- package/dist/admin/utils/getAllowedFiles.js.map +1 -0
- package/dist/admin/utils/getAllowedFiles.mjs +23 -0
- package/dist/admin/utils/getAllowedFiles.mjs.map +1 -0
- package/dist/admin/utils/getBreadcrumbDataCM.js +36 -0
- package/dist/admin/utils/getBreadcrumbDataCM.js.map +1 -0
- package/dist/admin/utils/getBreadcrumbDataCM.mjs +34 -0
- package/dist/admin/utils/getBreadcrumbDataCM.mjs.map +1 -0
- package/dist/admin/utils/getBreadcrumbDataML.js +40 -0
- package/dist/admin/utils/getBreadcrumbDataML.js.map +1 -0
- package/dist/admin/utils/getBreadcrumbDataML.mjs +38 -0
- package/dist/admin/utils/getBreadcrumbDataML.mjs.map +1 -0
- package/dist/admin/utils/getFileExtension.js +6 -0
- package/dist/admin/utils/getFileExtension.js.map +1 -0
- package/dist/admin/utils/getFileExtension.mjs +4 -0
- package/dist/admin/utils/getFileExtension.mjs.map +1 -0
- package/dist/admin/utils/getFolderParents.js +26 -0
- package/dist/admin/utils/getFolderParents.js.map +1 -0
- package/dist/admin/utils/getFolderParents.mjs +24 -0
- package/dist/admin/utils/getFolderParents.mjs.map +1 -0
- package/dist/admin/utils/getFolderURL.js +20 -0
- package/dist/admin/utils/getFolderURL.js.map +1 -0
- package/dist/admin/utils/getFolderURL.mjs +18 -0
- package/dist/admin/utils/getFolderURL.mjs.map +1 -0
- package/dist/admin/utils/getTrad.js +8 -0
- package/dist/admin/utils/getTrad.js.map +1 -0
- package/dist/admin/utils/getTrad.mjs +6 -0
- package/dist/admin/utils/getTrad.mjs.map +1 -0
- package/dist/admin/utils/moveElement.js +16 -0
- package/dist/admin/utils/moveElement.js.map +1 -0
- package/dist/admin/utils/moveElement.mjs +14 -0
- package/dist/admin/utils/moveElement.mjs.map +1 -0
- package/dist/admin/utils/normalizeAPIError.js +55 -0
- package/dist/admin/utils/normalizeAPIError.js.map +1 -0
- package/dist/admin/utils/normalizeAPIError.mjs +53 -0
- package/dist/admin/utils/normalizeAPIError.mjs.map +1 -0
- package/dist/admin/utils/prefixFileUrlWithBackendUrl.js +8 -0
- package/dist/admin/utils/prefixFileUrlWithBackendUrl.js.map +1 -0
- package/dist/admin/utils/prefixFileUrlWithBackendUrl.mjs +6 -0
- package/dist/admin/utils/prefixFileUrlWithBackendUrl.mjs.map +1 -0
- package/dist/admin/utils/prefixPluginTranslations.js +14 -0
- package/dist/admin/utils/prefixPluginTranslations.js.map +1 -0
- package/dist/admin/utils/prefixPluginTranslations.mjs +12 -0
- package/dist/admin/utils/prefixPluginTranslations.mjs.map +1 -0
- package/dist/admin/utils/rawFileToAsset.js +21 -0
- package/dist/admin/utils/rawFileToAsset.js.map +1 -0
- package/dist/admin/utils/rawFileToAsset.mjs +19 -0
- package/dist/admin/utils/rawFileToAsset.mjs.map +1 -0
- package/dist/admin/utils/toSingularTypes.js +11 -0
- package/dist/admin/utils/toSingularTypes.js.map +1 -0
- package/dist/admin/utils/toSingularTypes.mjs +9 -0
- package/dist/admin/utils/toSingularTypes.mjs.map +1 -0
- package/dist/admin/utils/typeFromMime.js +19 -0
- package/dist/admin/utils/typeFromMime.js.map +1 -0
- package/dist/admin/utils/typeFromMime.mjs +17 -0
- package/dist/admin/utils/typeFromMime.mjs.map +1 -0
- package/dist/admin/utils/urlYupSchema.js +72 -0
- package/dist/admin/utils/urlYupSchema.js.map +1 -0
- package/dist/admin/utils/urlYupSchema.mjs +51 -0
- package/dist/admin/utils/urlYupSchema.mjs.map +1 -0
- package/dist/admin/utils/urlsToAssets.js +39 -0
- package/dist/admin/utils/urlsToAssets.js.map +1 -0
- package/dist/admin/utils/urlsToAssets.mjs +37 -0
- package/dist/admin/utils/urlsToAssets.mjs.map +1 -0
- package/dist/server/bootstrap.js +98 -0
- package/dist/server/bootstrap.js.map +1 -0
- package/dist/server/bootstrap.mjs +96 -0
- package/dist/server/bootstrap.mjs.map +1 -0
- package/dist/server/config.js +14 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/config.mjs +12 -0
- package/dist/server/config.mjs.map +1 -0
- package/dist/server/constants.js +35 -0
- package/dist/server/constants.js.map +1 -0
- package/dist/server/constants.mjs +28 -0
- package/dist/server/constants.mjs.map +1 -0
- package/dist/server/content-types/file.js +155 -0
- package/dist/server/content-types/file.js.map +1 -0
- package/dist/server/content-types/file.mjs +153 -0
- package/dist/server/content-types/file.mjs.map +1 -0
- package/dist/server/content-types/folder.js +78 -0
- package/dist/server/content-types/folder.js.map +1 -0
- package/dist/server/content-types/folder.mjs +76 -0
- package/dist/server/content-types/folder.mjs.map +1 -0
- package/dist/server/content-types/index.js +12 -0
- package/dist/server/content-types/index.js.map +1 -0
- package/dist/server/content-types/index.mjs +10 -0
- package/dist/server/content-types/index.mjs.map +1 -0
- package/dist/server/controllers/admin-file.js +61 -0
- package/dist/server/controllers/admin-file.js.map +1 -0
- package/dist/server/controllers/admin-file.mjs +59 -0
- package/dist/server/controllers/admin-file.mjs.map +1 -0
- package/dist/server/controllers/admin-folder-file.js +189 -0
- package/dist/server/controllers/admin-folder-file.js.map +1 -0
- package/dist/server/controllers/admin-folder-file.mjs +187 -0
- package/dist/server/controllers/admin-folder-file.mjs.map +1 -0
- package/dist/server/controllers/admin-folder.js +104 -0
- package/dist/server/controllers/admin-folder.js.map +1 -0
- package/dist/server/controllers/admin-folder.mjs +102 -0
- package/dist/server/controllers/admin-folder.mjs.map +1 -0
- package/dist/server/controllers/admin-settings.js +32 -0
- package/dist/server/controllers/admin-settings.js.map +1 -0
- package/dist/server/controllers/admin-settings.mjs +30 -0
- package/dist/server/controllers/admin-settings.mjs.map +1 -0
- package/dist/server/controllers/admin-upload.js +88 -0
- package/dist/server/controllers/admin-upload.js.map +1 -0
- package/dist/server/controllers/admin-upload.mjs +86 -0
- package/dist/server/controllers/admin-upload.mjs.map +1 -0
- package/dist/server/controllers/content-api.js +122 -0
- package/dist/server/controllers/content-api.js.map +1 -0
- package/dist/server/controllers/content-api.mjs +120 -0
- package/dist/server/controllers/content-api.mjs.map +1 -0
- package/dist/server/controllers/index.js +22 -0
- package/dist/server/controllers/index.js.map +1 -0
- package/dist/server/controllers/index.mjs +20 -0
- package/dist/server/controllers/index.mjs.map +1 -0
- package/dist/server/controllers/utils/find-entity-and-check-permissions.js +38 -0
- package/dist/server/controllers/utils/find-entity-and-check-permissions.js.map +1 -0
- package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs +36 -0
- package/dist/server/controllers/utils/find-entity-and-check-permissions.mjs.map +1 -0
- package/dist/server/controllers/utils/folders.js +6 -0
- package/dist/server/controllers/utils/folders.js.map +1 -0
- package/dist/server/controllers/utils/folders.mjs +4 -0
- package/dist/server/controllers/utils/folders.mjs.map +1 -0
- package/dist/server/controllers/validation/admin/configureView.js +13 -0
- package/dist/server/controllers/validation/admin/configureView.js.map +1 -0
- package/dist/server/controllers/validation/admin/configureView.mjs +11 -0
- package/dist/server/controllers/validation/admin/configureView.mjs.map +1 -0
- package/dist/server/controllers/validation/admin/folder-file.js +88 -0
- package/dist/server/controllers/validation/admin/folder-file.js.map +1 -0
- package/dist/server/controllers/validation/admin/folder-file.mjs +85 -0
- package/dist/server/controllers/validation/admin/folder-file.mjs.map +1 -0
- package/dist/server/controllers/validation/admin/folder.js +69 -0
- package/dist/server/controllers/validation/admin/folder.js.map +1 -0
- package/dist/server/controllers/validation/admin/folder.mjs +66 -0
- package/dist/server/controllers/validation/admin/folder.mjs.map +1 -0
- package/dist/server/controllers/validation/admin/settings.js +13 -0
- package/dist/server/controllers/validation/admin/settings.js.map +1 -0
- package/dist/server/controllers/validation/admin/settings.mjs +11 -0
- package/dist/server/controllers/validation/admin/settings.mjs.map +1 -0
- package/dist/server/controllers/validation/admin/upload.js +35 -0
- package/dist/server/controllers/validation/admin/upload.js.map +1 -0
- package/dist/server/controllers/validation/admin/upload.mjs +33 -0
- package/dist/server/controllers/validation/admin/upload.mjs.map +1 -0
- package/dist/server/controllers/validation/admin/utils.js +17 -0
- package/dist/server/controllers/validation/admin/utils.js.map +1 -0
- package/dist/server/controllers/validation/admin/utils.mjs +15 -0
- package/dist/server/controllers/validation/admin/utils.mjs.map +1 -0
- package/dist/server/controllers/validation/content-api/upload.js +24 -0
- package/dist/server/controllers/validation/content-api/upload.js.map +1 -0
- package/dist/server/controllers/validation/content-api/upload.mjs +22 -0
- package/dist/server/controllers/validation/content-api/upload.mjs.map +1 -0
- package/dist/server/controllers/view-configuration.js +28 -0
- package/dist/server/controllers/view-configuration.js.map +1 -0
- package/dist/server/controllers/view-configuration.mjs +26 -0
- package/dist/server/controllers/view-configuration.mjs.map +1 -0
- package/dist/server/documentation/content-api.json.js +290 -0
- package/dist/server/documentation/content-api.json.js.map +1 -0
- package/dist/server/documentation/content-api.json.mjs +284 -0
- package/dist/server/documentation/content-api.json.mjs.map +1 -0
- package/dist/server/{chunks/graphql-CwNPX8zo.js → graphql.js} +3 -16
- package/dist/server/graphql.js.map +1 -0
- package/dist/server/{chunks/graphql-K9HaGS9d.mjs → graphql.mjs} +2 -15
- package/dist/server/graphql.mjs.map +1 -0
- package/dist/server/index.js +17 -16
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +19 -14
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/middlewares/upload.js +38 -0
- package/dist/server/middlewares/upload.js.map +1 -0
- package/dist/server/middlewares/upload.mjs +36 -0
- package/dist/server/middlewares/upload.mjs.map +1 -0
- package/dist/server/register.js +88 -0
- package/dist/server/register.js.map +1 -0
- package/dist/server/register.mjs +86 -0
- package/dist/server/register.mjs.map +1 -0
- package/dist/server/routes/admin.js +236 -0
- package/dist/server/routes/admin.js.map +1 -0
- package/dist/server/routes/admin.mjs +234 -0
- package/dist/server/routes/admin.mjs.map +1 -0
- package/dist/server/routes/content-api.js +30 -0
- package/dist/server/routes/content-api.js.map +1 -0
- package/dist/server/routes/content-api.mjs +28 -0
- package/dist/server/routes/content-api.mjs.map +1 -0
- package/dist/server/routes/index.js +14 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/index.mjs +12 -0
- package/dist/server/routes/index.mjs.map +1 -0
- package/dist/server/routes/view-configuration.js +40 -0
- package/dist/server/routes/view-configuration.js.map +1 -0
- package/dist/server/routes/view-configuration.mjs +38 -0
- package/dist/server/routes/view-configuration.mjs.map +1 -0
- package/dist/server/services/api-upload-folder.js +52 -0
- package/dist/server/services/api-upload-folder.js.map +1 -0
- package/dist/server/services/api-upload-folder.mjs +50 -0
- package/dist/server/services/api-upload-folder.mjs.map +1 -0
- package/dist/server/services/extensions/index.js +40 -0
- package/dist/server/services/extensions/index.js.map +1 -0
- package/dist/server/services/extensions/index.mjs +38 -0
- package/dist/server/services/extensions/index.mjs.map +1 -0
- package/dist/server/services/extensions/utils.js +53 -0
- package/dist/server/services/extensions/utils.js.map +1 -0
- package/dist/server/services/extensions/utils.mjs +51 -0
- package/dist/server/services/extensions/utils.mjs.map +1 -0
- package/dist/server/services/file.js +57 -0
- package/dist/server/services/file.js.map +1 -0
- package/dist/server/services/file.mjs +55 -0
- package/dist/server/services/file.mjs.map +1 -0
- package/dist/server/services/folder.js +275 -0
- package/dist/server/services/folder.js.map +1 -0
- package/dist/server/services/folder.mjs +273 -0
- package/dist/server/services/folder.mjs.map +1 -0
- package/dist/server/services/image-manipulation.js +255 -0
- package/dist/server/services/image-manipulation.js.map +1 -0
- package/dist/server/services/image-manipulation.mjs +253 -0
- package/dist/server/services/image-manipulation.mjs.map +1 -0
- package/dist/server/services/index.js +26 -0
- package/dist/server/services/index.js.map +1 -0
- package/dist/server/services/index.mjs +24 -0
- package/dist/server/services/index.mjs.map +1 -0
- package/dist/server/services/metrics.js +19 -0
- package/dist/server/services/metrics.js.map +1 -0
- package/dist/server/services/metrics.mjs +17 -0
- package/dist/server/services/metrics.mjs.map +1 -0
- package/dist/server/services/provider.js +33 -0
- package/dist/server/services/provider.js.map +1 -0
- package/dist/server/services/provider.mjs +31 -0
- package/dist/server/services/provider.mjs.map +1 -0
- package/dist/server/services/upload.js +445 -0
- package/dist/server/services/upload.js.map +1 -0
- package/dist/server/services/upload.mjs +443 -0
- package/dist/server/services/upload.mjs.map +1 -0
- package/dist/server/services/weekly-metrics.js +127 -0
- package/dist/server/services/weekly-metrics.js.map +1 -0
- package/dist/server/services/weekly-metrics.mjs +125 -0
- package/dist/server/services/weekly-metrics.mjs.map +1 -0
- package/dist/server/utils/cron.js +6 -0
- package/dist/server/utils/cron.js.map +1 -0
- package/dist/server/utils/cron.mjs +4 -0
- package/dist/server/utils/cron.mjs.map +1 -0
- package/dist/server/utils/index.js +8 -0
- package/dist/server/utils/index.js.map +1 -0
- package/dist/server/utils/index.mjs +6 -0
- package/dist/server/utils/index.mjs.map +1 -0
- package/package.json +5 -5
- package/dist/admin/chunks/App-BBHvDTKY.js +0 -993
- package/dist/admin/chunks/App-BBHvDTKY.js.map +0 -1
- package/dist/admin/chunks/App-DOvEuP1h.mjs +0 -972
- package/dist/admin/chunks/App-DOvEuP1h.mjs.map +0 -1
- package/dist/admin/chunks/ConfigureTheView-BZq26A26.js +0 -297
- package/dist/admin/chunks/ConfigureTheView-BZq26A26.js.map +0 -1
- package/dist/admin/chunks/ConfigureTheView-CzngS3_9.mjs +0 -276
- package/dist/admin/chunks/ConfigureTheView-CzngS3_9.mjs.map +0 -1
- package/dist/admin/chunks/SettingsPage-5TS6R8ax.js.map +0 -1
- package/dist/admin/chunks/SettingsPage-B7xS0X0V.mjs.map +0 -1
- package/dist/admin/chunks/ca-pCOhKIn8.js.map +0 -1
- package/dist/admin/chunks/de-BlbX8Dl_.mjs.map +0 -1
- package/dist/admin/chunks/de-DUjKLmOP.js.map +0 -1
- package/dist/admin/chunks/dk-C2ydE6A7.mjs.map +0 -1
- package/dist/admin/chunks/dk-DSsspA0e.js.map +0 -1
- package/dist/admin/chunks/en-Bw_Cb2IV.mjs.map +0 -1
- package/dist/admin/chunks/en-UjETkewz.js.map +0 -1
- package/dist/admin/chunks/es-CiEgbw0k.mjs.map +0 -1
- package/dist/admin/chunks/es-qAL8YcZz.js.map +0 -1
- package/dist/admin/chunks/fr-BL0Uyj6j.js.map +0 -1
- package/dist/admin/chunks/fr-CwRt2FJu.mjs.map +0 -1
- package/dist/admin/chunks/he-BAmhVpfZ.js.map +0 -1
- package/dist/admin/chunks/he-DdpYNQdt.mjs.map +0 -1
- package/dist/admin/chunks/index-mrIASzro.js +0 -7406
- package/dist/admin/chunks/index-mrIASzro.js.map +0 -1
- package/dist/admin/chunks/index-zOCLhXyV.mjs +0 -7349
- package/dist/admin/chunks/index-zOCLhXyV.mjs.map +0 -1
- package/dist/admin/chunks/it-Be4kgSNB.mjs.map +0 -1
- package/dist/admin/chunks/it-_NQZYepl.js.map +0 -1
- package/dist/admin/chunks/ja-B75QiyXf.js.map +0 -1
- package/dist/admin/chunks/ja-U1NhT0bU.mjs.map +0 -1
- package/dist/admin/chunks/ko-BOvUcJqv.js.map +0 -1
- package/dist/admin/chunks/ko-BciqXefq.mjs.map +0 -1
- package/dist/admin/chunks/ms-B7Zl6Lm9.js.map +0 -1
- package/dist/admin/chunks/ms-D-8McNeg.mjs.map +0 -1
- package/dist/admin/chunks/pl-DdUYocl5.mjs.map +0 -1
- package/dist/admin/chunks/pl-cYDYHOEf.js.map +0 -1
- package/dist/admin/chunks/pt-BR-D1u_azCM.js.map +0 -1
- package/dist/admin/chunks/pt-BR-Demjoq41.mjs.map +0 -1
- package/dist/admin/chunks/pt-D8is2LpS.mjs.map +0 -1
- package/dist/admin/chunks/pt-L2DZeTPL.js.map +0 -1
- package/dist/admin/chunks/ru-CGgHRTey.mjs.map +0 -1
- package/dist/admin/chunks/ru-Uxbk_WWv.js.map +0 -1
- package/dist/admin/chunks/sk-BlLP5HAX.js.map +0 -1
- package/dist/admin/chunks/sk-xtSwaPXq.mjs.map +0 -1
- package/dist/admin/chunks/th-BOpLVfmg.mjs.map +0 -1
- package/dist/admin/chunks/th-DNxPLegS.js.map +0 -1
- package/dist/admin/chunks/tr-BmAPh-f1.mjs.map +0 -1
- package/dist/admin/chunks/tr-DWgXG75k.js.map +0 -1
- package/dist/admin/chunks/uk-Cfm1dM3v.js.map +0 -1
- package/dist/admin/chunks/uk-DPZD6U8g.mjs.map +0 -1
- package/dist/admin/chunks/zh-BIl0qgBy.mjs.map +0 -1
- package/dist/admin/chunks/zh-Hans-B1GabBRx.mjs.map +0 -1
- package/dist/admin/chunks/zh-Hans-B8qxMQIl.js.map +0 -1
- package/dist/admin/chunks/zh-MemsyMV6.js.map +0 -1
- package/dist/server/chunks/graphql-CwNPX8zo.js.map +0 -1
- package/dist/server/chunks/graphql-K9HaGS9d.mjs.map +0 -1
- package/dist/server/chunks/index-BzVus140.mjs +0 -3161
- package/dist/server/chunks/index-BzVus140.mjs.map +0 -1
- package/dist/server/chunks/index-D2QOphAI.js +0 -3164
- package/dist/server/chunks/index-D2QOphAI.js.map +0 -1
|
@@ -1,3161 +0,0 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
import utils, { errors, file as file$2, contentTypes as contentTypes$1, strings, sanitize, setCreatorFields, async, traverseEntity, yup, validateYupSchema } from '@strapi/utils';
|
|
3
|
-
import range from 'koa-range';
|
|
4
|
-
import koaStatic from 'koa-static';
|
|
5
|
-
import { isFunction, map, isUndefined, sortBy, cloneDeep, defaultTo, get, isNil, merge, defaultsDeep, isEmpty, intersection } from 'lodash/fp';
|
|
6
|
-
import os from 'os';
|
|
7
|
-
import path, { join } from 'path';
|
|
8
|
-
import crypto from 'crypto';
|
|
9
|
-
import fs from 'fs';
|
|
10
|
-
import fse from 'fs-extra';
|
|
11
|
-
import { extension } from 'mime-types';
|
|
12
|
-
import sharp from 'sharp';
|
|
13
|
-
import { add } from 'date-fns';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Programmatic upload middleware. We do not want to expose it in the plugin
|
|
17
|
-
*/ var registerUploadMiddleware = (({ strapi })=>{
|
|
18
|
-
strapi.server.app.on('error', (err)=>{
|
|
19
|
-
if (err.code === 'EPIPE') {
|
|
20
|
-
// when serving audio or video the browsers sometimes close the connection to go to range requests instead.
|
|
21
|
-
// This causes koa to emit a write EPIPE error. We can ignore it.
|
|
22
|
-
// Right now this ignores it globally and we cannot do much more because it is how koa handles it.
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
strapi.server.app.onerror(err);
|
|
26
|
-
});
|
|
27
|
-
const localServerConfig = strapi.config.get('plugin::upload.providerOptions.localServer', {});
|
|
28
|
-
strapi.server.routes([
|
|
29
|
-
{
|
|
30
|
-
method: 'GET',
|
|
31
|
-
path: '/uploads/(.*)',
|
|
32
|
-
handler: [
|
|
33
|
-
range,
|
|
34
|
-
koaStatic(strapi.dirs.static.public, {
|
|
35
|
-
defer: true,
|
|
36
|
-
...localServerConfig
|
|
37
|
-
})
|
|
38
|
-
],
|
|
39
|
-
config: {
|
|
40
|
-
auth: false
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
]);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
var paths = {
|
|
47
|
-
"/upload": {
|
|
48
|
-
post: {
|
|
49
|
-
description: "Upload files",
|
|
50
|
-
responses: {
|
|
51
|
-
"200": {
|
|
52
|
-
description: "response",
|
|
53
|
-
content: {
|
|
54
|
-
"application/json": {
|
|
55
|
-
schema: {
|
|
56
|
-
type: "array",
|
|
57
|
-
items: {
|
|
58
|
-
$ref: "#/components/schemas/UploadFile"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
summary: "",
|
|
66
|
-
tags: [
|
|
67
|
-
"Upload - File"
|
|
68
|
-
],
|
|
69
|
-
requestBody: {
|
|
70
|
-
description: "Upload files",
|
|
71
|
-
required: true,
|
|
72
|
-
content: {
|
|
73
|
-
"multipart/form-data": {
|
|
74
|
-
schema: {
|
|
75
|
-
required: [
|
|
76
|
-
"files"
|
|
77
|
-
],
|
|
78
|
-
type: "object",
|
|
79
|
-
properties: {
|
|
80
|
-
path: {
|
|
81
|
-
type: "string",
|
|
82
|
-
description: "The folder where the file(s) will be uploaded to (only supported on strapi-provider-upload-aws-s3)."
|
|
83
|
-
},
|
|
84
|
-
refId: {
|
|
85
|
-
type: "string",
|
|
86
|
-
description: "The ID of the entry which the file(s) will be linked to"
|
|
87
|
-
},
|
|
88
|
-
ref: {
|
|
89
|
-
type: "string",
|
|
90
|
-
description: "The unique ID (uid) of the model which the file(s) will be linked to (api::restaurant.restaurant)."
|
|
91
|
-
},
|
|
92
|
-
field: {
|
|
93
|
-
type: "string",
|
|
94
|
-
description: "The field of the entry which the file(s) will be precisely linked to."
|
|
95
|
-
},
|
|
96
|
-
files: {
|
|
97
|
-
type: "array",
|
|
98
|
-
items: {
|
|
99
|
-
type: "string",
|
|
100
|
-
format: "binary"
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
"/upload?id={id}": {
|
|
111
|
-
post: {
|
|
112
|
-
parameters: [
|
|
113
|
-
{
|
|
114
|
-
name: "id",
|
|
115
|
-
"in": "query",
|
|
116
|
-
description: "File id",
|
|
117
|
-
required: true,
|
|
118
|
-
schema: {
|
|
119
|
-
type: "string"
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
],
|
|
123
|
-
description: "Upload file information",
|
|
124
|
-
responses: {
|
|
125
|
-
"200": {
|
|
126
|
-
description: "response",
|
|
127
|
-
content: {
|
|
128
|
-
"application/json": {
|
|
129
|
-
schema: {
|
|
130
|
-
type: "array",
|
|
131
|
-
items: {
|
|
132
|
-
$ref: "#/components/schemas/UploadFile"
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
summary: "",
|
|
140
|
-
tags: [
|
|
141
|
-
"Upload - File"
|
|
142
|
-
],
|
|
143
|
-
requestBody: {
|
|
144
|
-
description: "Upload files",
|
|
145
|
-
required: true,
|
|
146
|
-
content: {
|
|
147
|
-
"multipart/form-data": {
|
|
148
|
-
schema: {
|
|
149
|
-
type: "object",
|
|
150
|
-
properties: {
|
|
151
|
-
fileInfo: {
|
|
152
|
-
type: "object",
|
|
153
|
-
properties: {
|
|
154
|
-
name: {
|
|
155
|
-
type: "string"
|
|
156
|
-
},
|
|
157
|
-
alternativeText: {
|
|
158
|
-
type: "string"
|
|
159
|
-
},
|
|
160
|
-
caption: {
|
|
161
|
-
type: "string"
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
files: {
|
|
166
|
-
type: "string",
|
|
167
|
-
format: "binary"
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
"/upload/files": {
|
|
177
|
-
get: {
|
|
178
|
-
tags: [
|
|
179
|
-
"Upload - File"
|
|
180
|
-
],
|
|
181
|
-
responses: {
|
|
182
|
-
"200": {
|
|
183
|
-
description: "Get a list of files",
|
|
184
|
-
content: {
|
|
185
|
-
"application/json": {
|
|
186
|
-
schema: {
|
|
187
|
-
type: "array",
|
|
188
|
-
items: {
|
|
189
|
-
$ref: "#/components/schemas/UploadFile"
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
"/upload/files/{id}": {
|
|
199
|
-
get: {
|
|
200
|
-
parameters: [
|
|
201
|
-
{
|
|
202
|
-
name: "id",
|
|
203
|
-
"in": "path",
|
|
204
|
-
description: "",
|
|
205
|
-
deprecated: false,
|
|
206
|
-
required: true,
|
|
207
|
-
schema: {
|
|
208
|
-
type: "string"
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
],
|
|
212
|
-
tags: [
|
|
213
|
-
"Upload - File"
|
|
214
|
-
],
|
|
215
|
-
responses: {
|
|
216
|
-
"200": {
|
|
217
|
-
description: "Get a specific file",
|
|
218
|
-
content: {
|
|
219
|
-
"application/json": {
|
|
220
|
-
schema: {
|
|
221
|
-
$ref: "#/components/schemas/UploadFile"
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
"delete": {
|
|
229
|
-
parameters: [
|
|
230
|
-
{
|
|
231
|
-
name: "id",
|
|
232
|
-
"in": "path",
|
|
233
|
-
description: "",
|
|
234
|
-
deprecated: false,
|
|
235
|
-
required: true,
|
|
236
|
-
schema: {
|
|
237
|
-
type: "string"
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
],
|
|
241
|
-
tags: [
|
|
242
|
-
"Upload - File"
|
|
243
|
-
],
|
|
244
|
-
responses: {
|
|
245
|
-
"200": {
|
|
246
|
-
description: "Delete a file",
|
|
247
|
-
content: {
|
|
248
|
-
"application/json": {
|
|
249
|
-
schema: {
|
|
250
|
-
$ref: "#/components/schemas/UploadFile"
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
var components = {
|
|
260
|
-
schemas: {
|
|
261
|
-
UploadFile: {
|
|
262
|
-
properties: {
|
|
263
|
-
id: {
|
|
264
|
-
type: "number"
|
|
265
|
-
},
|
|
266
|
-
name: {
|
|
267
|
-
type: "string"
|
|
268
|
-
},
|
|
269
|
-
alternativeText: {
|
|
270
|
-
type: "string"
|
|
271
|
-
},
|
|
272
|
-
caption: {
|
|
273
|
-
type: "string"
|
|
274
|
-
},
|
|
275
|
-
width: {
|
|
276
|
-
type: "number",
|
|
277
|
-
format: "integer"
|
|
278
|
-
},
|
|
279
|
-
height: {
|
|
280
|
-
type: "number",
|
|
281
|
-
format: "integer"
|
|
282
|
-
},
|
|
283
|
-
formats: {
|
|
284
|
-
type: "number"
|
|
285
|
-
},
|
|
286
|
-
hash: {
|
|
287
|
-
type: "string"
|
|
288
|
-
},
|
|
289
|
-
ext: {
|
|
290
|
-
type: "string"
|
|
291
|
-
},
|
|
292
|
-
mime: {
|
|
293
|
-
type: "string"
|
|
294
|
-
},
|
|
295
|
-
size: {
|
|
296
|
-
type: "number",
|
|
297
|
-
format: "double"
|
|
298
|
-
},
|
|
299
|
-
url: {
|
|
300
|
-
type: "string"
|
|
301
|
-
},
|
|
302
|
-
previewUrl: {
|
|
303
|
-
type: "string"
|
|
304
|
-
},
|
|
305
|
-
provider: {
|
|
306
|
-
type: "string"
|
|
307
|
-
},
|
|
308
|
-
provider_metadata: {
|
|
309
|
-
type: "object"
|
|
310
|
-
},
|
|
311
|
-
createdAt: {
|
|
312
|
-
type: "string",
|
|
313
|
-
format: "date-time"
|
|
314
|
-
},
|
|
315
|
-
updatedAt: {
|
|
316
|
-
type: "string",
|
|
317
|
-
format: "date-time"
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
};
|
|
323
|
-
var spec = {
|
|
324
|
-
paths: paths,
|
|
325
|
-
components: components
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
const { PayloadTooLargeError } = errors;
|
|
329
|
-
const { bytesToHumanReadable, kbytesToBytes } = file$2;
|
|
330
|
-
/**
|
|
331
|
-
* Register upload plugin
|
|
332
|
-
*/ async function register({ strapi }) {
|
|
333
|
-
strapi.plugin('upload').provider = createProvider(strapi.config.get('plugin::upload'));
|
|
334
|
-
await registerUploadMiddleware({
|
|
335
|
-
strapi
|
|
336
|
-
});
|
|
337
|
-
if (strapi.plugin('graphql')) {
|
|
338
|
-
const { installGraphqlExtension } = await import('./graphql-K9HaGS9d.mjs');
|
|
339
|
-
installGraphqlExtension({
|
|
340
|
-
strapi
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
if (strapi.plugin('documentation')) {
|
|
344
|
-
strapi.plugin('documentation').service('override').registerOverride(spec, {
|
|
345
|
-
pluginOrigin: 'upload',
|
|
346
|
-
excludeFromGeneration: [
|
|
347
|
-
'upload'
|
|
348
|
-
]
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
const createProvider = (config)=>{
|
|
353
|
-
const { providerOptions, actionOptions = {} } = config;
|
|
354
|
-
const providerName = _.toLower(config.provider);
|
|
355
|
-
let provider;
|
|
356
|
-
let modulePath;
|
|
357
|
-
try {
|
|
358
|
-
modulePath = require.resolve(`@strapi/provider-upload-${providerName}`);
|
|
359
|
-
} catch (error) {
|
|
360
|
-
if (typeof error === 'object' && error !== null && 'code' in error && error.code === 'MODULE_NOT_FOUND') {
|
|
361
|
-
modulePath = providerName;
|
|
362
|
-
} else {
|
|
363
|
-
throw error;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
try {
|
|
367
|
-
provider = require(modulePath);
|
|
368
|
-
} catch (err) {
|
|
369
|
-
const newError = new Error(`Could not load upload provider "${providerName}".`);
|
|
370
|
-
if (err instanceof Error) {
|
|
371
|
-
newError.stack = err.stack;
|
|
372
|
-
}
|
|
373
|
-
throw newError;
|
|
374
|
-
}
|
|
375
|
-
const providerInstance = provider.init(providerOptions);
|
|
376
|
-
if (!providerInstance.delete) {
|
|
377
|
-
throw new Error(`The upload provider "${providerName}" doesn't implement the delete method.`);
|
|
378
|
-
}
|
|
379
|
-
if (!providerInstance.upload && !providerInstance.uploadStream) {
|
|
380
|
-
throw new Error(`The upload provider "${providerName}" doesn't implement the uploadStream nor the upload method.`);
|
|
381
|
-
}
|
|
382
|
-
if (!providerInstance.uploadStream) {
|
|
383
|
-
process.emitWarning(`The upload provider "${providerName}" doesn't implement the uploadStream function. Strapi will fallback on the upload method. Some performance issues may occur.`);
|
|
384
|
-
}
|
|
385
|
-
const wrappedProvider = _.mapValues(providerInstance, (method, methodName)=>{
|
|
386
|
-
return async (file, options = actionOptions[methodName])=>providerInstance[methodName](file, options);
|
|
387
|
-
});
|
|
388
|
-
return Object.assign(Object.create(baseProvider), wrappedProvider);
|
|
389
|
-
};
|
|
390
|
-
const baseProvider = {
|
|
391
|
-
extend (obj) {
|
|
392
|
-
Object.assign(this, obj);
|
|
393
|
-
},
|
|
394
|
-
checkFileSize (file, { sizeLimit }) {
|
|
395
|
-
if (sizeLimit && kbytesToBytes(file.size) > sizeLimit) {
|
|
396
|
-
throw new PayloadTooLargeError(`${file.originalFilename} exceeds size limit of ${bytesToHumanReadable(sizeLimit)}.`);
|
|
397
|
-
}
|
|
398
|
-
},
|
|
399
|
-
getSignedUrl (file) {
|
|
400
|
-
return file;
|
|
401
|
-
},
|
|
402
|
-
isPrivate () {
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
const getService = (name)=>{
|
|
408
|
-
return strapi.plugin('upload').service(name);
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
const ACTIONS = {
|
|
412
|
-
read: 'plugin::upload.read',
|
|
413
|
-
readSettings: 'plugin::upload.settings.read',
|
|
414
|
-
create: 'plugin::upload.assets.create',
|
|
415
|
-
update: 'plugin::upload.assets.update',
|
|
416
|
-
download: 'plugin::upload.assets.download',
|
|
417
|
-
copyLink: 'plugin::upload.assets.copy-link',
|
|
418
|
-
configureView: 'plugin::upload.configure-view'
|
|
419
|
-
};
|
|
420
|
-
const ALLOWED_SORT_STRINGS = [
|
|
421
|
-
'createdAt:DESC',
|
|
422
|
-
'createdAt:ASC',
|
|
423
|
-
'name:ASC',
|
|
424
|
-
'name:DESC',
|
|
425
|
-
'updatedAt:DESC',
|
|
426
|
-
'updatedAt:ASC'
|
|
427
|
-
];
|
|
428
|
-
const ALLOWED_WEBHOOK_EVENTS = {
|
|
429
|
-
MEDIA_CREATE: 'media.create',
|
|
430
|
-
MEDIA_UPDATE: 'media.update',
|
|
431
|
-
MEDIA_DELETE: 'media.delete'
|
|
432
|
-
};
|
|
433
|
-
const FOLDER_MODEL_UID = 'plugin::upload.folder';
|
|
434
|
-
const FILE_MODEL_UID = 'plugin::upload.file';
|
|
435
|
-
const API_UPLOAD_FOLDER_BASE_NAME = 'API Uploads';
|
|
436
|
-
|
|
437
|
-
async function bootstrap({ strapi: strapi1 }) {
|
|
438
|
-
const defaultConfig = {
|
|
439
|
-
settings: {
|
|
440
|
-
sizeOptimization: true,
|
|
441
|
-
responsiveDimensions: true,
|
|
442
|
-
autoOrientation: false
|
|
443
|
-
},
|
|
444
|
-
view_configuration: {
|
|
445
|
-
pageSize: 10,
|
|
446
|
-
sort: ALLOWED_SORT_STRINGS[0]
|
|
447
|
-
}
|
|
448
|
-
};
|
|
449
|
-
for (const [key, defaultValue] of Object.entries(defaultConfig)){
|
|
450
|
-
// set plugin store
|
|
451
|
-
const configurator = strapi1.store({
|
|
452
|
-
type: 'plugin',
|
|
453
|
-
name: 'upload',
|
|
454
|
-
key
|
|
455
|
-
});
|
|
456
|
-
const config = await configurator.get({});
|
|
457
|
-
if (config && Object.keys(defaultValue).every((key)=>Object.prototype.hasOwnProperty.call(config, key))) {
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
// if the config does not exist or does not have all the required keys
|
|
461
|
-
// set from the defaultValue ensuring all required settings are present
|
|
462
|
-
await configurator.set({
|
|
463
|
-
value: Object.assign(defaultValue, config || {})
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
await registerPermissionActions();
|
|
467
|
-
await registerWebhookEvents();
|
|
468
|
-
await getService('weeklyMetrics').registerCron();
|
|
469
|
-
getService('metrics').sendUploadPluginMetrics();
|
|
470
|
-
getService('extensions').signFileUrlsOnDocumentService();
|
|
471
|
-
}
|
|
472
|
-
const registerWebhookEvents = async ()=>Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value])=>{
|
|
473
|
-
strapi.get('webhookStore').addAllowedEvent(key, value);
|
|
474
|
-
});
|
|
475
|
-
const registerPermissionActions = async ()=>{
|
|
476
|
-
const actions = [
|
|
477
|
-
{
|
|
478
|
-
section: 'plugins',
|
|
479
|
-
displayName: 'Access the Media Library',
|
|
480
|
-
uid: 'read',
|
|
481
|
-
pluginName: 'upload'
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
section: 'plugins',
|
|
485
|
-
displayName: 'Create (upload)',
|
|
486
|
-
uid: 'assets.create',
|
|
487
|
-
subCategory: 'assets',
|
|
488
|
-
pluginName: 'upload'
|
|
489
|
-
},
|
|
490
|
-
{
|
|
491
|
-
section: 'plugins',
|
|
492
|
-
displayName: 'Update (crop, details, replace) + delete',
|
|
493
|
-
uid: 'assets.update',
|
|
494
|
-
subCategory: 'assets',
|
|
495
|
-
pluginName: 'upload'
|
|
496
|
-
},
|
|
497
|
-
{
|
|
498
|
-
section: 'plugins',
|
|
499
|
-
displayName: 'Download',
|
|
500
|
-
uid: 'assets.download',
|
|
501
|
-
subCategory: 'assets',
|
|
502
|
-
pluginName: 'upload'
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
section: 'plugins',
|
|
506
|
-
displayName: 'Copy link',
|
|
507
|
-
uid: 'assets.copy-link',
|
|
508
|
-
subCategory: 'assets',
|
|
509
|
-
pluginName: 'upload'
|
|
510
|
-
},
|
|
511
|
-
{
|
|
512
|
-
section: 'plugins',
|
|
513
|
-
displayName: 'Configure view',
|
|
514
|
-
uid: 'configure-view',
|
|
515
|
-
pluginName: 'upload'
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
section: 'settings',
|
|
519
|
-
displayName: 'Access the Media Library settings page',
|
|
520
|
-
uid: 'settings.read',
|
|
521
|
-
category: 'media library',
|
|
522
|
-
pluginName: 'upload'
|
|
523
|
-
}
|
|
524
|
-
];
|
|
525
|
-
await strapi.service('admin::permission').actionProvider.registerMany(actions);
|
|
526
|
-
};
|
|
527
|
-
|
|
528
|
-
var file$1 = {
|
|
529
|
-
schema: {
|
|
530
|
-
collectionName: 'files',
|
|
531
|
-
info: {
|
|
532
|
-
singularName: 'file',
|
|
533
|
-
pluralName: 'files',
|
|
534
|
-
displayName: 'File',
|
|
535
|
-
description: ''
|
|
536
|
-
},
|
|
537
|
-
options: {},
|
|
538
|
-
pluginOptions: {
|
|
539
|
-
'content-manager': {
|
|
540
|
-
visible: false
|
|
541
|
-
},
|
|
542
|
-
'content-type-builder': {
|
|
543
|
-
visible: false
|
|
544
|
-
}
|
|
545
|
-
},
|
|
546
|
-
attributes: {
|
|
547
|
-
name: {
|
|
548
|
-
type: 'string',
|
|
549
|
-
configurable: false,
|
|
550
|
-
required: true
|
|
551
|
-
},
|
|
552
|
-
alternativeText: {
|
|
553
|
-
type: 'string',
|
|
554
|
-
configurable: false
|
|
555
|
-
},
|
|
556
|
-
caption: {
|
|
557
|
-
type: 'string',
|
|
558
|
-
configurable: false
|
|
559
|
-
},
|
|
560
|
-
width: {
|
|
561
|
-
type: 'integer',
|
|
562
|
-
configurable: false
|
|
563
|
-
},
|
|
564
|
-
height: {
|
|
565
|
-
type: 'integer',
|
|
566
|
-
configurable: false
|
|
567
|
-
},
|
|
568
|
-
formats: {
|
|
569
|
-
type: 'json',
|
|
570
|
-
configurable: false
|
|
571
|
-
},
|
|
572
|
-
hash: {
|
|
573
|
-
type: 'string',
|
|
574
|
-
configurable: false,
|
|
575
|
-
required: true
|
|
576
|
-
},
|
|
577
|
-
ext: {
|
|
578
|
-
type: 'string',
|
|
579
|
-
configurable: false
|
|
580
|
-
},
|
|
581
|
-
mime: {
|
|
582
|
-
type: 'string',
|
|
583
|
-
configurable: false,
|
|
584
|
-
required: true
|
|
585
|
-
},
|
|
586
|
-
size: {
|
|
587
|
-
type: 'decimal',
|
|
588
|
-
configurable: false,
|
|
589
|
-
required: true
|
|
590
|
-
},
|
|
591
|
-
url: {
|
|
592
|
-
type: 'string',
|
|
593
|
-
configurable: false,
|
|
594
|
-
required: true
|
|
595
|
-
},
|
|
596
|
-
previewUrl: {
|
|
597
|
-
type: 'string',
|
|
598
|
-
configurable: false
|
|
599
|
-
},
|
|
600
|
-
provider: {
|
|
601
|
-
type: 'string',
|
|
602
|
-
configurable: false,
|
|
603
|
-
required: true
|
|
604
|
-
},
|
|
605
|
-
provider_metadata: {
|
|
606
|
-
type: 'json',
|
|
607
|
-
configurable: false
|
|
608
|
-
},
|
|
609
|
-
related: {
|
|
610
|
-
type: 'relation',
|
|
611
|
-
relation: 'morphToMany',
|
|
612
|
-
configurable: false
|
|
613
|
-
},
|
|
614
|
-
folder: {
|
|
615
|
-
type: 'relation',
|
|
616
|
-
relation: 'manyToOne',
|
|
617
|
-
target: FOLDER_MODEL_UID,
|
|
618
|
-
inversedBy: 'files',
|
|
619
|
-
private: true
|
|
620
|
-
},
|
|
621
|
-
folderPath: {
|
|
622
|
-
type: 'string',
|
|
623
|
-
minLength: 1,
|
|
624
|
-
required: true,
|
|
625
|
-
private: true,
|
|
626
|
-
searchable: false
|
|
627
|
-
}
|
|
628
|
-
},
|
|
629
|
-
// experimental feature:
|
|
630
|
-
indexes: [
|
|
631
|
-
{
|
|
632
|
-
name: 'upload_files_folder_path_index',
|
|
633
|
-
columns: [
|
|
634
|
-
'folder_path'
|
|
635
|
-
],
|
|
636
|
-
type: null
|
|
637
|
-
},
|
|
638
|
-
{
|
|
639
|
-
name: `upload_files_created_at_index`,
|
|
640
|
-
columns: [
|
|
641
|
-
'created_at'
|
|
642
|
-
],
|
|
643
|
-
type: null
|
|
644
|
-
},
|
|
645
|
-
{
|
|
646
|
-
name: `upload_files_updated_at_index`,
|
|
647
|
-
columns: [
|
|
648
|
-
'updated_at'
|
|
649
|
-
],
|
|
650
|
-
type: null
|
|
651
|
-
},
|
|
652
|
-
{
|
|
653
|
-
name: `upload_files_name_index`,
|
|
654
|
-
columns: [
|
|
655
|
-
'name'
|
|
656
|
-
],
|
|
657
|
-
type: null
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
name: `upload_files_size_index`,
|
|
661
|
-
columns: [
|
|
662
|
-
'size'
|
|
663
|
-
],
|
|
664
|
-
type: null
|
|
665
|
-
},
|
|
666
|
-
{
|
|
667
|
-
name: `upload_files_ext_index`,
|
|
668
|
-
columns: [
|
|
669
|
-
'ext'
|
|
670
|
-
],
|
|
671
|
-
type: null
|
|
672
|
-
}
|
|
673
|
-
]
|
|
674
|
-
}
|
|
675
|
-
};
|
|
676
|
-
|
|
677
|
-
var folder$1 = {
|
|
678
|
-
schema: {
|
|
679
|
-
collectionName: 'upload_folders',
|
|
680
|
-
info: {
|
|
681
|
-
singularName: 'folder',
|
|
682
|
-
pluralName: 'folders',
|
|
683
|
-
displayName: 'Folder'
|
|
684
|
-
},
|
|
685
|
-
options: {},
|
|
686
|
-
pluginOptions: {
|
|
687
|
-
'content-manager': {
|
|
688
|
-
visible: false
|
|
689
|
-
},
|
|
690
|
-
'content-type-builder': {
|
|
691
|
-
visible: false
|
|
692
|
-
}
|
|
693
|
-
},
|
|
694
|
-
attributes: {
|
|
695
|
-
name: {
|
|
696
|
-
type: 'string',
|
|
697
|
-
minLength: 1,
|
|
698
|
-
required: true
|
|
699
|
-
},
|
|
700
|
-
pathId: {
|
|
701
|
-
type: 'integer',
|
|
702
|
-
unique: true,
|
|
703
|
-
required: true
|
|
704
|
-
},
|
|
705
|
-
parent: {
|
|
706
|
-
type: 'relation',
|
|
707
|
-
relation: 'manyToOne',
|
|
708
|
-
target: FOLDER_MODEL_UID,
|
|
709
|
-
inversedBy: 'children'
|
|
710
|
-
},
|
|
711
|
-
children: {
|
|
712
|
-
type: 'relation',
|
|
713
|
-
relation: 'oneToMany',
|
|
714
|
-
target: FOLDER_MODEL_UID,
|
|
715
|
-
mappedBy: 'parent'
|
|
716
|
-
},
|
|
717
|
-
files: {
|
|
718
|
-
type: 'relation',
|
|
719
|
-
relation: 'oneToMany',
|
|
720
|
-
target: FILE_MODEL_UID,
|
|
721
|
-
mappedBy: 'folder'
|
|
722
|
-
},
|
|
723
|
-
path: {
|
|
724
|
-
type: 'string',
|
|
725
|
-
minLength: 1,
|
|
726
|
-
required: true
|
|
727
|
-
}
|
|
728
|
-
},
|
|
729
|
-
// experimental feature:
|
|
730
|
-
indexes: [
|
|
731
|
-
{
|
|
732
|
-
name: 'upload_folders_path_id_index',
|
|
733
|
-
columns: [
|
|
734
|
-
'path_id'
|
|
735
|
-
],
|
|
736
|
-
type: 'unique'
|
|
737
|
-
},
|
|
738
|
-
{
|
|
739
|
-
name: 'upload_folders_path_index',
|
|
740
|
-
columns: [
|
|
741
|
-
'path'
|
|
742
|
-
],
|
|
743
|
-
type: 'unique'
|
|
744
|
-
}
|
|
745
|
-
]
|
|
746
|
-
}
|
|
747
|
-
};
|
|
748
|
-
|
|
749
|
-
const contentTypes = {
|
|
750
|
-
file: file$1,
|
|
751
|
-
folder: folder$1
|
|
752
|
-
};
|
|
753
|
-
|
|
754
|
-
var provider = (({ strapi })=>({
|
|
755
|
-
async checkFileSize (file) {
|
|
756
|
-
const { sizeLimit } = strapi.config.get('plugin::upload');
|
|
757
|
-
await strapi.plugin('upload').provider.checkFileSize(file, {
|
|
758
|
-
sizeLimit
|
|
759
|
-
});
|
|
760
|
-
},
|
|
761
|
-
async upload (file) {
|
|
762
|
-
if (isFunction(strapi.plugin('upload').provider.uploadStream)) {
|
|
763
|
-
file.stream = file.getStream();
|
|
764
|
-
await strapi.plugin('upload').provider.uploadStream(file);
|
|
765
|
-
delete file.stream;
|
|
766
|
-
if ('filepath' in file) {
|
|
767
|
-
delete file.filepath;
|
|
768
|
-
}
|
|
769
|
-
} else {
|
|
770
|
-
file.buffer = await file$2.streamToBuffer(file.getStream());
|
|
771
|
-
await strapi.plugin('upload').provider.upload(file);
|
|
772
|
-
delete file.buffer;
|
|
773
|
-
if ('filepath' in file) {
|
|
774
|
-
delete file.filepath;
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
}));
|
|
779
|
-
|
|
780
|
-
const { UPDATED_BY_ATTRIBUTE, CREATED_BY_ATTRIBUTE } = contentTypes$1.constants;
|
|
781
|
-
const { MEDIA_CREATE, MEDIA_UPDATE, MEDIA_DELETE } = ALLOWED_WEBHOOK_EVENTS;
|
|
782
|
-
const { ApplicationError, NotFoundError } = errors;
|
|
783
|
-
const { bytesToKbytes: bytesToKbytes$1 } = file$2;
|
|
784
|
-
var upload = (({ strapi })=>{
|
|
785
|
-
const randomSuffix = ()=>crypto.randomBytes(5).toString('hex');
|
|
786
|
-
const generateFileName = (name)=>{
|
|
787
|
-
const baseName = strings.nameToSlug(name, {
|
|
788
|
-
separator: '_',
|
|
789
|
-
lowercase: false
|
|
790
|
-
});
|
|
791
|
-
return `${baseName}_${randomSuffix()}`;
|
|
792
|
-
};
|
|
793
|
-
const sendMediaMetrics = (data)=>{
|
|
794
|
-
if (_.has(data, 'caption') && !_.isEmpty(data.caption)) {
|
|
795
|
-
strapi.telemetry.send('didSaveMediaWithCaption');
|
|
796
|
-
}
|
|
797
|
-
if (_.has(data, 'alternativeText') && !_.isEmpty(data.alternativeText)) {
|
|
798
|
-
strapi.telemetry.send('didSaveMediaWithAlternativeText');
|
|
799
|
-
}
|
|
800
|
-
};
|
|
801
|
-
const createAndAssignTmpWorkingDirectoryToFiles = async (files)=>{
|
|
802
|
-
const tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-upload-'));
|
|
803
|
-
if (Array.isArray(files)) {
|
|
804
|
-
files.forEach((file)=>{
|
|
805
|
-
file.tmpWorkingDirectory = tmpWorkingDirectory;
|
|
806
|
-
});
|
|
807
|
-
} else {
|
|
808
|
-
files.tmpWorkingDirectory = tmpWorkingDirectory;
|
|
809
|
-
}
|
|
810
|
-
return tmpWorkingDirectory;
|
|
811
|
-
};
|
|
812
|
-
function filenameReservedRegex() {
|
|
813
|
-
// eslint-disable-next-line no-control-regex
|
|
814
|
-
return /[<>:"/\\|?*\u0000-\u001F]/g;
|
|
815
|
-
}
|
|
816
|
-
function windowsReservedNameRegex() {
|
|
817
|
-
return /^(con|prn|aux|nul|com\d|lpt\d)$/i;
|
|
818
|
-
}
|
|
819
|
-
/**
|
|
820
|
-
* Copied from https://github.com/sindresorhus/valid-filename package
|
|
821
|
-
*/ function isValidFilename(string) {
|
|
822
|
-
if (!string || string.length > 255) {
|
|
823
|
-
return false;
|
|
824
|
-
}
|
|
825
|
-
if (filenameReservedRegex().test(string) || windowsReservedNameRegex().test(string)) {
|
|
826
|
-
return false;
|
|
827
|
-
}
|
|
828
|
-
if (string === '.' || string === '..') {
|
|
829
|
-
return false;
|
|
830
|
-
}
|
|
831
|
-
return true;
|
|
832
|
-
}
|
|
833
|
-
async function emitEvent(event, data) {
|
|
834
|
-
const modelDef = strapi.getModel(FILE_MODEL_UID);
|
|
835
|
-
const sanitizedData = await sanitize.sanitizers.defaultSanitizeOutput({
|
|
836
|
-
schema: modelDef,
|
|
837
|
-
getModel (uid) {
|
|
838
|
-
return strapi.getModel(uid);
|
|
839
|
-
}
|
|
840
|
-
}, data);
|
|
841
|
-
strapi.eventHub.emit(event, {
|
|
842
|
-
media: sanitizedData
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
async function formatFileInfo({ filename, type, size }, fileInfo = {}, metas = {}) {
|
|
846
|
-
const fileService = getService('file');
|
|
847
|
-
if (!isValidFilename(filename)) {
|
|
848
|
-
throw new ApplicationError('File name contains invalid characters');
|
|
849
|
-
}
|
|
850
|
-
let ext = path.extname(filename);
|
|
851
|
-
if (!ext) {
|
|
852
|
-
ext = `.${extension(type)}`;
|
|
853
|
-
}
|
|
854
|
-
const usedName = (fileInfo.name || filename).normalize();
|
|
855
|
-
const basename = path.basename(usedName, ext);
|
|
856
|
-
// Prevent null characters in file name
|
|
857
|
-
if (!isValidFilename(filename)) {
|
|
858
|
-
throw new ApplicationError('File name contains invalid characters');
|
|
859
|
-
}
|
|
860
|
-
const entity = {
|
|
861
|
-
name: usedName,
|
|
862
|
-
alternativeText: fileInfo.alternativeText,
|
|
863
|
-
caption: fileInfo.caption,
|
|
864
|
-
folder: fileInfo.folder,
|
|
865
|
-
folderPath: await fileService.getFolderPath(fileInfo.folder),
|
|
866
|
-
hash: generateFileName(basename),
|
|
867
|
-
ext,
|
|
868
|
-
mime: type,
|
|
869
|
-
size: bytesToKbytes$1(size),
|
|
870
|
-
sizeInBytes: size
|
|
871
|
-
};
|
|
872
|
-
const { refId, ref, field } = metas;
|
|
873
|
-
if (refId && ref && field) {
|
|
874
|
-
entity.related = [
|
|
875
|
-
{
|
|
876
|
-
id: refId,
|
|
877
|
-
__type: ref,
|
|
878
|
-
__pivot: {
|
|
879
|
-
field
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
];
|
|
883
|
-
}
|
|
884
|
-
if (metas.path) {
|
|
885
|
-
entity.path = metas.path;
|
|
886
|
-
}
|
|
887
|
-
if (metas.tmpWorkingDirectory) {
|
|
888
|
-
entity.tmpWorkingDirectory = metas.tmpWorkingDirectory;
|
|
889
|
-
}
|
|
890
|
-
return entity;
|
|
891
|
-
}
|
|
892
|
-
async function enhanceAndValidateFile(file, fileInfo, metas) {
|
|
893
|
-
const currentFile = await formatFileInfo({
|
|
894
|
-
filename: file.originalFilename ?? 'unamed',
|
|
895
|
-
type: file.mimetype ?? 'application/octet-stream',
|
|
896
|
-
size: file.size
|
|
897
|
-
}, fileInfo, {
|
|
898
|
-
...metas,
|
|
899
|
-
tmpWorkingDirectory: file.tmpWorkingDirectory
|
|
900
|
-
});
|
|
901
|
-
currentFile.filepath = file.filepath;
|
|
902
|
-
currentFile.getStream = ()=>fs.createReadStream(file.filepath);
|
|
903
|
-
const { optimize, isImage, isFaultyImage, isOptimizableImage } = strapi.plugin('upload').service('image-manipulation');
|
|
904
|
-
if (await isImage(currentFile)) {
|
|
905
|
-
if (await isFaultyImage(currentFile)) {
|
|
906
|
-
throw new ApplicationError('File is not a valid image');
|
|
907
|
-
}
|
|
908
|
-
if (await isOptimizableImage(currentFile)) {
|
|
909
|
-
return optimize(currentFile);
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
return currentFile;
|
|
913
|
-
}
|
|
914
|
-
async function upload({ data, files }, opts) {
|
|
915
|
-
const { user } = opts ?? {};
|
|
916
|
-
// create temporary folder to store files for stream manipulation
|
|
917
|
-
const tmpWorkingDirectory = await createAndAssignTmpWorkingDirectoryToFiles(files);
|
|
918
|
-
let uploadedFiles = [];
|
|
919
|
-
try {
|
|
920
|
-
const { fileInfo, ...metas } = data;
|
|
921
|
-
const fileArray = Array.isArray(files) ? files : [
|
|
922
|
-
files
|
|
923
|
-
];
|
|
924
|
-
const fileInfoArray = Array.isArray(fileInfo) ? fileInfo : [
|
|
925
|
-
fileInfo
|
|
926
|
-
];
|
|
927
|
-
const doUpload = async (file, fileInfo)=>{
|
|
928
|
-
const fileData = await enhanceAndValidateFile(file, fileInfo, metas);
|
|
929
|
-
return uploadFileAndPersist(fileData, {
|
|
930
|
-
user
|
|
931
|
-
});
|
|
932
|
-
};
|
|
933
|
-
uploadedFiles = await Promise.all(fileArray.map((file, idx)=>doUpload(file, fileInfoArray[idx] || {})));
|
|
934
|
-
} finally{
|
|
935
|
-
// delete temporary folder
|
|
936
|
-
await fse.remove(tmpWorkingDirectory);
|
|
937
|
-
}
|
|
938
|
-
return uploadedFiles;
|
|
939
|
-
}
|
|
940
|
-
/**
|
|
941
|
-
* When uploading an image, an additional thumbnail is generated.
|
|
942
|
-
* Also, if there are responsive formats defined, another set of images will be generated too.
|
|
943
|
-
*
|
|
944
|
-
* @param {*} fileData
|
|
945
|
-
*/ async function uploadImage(fileData) {
|
|
946
|
-
const { getDimensions, generateThumbnail, generateResponsiveFormats, isResizableImage } = getService('image-manipulation');
|
|
947
|
-
// Store width and height of the original image
|
|
948
|
-
const { width, height } = await getDimensions(fileData);
|
|
949
|
-
// Make sure this is assigned before calling any upload
|
|
950
|
-
// That way it can mutate the width and height
|
|
951
|
-
_.assign(fileData, {
|
|
952
|
-
width,
|
|
953
|
-
height
|
|
954
|
-
});
|
|
955
|
-
// For performance reasons, all uploads are wrapped in a single Promise.all
|
|
956
|
-
const uploadThumbnail = async (thumbnailFile)=>{
|
|
957
|
-
await getService('provider').upload(thumbnailFile);
|
|
958
|
-
_.set(fileData, 'formats.thumbnail', thumbnailFile);
|
|
959
|
-
};
|
|
960
|
-
// Generate thumbnail and responsive formats
|
|
961
|
-
const uploadResponsiveFormat = async (format)=>{
|
|
962
|
-
const { key, file } = format;
|
|
963
|
-
await getService('provider').upload(file);
|
|
964
|
-
_.set(fileData, [
|
|
965
|
-
'formats',
|
|
966
|
-
key
|
|
967
|
-
], file);
|
|
968
|
-
};
|
|
969
|
-
const uploadPromises = [];
|
|
970
|
-
// Upload image
|
|
971
|
-
uploadPromises.push(getService('provider').upload(fileData));
|
|
972
|
-
// Generate & Upload thumbnail and responsive formats
|
|
973
|
-
if (await isResizableImage(fileData)) {
|
|
974
|
-
const thumbnailFile = await generateThumbnail(fileData);
|
|
975
|
-
if (thumbnailFile) {
|
|
976
|
-
uploadPromises.push(uploadThumbnail(thumbnailFile));
|
|
977
|
-
}
|
|
978
|
-
const formats = await generateResponsiveFormats(fileData);
|
|
979
|
-
if (Array.isArray(formats) && formats.length > 0) {
|
|
980
|
-
for (const format of formats){
|
|
981
|
-
// eslint-disable-next-line no-continue
|
|
982
|
-
if (!format) continue;
|
|
983
|
-
uploadPromises.push(uploadResponsiveFormat(format));
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
// Wait for all uploads to finish
|
|
988
|
-
await Promise.all(uploadPromises);
|
|
989
|
-
}
|
|
990
|
-
/**
|
|
991
|
-
* Upload a file. If it is an image it will generate a thumbnail
|
|
992
|
-
* and responsive formats (if enabled).
|
|
993
|
-
*/ async function uploadFileAndPersist(fileData, opts) {
|
|
994
|
-
const { user } = opts ?? {};
|
|
995
|
-
const config = strapi.config.get('plugin::upload');
|
|
996
|
-
const { isImage } = getService('image-manipulation');
|
|
997
|
-
await getService('provider').checkFileSize(fileData);
|
|
998
|
-
if (await isImage(fileData)) {
|
|
999
|
-
await uploadImage(fileData);
|
|
1000
|
-
} else {
|
|
1001
|
-
await getService('provider').upload(fileData);
|
|
1002
|
-
}
|
|
1003
|
-
_.set(fileData, 'provider', config.provider);
|
|
1004
|
-
// Persist file(s)
|
|
1005
|
-
return add(fileData, {
|
|
1006
|
-
user
|
|
1007
|
-
});
|
|
1008
|
-
}
|
|
1009
|
-
async function updateFileInfo(id, { name, alternativeText, caption, folder }, opts) {
|
|
1010
|
-
const { user } = opts ?? {};
|
|
1011
|
-
const dbFile = await findOne(id);
|
|
1012
|
-
if (!dbFile) {
|
|
1013
|
-
throw new NotFoundError();
|
|
1014
|
-
}
|
|
1015
|
-
const fileService = getService('file');
|
|
1016
|
-
const newName = _.isNil(name) ? dbFile.name : name;
|
|
1017
|
-
const newInfos = {
|
|
1018
|
-
name: newName,
|
|
1019
|
-
alternativeText: _.isNil(alternativeText) ? dbFile.alternativeText : alternativeText,
|
|
1020
|
-
caption: _.isNil(caption) ? dbFile.caption : caption,
|
|
1021
|
-
folder: _.isUndefined(folder) ? dbFile.folder : folder,
|
|
1022
|
-
folderPath: _.isUndefined(folder) ? dbFile.path : await fileService.getFolderPath(folder)
|
|
1023
|
-
};
|
|
1024
|
-
return update(id, newInfos, {
|
|
1025
|
-
user
|
|
1026
|
-
});
|
|
1027
|
-
}
|
|
1028
|
-
async function replace(id, { data, file }, opts) {
|
|
1029
|
-
const { user } = opts ?? {};
|
|
1030
|
-
const config = strapi.config.get('plugin::upload');
|
|
1031
|
-
const { isImage } = getService('image-manipulation');
|
|
1032
|
-
const dbFile = await findOne(id);
|
|
1033
|
-
if (!dbFile) {
|
|
1034
|
-
throw new NotFoundError();
|
|
1035
|
-
}
|
|
1036
|
-
// create temporary folder to store files for stream manipulation
|
|
1037
|
-
const tmpWorkingDirectory = await createAndAssignTmpWorkingDirectoryToFiles(file);
|
|
1038
|
-
let fileData;
|
|
1039
|
-
try {
|
|
1040
|
-
const { fileInfo } = data;
|
|
1041
|
-
fileData = await enhanceAndValidateFile(file, fileInfo);
|
|
1042
|
-
// keep a constant hash and extension so the file url doesn't change when the file is replaced
|
|
1043
|
-
_.assign(fileData, {
|
|
1044
|
-
hash: dbFile.hash,
|
|
1045
|
-
ext: dbFile.ext
|
|
1046
|
-
});
|
|
1047
|
-
// execute delete function of the provider
|
|
1048
|
-
if (dbFile.provider === config.provider) {
|
|
1049
|
-
await strapi.plugin('upload').provider.delete(dbFile);
|
|
1050
|
-
if (dbFile.formats) {
|
|
1051
|
-
await Promise.all(Object.keys(dbFile.formats).map((key)=>{
|
|
1052
|
-
return strapi.plugin('upload').provider.delete(dbFile.formats[key]);
|
|
1053
|
-
}));
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
// clear old formats
|
|
1057
|
-
_.set(fileData, 'formats', {});
|
|
1058
|
-
if (await isImage(fileData)) {
|
|
1059
|
-
await uploadImage(fileData);
|
|
1060
|
-
} else {
|
|
1061
|
-
await getService('provider').upload(fileData);
|
|
1062
|
-
}
|
|
1063
|
-
_.set(fileData, 'provider', config.provider);
|
|
1064
|
-
} finally{
|
|
1065
|
-
// delete temporary folder
|
|
1066
|
-
await fse.remove(tmpWorkingDirectory);
|
|
1067
|
-
}
|
|
1068
|
-
return update(id, fileData, {
|
|
1069
|
-
user
|
|
1070
|
-
});
|
|
1071
|
-
}
|
|
1072
|
-
async function update(id, values, opts) {
|
|
1073
|
-
const { user } = opts ?? {};
|
|
1074
|
-
const fileValues = {
|
|
1075
|
-
...values
|
|
1076
|
-
};
|
|
1077
|
-
if (user) {
|
|
1078
|
-
Object.assign(fileValues, {
|
|
1079
|
-
[UPDATED_BY_ATTRIBUTE]: user.id
|
|
1080
|
-
});
|
|
1081
|
-
}
|
|
1082
|
-
sendMediaMetrics(fileValues);
|
|
1083
|
-
const res = await strapi.db.query(FILE_MODEL_UID).update({
|
|
1084
|
-
where: {
|
|
1085
|
-
id
|
|
1086
|
-
},
|
|
1087
|
-
data: fileValues
|
|
1088
|
-
});
|
|
1089
|
-
await emitEvent(MEDIA_UPDATE, res);
|
|
1090
|
-
return res;
|
|
1091
|
-
}
|
|
1092
|
-
async function add(values, opts) {
|
|
1093
|
-
const { user } = opts ?? {};
|
|
1094
|
-
const fileValues = {
|
|
1095
|
-
...values
|
|
1096
|
-
};
|
|
1097
|
-
if (user) {
|
|
1098
|
-
Object.assign(fileValues, {
|
|
1099
|
-
[UPDATED_BY_ATTRIBUTE]: user.id,
|
|
1100
|
-
[CREATED_BY_ATTRIBUTE]: user.id
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
sendMediaMetrics(fileValues);
|
|
1104
|
-
const res = await strapi.db.query(FILE_MODEL_UID).create({
|
|
1105
|
-
data: fileValues
|
|
1106
|
-
});
|
|
1107
|
-
await emitEvent(MEDIA_CREATE, res);
|
|
1108
|
-
return res;
|
|
1109
|
-
}
|
|
1110
|
-
function findOne(id, populate = {}) {
|
|
1111
|
-
const query = strapi.get('query-params').transform(FILE_MODEL_UID, {
|
|
1112
|
-
populate
|
|
1113
|
-
});
|
|
1114
|
-
return strapi.db.query(FILE_MODEL_UID).findOne({
|
|
1115
|
-
where: {
|
|
1116
|
-
id
|
|
1117
|
-
},
|
|
1118
|
-
...query
|
|
1119
|
-
});
|
|
1120
|
-
}
|
|
1121
|
-
function findMany(query = {}) {
|
|
1122
|
-
return strapi.db.query(FILE_MODEL_UID).findMany(strapi.get('query-params').transform(FILE_MODEL_UID, query));
|
|
1123
|
-
}
|
|
1124
|
-
function findPage(query = {}) {
|
|
1125
|
-
return strapi.db.query(FILE_MODEL_UID).findPage(strapi.get('query-params').transform(FILE_MODEL_UID, query));
|
|
1126
|
-
}
|
|
1127
|
-
async function remove(file) {
|
|
1128
|
-
const config = strapi.config.get('plugin::upload');
|
|
1129
|
-
// execute delete function of the provider
|
|
1130
|
-
if (file.provider === config.provider) {
|
|
1131
|
-
await strapi.plugin('upload').provider.delete(file);
|
|
1132
|
-
if (file.formats) {
|
|
1133
|
-
const keys = Object.keys(file.formats);
|
|
1134
|
-
await Promise.all(keys.map((key)=>{
|
|
1135
|
-
return strapi.plugin('upload').provider.delete(file.formats[key]);
|
|
1136
|
-
}));
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
const media = await strapi.db.query(FILE_MODEL_UID).findOne({
|
|
1140
|
-
where: {
|
|
1141
|
-
id: file.id
|
|
1142
|
-
}
|
|
1143
|
-
});
|
|
1144
|
-
await emitEvent(MEDIA_DELETE, media);
|
|
1145
|
-
return strapi.db.query(FILE_MODEL_UID).delete({
|
|
1146
|
-
where: {
|
|
1147
|
-
id: file.id
|
|
1148
|
-
}
|
|
1149
|
-
});
|
|
1150
|
-
}
|
|
1151
|
-
async function getSettings() {
|
|
1152
|
-
const res = await strapi.store({
|
|
1153
|
-
type: 'plugin',
|
|
1154
|
-
name: 'upload',
|
|
1155
|
-
key: 'settings'
|
|
1156
|
-
}).get({});
|
|
1157
|
-
return res;
|
|
1158
|
-
}
|
|
1159
|
-
function setSettings(value) {
|
|
1160
|
-
if (value.responsiveDimensions === true) {
|
|
1161
|
-
strapi.telemetry.send('didEnableResponsiveDimensions');
|
|
1162
|
-
} else {
|
|
1163
|
-
strapi.telemetry.send('didDisableResponsiveDimensions');
|
|
1164
|
-
}
|
|
1165
|
-
return strapi.store({
|
|
1166
|
-
type: 'plugin',
|
|
1167
|
-
name: 'upload',
|
|
1168
|
-
key: 'settings'
|
|
1169
|
-
}).set({
|
|
1170
|
-
value
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
async function getConfiguration() {
|
|
1174
|
-
const res = await strapi.store({
|
|
1175
|
-
type: 'plugin',
|
|
1176
|
-
name: 'upload',
|
|
1177
|
-
key: 'view_configuration'
|
|
1178
|
-
}).get({});
|
|
1179
|
-
return res;
|
|
1180
|
-
}
|
|
1181
|
-
function setConfiguration(value) {
|
|
1182
|
-
return strapi.store({
|
|
1183
|
-
type: 'plugin',
|
|
1184
|
-
name: 'upload',
|
|
1185
|
-
key: 'view_configuration'
|
|
1186
|
-
}).set({
|
|
1187
|
-
value
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
return {
|
|
1191
|
-
formatFileInfo,
|
|
1192
|
-
upload,
|
|
1193
|
-
updateFileInfo,
|
|
1194
|
-
replace,
|
|
1195
|
-
findOne,
|
|
1196
|
-
findMany,
|
|
1197
|
-
findPage,
|
|
1198
|
-
remove,
|
|
1199
|
-
getSettings,
|
|
1200
|
-
setSettings,
|
|
1201
|
-
getConfiguration,
|
|
1202
|
-
setConfiguration,
|
|
1203
|
-
/**
|
|
1204
|
-
* exposed for testing only
|
|
1205
|
-
* @internal
|
|
1206
|
-
*/ _uploadImage: uploadImage
|
|
1207
|
-
};
|
|
1208
|
-
});
|
|
1209
|
-
|
|
1210
|
-
const { bytesToKbytes } = file$2;
|
|
1211
|
-
const FORMATS_TO_RESIZE = [
|
|
1212
|
-
'jpeg',
|
|
1213
|
-
'png',
|
|
1214
|
-
'webp',
|
|
1215
|
-
'tiff',
|
|
1216
|
-
'gif'
|
|
1217
|
-
];
|
|
1218
|
-
const FORMATS_TO_PROCESS = [
|
|
1219
|
-
'jpeg',
|
|
1220
|
-
'png',
|
|
1221
|
-
'webp',
|
|
1222
|
-
'tiff',
|
|
1223
|
-
'svg',
|
|
1224
|
-
'gif',
|
|
1225
|
-
'avif'
|
|
1226
|
-
];
|
|
1227
|
-
const FORMATS_TO_OPTIMIZE = [
|
|
1228
|
-
'jpeg',
|
|
1229
|
-
'png',
|
|
1230
|
-
'webp',
|
|
1231
|
-
'tiff',
|
|
1232
|
-
'avif'
|
|
1233
|
-
];
|
|
1234
|
-
const isOptimizableFormat = (format)=>format !== undefined && FORMATS_TO_OPTIMIZE.includes(format);
|
|
1235
|
-
const writeStreamToFile = (stream, path)=>new Promise((resolve, reject)=>{
|
|
1236
|
-
const writeStream = fs.createWriteStream(path);
|
|
1237
|
-
// Reject promise if there is an error with the provided stream
|
|
1238
|
-
stream.on('error', reject);
|
|
1239
|
-
stream.pipe(writeStream);
|
|
1240
|
-
writeStream.on('close', resolve);
|
|
1241
|
-
writeStream.on('error', reject);
|
|
1242
|
-
});
|
|
1243
|
-
const getMetadata = (file)=>{
|
|
1244
|
-
if (!file.filepath) {
|
|
1245
|
-
return new Promise((resolve, reject)=>{
|
|
1246
|
-
const pipeline = sharp();
|
|
1247
|
-
pipeline.metadata().then(resolve).catch(reject);
|
|
1248
|
-
file.getStream().pipe(pipeline);
|
|
1249
|
-
});
|
|
1250
|
-
}
|
|
1251
|
-
return sharp(file.filepath).metadata();
|
|
1252
|
-
};
|
|
1253
|
-
const getDimensions = async (file)=>{
|
|
1254
|
-
const { width = null, height = null } = await getMetadata(file);
|
|
1255
|
-
return {
|
|
1256
|
-
width,
|
|
1257
|
-
height
|
|
1258
|
-
};
|
|
1259
|
-
};
|
|
1260
|
-
const THUMBNAIL_RESIZE_OPTIONS = {
|
|
1261
|
-
width: 245,
|
|
1262
|
-
height: 156,
|
|
1263
|
-
fit: 'inside'
|
|
1264
|
-
};
|
|
1265
|
-
const resizeFileTo = async (file, options, { name, hash })=>{
|
|
1266
|
-
const filePath = file.tmpWorkingDirectory ? join(file.tmpWorkingDirectory, hash) : hash;
|
|
1267
|
-
let newInfo;
|
|
1268
|
-
if (!file.filepath) {
|
|
1269
|
-
const transform = sharp().resize(options).on('info', (info)=>{
|
|
1270
|
-
newInfo = info;
|
|
1271
|
-
});
|
|
1272
|
-
await writeStreamToFile(file.getStream().pipe(transform), filePath);
|
|
1273
|
-
} else {
|
|
1274
|
-
newInfo = await sharp(file.filepath).resize(options).toFile(filePath);
|
|
1275
|
-
}
|
|
1276
|
-
const { width, height, size } = newInfo ?? {};
|
|
1277
|
-
const newFile = {
|
|
1278
|
-
name,
|
|
1279
|
-
hash,
|
|
1280
|
-
ext: file.ext,
|
|
1281
|
-
mime: file.mime,
|
|
1282
|
-
filepath: filePath,
|
|
1283
|
-
path: file.path || null,
|
|
1284
|
-
getStream: ()=>fs.createReadStream(filePath)
|
|
1285
|
-
};
|
|
1286
|
-
Object.assign(newFile, {
|
|
1287
|
-
width,
|
|
1288
|
-
height,
|
|
1289
|
-
size: size ? bytesToKbytes(size) : 0,
|
|
1290
|
-
sizeInBytes: size
|
|
1291
|
-
});
|
|
1292
|
-
return newFile;
|
|
1293
|
-
};
|
|
1294
|
-
const generateThumbnail = async (file)=>{
|
|
1295
|
-
if (file.width && file.height && (file.width > THUMBNAIL_RESIZE_OPTIONS.width || file.height > THUMBNAIL_RESIZE_OPTIONS.height)) {
|
|
1296
|
-
return resizeFileTo(file, THUMBNAIL_RESIZE_OPTIONS, {
|
|
1297
|
-
name: `thumbnail_${file.name}`,
|
|
1298
|
-
hash: `thumbnail_${file.hash}`
|
|
1299
|
-
});
|
|
1300
|
-
}
|
|
1301
|
-
return null;
|
|
1302
|
-
};
|
|
1303
|
-
/**
|
|
1304
|
-
* Optimize image by:
|
|
1305
|
-
* - auto orienting image based on EXIF data
|
|
1306
|
-
* - reduce image quality
|
|
1307
|
-
*
|
|
1308
|
-
*/ const optimize = async (file)=>{
|
|
1309
|
-
const { sizeOptimization = false, autoOrientation = false } = await getService('upload').getSettings() ?? {};
|
|
1310
|
-
const { format, size } = await getMetadata(file);
|
|
1311
|
-
if ((sizeOptimization || autoOrientation) && isOptimizableFormat(format)) {
|
|
1312
|
-
let transformer;
|
|
1313
|
-
if (!file.filepath) {
|
|
1314
|
-
transformer = sharp();
|
|
1315
|
-
} else {
|
|
1316
|
-
transformer = sharp(file.filepath);
|
|
1317
|
-
}
|
|
1318
|
-
// reduce image quality
|
|
1319
|
-
transformer[format]({
|
|
1320
|
-
quality: sizeOptimization ? 80 : 100
|
|
1321
|
-
});
|
|
1322
|
-
// rotate image based on EXIF data
|
|
1323
|
-
if (autoOrientation) {
|
|
1324
|
-
transformer.rotate();
|
|
1325
|
-
}
|
|
1326
|
-
const filePath = file.tmpWorkingDirectory ? join(file.tmpWorkingDirectory, `optimized-${file.hash}`) : `optimized-${file.hash}`;
|
|
1327
|
-
let newInfo;
|
|
1328
|
-
if (!file.filepath) {
|
|
1329
|
-
transformer.on('info', (info)=>{
|
|
1330
|
-
newInfo = info;
|
|
1331
|
-
});
|
|
1332
|
-
await writeStreamToFile(file.getStream().pipe(transformer), filePath);
|
|
1333
|
-
} else {
|
|
1334
|
-
newInfo = await transformer.toFile(filePath);
|
|
1335
|
-
}
|
|
1336
|
-
const { width: newWidth, height: newHeight, size: newSize } = newInfo ?? {};
|
|
1337
|
-
const newFile = {
|
|
1338
|
-
...file
|
|
1339
|
-
};
|
|
1340
|
-
newFile.getStream = ()=>fs.createReadStream(filePath);
|
|
1341
|
-
newFile.filepath = filePath;
|
|
1342
|
-
if (newSize && size && newSize > size) {
|
|
1343
|
-
// Ignore optimization if output is bigger than original
|
|
1344
|
-
return file;
|
|
1345
|
-
}
|
|
1346
|
-
return Object.assign(newFile, {
|
|
1347
|
-
width: newWidth,
|
|
1348
|
-
height: newHeight,
|
|
1349
|
-
size: newSize ? bytesToKbytes(newSize) : 0,
|
|
1350
|
-
sizeInBytes: newSize
|
|
1351
|
-
});
|
|
1352
|
-
}
|
|
1353
|
-
return file;
|
|
1354
|
-
};
|
|
1355
|
-
const DEFAULT_BREAKPOINTS = {
|
|
1356
|
-
large: 1000,
|
|
1357
|
-
medium: 750,
|
|
1358
|
-
small: 500
|
|
1359
|
-
};
|
|
1360
|
-
const getBreakpoints = ()=>strapi.config.get('plugin::upload.breakpoints', DEFAULT_BREAKPOINTS);
|
|
1361
|
-
const generateResponsiveFormats = async (file)=>{
|
|
1362
|
-
const { responsiveDimensions = false } = await getService('upload').getSettings() ?? {};
|
|
1363
|
-
if (!responsiveDimensions) return [];
|
|
1364
|
-
const originalDimensions = await getDimensions(file);
|
|
1365
|
-
const breakpoints = getBreakpoints();
|
|
1366
|
-
return Promise.all(Object.keys(breakpoints).map((key)=>{
|
|
1367
|
-
const breakpoint = breakpoints[key];
|
|
1368
|
-
if (breakpointSmallerThan(breakpoint, originalDimensions)) {
|
|
1369
|
-
return generateBreakpoint(key, {
|
|
1370
|
-
file,
|
|
1371
|
-
breakpoint
|
|
1372
|
-
});
|
|
1373
|
-
}
|
|
1374
|
-
return undefined;
|
|
1375
|
-
}));
|
|
1376
|
-
};
|
|
1377
|
-
const generateBreakpoint = async (key, { file, breakpoint })=>{
|
|
1378
|
-
const newFile = await resizeFileTo(file, {
|
|
1379
|
-
width: breakpoint,
|
|
1380
|
-
height: breakpoint,
|
|
1381
|
-
fit: 'inside'
|
|
1382
|
-
}, {
|
|
1383
|
-
name: `${key}_${file.name}`,
|
|
1384
|
-
hash: `${key}_${file.hash}`
|
|
1385
|
-
});
|
|
1386
|
-
return {
|
|
1387
|
-
key,
|
|
1388
|
-
file: newFile
|
|
1389
|
-
};
|
|
1390
|
-
};
|
|
1391
|
-
const breakpointSmallerThan = (breakpoint, { width, height })=>{
|
|
1392
|
-
return breakpoint < (width ?? 0) || breakpoint < (height ?? 0);
|
|
1393
|
-
};
|
|
1394
|
-
/**
|
|
1395
|
-
* Applies a simple image transformation to see if the image is faulty/corrupted.
|
|
1396
|
-
*/ const isFaultyImage = async (file)=>{
|
|
1397
|
-
if (!file.filepath) {
|
|
1398
|
-
return new Promise((resolve, reject)=>{
|
|
1399
|
-
const pipeline = sharp();
|
|
1400
|
-
pipeline.stats().then(resolve).catch(reject);
|
|
1401
|
-
file.getStream().pipe(pipeline);
|
|
1402
|
-
});
|
|
1403
|
-
}
|
|
1404
|
-
try {
|
|
1405
|
-
await sharp(file.filepath).stats();
|
|
1406
|
-
return false;
|
|
1407
|
-
} catch (e) {
|
|
1408
|
-
return true;
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
const isOptimizableImage = async (file)=>{
|
|
1412
|
-
let format;
|
|
1413
|
-
try {
|
|
1414
|
-
const metadata = await getMetadata(file);
|
|
1415
|
-
format = metadata.format;
|
|
1416
|
-
} catch (e) {
|
|
1417
|
-
// throw when the file is not a supported image
|
|
1418
|
-
return false;
|
|
1419
|
-
}
|
|
1420
|
-
return format && FORMATS_TO_OPTIMIZE.includes(format);
|
|
1421
|
-
};
|
|
1422
|
-
const isResizableImage = async (file)=>{
|
|
1423
|
-
let format;
|
|
1424
|
-
try {
|
|
1425
|
-
const metadata = await getMetadata(file);
|
|
1426
|
-
format = metadata.format;
|
|
1427
|
-
} catch (e) {
|
|
1428
|
-
// throw when the file is not a supported image
|
|
1429
|
-
return false;
|
|
1430
|
-
}
|
|
1431
|
-
return format && FORMATS_TO_RESIZE.includes(format);
|
|
1432
|
-
};
|
|
1433
|
-
const isImage = async (file)=>{
|
|
1434
|
-
let format;
|
|
1435
|
-
try {
|
|
1436
|
-
const metadata = await getMetadata(file);
|
|
1437
|
-
format = metadata.format;
|
|
1438
|
-
} catch (e) {
|
|
1439
|
-
// throw when the file is not a supported image
|
|
1440
|
-
return false;
|
|
1441
|
-
}
|
|
1442
|
-
return format && FORMATS_TO_PROCESS.includes(format);
|
|
1443
|
-
};
|
|
1444
|
-
var imageManipulation = {
|
|
1445
|
-
isFaultyImage,
|
|
1446
|
-
isOptimizableImage,
|
|
1447
|
-
isResizableImage,
|
|
1448
|
-
isImage,
|
|
1449
|
-
getDimensions,
|
|
1450
|
-
generateResponsiveFormats,
|
|
1451
|
-
generateThumbnail,
|
|
1452
|
-
optimize
|
|
1453
|
-
};
|
|
1454
|
-
|
|
1455
|
-
const setPathIdAndPath = async (folder)=>{
|
|
1456
|
-
const { max } = await strapi.db.queryBuilder(FOLDER_MODEL_UID).max('pathId').first().execute();
|
|
1457
|
-
const pathId = max + 1;
|
|
1458
|
-
let parentPath = '/';
|
|
1459
|
-
if (folder.parent) {
|
|
1460
|
-
const parentFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
1461
|
-
where: {
|
|
1462
|
-
id: folder.parent
|
|
1463
|
-
}
|
|
1464
|
-
});
|
|
1465
|
-
parentPath = parentFolder.path;
|
|
1466
|
-
}
|
|
1467
|
-
return Object.assign(folder, {
|
|
1468
|
-
pathId,
|
|
1469
|
-
path: strings.joinBy('/', parentPath, `${pathId}`)
|
|
1470
|
-
});
|
|
1471
|
-
};
|
|
1472
|
-
const create = async (folderData, opts)=>{
|
|
1473
|
-
const folderService = getService('folder');
|
|
1474
|
-
const { user } = opts || {};
|
|
1475
|
-
let enrichedFolder = await folderService.setPathIdAndPath(folderData);
|
|
1476
|
-
if (user) {
|
|
1477
|
-
enrichedFolder = await setCreatorFields({
|
|
1478
|
-
user
|
|
1479
|
-
})(enrichedFolder);
|
|
1480
|
-
}
|
|
1481
|
-
const folder = await strapi.db.query(FOLDER_MODEL_UID).create({
|
|
1482
|
-
data: enrichedFolder
|
|
1483
|
-
});
|
|
1484
|
-
strapi.eventHub.emit('media-folder.create', {
|
|
1485
|
-
folder
|
|
1486
|
-
});
|
|
1487
|
-
return folder;
|
|
1488
|
-
};
|
|
1489
|
-
/**
|
|
1490
|
-
* Recursively delete folders and included files
|
|
1491
|
-
* @param ids ids of the folders to delete
|
|
1492
|
-
* @returns {Promise<Object[]>}
|
|
1493
|
-
*/ const deleteByIds$1 = async (ids = [])=>{
|
|
1494
|
-
const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({
|
|
1495
|
-
where: {
|
|
1496
|
-
id: {
|
|
1497
|
-
$in: ids
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
});
|
|
1501
|
-
if (folders.length === 0) {
|
|
1502
|
-
return {
|
|
1503
|
-
folders: [],
|
|
1504
|
-
totalFolderNumber: 0,
|
|
1505
|
-
totalFileNumber: 0
|
|
1506
|
-
};
|
|
1507
|
-
}
|
|
1508
|
-
const pathsToDelete = map('path', folders);
|
|
1509
|
-
// delete files
|
|
1510
|
-
const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({
|
|
1511
|
-
where: {
|
|
1512
|
-
$or: pathsToDelete.flatMap((path)=>[
|
|
1513
|
-
{
|
|
1514
|
-
folderPath: {
|
|
1515
|
-
$eq: path
|
|
1516
|
-
}
|
|
1517
|
-
},
|
|
1518
|
-
{
|
|
1519
|
-
folderPath: {
|
|
1520
|
-
$startsWith: `${path}/`
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
])
|
|
1524
|
-
}
|
|
1525
|
-
});
|
|
1526
|
-
await Promise.all(filesToDelete.map((file)=>getService('upload').remove(file)));
|
|
1527
|
-
// delete folders and subfolders
|
|
1528
|
-
const { count: totalFolderNumber } = await strapi.db.query(FOLDER_MODEL_UID).deleteMany({
|
|
1529
|
-
where: {
|
|
1530
|
-
$or: pathsToDelete.flatMap((path)=>[
|
|
1531
|
-
{
|
|
1532
|
-
path: {
|
|
1533
|
-
$eq: path
|
|
1534
|
-
}
|
|
1535
|
-
},
|
|
1536
|
-
{
|
|
1537
|
-
path: {
|
|
1538
|
-
$startsWith: `${path}/`
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
])
|
|
1542
|
-
}
|
|
1543
|
-
});
|
|
1544
|
-
strapi.eventHub.emit('media-folder.delete', {
|
|
1545
|
-
folders
|
|
1546
|
-
});
|
|
1547
|
-
return {
|
|
1548
|
-
folders,
|
|
1549
|
-
totalFolderNumber,
|
|
1550
|
-
totalFileNumber: filesToDelete.length
|
|
1551
|
-
};
|
|
1552
|
-
};
|
|
1553
|
-
/**
|
|
1554
|
-
* Update name and location of a folder and its belonging folders and files
|
|
1555
|
-
*/ const update = async (id, { name, parent }, { user })=>{
|
|
1556
|
-
// only name is updated
|
|
1557
|
-
if (isUndefined(parent)) {
|
|
1558
|
-
const existingFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
1559
|
-
where: {
|
|
1560
|
-
id
|
|
1561
|
-
}
|
|
1562
|
-
});
|
|
1563
|
-
if (!existingFolder) {
|
|
1564
|
-
return undefined;
|
|
1565
|
-
}
|
|
1566
|
-
const newFolder = setCreatorFields({
|
|
1567
|
-
user,
|
|
1568
|
-
isEdition: true
|
|
1569
|
-
})({
|
|
1570
|
-
name,
|
|
1571
|
-
parent
|
|
1572
|
-
});
|
|
1573
|
-
if (isUndefined(parent)) {
|
|
1574
|
-
const folder = await strapi.db.query(FOLDER_MODEL_UID).update({
|
|
1575
|
-
where: {
|
|
1576
|
-
id
|
|
1577
|
-
},
|
|
1578
|
-
data: newFolder
|
|
1579
|
-
});
|
|
1580
|
-
return folder;
|
|
1581
|
-
}
|
|
1582
|
-
// location is updated => using transaction
|
|
1583
|
-
} else {
|
|
1584
|
-
const trx = await strapi.db.transaction();
|
|
1585
|
-
try {
|
|
1586
|
-
// fetch existing folder
|
|
1587
|
-
const existingFolder = await strapi.db.queryBuilder(FOLDER_MODEL_UID).select([
|
|
1588
|
-
'pathId',
|
|
1589
|
-
'path'
|
|
1590
|
-
]).where({
|
|
1591
|
-
id
|
|
1592
|
-
}).transacting(trx.get()).forUpdate().first().execute();
|
|
1593
|
-
// update parent folder (delete + insert; upsert not possible)
|
|
1594
|
-
// @ts-expect-error - no dynamic types
|
|
1595
|
-
const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;
|
|
1596
|
-
await strapi.db.queryBuilder(joinTable.name).transacting(trx.get()).delete().where({
|
|
1597
|
-
[joinTable.joinColumn.name]: id
|
|
1598
|
-
}).execute();
|
|
1599
|
-
if (parent !== null) {
|
|
1600
|
-
await strapi.db.queryBuilder(joinTable.name).transacting(trx.get()).insert({
|
|
1601
|
-
[joinTable.inverseJoinColumn.name]: parent,
|
|
1602
|
-
[joinTable.joinColumn.name]: id
|
|
1603
|
-
}).where({
|
|
1604
|
-
[joinTable.joinColumn.name]: id
|
|
1605
|
-
}).execute();
|
|
1606
|
-
}
|
|
1607
|
-
// fetch destinationFolder path
|
|
1608
|
-
let destinationFolderPath = '/';
|
|
1609
|
-
if (parent !== null) {
|
|
1610
|
-
const destinationFolder = await strapi.db.queryBuilder(FOLDER_MODEL_UID).select('path').where({
|
|
1611
|
-
id: parent
|
|
1612
|
-
}).transacting(trx.get()).first().execute();
|
|
1613
|
-
destinationFolderPath = destinationFolder.path;
|
|
1614
|
-
}
|
|
1615
|
-
const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;
|
|
1616
|
-
const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;
|
|
1617
|
-
const folderPathColumnName = // @ts-expect-error - no dynamic types
|
|
1618
|
-
strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;
|
|
1619
|
-
// @ts-expect-error - no dynamic types
|
|
1620
|
-
const pathColumnName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;
|
|
1621
|
-
// update folders below
|
|
1622
|
-
await strapi.db.getConnection(folderTable).transacting(trx.get()).where(pathColumnName, existingFolder.path).orWhere(pathColumnName, 'like', `${existingFolder.path}/%`).update(pathColumnName, strapi.db.connection.raw('REPLACE(??, ?, ?)', [
|
|
1623
|
-
pathColumnName,
|
|
1624
|
-
existingFolder.path,
|
|
1625
|
-
strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`)
|
|
1626
|
-
]));
|
|
1627
|
-
// update files below
|
|
1628
|
-
await strapi.db.getConnection(fileTable).transacting(trx.get()).where(folderPathColumnName, existingFolder.path).orWhere(folderPathColumnName, 'like', `${existingFolder.path}/%`).update(folderPathColumnName, strapi.db.connection.raw('REPLACE(??, ?, ?)', [
|
|
1629
|
-
folderPathColumnName,
|
|
1630
|
-
existingFolder.path,
|
|
1631
|
-
strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`)
|
|
1632
|
-
]));
|
|
1633
|
-
await trx.commit();
|
|
1634
|
-
} catch (e) {
|
|
1635
|
-
await trx.rollback();
|
|
1636
|
-
throw e;
|
|
1637
|
-
}
|
|
1638
|
-
// update less critical information (name + updatedBy)
|
|
1639
|
-
const newFolder = setCreatorFields({
|
|
1640
|
-
user,
|
|
1641
|
-
isEdition: true
|
|
1642
|
-
})({
|
|
1643
|
-
name
|
|
1644
|
-
});
|
|
1645
|
-
const folder = await strapi.db.query(FOLDER_MODEL_UID).update({
|
|
1646
|
-
where: {
|
|
1647
|
-
id
|
|
1648
|
-
},
|
|
1649
|
-
data: newFolder
|
|
1650
|
-
});
|
|
1651
|
-
strapi.eventHub.emit('media-folder.update', {
|
|
1652
|
-
folder
|
|
1653
|
-
});
|
|
1654
|
-
return folder;
|
|
1655
|
-
}
|
|
1656
|
-
};
|
|
1657
|
-
/**
|
|
1658
|
-
* Check if a folder exists in database
|
|
1659
|
-
* @param params query params to find the folder
|
|
1660
|
-
* @returns {Promise<boolean>}
|
|
1661
|
-
*/ const exists = async (params = {})=>{
|
|
1662
|
-
const count = await strapi.db.query(FOLDER_MODEL_UID).count({
|
|
1663
|
-
where: params
|
|
1664
|
-
});
|
|
1665
|
-
return count > 0;
|
|
1666
|
-
};
|
|
1667
|
-
/**
|
|
1668
|
-
* Returns the nested structure of folders
|
|
1669
|
-
* @returns {Promise<array>}
|
|
1670
|
-
*/ const getStructure = async ()=>{
|
|
1671
|
-
// @ts-expect-error - no dynamic types
|
|
1672
|
-
const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;
|
|
1673
|
-
const qb = strapi.db.queryBuilder(FOLDER_MODEL_UID);
|
|
1674
|
-
const alias = qb.getAlias();
|
|
1675
|
-
const folders = await qb.select([
|
|
1676
|
-
'id',
|
|
1677
|
-
'name',
|
|
1678
|
-
`${alias}.${joinTable.inverseJoinColumn.name} as parent`
|
|
1679
|
-
]).join({
|
|
1680
|
-
alias,
|
|
1681
|
-
referencedTable: joinTable.name,
|
|
1682
|
-
referencedColumn: joinTable.joinColumn.name,
|
|
1683
|
-
rootColumn: joinTable.joinColumn.referencedColumn,
|
|
1684
|
-
rootTable: qb.alias
|
|
1685
|
-
}).execute({
|
|
1686
|
-
mapResults: false
|
|
1687
|
-
});
|
|
1688
|
-
const folderMap = {
|
|
1689
|
-
null: {
|
|
1690
|
-
children: []
|
|
1691
|
-
}
|
|
1692
|
-
};
|
|
1693
|
-
folders.forEach((f)=>{
|
|
1694
|
-
folderMap[f.id] = {
|
|
1695
|
-
...f,
|
|
1696
|
-
children: []
|
|
1697
|
-
};
|
|
1698
|
-
});
|
|
1699
|
-
folders.forEach((f)=>{
|
|
1700
|
-
const parentId = f.parent || 'null';
|
|
1701
|
-
if (!folderMap[parentId]) {
|
|
1702
|
-
folderMap[parentId] = {
|
|
1703
|
-
children: []
|
|
1704
|
-
};
|
|
1705
|
-
}
|
|
1706
|
-
folderMap[parentId].children.push(folderMap[f.id]);
|
|
1707
|
-
folderMap[parentId].children = sortBy('name', folderMap[parentId].children);
|
|
1708
|
-
delete folderMap[f.id].parent;
|
|
1709
|
-
});
|
|
1710
|
-
return folderMap.null.children;
|
|
1711
|
-
};
|
|
1712
|
-
var folder = {
|
|
1713
|
-
create,
|
|
1714
|
-
exists,
|
|
1715
|
-
deleteByIds: deleteByIds$1,
|
|
1716
|
-
update,
|
|
1717
|
-
setPathIdAndPath,
|
|
1718
|
-
getStructure
|
|
1719
|
-
};
|
|
1720
|
-
|
|
1721
|
-
const getFolderPath = async (folderId)=>{
|
|
1722
|
-
if (!folderId) return '/';
|
|
1723
|
-
const parentFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
1724
|
-
where: {
|
|
1725
|
-
id: folderId
|
|
1726
|
-
}
|
|
1727
|
-
});
|
|
1728
|
-
return parentFolder.path;
|
|
1729
|
-
};
|
|
1730
|
-
const deleteByIds = async (ids = [])=>{
|
|
1731
|
-
const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({
|
|
1732
|
-
where: {
|
|
1733
|
-
id: {
|
|
1734
|
-
$in: ids
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
});
|
|
1738
|
-
await Promise.all(filesToDelete.map((file)=>getService('upload').remove(file)));
|
|
1739
|
-
return filesToDelete;
|
|
1740
|
-
};
|
|
1741
|
-
const signFileUrls = async (file)=>{
|
|
1742
|
-
const { provider } = strapi.plugins.upload;
|
|
1743
|
-
const { provider: providerConfig } = strapi.config.get('plugin::upload');
|
|
1744
|
-
const isPrivate = await provider.isPrivate();
|
|
1745
|
-
file.isUrlSigned = false;
|
|
1746
|
-
// Check file provider and if provider is private
|
|
1747
|
-
if (file.provider !== providerConfig || !isPrivate) {
|
|
1748
|
-
return file;
|
|
1749
|
-
}
|
|
1750
|
-
const signUrl = async (file)=>{
|
|
1751
|
-
const signedUrl = await provider.getSignedUrl(file);
|
|
1752
|
-
file.url = signedUrl.url;
|
|
1753
|
-
file.isUrlSigned = true;
|
|
1754
|
-
};
|
|
1755
|
-
const signedFile = cloneDeep(file);
|
|
1756
|
-
// Sign each file format
|
|
1757
|
-
await signUrl(signedFile);
|
|
1758
|
-
if (file.formats) {
|
|
1759
|
-
await async.map(Object.values(signedFile.formats ?? {}), signUrl);
|
|
1760
|
-
}
|
|
1761
|
-
return signedFile;
|
|
1762
|
-
};
|
|
1763
|
-
var file = {
|
|
1764
|
-
getFolderPath,
|
|
1765
|
-
deleteByIds,
|
|
1766
|
-
signFileUrls
|
|
1767
|
-
};
|
|
1768
|
-
|
|
1769
|
-
const getWeeklyCronScheduleAt = (date)=>`${date.getSeconds()} ${date.getMinutes()} ${date.getHours()} * * ${date.getDay()}`;
|
|
1770
|
-
|
|
1771
|
-
const ONE_WEEK = 7 * 24 * 60 * 60 * 1000;
|
|
1772
|
-
const getMetricsStoreValue = async ()=>{
|
|
1773
|
-
const value = await strapi.store.get({
|
|
1774
|
-
type: 'plugin',
|
|
1775
|
-
name: 'upload',
|
|
1776
|
-
key: 'metrics'
|
|
1777
|
-
});
|
|
1778
|
-
return defaultTo({}, value);
|
|
1779
|
-
};
|
|
1780
|
-
const setMetricsStoreValue = (value)=>strapi.store.set({
|
|
1781
|
-
type: 'plugin',
|
|
1782
|
-
name: 'upload',
|
|
1783
|
-
key: 'metrics',
|
|
1784
|
-
value
|
|
1785
|
-
});
|
|
1786
|
-
var weeklyMetrics = (({ strapi: strapi1 })=>({
|
|
1787
|
-
async computeMetrics () {
|
|
1788
|
-
// Folder metrics
|
|
1789
|
-
// @ts-expect-error - no dynamic types for the metadata
|
|
1790
|
-
const pathColName = strapi1.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;
|
|
1791
|
-
const folderTable = strapi1.getModel(FOLDER_MODEL_UID).collectionName;
|
|
1792
|
-
let keepOnlySlashesSQLString = '??';
|
|
1793
|
-
const queryParams = [
|
|
1794
|
-
pathColName
|
|
1795
|
-
];
|
|
1796
|
-
for(let i = 0; i < 10; i += 1){
|
|
1797
|
-
keepOnlySlashesSQLString = `REPLACE(${keepOnlySlashesSQLString}, ?, ?)`;
|
|
1798
|
-
queryParams.push(String(i), '');
|
|
1799
|
-
}
|
|
1800
|
-
/*
|
|
1801
|
-
The following query goal is to count the number of folders with depth 1, depth 2 etc.
|
|
1802
|
-
The query returns :
|
|
1803
|
-
[
|
|
1804
|
-
{ depth: 1, occurence: 4 },
|
|
1805
|
-
{ depth: 2, occurence: 2 },
|
|
1806
|
-
{ depth: 3, occurence: 5 },
|
|
1807
|
-
]
|
|
1808
|
-
|
|
1809
|
-
The query is built as follow:
|
|
1810
|
-
1. In order to get the depth level of a folder:
|
|
1811
|
-
- we take their path
|
|
1812
|
-
- remove all numbers (by replacing 0123456789 by '', thus the 10 REPLACE in the query)
|
|
1813
|
-
- count the remaining `/`, which correspond to their depth (by using LENGTH)
|
|
1814
|
-
We now have, for each folder, its depth.
|
|
1815
|
-
2. In order to get the number of folders for each depth:
|
|
1816
|
-
- we group them by their depth and use COUNT(*)
|
|
1817
|
-
*/ const res = await strapi1.db.getConnection(folderTable).select(strapi1.db.connection.raw(`LENGTH(${keepOnlySlashesSQLString}) AS depth, COUNT(*) AS occurence`, queryParams)).groupBy('depth');
|
|
1818
|
-
const folderLevelsArray = res.map((map)=>({
|
|
1819
|
-
depth: Number(map.depth),
|
|
1820
|
-
occurence: Number(map.occurence)
|
|
1821
|
-
})); // values can be strings depending on the database
|
|
1822
|
-
let product = 0;
|
|
1823
|
-
let folderNumber = 0;
|
|
1824
|
-
let maxDepth = 0;
|
|
1825
|
-
for (const folderLevel of folderLevelsArray){
|
|
1826
|
-
product += folderLevel.depth * folderLevel.occurence;
|
|
1827
|
-
folderNumber += folderLevel.occurence;
|
|
1828
|
-
if (folderLevel.depth > maxDepth) {
|
|
1829
|
-
maxDepth = folderLevel.depth;
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1832
|
-
const averageDepth = folderNumber !== 0 ? product / folderNumber : 0;
|
|
1833
|
-
let sumOfDeviation = 0;
|
|
1834
|
-
for (const folderLevel of folderLevelsArray){
|
|
1835
|
-
sumOfDeviation += Math.abs(folderLevel.depth - averageDepth) * folderLevel.occurence;
|
|
1836
|
-
}
|
|
1837
|
-
const averageDeviationDepth = folderNumber !== 0 ? sumOfDeviation / folderNumber : 0;
|
|
1838
|
-
// File metrics
|
|
1839
|
-
const assetNumber = await strapi1.db.query(FILE_MODEL_UID).count();
|
|
1840
|
-
return {
|
|
1841
|
-
assetNumber,
|
|
1842
|
-
folderNumber,
|
|
1843
|
-
averageDepth,
|
|
1844
|
-
maxDepth,
|
|
1845
|
-
averageDeviationDepth
|
|
1846
|
-
};
|
|
1847
|
-
},
|
|
1848
|
-
async sendMetrics () {
|
|
1849
|
-
const metrics = await this.computeMetrics();
|
|
1850
|
-
strapi1.telemetry.send('didSendUploadPropertiesOnceAWeek', {
|
|
1851
|
-
groupProperties: {
|
|
1852
|
-
metrics
|
|
1853
|
-
}
|
|
1854
|
-
});
|
|
1855
|
-
const metricsInfoStored = await getMetricsStoreValue();
|
|
1856
|
-
await setMetricsStoreValue({
|
|
1857
|
-
...metricsInfoStored,
|
|
1858
|
-
lastWeeklyUpdate: new Date().getTime()
|
|
1859
|
-
});
|
|
1860
|
-
},
|
|
1861
|
-
async ensureWeeklyStoredCronSchedule () {
|
|
1862
|
-
const metricsInfoStored = await getMetricsStoreValue();
|
|
1863
|
-
const { weeklySchedule: currentSchedule, lastWeeklyUpdate } = metricsInfoStored;
|
|
1864
|
-
const now = new Date();
|
|
1865
|
-
let weeklySchedule = currentSchedule;
|
|
1866
|
-
if (!weeklySchedule || !lastWeeklyUpdate || lastWeeklyUpdate + ONE_WEEK < now.getTime()) {
|
|
1867
|
-
weeklySchedule = getWeeklyCronScheduleAt(add(now, {
|
|
1868
|
-
seconds: 15
|
|
1869
|
-
}));
|
|
1870
|
-
await setMetricsStoreValue({
|
|
1871
|
-
...metricsInfoStored,
|
|
1872
|
-
weeklySchedule
|
|
1873
|
-
});
|
|
1874
|
-
return weeklySchedule;
|
|
1875
|
-
}
|
|
1876
|
-
return weeklySchedule;
|
|
1877
|
-
},
|
|
1878
|
-
async registerCron () {
|
|
1879
|
-
const weeklySchedule = await this.ensureWeeklyStoredCronSchedule();
|
|
1880
|
-
strapi1.cron.add({
|
|
1881
|
-
uploadWeekly: {
|
|
1882
|
-
task: this.sendMetrics.bind(this),
|
|
1883
|
-
options: weeklySchedule
|
|
1884
|
-
}
|
|
1885
|
-
});
|
|
1886
|
-
}
|
|
1887
|
-
}));
|
|
1888
|
-
|
|
1889
|
-
const getProviderName = ()=>strapi.config.get('plugin::upload.provider', 'local');
|
|
1890
|
-
const isProviderPrivate = async ()=>strapi.plugin('upload').provider.isPrivate();
|
|
1891
|
-
var metrics = (({ strapi: strapi1 })=>({
|
|
1892
|
-
async sendUploadPluginMetrics () {
|
|
1893
|
-
const uploadProvider = getProviderName();
|
|
1894
|
-
const privateProvider = await isProviderPrivate();
|
|
1895
|
-
strapi1.telemetry.send('didInitializePluginUpload', {
|
|
1896
|
-
groupProperties: {
|
|
1897
|
-
uploadProvider,
|
|
1898
|
-
privateProvider
|
|
1899
|
-
}
|
|
1900
|
-
});
|
|
1901
|
-
}
|
|
1902
|
-
}));
|
|
1903
|
-
|
|
1904
|
-
const getStore = ()=>strapi.store({
|
|
1905
|
-
type: 'plugin',
|
|
1906
|
-
name: 'upload',
|
|
1907
|
-
key: 'api-folder'
|
|
1908
|
-
});
|
|
1909
|
-
const createApiUploadFolder = async ()=>{
|
|
1910
|
-
let name = API_UPLOAD_FOLDER_BASE_NAME;
|
|
1911
|
-
const folderService = getService('folder');
|
|
1912
|
-
let exists = true;
|
|
1913
|
-
let index = 1;
|
|
1914
|
-
while(exists){
|
|
1915
|
-
exists = await folderService.exists({
|
|
1916
|
-
name,
|
|
1917
|
-
parent: null
|
|
1918
|
-
});
|
|
1919
|
-
if (exists) {
|
|
1920
|
-
name = `${API_UPLOAD_FOLDER_BASE_NAME} (${index})`;
|
|
1921
|
-
index += 1;
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
|
-
const folder = await folderService.create({
|
|
1925
|
-
name
|
|
1926
|
-
});
|
|
1927
|
-
await getStore().set({
|
|
1928
|
-
value: {
|
|
1929
|
-
id: folder.id
|
|
1930
|
-
}
|
|
1931
|
-
});
|
|
1932
|
-
return folder;
|
|
1933
|
-
};
|
|
1934
|
-
const getAPIUploadFolder = async ()=>{
|
|
1935
|
-
const storeValue = await getStore().get({});
|
|
1936
|
-
const folderId = get('id', storeValue);
|
|
1937
|
-
const folder = folderId ? await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
1938
|
-
where: {
|
|
1939
|
-
id: folderId
|
|
1940
|
-
}
|
|
1941
|
-
}) : null;
|
|
1942
|
-
return isNil(folder) ? createApiUploadFolder() : folder;
|
|
1943
|
-
};
|
|
1944
|
-
var apiUploadFolder = {
|
|
1945
|
-
getAPIUploadFolder
|
|
1946
|
-
};
|
|
1947
|
-
|
|
1948
|
-
function isFile(value, attribute) {
|
|
1949
|
-
if (!value || attribute.type !== 'media') {
|
|
1950
|
-
return false;
|
|
1951
|
-
}
|
|
1952
|
-
return true;
|
|
1953
|
-
}
|
|
1954
|
-
/**
|
|
1955
|
-
* Visitor function to sign media URLs
|
|
1956
|
-
*/ const signEntityMediaVisitor = async ({ key, value, attribute }, { set })=>{
|
|
1957
|
-
const { signFileUrls } = getService('file');
|
|
1958
|
-
if (!attribute) {
|
|
1959
|
-
return;
|
|
1960
|
-
}
|
|
1961
|
-
if (attribute.type !== 'media') {
|
|
1962
|
-
return;
|
|
1963
|
-
}
|
|
1964
|
-
if (isFile(value, attribute)) {
|
|
1965
|
-
// If the attribute is repeatable sign each file
|
|
1966
|
-
if (attribute.multiple) {
|
|
1967
|
-
const signedFiles = await async.map(value, signFileUrls);
|
|
1968
|
-
set(key, signedFiles);
|
|
1969
|
-
return;
|
|
1970
|
-
}
|
|
1971
|
-
// If the attribute is not repeatable only sign a single file
|
|
1972
|
-
const signedFile = await signFileUrls(value);
|
|
1973
|
-
set(key, signedFile);
|
|
1974
|
-
}
|
|
1975
|
-
};
|
|
1976
|
-
/**
|
|
1977
|
-
*
|
|
1978
|
-
* Iterate through an entity manager result
|
|
1979
|
-
* Check which modelAttributes are media and pre sign the image URLs
|
|
1980
|
-
* if they are from the current upload provider
|
|
1981
|
-
*
|
|
1982
|
-
* @param {Object} entity
|
|
1983
|
-
* @param {Object} modelAttributes
|
|
1984
|
-
* @returns
|
|
1985
|
-
*/ const signEntityMedia = async (entity, uid)=>{
|
|
1986
|
-
const model = strapi.getModel(uid);
|
|
1987
|
-
return traverseEntity(// @ts-expect-error - FIXME: fix traverseEntity using wrong types
|
|
1988
|
-
signEntityMediaVisitor, {
|
|
1989
|
-
schema: model,
|
|
1990
|
-
getModel: strapi.getModel.bind(strapi)
|
|
1991
|
-
}, entity);
|
|
1992
|
-
};
|
|
1993
|
-
|
|
1994
|
-
const signFileUrlsOnDocumentService = async ()=>{
|
|
1995
|
-
const { provider } = strapi.plugins.upload;
|
|
1996
|
-
const isPrivate = await provider.isPrivate();
|
|
1997
|
-
// We only need to sign the file urls if the provider is private
|
|
1998
|
-
if (!isPrivate) {
|
|
1999
|
-
return;
|
|
2000
|
-
}
|
|
2001
|
-
strapi.documents.use(async (ctx, next)=>{
|
|
2002
|
-
const uid = ctx.uid;
|
|
2003
|
-
const result = await next();
|
|
2004
|
-
if (ctx.action === 'findMany') {
|
|
2005
|
-
// Shape: [ entry ]
|
|
2006
|
-
return async.map(result, (entry)=>signEntityMedia(entry, uid));
|
|
2007
|
-
}
|
|
2008
|
-
if (ctx.action === 'findFirst' || ctx.action === 'findOne' || ctx.action === 'create' || ctx.action === 'update') {
|
|
2009
|
-
// Shape: entry
|
|
2010
|
-
return signEntityMedia(result, uid);
|
|
2011
|
-
}
|
|
2012
|
-
if (ctx.action === 'delete' || ctx.action === 'clone' || ctx.action === 'publish' || ctx.action === 'unpublish' || ctx.action === 'discardDraft') {
|
|
2013
|
-
// Shape: { entries: [ entry ] }
|
|
2014
|
-
// ...
|
|
2015
|
-
return {
|
|
2016
|
-
...result,
|
|
2017
|
-
entries: await async.map(result.entries, (entry)=>signEntityMedia(entry, uid))
|
|
2018
|
-
};
|
|
2019
|
-
}
|
|
2020
|
-
return result;
|
|
2021
|
-
});
|
|
2022
|
-
};
|
|
2023
|
-
var extensions = {
|
|
2024
|
-
signFileUrlsOnDocumentService
|
|
2025
|
-
};
|
|
2026
|
-
|
|
2027
|
-
const services = {
|
|
2028
|
-
provider,
|
|
2029
|
-
upload,
|
|
2030
|
-
folder,
|
|
2031
|
-
file,
|
|
2032
|
-
weeklyMetrics,
|
|
2033
|
-
metrics,
|
|
2034
|
-
'image-manipulation': imageManipulation,
|
|
2035
|
-
'api-upload-folder': apiUploadFolder,
|
|
2036
|
-
extensions
|
|
2037
|
-
};
|
|
2038
|
-
|
|
2039
|
-
const routes$3 = {
|
|
2040
|
-
type: 'admin',
|
|
2041
|
-
routes: [
|
|
2042
|
-
{
|
|
2043
|
-
method: 'GET',
|
|
2044
|
-
path: '/settings',
|
|
2045
|
-
handler: 'admin-settings.getSettings',
|
|
2046
|
-
config: {
|
|
2047
|
-
policies: [
|
|
2048
|
-
'admin::isAuthenticatedAdmin',
|
|
2049
|
-
{
|
|
2050
|
-
name: 'admin::hasPermissions',
|
|
2051
|
-
config: {
|
|
2052
|
-
actions: [
|
|
2053
|
-
'plugin::upload.settings.read'
|
|
2054
|
-
]
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
]
|
|
2058
|
-
}
|
|
2059
|
-
},
|
|
2060
|
-
{
|
|
2061
|
-
method: 'PUT',
|
|
2062
|
-
path: '/settings',
|
|
2063
|
-
handler: 'admin-settings.updateSettings',
|
|
2064
|
-
config: {
|
|
2065
|
-
policies: [
|
|
2066
|
-
'admin::isAuthenticatedAdmin',
|
|
2067
|
-
{
|
|
2068
|
-
name: 'admin::hasPermissions',
|
|
2069
|
-
config: {
|
|
2070
|
-
actions: [
|
|
2071
|
-
'plugin::upload.settings.read'
|
|
2072
|
-
]
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
]
|
|
2076
|
-
}
|
|
2077
|
-
},
|
|
2078
|
-
{
|
|
2079
|
-
method: 'POST',
|
|
2080
|
-
path: '/',
|
|
2081
|
-
handler: 'admin-upload.upload',
|
|
2082
|
-
config: {
|
|
2083
|
-
policies: [
|
|
2084
|
-
'admin::isAuthenticatedAdmin'
|
|
2085
|
-
]
|
|
2086
|
-
}
|
|
2087
|
-
},
|
|
2088
|
-
{
|
|
2089
|
-
method: 'GET',
|
|
2090
|
-
path: '/files',
|
|
2091
|
-
handler: 'admin-file.find',
|
|
2092
|
-
config: {
|
|
2093
|
-
policies: [
|
|
2094
|
-
'admin::isAuthenticatedAdmin',
|
|
2095
|
-
{
|
|
2096
|
-
name: 'admin::hasPermissions',
|
|
2097
|
-
config: {
|
|
2098
|
-
actions: [
|
|
2099
|
-
'plugin::upload.read'
|
|
2100
|
-
]
|
|
2101
|
-
}
|
|
2102
|
-
}
|
|
2103
|
-
]
|
|
2104
|
-
}
|
|
2105
|
-
},
|
|
2106
|
-
{
|
|
2107
|
-
method: 'GET',
|
|
2108
|
-
path: '/files/:id',
|
|
2109
|
-
handler: 'admin-file.findOne',
|
|
2110
|
-
config: {
|
|
2111
|
-
policies: [
|
|
2112
|
-
'admin::isAuthenticatedAdmin',
|
|
2113
|
-
{
|
|
2114
|
-
name: 'admin::hasPermissions',
|
|
2115
|
-
config: {
|
|
2116
|
-
actions: [
|
|
2117
|
-
'plugin::upload.read'
|
|
2118
|
-
]
|
|
2119
|
-
}
|
|
2120
|
-
}
|
|
2121
|
-
]
|
|
2122
|
-
}
|
|
2123
|
-
},
|
|
2124
|
-
{
|
|
2125
|
-
method: 'DELETE',
|
|
2126
|
-
path: '/files/:id',
|
|
2127
|
-
handler: 'admin-file.destroy',
|
|
2128
|
-
config: {
|
|
2129
|
-
policies: [
|
|
2130
|
-
'admin::isAuthenticatedAdmin',
|
|
2131
|
-
{
|
|
2132
|
-
name: 'admin::hasPermissions',
|
|
2133
|
-
config: {
|
|
2134
|
-
actions: [
|
|
2135
|
-
'plugin::upload.assets.update'
|
|
2136
|
-
]
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
]
|
|
2140
|
-
}
|
|
2141
|
-
},
|
|
2142
|
-
{
|
|
2143
|
-
method: 'GET',
|
|
2144
|
-
path: '/folders/:id',
|
|
2145
|
-
handler: 'admin-folder.findOne',
|
|
2146
|
-
config: {
|
|
2147
|
-
policies: [
|
|
2148
|
-
'admin::isAuthenticatedAdmin',
|
|
2149
|
-
{
|
|
2150
|
-
name: 'admin::hasPermissions',
|
|
2151
|
-
config: {
|
|
2152
|
-
actions: [
|
|
2153
|
-
'plugin::upload.read'
|
|
2154
|
-
]
|
|
2155
|
-
}
|
|
2156
|
-
}
|
|
2157
|
-
]
|
|
2158
|
-
}
|
|
2159
|
-
},
|
|
2160
|
-
{
|
|
2161
|
-
method: 'GET',
|
|
2162
|
-
path: '/folders',
|
|
2163
|
-
handler: 'admin-folder.find',
|
|
2164
|
-
config: {
|
|
2165
|
-
policies: [
|
|
2166
|
-
'admin::isAuthenticatedAdmin',
|
|
2167
|
-
{
|
|
2168
|
-
name: 'admin::hasPermissions',
|
|
2169
|
-
config: {
|
|
2170
|
-
actions: [
|
|
2171
|
-
'plugin::upload.read'
|
|
2172
|
-
]
|
|
2173
|
-
}
|
|
2174
|
-
}
|
|
2175
|
-
]
|
|
2176
|
-
}
|
|
2177
|
-
},
|
|
2178
|
-
{
|
|
2179
|
-
method: 'POST',
|
|
2180
|
-
path: '/folders',
|
|
2181
|
-
handler: 'admin-folder.create',
|
|
2182
|
-
config: {
|
|
2183
|
-
policies: [
|
|
2184
|
-
'admin::isAuthenticatedAdmin',
|
|
2185
|
-
{
|
|
2186
|
-
name: 'admin::hasPermissions',
|
|
2187
|
-
config: {
|
|
2188
|
-
actions: [
|
|
2189
|
-
'plugin::upload.assets.create'
|
|
2190
|
-
]
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
]
|
|
2194
|
-
}
|
|
2195
|
-
},
|
|
2196
|
-
{
|
|
2197
|
-
method: 'PUT',
|
|
2198
|
-
path: '/folders/:id',
|
|
2199
|
-
handler: 'admin-folder.update',
|
|
2200
|
-
config: {
|
|
2201
|
-
policies: [
|
|
2202
|
-
'admin::isAuthenticatedAdmin',
|
|
2203
|
-
{
|
|
2204
|
-
name: 'admin::hasPermissions',
|
|
2205
|
-
config: {
|
|
2206
|
-
actions: [
|
|
2207
|
-
'plugin::upload.assets.update'
|
|
2208
|
-
]
|
|
2209
|
-
}
|
|
2210
|
-
}
|
|
2211
|
-
]
|
|
2212
|
-
}
|
|
2213
|
-
},
|
|
2214
|
-
{
|
|
2215
|
-
method: 'GET',
|
|
2216
|
-
path: '/folder-structure',
|
|
2217
|
-
handler: 'admin-folder.getStructure',
|
|
2218
|
-
config: {
|
|
2219
|
-
policies: [
|
|
2220
|
-
'admin::isAuthenticatedAdmin',
|
|
2221
|
-
{
|
|
2222
|
-
name: 'admin::hasPermissions',
|
|
2223
|
-
config: {
|
|
2224
|
-
actions: [
|
|
2225
|
-
'plugin::upload.read'
|
|
2226
|
-
]
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2229
|
-
]
|
|
2230
|
-
}
|
|
2231
|
-
},
|
|
2232
|
-
{
|
|
2233
|
-
method: 'POST',
|
|
2234
|
-
path: '/actions/bulk-delete',
|
|
2235
|
-
handler: 'admin-folder-file.deleteMany',
|
|
2236
|
-
config: {
|
|
2237
|
-
policies: [
|
|
2238
|
-
'admin::isAuthenticatedAdmin',
|
|
2239
|
-
{
|
|
2240
|
-
name: 'admin::hasPermissions',
|
|
2241
|
-
config: {
|
|
2242
|
-
actions: [
|
|
2243
|
-
'plugin::upload.assets.update'
|
|
2244
|
-
]
|
|
2245
|
-
}
|
|
2246
|
-
}
|
|
2247
|
-
]
|
|
2248
|
-
}
|
|
2249
|
-
},
|
|
2250
|
-
{
|
|
2251
|
-
method: 'POST',
|
|
2252
|
-
path: '/actions/bulk-move',
|
|
2253
|
-
handler: 'admin-folder-file.moveMany',
|
|
2254
|
-
config: {
|
|
2255
|
-
policies: [
|
|
2256
|
-
'admin::isAuthenticatedAdmin',
|
|
2257
|
-
{
|
|
2258
|
-
name: 'admin::hasPermissions',
|
|
2259
|
-
config: {
|
|
2260
|
-
actions: [
|
|
2261
|
-
'plugin::upload.assets.update'
|
|
2262
|
-
]
|
|
2263
|
-
}
|
|
2264
|
-
}
|
|
2265
|
-
]
|
|
2266
|
-
}
|
|
2267
|
-
}
|
|
2268
|
-
]
|
|
2269
|
-
};
|
|
2270
|
-
|
|
2271
|
-
const routes$2 = {
|
|
2272
|
-
type: 'content-api',
|
|
2273
|
-
routes: [
|
|
2274
|
-
{
|
|
2275
|
-
method: 'POST',
|
|
2276
|
-
path: '/',
|
|
2277
|
-
handler: 'content-api.upload'
|
|
2278
|
-
},
|
|
2279
|
-
{
|
|
2280
|
-
method: 'GET',
|
|
2281
|
-
path: '/files',
|
|
2282
|
-
handler: 'content-api.find'
|
|
2283
|
-
},
|
|
2284
|
-
{
|
|
2285
|
-
method: 'GET',
|
|
2286
|
-
path: '/files/:id',
|
|
2287
|
-
handler: 'content-api.findOne'
|
|
2288
|
-
},
|
|
2289
|
-
{
|
|
2290
|
-
method: 'DELETE',
|
|
2291
|
-
path: '/files/:id',
|
|
2292
|
-
handler: 'content-api.destroy'
|
|
2293
|
-
}
|
|
2294
|
-
]
|
|
2295
|
-
};
|
|
2296
|
-
|
|
2297
|
-
const routes$1 = {
|
|
2298
|
-
type: 'admin',
|
|
2299
|
-
routes: [
|
|
2300
|
-
{
|
|
2301
|
-
method: 'GET',
|
|
2302
|
-
path: '/configuration',
|
|
2303
|
-
handler: 'view-configuration.findViewConfiguration',
|
|
2304
|
-
config: {
|
|
2305
|
-
policies: [
|
|
2306
|
-
'admin::isAuthenticatedAdmin'
|
|
2307
|
-
]
|
|
2308
|
-
}
|
|
2309
|
-
},
|
|
2310
|
-
{
|
|
2311
|
-
method: 'PUT',
|
|
2312
|
-
path: '/configuration',
|
|
2313
|
-
handler: 'view-configuration.updateViewConfiguration',
|
|
2314
|
-
config: {
|
|
2315
|
-
policies: [
|
|
2316
|
-
'admin::isAuthenticatedAdmin',
|
|
2317
|
-
{
|
|
2318
|
-
name: 'admin::hasPermissions',
|
|
2319
|
-
config: {
|
|
2320
|
-
actions: [
|
|
2321
|
-
ACTIONS.configureView
|
|
2322
|
-
]
|
|
2323
|
-
}
|
|
2324
|
-
}
|
|
2325
|
-
]
|
|
2326
|
-
}
|
|
2327
|
-
}
|
|
2328
|
-
]
|
|
2329
|
-
};
|
|
2330
|
-
|
|
2331
|
-
const routes = {
|
|
2332
|
-
admin: routes$3,
|
|
2333
|
-
'content-api': routes$2,
|
|
2334
|
-
viewConfiguration: routes$1
|
|
2335
|
-
};
|
|
2336
|
-
|
|
2337
|
-
const config = {
|
|
2338
|
-
default: {
|
|
2339
|
-
enabled: true,
|
|
2340
|
-
provider: 'local',
|
|
2341
|
-
sizeLimit: 1000000000,
|
|
2342
|
-
actionOptions: {}
|
|
2343
|
-
},
|
|
2344
|
-
validator () {}
|
|
2345
|
-
};
|
|
2346
|
-
|
|
2347
|
-
const findEntityAndCheckPermissions = async (ability, action, model, id)=>{
|
|
2348
|
-
const file = await getService('upload').findOne(id, [
|
|
2349
|
-
contentTypes$1.constants.CREATED_BY_ATTRIBUTE,
|
|
2350
|
-
'folder'
|
|
2351
|
-
]);
|
|
2352
|
-
if (_.isNil(file)) {
|
|
2353
|
-
throw new errors.NotFoundError();
|
|
2354
|
-
}
|
|
2355
|
-
const pm = strapi.service('admin::permission').createPermissionsManager({
|
|
2356
|
-
ability,
|
|
2357
|
-
action,
|
|
2358
|
-
model
|
|
2359
|
-
});
|
|
2360
|
-
const creatorId = _.get(file, [
|
|
2361
|
-
contentTypes$1.constants.CREATED_BY_ATTRIBUTE,
|
|
2362
|
-
'id'
|
|
2363
|
-
]);
|
|
2364
|
-
const author = creatorId ? await strapi.service('admin::user').findOne(creatorId, [
|
|
2365
|
-
'roles'
|
|
2366
|
-
]) : null;
|
|
2367
|
-
const fileWithRoles = _.set(_.cloneDeep(file), 'createdBy', author);
|
|
2368
|
-
if (pm.ability.cannot(pm.action, pm.toSubject(fileWithRoles))) {
|
|
2369
|
-
throw new errors.ForbiddenError();
|
|
2370
|
-
}
|
|
2371
|
-
return {
|
|
2372
|
-
pm,
|
|
2373
|
-
file
|
|
2374
|
-
};
|
|
2375
|
-
};
|
|
2376
|
-
|
|
2377
|
-
var adminFile = {
|
|
2378
|
-
async find (ctx) {
|
|
2379
|
-
const { state: { userAbility } } = ctx;
|
|
2380
|
-
const defaultQuery = {
|
|
2381
|
-
populate: {
|
|
2382
|
-
folder: true
|
|
2383
|
-
}
|
|
2384
|
-
};
|
|
2385
|
-
const pm = strapi.service('admin::permission').createPermissionsManager({
|
|
2386
|
-
ability: userAbility,
|
|
2387
|
-
action: ACTIONS.read,
|
|
2388
|
-
model: FILE_MODEL_UID
|
|
2389
|
-
});
|
|
2390
|
-
if (!pm.isAllowed) {
|
|
2391
|
-
return ctx.forbidden();
|
|
2392
|
-
}
|
|
2393
|
-
// validate the incoming user query params
|
|
2394
|
-
await pm.validateQuery(ctx.query);
|
|
2395
|
-
const query = await async.pipe(// Start by sanitizing the incoming query
|
|
2396
|
-
(q)=>pm.sanitizeQuery(q), // Add the default query which should not be validated or sanitized
|
|
2397
|
-
(q)=>merge(defaultQuery, q), // Add the dynamic filters based on permissions' conditions
|
|
2398
|
-
(q)=>pm.addPermissionsQueryTo(q))(ctx.query);
|
|
2399
|
-
const { results: files, pagination } = await getService('upload').findPage(query);
|
|
2400
|
-
// Sign file urls for private providers
|
|
2401
|
-
const signedFiles = await async.map(files, getService('file').signFileUrls);
|
|
2402
|
-
const sanitizedFiles = await pm.sanitizeOutput(signedFiles);
|
|
2403
|
-
return {
|
|
2404
|
-
results: sanitizedFiles,
|
|
2405
|
-
pagination
|
|
2406
|
-
};
|
|
2407
|
-
},
|
|
2408
|
-
async findOne (ctx) {
|
|
2409
|
-
const { state: { userAbility }, params: { id } } = ctx;
|
|
2410
|
-
const { pm, file } = await findEntityAndCheckPermissions(userAbility, ACTIONS.read, FILE_MODEL_UID, id);
|
|
2411
|
-
const signedFile = await getService('file').signFileUrls(file);
|
|
2412
|
-
ctx.body = await pm.sanitizeOutput(signedFile);
|
|
2413
|
-
},
|
|
2414
|
-
async destroy (ctx) {
|
|
2415
|
-
const { id } = ctx.params;
|
|
2416
|
-
const { userAbility } = ctx.state;
|
|
2417
|
-
const { pm, file } = await findEntityAndCheckPermissions(userAbility, ACTIONS.update, FILE_MODEL_UID, id);
|
|
2418
|
-
const [body] = await Promise.all([
|
|
2419
|
-
pm.sanitizeOutput(file, {
|
|
2420
|
-
action: ACTIONS.read
|
|
2421
|
-
}),
|
|
2422
|
-
getService('upload').remove(file)
|
|
2423
|
-
]);
|
|
2424
|
-
ctx.body = body;
|
|
2425
|
-
}
|
|
2426
|
-
};
|
|
2427
|
-
|
|
2428
|
-
const folderExists = async (folderId)=>{
|
|
2429
|
-
if (isNil(folderId)) {
|
|
2430
|
-
return true;
|
|
2431
|
-
}
|
|
2432
|
-
const exists = await getService('folder').exists({
|
|
2433
|
-
id: folderId
|
|
2434
|
-
});
|
|
2435
|
-
return exists;
|
|
2436
|
-
};
|
|
2437
|
-
|
|
2438
|
-
const isFolderOrChild = (folderOrChild, folder)=>folderOrChild.path === folder.path || folderOrChild.path.startsWith(`${folder.path}/`);
|
|
2439
|
-
|
|
2440
|
-
const NO_SLASH_REGEX = /^[^/]+$/;
|
|
2441
|
-
const NO_SPACES_AROUND = RegExp("^(?! ).+(?<! )$");
|
|
2442
|
-
const isNameUniqueInFolder = (id)=>{
|
|
2443
|
-
return async function test(name) {
|
|
2444
|
-
const { exists } = getService('folder');
|
|
2445
|
-
const filters = {
|
|
2446
|
-
name,
|
|
2447
|
-
parent: this.parent.parent || null
|
|
2448
|
-
};
|
|
2449
|
-
if (id) {
|
|
2450
|
-
filters.id = {
|
|
2451
|
-
$ne: id
|
|
2452
|
-
};
|
|
2453
|
-
if (isUndefined(name)) {
|
|
2454
|
-
const existingFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
2455
|
-
where: {
|
|
2456
|
-
id
|
|
2457
|
-
}
|
|
2458
|
-
});
|
|
2459
|
-
filters.name = get('name', existingFolder);
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
const doesExist = await exists(filters);
|
|
2463
|
-
return !doesExist;
|
|
2464
|
-
};
|
|
2465
|
-
};
|
|
2466
|
-
const validateCreateFolderSchema = yup.object().shape({
|
|
2467
|
-
name: yup.string().min(1).matches(NO_SLASH_REGEX, 'name cannot contain slashes').matches(NO_SPACES_AROUND, 'name cannot start or end with a whitespace').required().test('is-folder-unique', 'A folder with this name already exists', isNameUniqueInFolder()),
|
|
2468
|
-
parent: yup.strapiID().nullable().test('folder-exists', 'parent folder does not exist', folderExists)
|
|
2469
|
-
}).noUnknown().required();
|
|
2470
|
-
const validateUpdateFolderSchema = (id)=>yup.object().shape({
|
|
2471
|
-
name: yup.string().min(1).matches(NO_SLASH_REGEX, 'name cannot contain slashes').matches(NO_SPACES_AROUND, 'name cannot start or end with a whitespace').test('is-folder-unique', 'A folder with this name already exists', isNameUniqueInFolder(id)),
|
|
2472
|
-
parent: yup.strapiID().nullable().test('folder-exists', 'parent folder does not exist', folderExists).test('dont-move-inside-self', 'folder cannot be moved inside itself', async function test(parent) {
|
|
2473
|
-
if (isNil(parent)) return true;
|
|
2474
|
-
const destinationFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
2475
|
-
select: [
|
|
2476
|
-
'path'
|
|
2477
|
-
],
|
|
2478
|
-
where: {
|
|
2479
|
-
id: parent
|
|
2480
|
-
}
|
|
2481
|
-
});
|
|
2482
|
-
const currentFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
2483
|
-
select: [
|
|
2484
|
-
'path'
|
|
2485
|
-
],
|
|
2486
|
-
where: {
|
|
2487
|
-
id
|
|
2488
|
-
}
|
|
2489
|
-
});
|
|
2490
|
-
if (!destinationFolder || !currentFolder) return true;
|
|
2491
|
-
return !isFolderOrChild(destinationFolder, currentFolder);
|
|
2492
|
-
})
|
|
2493
|
-
}).noUnknown().required();
|
|
2494
|
-
const validateCreateFolder = validateYupSchema(validateCreateFolderSchema);
|
|
2495
|
-
const validateUpdateFolder = (id)=>validateYupSchema(validateUpdateFolderSchema(id));
|
|
2496
|
-
|
|
2497
|
-
var adminFolder = {
|
|
2498
|
-
async findOne (ctx) {
|
|
2499
|
-
const { id } = ctx.params;
|
|
2500
|
-
const permissionsManager = strapi.service('admin::permission').createPermissionsManager({
|
|
2501
|
-
ability: ctx.state.userAbility,
|
|
2502
|
-
model: FOLDER_MODEL_UID
|
|
2503
|
-
});
|
|
2504
|
-
await permissionsManager.validateQuery(ctx.query);
|
|
2505
|
-
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
2506
|
-
const { results } = await strapi.db.query(FOLDER_MODEL_UID).findPage(strapi.get('query-params').transform(FOLDER_MODEL_UID, defaultsDeep({
|
|
2507
|
-
filters: {
|
|
2508
|
-
id
|
|
2509
|
-
},
|
|
2510
|
-
populate: {
|
|
2511
|
-
children: {
|
|
2512
|
-
count: true
|
|
2513
|
-
},
|
|
2514
|
-
files: {
|
|
2515
|
-
count: true
|
|
2516
|
-
}
|
|
2517
|
-
}
|
|
2518
|
-
}, query)));
|
|
2519
|
-
if (results.length === 0) {
|
|
2520
|
-
return ctx.notFound('folder not found');
|
|
2521
|
-
}
|
|
2522
|
-
ctx.body = {
|
|
2523
|
-
data: await permissionsManager.sanitizeOutput(results[0])
|
|
2524
|
-
};
|
|
2525
|
-
},
|
|
2526
|
-
async find (ctx) {
|
|
2527
|
-
const permissionsManager = strapi.service('admin::permission').createPermissionsManager({
|
|
2528
|
-
ability: ctx.state.userAbility,
|
|
2529
|
-
model: FOLDER_MODEL_UID
|
|
2530
|
-
});
|
|
2531
|
-
await permissionsManager.validateQuery(ctx.query);
|
|
2532
|
-
const query = await permissionsManager.sanitizeQuery(ctx.query);
|
|
2533
|
-
const results = await strapi.db.query(FOLDER_MODEL_UID).findMany(strapi.get('query-params').transform(FOLDER_MODEL_UID, defaultsDeep({
|
|
2534
|
-
populate: {
|
|
2535
|
-
children: {
|
|
2536
|
-
count: true
|
|
2537
|
-
},
|
|
2538
|
-
files: {
|
|
2539
|
-
count: true
|
|
2540
|
-
}
|
|
2541
|
-
}
|
|
2542
|
-
}, query)));
|
|
2543
|
-
ctx.body = {
|
|
2544
|
-
data: await permissionsManager.sanitizeOutput(results)
|
|
2545
|
-
};
|
|
2546
|
-
},
|
|
2547
|
-
async create (ctx) {
|
|
2548
|
-
const { user } = ctx.state;
|
|
2549
|
-
const { body } = ctx.request;
|
|
2550
|
-
await validateCreateFolder(body);
|
|
2551
|
-
const folderService = getService('folder');
|
|
2552
|
-
const folder = await folderService.create(body, {
|
|
2553
|
-
user
|
|
2554
|
-
});
|
|
2555
|
-
const permissionsManager = strapi.service('admin::permission').createPermissionsManager({
|
|
2556
|
-
ability: ctx.state.userAbility,
|
|
2557
|
-
model: FOLDER_MODEL_UID
|
|
2558
|
-
});
|
|
2559
|
-
ctx.created({
|
|
2560
|
-
data: await permissionsManager.sanitizeOutput(folder)
|
|
2561
|
-
});
|
|
2562
|
-
},
|
|
2563
|
-
async update (ctx) {
|
|
2564
|
-
const { id } = ctx.params;
|
|
2565
|
-
const { user } = ctx.state;
|
|
2566
|
-
const { body } = ctx.request;
|
|
2567
|
-
const permissionsManager = strapi.service('admin::permission').createPermissionsManager({
|
|
2568
|
-
ability: ctx.state.userAbility,
|
|
2569
|
-
model: FOLDER_MODEL_UID
|
|
2570
|
-
});
|
|
2571
|
-
await validateUpdateFolder(id)(body);
|
|
2572
|
-
const folderService = getService('folder');
|
|
2573
|
-
const updatedFolder = await folderService.update(id, body, {
|
|
2574
|
-
user
|
|
2575
|
-
});
|
|
2576
|
-
if (!updatedFolder) {
|
|
2577
|
-
return ctx.notFound('folder not found');
|
|
2578
|
-
}
|
|
2579
|
-
ctx.body = {
|
|
2580
|
-
data: await permissionsManager.sanitizeOutput(updatedFolder)
|
|
2581
|
-
};
|
|
2582
|
-
},
|
|
2583
|
-
async getStructure (ctx) {
|
|
2584
|
-
const { getStructure } = getService('folder');
|
|
2585
|
-
const structure = await getStructure();
|
|
2586
|
-
ctx.body = {
|
|
2587
|
-
data: structure
|
|
2588
|
-
};
|
|
2589
|
-
}
|
|
2590
|
-
};
|
|
2591
|
-
|
|
2592
|
-
const validateDeleteManyFoldersFilesSchema = yup.object().shape({
|
|
2593
|
-
fileIds: yup.array().of(yup.strapiID().required()),
|
|
2594
|
-
folderIds: yup.array().of(yup.strapiID().required())
|
|
2595
|
-
}).noUnknown().required();
|
|
2596
|
-
const validateStructureMoveManyFoldersFilesSchema = yup.object().shape({
|
|
2597
|
-
destinationFolderId: yup.strapiID().nullable().defined().test('folder-exists', 'destination folder does not exist', folderExists),
|
|
2598
|
-
fileIds: yup.array().of(yup.strapiID().required()),
|
|
2599
|
-
folderIds: yup.array().of(yup.strapiID().required())
|
|
2600
|
-
}).noUnknown().required();
|
|
2601
|
-
const validateDuplicatesMoveManyFoldersFilesSchema = yup.object().test('are-folders-unique', 'some folders already exist', async function areFoldersUnique(value) {
|
|
2602
|
-
const { folderIds, destinationFolderId } = value;
|
|
2603
|
-
if (isEmpty(folderIds)) return true;
|
|
2604
|
-
const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({
|
|
2605
|
-
select: [
|
|
2606
|
-
'name'
|
|
2607
|
-
],
|
|
2608
|
-
where: {
|
|
2609
|
-
id: {
|
|
2610
|
-
$in: folderIds
|
|
2611
|
-
}
|
|
2612
|
-
}
|
|
2613
|
-
});
|
|
2614
|
-
const existingFolders = await strapi.db.query(FOLDER_MODEL_UID).findMany({
|
|
2615
|
-
select: [
|
|
2616
|
-
'name'
|
|
2617
|
-
],
|
|
2618
|
-
where: {
|
|
2619
|
-
parent: {
|
|
2620
|
-
id: destinationFolderId
|
|
2621
|
-
}
|
|
2622
|
-
}
|
|
2623
|
-
});
|
|
2624
|
-
const duplicatedNames = intersection(map('name', folders), map('name', existingFolders));
|
|
2625
|
-
if (duplicatedNames.length > 0) {
|
|
2626
|
-
return this.createError({
|
|
2627
|
-
message: `some folders already exists: ${duplicatedNames.join(', ')}`
|
|
2628
|
-
});
|
|
2629
|
-
}
|
|
2630
|
-
return true;
|
|
2631
|
-
});
|
|
2632
|
-
const validateMoveFoldersNotInsideThemselvesSchema = yup.object().test('dont-move-inside-self', 'folders cannot be moved inside themselves or one of its children', async function validateMoveFoldersNotInsideThemselves(value) {
|
|
2633
|
-
const { folderIds, destinationFolderId } = value;
|
|
2634
|
-
if (destinationFolderId === null || isEmpty(folderIds)) return true;
|
|
2635
|
-
const destinationFolder = await strapi.db.query(FOLDER_MODEL_UID).findOne({
|
|
2636
|
-
select: [
|
|
2637
|
-
'path'
|
|
2638
|
-
],
|
|
2639
|
-
where: {
|
|
2640
|
-
id: destinationFolderId
|
|
2641
|
-
}
|
|
2642
|
-
});
|
|
2643
|
-
const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({
|
|
2644
|
-
select: [
|
|
2645
|
-
'name',
|
|
2646
|
-
'path'
|
|
2647
|
-
],
|
|
2648
|
-
where: {
|
|
2649
|
-
id: {
|
|
2650
|
-
$in: folderIds
|
|
2651
|
-
}
|
|
2652
|
-
}
|
|
2653
|
-
});
|
|
2654
|
-
const unmovableFoldersNames = folders.filter((folder)=>isFolderOrChild(destinationFolder, folder)).map((f)=>f.name);
|
|
2655
|
-
if (unmovableFoldersNames.length > 0) {
|
|
2656
|
-
return this.createError({
|
|
2657
|
-
message: `folders cannot be moved inside themselves or one of its children: ${unmovableFoldersNames.join(', ')}`
|
|
2658
|
-
});
|
|
2659
|
-
}
|
|
2660
|
-
return true;
|
|
2661
|
-
});
|
|
2662
|
-
const validateDeleteManyFoldersFiles = validateYupSchema(validateDeleteManyFoldersFilesSchema);
|
|
2663
|
-
async function validateMoveManyFoldersFiles(body) {
|
|
2664
|
-
await validateYupSchema(validateStructureMoveManyFoldersFilesSchema)(body);
|
|
2665
|
-
await validateYupSchema(validateDuplicatesMoveManyFoldersFilesSchema)(body);
|
|
2666
|
-
await validateYupSchema(validateMoveFoldersNotInsideThemselvesSchema)(body);
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
var adminFolderFile = {
|
|
2670
|
-
async deleteMany (ctx) {
|
|
2671
|
-
const { body } = ctx.request;
|
|
2672
|
-
const { state: { userAbility } } = ctx;
|
|
2673
|
-
const pmFolder = strapi.service('admin::permission').createPermissionsManager({
|
|
2674
|
-
ability: ctx.state.userAbility,
|
|
2675
|
-
model: FOLDER_MODEL_UID
|
|
2676
|
-
});
|
|
2677
|
-
const pmFile = strapi.service('admin::permission').createPermissionsManager({
|
|
2678
|
-
ability: userAbility,
|
|
2679
|
-
action: ACTIONS.read,
|
|
2680
|
-
model: FILE_MODEL_UID
|
|
2681
|
-
});
|
|
2682
|
-
await validateDeleteManyFoldersFiles(body);
|
|
2683
|
-
const fileService = getService('file');
|
|
2684
|
-
const folderService = getService('folder');
|
|
2685
|
-
const deletedFiles = await fileService.deleteByIds(body.fileIds);
|
|
2686
|
-
const { folders: deletedFolders, totalFolderNumber, totalFileNumber } = await folderService.deleteByIds(body.folderIds);
|
|
2687
|
-
if (deletedFiles.length + deletedFolders.length > 1) {
|
|
2688
|
-
strapi.telemetry.send('didBulkDeleteMediaLibraryElements', {
|
|
2689
|
-
eventProperties: {
|
|
2690
|
-
rootFolderNumber: deletedFolders.length,
|
|
2691
|
-
rootAssetNumber: deletedFiles.length,
|
|
2692
|
-
totalFolderNumber,
|
|
2693
|
-
totalAssetNumber: totalFileNumber + deletedFiles.length
|
|
2694
|
-
}
|
|
2695
|
-
});
|
|
2696
|
-
}
|
|
2697
|
-
ctx.body = {
|
|
2698
|
-
data: {
|
|
2699
|
-
files: await pmFile.sanitizeOutput(deletedFiles),
|
|
2700
|
-
folders: await pmFolder.sanitizeOutput(deletedFolders)
|
|
2701
|
-
}
|
|
2702
|
-
};
|
|
2703
|
-
},
|
|
2704
|
-
async moveMany (ctx) {
|
|
2705
|
-
const { body } = ctx.request;
|
|
2706
|
-
const { state: { userAbility } } = ctx;
|
|
2707
|
-
const pmFolder = strapi.service('admin::permission').createPermissionsManager({
|
|
2708
|
-
ability: ctx.state.userAbility,
|
|
2709
|
-
model: FOLDER_MODEL_UID
|
|
2710
|
-
});
|
|
2711
|
-
const pmFile = strapi.service('admin::permission').createPermissionsManager({
|
|
2712
|
-
ability: userAbility,
|
|
2713
|
-
action: ACTIONS.read,
|
|
2714
|
-
model: FILE_MODEL_UID
|
|
2715
|
-
});
|
|
2716
|
-
await validateMoveManyFoldersFiles(body);
|
|
2717
|
-
const { folderIds = [], fileIds = [], destinationFolderId } = body;
|
|
2718
|
-
let totalFolderNumber = 0;
|
|
2719
|
-
let totalFileNumber = 0;
|
|
2720
|
-
const trx = await strapi.db.transaction();
|
|
2721
|
-
try {
|
|
2722
|
-
// fetch folders
|
|
2723
|
-
const existingFolders = await strapi.db.queryBuilder(FOLDER_MODEL_UID).select([
|
|
2724
|
-
'id',
|
|
2725
|
-
'pathId',
|
|
2726
|
-
'path'
|
|
2727
|
-
]).where({
|
|
2728
|
-
id: {
|
|
2729
|
-
$in: folderIds
|
|
2730
|
-
}
|
|
2731
|
-
}).transacting(trx.get()).forUpdate().execute();
|
|
2732
|
-
// fetch files
|
|
2733
|
-
const existingFiles = await strapi.db.queryBuilder(FILE_MODEL_UID).select([
|
|
2734
|
-
'id'
|
|
2735
|
-
]).where({
|
|
2736
|
-
id: {
|
|
2737
|
-
$in: fileIds
|
|
2738
|
-
}
|
|
2739
|
-
}).transacting(trx.get()).forUpdate().execute();
|
|
2740
|
-
// fetch destinationFolder path
|
|
2741
|
-
let destinationFolderPath = '/';
|
|
2742
|
-
if (destinationFolderId !== null) {
|
|
2743
|
-
const destinationFolder = await strapi.db.queryBuilder(FOLDER_MODEL_UID).select('path').where({
|
|
2744
|
-
id: destinationFolderId
|
|
2745
|
-
}).transacting(trx.get()).first().execute();
|
|
2746
|
-
destinationFolderPath = destinationFolder.path;
|
|
2747
|
-
}
|
|
2748
|
-
const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;
|
|
2749
|
-
const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;
|
|
2750
|
-
const folderPathColName = // @ts-expect-error - no dynamic typings for the models
|
|
2751
|
-
strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath.columnName;
|
|
2752
|
-
// @ts-expect-error - no dynamic typings for the models
|
|
2753
|
-
const pathColName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;
|
|
2754
|
-
if (existingFolders.length > 0) {
|
|
2755
|
-
// update folders' parent relation
|
|
2756
|
-
// @ts-expect-error - no dynamic typings for the models
|
|
2757
|
-
const { joinTable } = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent;
|
|
2758
|
-
await strapi.db.queryBuilder(joinTable.name).transacting(trx.get()).delete().where({
|
|
2759
|
-
[joinTable.joinColumn.name]: {
|
|
2760
|
-
$in: folderIds
|
|
2761
|
-
}
|
|
2762
|
-
}).execute();
|
|
2763
|
-
if (destinationFolderId !== null) {
|
|
2764
|
-
await strapi.db.queryBuilder(joinTable.name).transacting(trx.get()).insert(existingFolders.map((folder)=>({
|
|
2765
|
-
[joinTable.inverseJoinColumn.name]: destinationFolderId,
|
|
2766
|
-
[joinTable.joinColumn.name]: folder.id
|
|
2767
|
-
}))).execute();
|
|
2768
|
-
}
|
|
2769
|
-
for (const existingFolder of existingFolders){
|
|
2770
|
-
let replaceQuery;
|
|
2771
|
-
switch(strapi.db.dialect.client){
|
|
2772
|
-
case 'sqlite':
|
|
2773
|
-
replaceQuery = '? || SUBSTRING(??, ?)';
|
|
2774
|
-
break;
|
|
2775
|
-
case 'postgres':
|
|
2776
|
-
replaceQuery = 'CONCAT(?::TEXT, SUBSTRING(??, ?::INTEGER))';
|
|
2777
|
-
break;
|
|
2778
|
-
default:
|
|
2779
|
-
replaceQuery = 'CONCAT(?, SUBSTRING(??, ?))';
|
|
2780
|
-
}
|
|
2781
|
-
// update path for folders themselves & folders below
|
|
2782
|
-
totalFolderNumber = await strapi.db.getConnection(folderTable).transacting(trx.get()).where(pathColName, existingFolder.path).orWhere(pathColName, 'like', `${existingFolder.path}/%`).update(pathColName, strapi.db.connection.raw(replaceQuery, [
|
|
2783
|
-
strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),
|
|
2784
|
-
pathColName,
|
|
2785
|
-
existingFolder.path.length + 1
|
|
2786
|
-
]));
|
|
2787
|
-
// update path of files below
|
|
2788
|
-
totalFileNumber = await strapi.db.getConnection(fileTable).transacting(trx.get()).where(folderPathColName, existingFolder.path).orWhere(folderPathColName, 'like', `${existingFolder.path}/%`).update(folderPathColName, strapi.db.connection.raw(replaceQuery, [
|
|
2789
|
-
strings.joinBy('/', destinationFolderPath, `${existingFolder.pathId}`),
|
|
2790
|
-
folderPathColName,
|
|
2791
|
-
existingFolder.path.length + 1
|
|
2792
|
-
]));
|
|
2793
|
-
}
|
|
2794
|
-
}
|
|
2795
|
-
if (existingFiles.length > 0) {
|
|
2796
|
-
// update files' folder relation (delete + insert; upsert not possible)
|
|
2797
|
-
// @ts-expect-error - no dynamic typings for the models
|
|
2798
|
-
const fileJoinTable = strapi.db.metadata.get(FILE_MODEL_UID).attributes.folder.joinTable;
|
|
2799
|
-
await strapi.db.queryBuilder(fileJoinTable.name).transacting(trx.get()).delete().where({
|
|
2800
|
-
[fileJoinTable.joinColumn.name]: {
|
|
2801
|
-
$in: fileIds
|
|
2802
|
-
}
|
|
2803
|
-
}).execute();
|
|
2804
|
-
if (destinationFolderId !== null) {
|
|
2805
|
-
await strapi.db.queryBuilder(fileJoinTable.name).transacting(trx.get()).insert(existingFiles.map((file)=>({
|
|
2806
|
-
[fileJoinTable.inverseJoinColumn.name]: destinationFolderId,
|
|
2807
|
-
[fileJoinTable.joinColumn.name]: file.id
|
|
2808
|
-
}))).execute();
|
|
2809
|
-
}
|
|
2810
|
-
// update files main fields (path + updatedBy)
|
|
2811
|
-
await strapi.db.getConnection(fileTable).transacting(trx.get()).whereIn('id', fileIds).update(folderPathColName, destinationFolderPath);
|
|
2812
|
-
}
|
|
2813
|
-
await trx.commit();
|
|
2814
|
-
} catch (e) {
|
|
2815
|
-
await trx.rollback();
|
|
2816
|
-
throw e;
|
|
2817
|
-
}
|
|
2818
|
-
const updatedFolders = await strapi.db.query(FOLDER_MODEL_UID).findMany({
|
|
2819
|
-
where: {
|
|
2820
|
-
id: {
|
|
2821
|
-
$in: folderIds
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
});
|
|
2825
|
-
const updatedFiles = await strapi.db.query(FILE_MODEL_UID).findMany({
|
|
2826
|
-
where: {
|
|
2827
|
-
id: {
|
|
2828
|
-
$in: fileIds
|
|
2829
|
-
}
|
|
2830
|
-
}
|
|
2831
|
-
});
|
|
2832
|
-
strapi.telemetry.send('didBulkMoveMediaLibraryElements', {
|
|
2833
|
-
eventProperties: {
|
|
2834
|
-
rootFolderNumber: updatedFolders.length,
|
|
2835
|
-
rootAssetNumber: updatedFiles.length,
|
|
2836
|
-
totalFolderNumber,
|
|
2837
|
-
totalAssetNumber: totalFileNumber + updatedFiles.length
|
|
2838
|
-
}
|
|
2839
|
-
});
|
|
2840
|
-
ctx.body = {
|
|
2841
|
-
data: {
|
|
2842
|
-
files: await pmFile.sanitizeOutput(updatedFiles),
|
|
2843
|
-
folders: await pmFolder.sanitizeOutput(updatedFolders)
|
|
2844
|
-
}
|
|
2845
|
-
};
|
|
2846
|
-
}
|
|
2847
|
-
};
|
|
2848
|
-
|
|
2849
|
-
const settingsSchema = yup.object({
|
|
2850
|
-
sizeOptimization: yup.boolean().required(),
|
|
2851
|
-
responsiveDimensions: yup.boolean().required(),
|
|
2852
|
-
autoOrientation: yup.boolean()
|
|
2853
|
-
});
|
|
2854
|
-
var validateSettings = validateYupSchema(settingsSchema);
|
|
2855
|
-
|
|
2856
|
-
var adminSettings = {
|
|
2857
|
-
async updateSettings (ctx) {
|
|
2858
|
-
const { request: { body }, state: { userAbility } } = ctx;
|
|
2859
|
-
if (userAbility.cannot(ACTIONS.readSettings, FILE_MODEL_UID)) {
|
|
2860
|
-
return ctx.forbidden();
|
|
2861
|
-
}
|
|
2862
|
-
const data = await validateSettings(body);
|
|
2863
|
-
await getService('upload').setSettings(data);
|
|
2864
|
-
ctx.body = {
|
|
2865
|
-
data
|
|
2866
|
-
};
|
|
2867
|
-
},
|
|
2868
|
-
async getSettings (ctx) {
|
|
2869
|
-
const { state: { userAbility } } = ctx;
|
|
2870
|
-
if (userAbility.cannot(ACTIONS.readSettings, FILE_MODEL_UID)) {
|
|
2871
|
-
return ctx.forbidden();
|
|
2872
|
-
}
|
|
2873
|
-
const data = await getService('upload').getSettings();
|
|
2874
|
-
ctx.body = {
|
|
2875
|
-
data
|
|
2876
|
-
};
|
|
2877
|
-
}
|
|
2878
|
-
};
|
|
2879
|
-
|
|
2880
|
-
const fileInfoSchema$1 = yup.object({
|
|
2881
|
-
name: yup.string().nullable(),
|
|
2882
|
-
alternativeText: yup.string().nullable(),
|
|
2883
|
-
caption: yup.string().nullable(),
|
|
2884
|
-
folder: yup.strapiID().nullable().test('folder-exists', 'the folder does not exist', async (folderId)=>{
|
|
2885
|
-
if (isNil(folderId)) {
|
|
2886
|
-
return true;
|
|
2887
|
-
}
|
|
2888
|
-
const exists = await getService('folder').exists({
|
|
2889
|
-
id: folderId
|
|
2890
|
-
});
|
|
2891
|
-
return exists;
|
|
2892
|
-
})
|
|
2893
|
-
});
|
|
2894
|
-
const uploadSchema$1 = yup.object({
|
|
2895
|
-
fileInfo: fileInfoSchema$1
|
|
2896
|
-
});
|
|
2897
|
-
const multiUploadSchema$1 = yup.object({
|
|
2898
|
-
fileInfo: yup.array().of(fileInfoSchema$1)
|
|
2899
|
-
});
|
|
2900
|
-
const validateUploadBody$1 = (data = {}, isMulti = false)=>{
|
|
2901
|
-
const schema = isMulti ? multiUploadSchema$1 : uploadSchema$1;
|
|
2902
|
-
return validateYupSchema(schema, {
|
|
2903
|
-
strict: false
|
|
2904
|
-
})(data);
|
|
2905
|
-
};
|
|
2906
|
-
|
|
2907
|
-
var adminUpload = {
|
|
2908
|
-
async updateFileInfo (ctx) {
|
|
2909
|
-
const { state: { userAbility, user }, query: { id }, request: { body } } = ctx;
|
|
2910
|
-
if (typeof id !== 'string') {
|
|
2911
|
-
throw new errors.ValidationError('File id is required');
|
|
2912
|
-
}
|
|
2913
|
-
const uploadService = getService('upload');
|
|
2914
|
-
const { pm } = await findEntityAndCheckPermissions(userAbility, ACTIONS.update, FILE_MODEL_UID, id);
|
|
2915
|
-
const data = await validateUploadBody$1(body);
|
|
2916
|
-
const file = await uploadService.updateFileInfo(id, data.fileInfo, {
|
|
2917
|
-
user
|
|
2918
|
-
});
|
|
2919
|
-
ctx.body = await pm.sanitizeOutput(file, {
|
|
2920
|
-
action: ACTIONS.read
|
|
2921
|
-
});
|
|
2922
|
-
},
|
|
2923
|
-
async replaceFile (ctx) {
|
|
2924
|
-
const { state: { userAbility, user }, query: { id }, request: { body, files: { files } = {} } } = ctx;
|
|
2925
|
-
if (typeof id !== 'string') {
|
|
2926
|
-
throw new errors.ValidationError('File id is required');
|
|
2927
|
-
}
|
|
2928
|
-
const uploadService = getService('upload');
|
|
2929
|
-
const { pm } = await findEntityAndCheckPermissions(userAbility, ACTIONS.update, FILE_MODEL_UID, id);
|
|
2930
|
-
if (Array.isArray(files)) {
|
|
2931
|
-
throw new errors.ApplicationError('Cannot replace a file with multiple ones');
|
|
2932
|
-
}
|
|
2933
|
-
const data = await validateUploadBody$1(body);
|
|
2934
|
-
const replacedFile = await uploadService.replace(id, {
|
|
2935
|
-
data,
|
|
2936
|
-
file: files
|
|
2937
|
-
}, {
|
|
2938
|
-
user
|
|
2939
|
-
});
|
|
2940
|
-
// Sign file urls for private providers
|
|
2941
|
-
const signedFile = await getService('file').signFileUrls(replacedFile);
|
|
2942
|
-
ctx.body = await pm.sanitizeOutput(signedFile, {
|
|
2943
|
-
action: ACTIONS.read
|
|
2944
|
-
});
|
|
2945
|
-
},
|
|
2946
|
-
async uploadFiles (ctx) {
|
|
2947
|
-
const { state: { userAbility, user }, request: { body, files: { files } = {} } } = ctx;
|
|
2948
|
-
const uploadService = getService('upload');
|
|
2949
|
-
const pm = strapi.service('admin::permission').createPermissionsManager({
|
|
2950
|
-
ability: userAbility,
|
|
2951
|
-
action: ACTIONS.create,
|
|
2952
|
-
model: FILE_MODEL_UID
|
|
2953
|
-
});
|
|
2954
|
-
if (!pm.isAllowed) {
|
|
2955
|
-
return ctx.forbidden();
|
|
2956
|
-
}
|
|
2957
|
-
const data = await validateUploadBody$1(body);
|
|
2958
|
-
const uploadedFiles = await uploadService.upload({
|
|
2959
|
-
data,
|
|
2960
|
-
files
|
|
2961
|
-
}, {
|
|
2962
|
-
user
|
|
2963
|
-
});
|
|
2964
|
-
// Sign file urls for private providers
|
|
2965
|
-
const signedFiles = await async.map(uploadedFiles, getService('file').signFileUrls);
|
|
2966
|
-
ctx.body = await pm.sanitizeOutput(signedFiles, {
|
|
2967
|
-
action: ACTIONS.read
|
|
2968
|
-
});
|
|
2969
|
-
ctx.status = 201;
|
|
2970
|
-
},
|
|
2971
|
-
// TODO: split into multiple endpoints
|
|
2972
|
-
async upload (ctx) {
|
|
2973
|
-
const { query: { id }, request: { files: { files } = {} } } = ctx;
|
|
2974
|
-
if (_.isEmpty(files) || !Array.isArray(files) && files.size === 0) {
|
|
2975
|
-
if (id) {
|
|
2976
|
-
return this.updateFileInfo(ctx);
|
|
2977
|
-
}
|
|
2978
|
-
throw new errors.ApplicationError('Files are empty');
|
|
2979
|
-
}
|
|
2980
|
-
await (id ? this.replaceFile : this.uploadFiles)(ctx);
|
|
2981
|
-
}
|
|
2982
|
-
};
|
|
2983
|
-
|
|
2984
|
-
const fileInfoSchema = yup.object({
|
|
2985
|
-
name: yup.string().nullable(),
|
|
2986
|
-
alternativeText: yup.string().nullable(),
|
|
2987
|
-
caption: yup.string().nullable()
|
|
2988
|
-
}).noUnknown();
|
|
2989
|
-
const uploadSchema = yup.object({
|
|
2990
|
-
fileInfo: fileInfoSchema
|
|
2991
|
-
});
|
|
2992
|
-
const multiUploadSchema = yup.object({
|
|
2993
|
-
fileInfo: yup.array().of(fileInfoSchema)
|
|
2994
|
-
});
|
|
2995
|
-
const validateUploadBody = (data = {}, isMulti = false)=>{
|
|
2996
|
-
const schema = isMulti ? multiUploadSchema : uploadSchema;
|
|
2997
|
-
return validateYupSchema(schema, {
|
|
2998
|
-
strict: false
|
|
2999
|
-
})(data);
|
|
3000
|
-
};
|
|
3001
|
-
|
|
3002
|
-
const { ValidationError } = utils.errors;
|
|
3003
|
-
var contentApi = (({ strapi })=>{
|
|
3004
|
-
const sanitizeOutput = async (data, ctx)=>{
|
|
3005
|
-
const schema = strapi.getModel(FILE_MODEL_UID);
|
|
3006
|
-
const { auth } = ctx.state;
|
|
3007
|
-
return strapi.contentAPI.sanitize.output(data, schema, {
|
|
3008
|
-
auth
|
|
3009
|
-
});
|
|
3010
|
-
};
|
|
3011
|
-
const validateQuery = async (data, ctx)=>{
|
|
3012
|
-
const schema = strapi.getModel(FILE_MODEL_UID);
|
|
3013
|
-
const { auth } = ctx.state;
|
|
3014
|
-
return strapi.contentAPI.validate.query(data, schema, {
|
|
3015
|
-
auth
|
|
3016
|
-
});
|
|
3017
|
-
};
|
|
3018
|
-
const sanitizeQuery = async (data, ctx)=>{
|
|
3019
|
-
const schema = strapi.getModel(FILE_MODEL_UID);
|
|
3020
|
-
const { auth } = ctx.state;
|
|
3021
|
-
return strapi.contentAPI.sanitize.query(data, schema, {
|
|
3022
|
-
auth
|
|
3023
|
-
});
|
|
3024
|
-
};
|
|
3025
|
-
return {
|
|
3026
|
-
async find (ctx) {
|
|
3027
|
-
await validateQuery(ctx.query, ctx);
|
|
3028
|
-
const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);
|
|
3029
|
-
const files = await getService('upload').findMany(sanitizedQuery);
|
|
3030
|
-
ctx.body = await sanitizeOutput(files, ctx);
|
|
3031
|
-
},
|
|
3032
|
-
async findOne (ctx) {
|
|
3033
|
-
const { params: { id } } = ctx;
|
|
3034
|
-
await validateQuery(ctx.query, ctx);
|
|
3035
|
-
const sanitizedQuery = await sanitizeQuery(ctx.query, ctx);
|
|
3036
|
-
const file = await getService('upload').findOne(id, sanitizedQuery.populate);
|
|
3037
|
-
if (!file) {
|
|
3038
|
-
return ctx.notFound('file.notFound');
|
|
3039
|
-
}
|
|
3040
|
-
ctx.body = await sanitizeOutput(file, ctx);
|
|
3041
|
-
},
|
|
3042
|
-
async destroy (ctx) {
|
|
3043
|
-
const { params: { id } } = ctx;
|
|
3044
|
-
const file = await getService('upload').findOne(id);
|
|
3045
|
-
if (!file) {
|
|
3046
|
-
return ctx.notFound('file.notFound');
|
|
3047
|
-
}
|
|
3048
|
-
await getService('upload').remove(file);
|
|
3049
|
-
ctx.body = await sanitizeOutput(file, ctx);
|
|
3050
|
-
},
|
|
3051
|
-
async updateFileInfo (ctx) {
|
|
3052
|
-
const { query: { id }, request: { body } } = ctx;
|
|
3053
|
-
const data = await validateUploadBody(body);
|
|
3054
|
-
if (!id || typeof id !== 'string' && typeof id !== 'number') {
|
|
3055
|
-
throw new ValidationError('File id is required and must be a single value');
|
|
3056
|
-
}
|
|
3057
|
-
const result = await getService('upload').updateFileInfo(id, data.fileInfo);
|
|
3058
|
-
ctx.body = await sanitizeOutput(result, ctx);
|
|
3059
|
-
},
|
|
3060
|
-
async replaceFile (ctx) {
|
|
3061
|
-
const { query: { id }, request: { body, files: { files } = {} } } = ctx;
|
|
3062
|
-
// cannot replace with more than one file
|
|
3063
|
-
if (Array.isArray(files)) {
|
|
3064
|
-
throw new ValidationError('Cannot replace a file with multiple ones');
|
|
3065
|
-
}
|
|
3066
|
-
if (!id || typeof id !== 'string' && typeof id !== 'number') {
|
|
3067
|
-
throw new ValidationError('File id is required and must be a single value');
|
|
3068
|
-
}
|
|
3069
|
-
const data = await validateUploadBody(body);
|
|
3070
|
-
const replacedFiles = await getService('upload').replace(id, {
|
|
3071
|
-
data,
|
|
3072
|
-
file: files
|
|
3073
|
-
});
|
|
3074
|
-
ctx.body = await sanitizeOutput(replacedFiles, ctx);
|
|
3075
|
-
},
|
|
3076
|
-
async uploadFiles (ctx) {
|
|
3077
|
-
const { request: { body, files: { files } = {} } } = ctx;
|
|
3078
|
-
const data = await validateUploadBody(body, Array.isArray(files));
|
|
3079
|
-
const apiUploadFolderService = getService('api-upload-folder');
|
|
3080
|
-
const apiUploadFolder = await apiUploadFolderService.getAPIUploadFolder();
|
|
3081
|
-
if (Array.isArray(files)) {
|
|
3082
|
-
data.fileInfo = data.fileInfo || [];
|
|
3083
|
-
data.fileInfo = files.map((_f, i)=>({
|
|
3084
|
-
...data.fileInfo[i],
|
|
3085
|
-
folder: apiUploadFolder.id
|
|
3086
|
-
}));
|
|
3087
|
-
} else {
|
|
3088
|
-
data.fileInfo = {
|
|
3089
|
-
...data.fileInfo,
|
|
3090
|
-
folder: apiUploadFolder.id
|
|
3091
|
-
};
|
|
3092
|
-
}
|
|
3093
|
-
const uploadedFiles = await getService('upload').upload({
|
|
3094
|
-
data,
|
|
3095
|
-
files
|
|
3096
|
-
});
|
|
3097
|
-
ctx.body = await sanitizeOutput(uploadedFiles, ctx);
|
|
3098
|
-
ctx.status = 201;
|
|
3099
|
-
},
|
|
3100
|
-
// TODO: split into multiple endpoints
|
|
3101
|
-
async upload (ctx) {
|
|
3102
|
-
const { query: { id }, request: { files: { files } = {} } } = ctx;
|
|
3103
|
-
if (_.isEmpty(files) || !Array.isArray(files) && files.size === 0) {
|
|
3104
|
-
if (id) {
|
|
3105
|
-
return this.updateFileInfo(ctx);
|
|
3106
|
-
}
|
|
3107
|
-
throw new ValidationError('Files are empty');
|
|
3108
|
-
}
|
|
3109
|
-
await (id ? this.replaceFile : this.uploadFiles)(ctx);
|
|
3110
|
-
}
|
|
3111
|
-
};
|
|
3112
|
-
});
|
|
3113
|
-
|
|
3114
|
-
const configSchema = yup.object({
|
|
3115
|
-
pageSize: yup.number().required(),
|
|
3116
|
-
sort: yup.mixed().oneOf(ALLOWED_SORT_STRINGS)
|
|
3117
|
-
});
|
|
3118
|
-
const validateViewConfiguration = validateYupSchema(configSchema);
|
|
3119
|
-
|
|
3120
|
-
var viewConfiguration = {
|
|
3121
|
-
async updateViewConfiguration (ctx) {
|
|
3122
|
-
const { request: { body }, state: { userAbility } } = ctx;
|
|
3123
|
-
if (userAbility.cannot(ACTIONS.configureView)) {
|
|
3124
|
-
return ctx.forbidden();
|
|
3125
|
-
}
|
|
3126
|
-
const data = await validateViewConfiguration(body);
|
|
3127
|
-
await getService('upload').setConfiguration(data);
|
|
3128
|
-
ctx.body = {
|
|
3129
|
-
data
|
|
3130
|
-
};
|
|
3131
|
-
},
|
|
3132
|
-
async findViewConfiguration (ctx) {
|
|
3133
|
-
const data = await getService('upload').getConfiguration();
|
|
3134
|
-
ctx.body = {
|
|
3135
|
-
data
|
|
3136
|
-
};
|
|
3137
|
-
}
|
|
3138
|
-
};
|
|
3139
|
-
|
|
3140
|
-
const controllers = {
|
|
3141
|
-
'admin-file': adminFile,
|
|
3142
|
-
'admin-folder': adminFolder,
|
|
3143
|
-
'admin-folder-file': adminFolderFile,
|
|
3144
|
-
'admin-settings': adminSettings,
|
|
3145
|
-
'admin-upload': adminUpload,
|
|
3146
|
-
'content-api': contentApi,
|
|
3147
|
-
'view-configuration': viewConfiguration
|
|
3148
|
-
};
|
|
3149
|
-
|
|
3150
|
-
var index = (()=>({
|
|
3151
|
-
register,
|
|
3152
|
-
bootstrap,
|
|
3153
|
-
config,
|
|
3154
|
-
routes,
|
|
3155
|
-
controllers,
|
|
3156
|
-
contentTypes,
|
|
3157
|
-
services
|
|
3158
|
-
}));
|
|
3159
|
-
|
|
3160
|
-
export { FILE_MODEL_UID as F, index as i };
|
|
3161
|
-
//# sourceMappingURL=index-BzVus140.mjs.map
|