fix(ui): restrict file picking via upload config mimetypes (#8710)

Fixes #8673

This PR restricts inputs with `type="file"` to only those mimetypes
specified in collection upload configs. This also works for the input in
`bulkUpload` and drag-and-drop capabilities by omitting dropped files if
they do not conform to the upload config mimetypes. This PR also assumes
that an upload config with an empty mimetype array should accept all
files since the negation of that statement makes an upload collection
redundant.
This commit is contained in:
Said Akhrarov
2024-10-16 09:24:21 -04:00
committed by GitHub
parent a9c6a91c1c
commit c4fa885e84
3 changed files with 31 additions and 4 deletions

View File

@@ -11,10 +11,11 @@ import './index.scss'
const baseClass = 'bulk-upload--add-files'
type Props = {
readonly acceptMimeTypes?: string
readonly onCancel: () => void
readonly onDrop: (acceptedFiles: FileList) => void
}
export function AddFilesView({ onCancel, onDrop }: Props) {
export function AddFilesView({ acceptMimeTypes, onCancel, onDrop }: Props) {
const { t } = useTranslation()
const inputRef = React.useRef(null)
@@ -37,6 +38,7 @@ export function AddFilesView({ onCancel, onDrop }: Props) {
{t('upload:selectFile')}
</Button>
<input
accept={acceptMimeTypes}
aria-hidden="true"
className={`${baseClass}__hidden-input`}
hidden

View File

@@ -5,6 +5,7 @@ import type { JsonObject } from 'payload'
import { useModal } from '@faceless-ui/modal'
import React from 'react'
import { useConfig } from '../../providers/Config/index.js'
import { EditDepthProvider, useEditDepth } from '../../providers/EditDepth/index.js'
import { Drawer } from '../Drawer/index.js'
import { AddFilesView } from './AddFilesView/index.js'
@@ -17,12 +18,27 @@ function DrawerContent() {
const { addFiles, forms, isInitializing } = useFormsManager()
const { closeModal } = useModal()
const { collectionSlug, drawerSlug } = useBulkUpload()
const { config } = useConfig()
const uploadCollection = config.collections.find((col) => col.slug === collectionSlug)
const uploadConfig = uploadCollection.upload
const uploadMimeTypes = uploadConfig.mimeTypes
const onDrop = React.useCallback(
(acceptedFiles: FileList) => {
void addFiles(acceptedFiles)
const fileTransfer = new DataTransfer()
for (const candidateFile of acceptedFiles) {
if (
uploadMimeTypes === undefined ||
uploadMimeTypes.length === 0 ||
uploadMimeTypes?.includes(candidateFile.type)
) {
fileTransfer.items.add(candidateFile)
}
}
void addFiles(fileTransfer.files)
},
[addFiles],
[addFiles, uploadMimeTypes],
)
if (!collectionSlug) {
@@ -30,7 +46,13 @@ function DrawerContent() {
}
if (!forms.length && !isInitializing) {
return <AddFilesView onCancel={() => closeModal(drawerSlug)} onDrop={onDrop} />
return (
<AddFilesView
acceptMimeTypes={uploadMimeTypes?.join(', ')}
onCancel={() => closeModal(drawerSlug)}
onDrop={onDrop}
/>
)
} else {
return <AddingFilesView />
}

View File

@@ -218,6 +218,8 @@ export const Upload: React.FC<UploadProps> = (props) => {
const showFocalPoint = focalPoint && (hasImageSizes || hasResizeOptions || focalPointEnabled)
const acceptMimeTypes = uploadConfig.mimeTypes?.join(', ')
return (
<div className={[fieldBaseClass, baseClass].filter(Boolean).join(' ')}>
<FieldError field={null} message={errorMessage} showError={showError} />
@@ -251,6 +253,7 @@ export const Upload: React.FC<UploadProps> = (props) => {
{t('upload:selectFile')}
</Button>
<input
accept={acceptMimeTypes}
aria-hidden="true"
className={`${baseClass}__hidden-input`}
hidden