Skip to content

Commit c4fa885

Browse files
authored
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.
1 parent a9c6a91 commit c4fa885

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

packages/ui/src/elements/BulkUpload/AddFilesView/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import './index.scss'
1111
const baseClass = 'bulk-upload--add-files'
1212

1313
type Props = {
14+
readonly acceptMimeTypes?: string
1415
readonly onCancel: () => void
1516
readonly onDrop: (acceptedFiles: FileList) => void
1617
}
17-
export function AddFilesView({ onCancel, onDrop }: Props) {
18+
export function AddFilesView({ acceptMimeTypes, onCancel, onDrop }: Props) {
1819
const { t } = useTranslation()
1920

2021
const inputRef = React.useRef(null)
@@ -37,6 +38,7 @@ export function AddFilesView({ onCancel, onDrop }: Props) {
3738
{t('upload:selectFile')}
3839
</Button>
3940
<input
41+
accept={acceptMimeTypes}
4042
aria-hidden="true"
4143
className={`${baseClass}__hidden-input`}
4244
hidden

packages/ui/src/elements/BulkUpload/index.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { JsonObject } from 'payload'
55
import { useModal } from '@faceless-ui/modal'
66
import React from 'react'
77

8+
import { useConfig } from '../../providers/Config/index.js'
89
import { EditDepthProvider, useEditDepth } from '../../providers/EditDepth/index.js'
910
import { Drawer } from '../Drawer/index.js'
1011
import { AddFilesView } from './AddFilesView/index.js'
@@ -17,20 +18,41 @@ function DrawerContent() {
1718
const { addFiles, forms, isInitializing } = useFormsManager()
1819
const { closeModal } = useModal()
1920
const { collectionSlug, drawerSlug } = useBulkUpload()
21+
const { config } = useConfig()
22+
23+
const uploadCollection = config.collections.find((col) => col.slug === collectionSlug)
24+
const uploadConfig = uploadCollection.upload
25+
const uploadMimeTypes = uploadConfig.mimeTypes
2026

2127
const onDrop = React.useCallback(
2228
(acceptedFiles: FileList) => {
23-
void addFiles(acceptedFiles)
29+
const fileTransfer = new DataTransfer()
30+
for (const candidateFile of acceptedFiles) {
31+
if (
32+
uploadMimeTypes === undefined ||
33+
uploadMimeTypes.length === 0 ||
34+
uploadMimeTypes?.includes(candidateFile.type)
35+
) {
36+
fileTransfer.items.add(candidateFile)
37+
}
38+
}
39+
void addFiles(fileTransfer.files)
2440
},
25-
[addFiles],
41+
[addFiles, uploadMimeTypes],
2642
)
2743

2844
if (!collectionSlug) {
2945
return null
3046
}
3147

3248
if (!forms.length && !isInitializing) {
33-
return <AddFilesView onCancel={() => closeModal(drawerSlug)} onDrop={onDrop} />
49+
return (
50+
<AddFilesView
51+
acceptMimeTypes={uploadMimeTypes?.join(', ')}
52+
onCancel={() => closeModal(drawerSlug)}
53+
onDrop={onDrop}
54+
/>
55+
)
3456
} else {
3557
return <AddingFilesView />
3658
}

packages/ui/src/elements/Upload/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ export const Upload: React.FC<UploadProps> = (props) => {
218218

219219
const showFocalPoint = focalPoint && (hasImageSizes || hasResizeOptions || focalPointEnabled)
220220

221+
const acceptMimeTypes = uploadConfig.mimeTypes?.join(', ')
222+
221223
return (
222224
<div className={[fieldBaseClass, baseClass].filter(Boolean).join(' ')}>
223225
<FieldError field={null} message={errorMessage} showError={showError} />
@@ -251,6 +253,7 @@ export const Upload: React.FC<UploadProps> = (props) => {
251253
{t('upload:selectFile')}
252254
</Button>
253255
<input
256+
accept={acceptMimeTypes}
254257
aria-hidden="true"
255258
className={`${baseClass}__hidden-input`}
256259
hidden

0 commit comments

Comments
 (0)