From 64a2c258d4862ade80ac58339862a7256e272eca Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Wed, 22 May 2024 17:30:58 -0300 Subject: [PATCH 01/13] feat: Add setting to allow uploading unknown media types --- apps/meteor/app/api/server/lib/getUploadFormData.ts | 5 ++++- .../client/views/room/body/hooks/useFileUploadDropTarget.ts | 6 ++++-- .../MessageBoxActionsToolbar/hooks/useFileUploadAction.ts | 6 ++++-- apps/meteor/server/settings/file-upload.ts | 5 +++++ packages/i18n/src/locales/en.i18n.json | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/meteor/app/api/server/lib/getUploadFormData.ts b/apps/meteor/app/api/server/lib/getUploadFormData.ts index 9b8f69fb3a66..a8224d56cf57 100644 --- a/apps/meteor/app/api/server/lib/getUploadFormData.ts +++ b/apps/meteor/app/api/server/lib/getUploadFormData.ts @@ -5,6 +5,8 @@ import type { ValidateFunction } from 'ajv'; import busboy from 'busboy'; import type { Request } from 'express'; +import { mime } from '../../../utils/lib/mimeTypes'; + type UploadResult = { file: Readable & { truncated: boolean }; fieldname: string; @@ -78,12 +80,13 @@ export async function getUploadFormData< fileChunks.length = 0; return returnError(new MeteorError('error-file-too-large')); } + const mimeTypeFromFilename = mime.lookup(filename); uploadedFile = { file, filename, encoding, - mimetype, + mimetype: typeof mimeTypeFromFilename === 'string' ? mimeTypeFromFilename : mimetype, fieldname, fields, fileBuffer: Buffer.concat(fileChunks), diff --git a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts index 2427f7217401..214d8109dbfb 100644 --- a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts +++ b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts @@ -29,7 +29,8 @@ export const useFileUploadDropTarget = (): readonly [ const t = useTranslation(); - const fileUploadEnabled = useSetting('FileUpload_Enabled') as boolean; + const fileUploadEnabled = useSetting('FileUpload_Enabled'); + const rejectUnknownMediaTypes = useSetting('FileUpload_RejectUnknownMediaTypes'); const user = useUser(); const fileUploadAllowedForUser = useReactiveValue( useCallback(() => !roomCoordinator.readOnly(room._id, { username: user?.username }), [room._id, user?.username]), @@ -55,7 +56,8 @@ export const useFileUploadDropTarget = (): readonly [ const uniqueFiles = getUniqueFiles(); const uploads = Array.from(uniqueFiles).map((file) => { - Object.defineProperty(file, 'type', { value: mime.lookup(file.name) }); + const fileMimeType = mime.lookup(file.name); + Object.defineProperty(file, 'type', { value: fileMimeType ?? (rejectUnknownMediaTypes ? undefined : 'application/octet-stream') }); return file; }); diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts index aba008a353a5..d9487d454e88 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts @@ -9,7 +9,8 @@ const fileInputProps = { type: 'file', multiple: true }; export const useFileUploadAction = (disabled: boolean): GenericMenuItemProps => { const t = useTranslation(); - const fileUploadEnabled = useSetting('FileUpload_Enabled'); + const fileUploadEnabled = useSetting('FileUpload_Enabled'); + const rejectUnknownMediaTypes = useSetting('FileUpload_RejectUnknownMediaTypes'); const fileInputRef = useFileInput(fileInputProps); const chat = useChat(); @@ -25,8 +26,9 @@ export const useFileUploadAction = (disabled: boolean): GenericMenuItemProps => const handleUploadChange = async () => { const { mime } = await import('../../../../../../../app/utils/lib/mimeTypes'); const filesToUpload = Array.from(fileInputRef?.current?.files ?? []).map((file) => { + const fileMimeType = mime.lookup(file.name); Object.defineProperty(file, 'type', { - value: mime.lookup(file.name), + value: fileMimeType ?? (rejectUnknownMediaTypes ? undefined : 'application/octet-stream'), }); return file; }); diff --git a/apps/meteor/server/settings/file-upload.ts b/apps/meteor/server/settings/file-upload.ts index 76e788cda0e2..87d6d01e25b8 100644 --- a/apps/meteor/server/settings/file-upload.ts +++ b/apps/meteor/server/settings/file-upload.ts @@ -25,6 +25,11 @@ export const createFileUploadSettings = () => i18nDescription: 'FileUpload_MediaTypeBlackListDescription', }); + await this.add('FileUpload_RejectUnknownMediaTypes', true, { + type: 'boolean', + public: true, + }); + await this.add('FileUpload_ProtectFiles', true, { type: 'boolean', public: true, diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index c59f3887106c..24a5a622ec82 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2377,6 +2377,8 @@ "FileUpload_ProtectFiles": "Protect Uploaded Files", "FileUpload_ProtectFilesDescription": "Only authenticated users will have access", "FileUpload_ProtectFilesEnabled_JWTNotSet": "Uploaded files are protected, but JWT access is not setup, this is required for Twilio to send media messages. Setup in Settings -> FileUpload", + "FileUpload_RejectUnknownMediaTypes": "Reject unknown media types", + "FileUpload_RejectUnknownMediaTypes_Description": "Uploading unknown media types is blocked by default. When this setting is disabled, the `application/octet-stream` MIME type will be assigned to files with unknown media types so that they can be uploaded.", "FileUpload_RotateImages": "Rotate images on upload", "FileUpload_RotateImages_Description": "Enabling this setting may cause image quality loss", "FileUpload_S3_Acl": "Acl", From 8b36f09b07d1ed6ed3dd67e7ac0eb31ea38155af Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Wed, 22 May 2024 17:31:44 -0300 Subject: [PATCH 02/13] test: add end-to-end tests --- apps/meteor/tests/e2e/file-upload.spec.ts | 38 +++++++++++++++++++ .../tests/e2e/fixtures/files/diagram.drawio | 13 +++++++ 2 files changed, 51 insertions(+) create mode 100644 apps/meteor/tests/e2e/fixtures/files/diagram.drawio diff --git a/apps/meteor/tests/e2e/file-upload.spec.ts b/apps/meteor/tests/e2e/file-upload.spec.ts index b382476c0a2f..de86de5c2120 100644 --- a/apps/meteor/tests/e2e/file-upload.spec.ts +++ b/apps/meteor/tests/e2e/file-upload.spec.ts @@ -1,6 +1,7 @@ import { Users } from './fixtures/userStates'; import { HomeChannel } from './page-objects'; import { createTargetChannel } from './utils'; +import { setSettingValueById } from './utils/setSettingValueById'; import { expect, test } from './utils/test'; test.use({ storageState: Users.user1.state }); @@ -10,6 +11,10 @@ test.describe.serial('file-upload', () => { let targetChannel: string; test.beforeAll(async ({ api }) => { + await Promise.all([ + setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', true), + setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'), + ]); targetChannel = await createTargetChannel(api); }); @@ -21,6 +26,10 @@ test.describe.serial('file-upload', () => { }); test.afterAll(async ({ api }) => { + await Promise.all([ + setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', true), + setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'), + ]); expect((await api.post('/channels.delete', { roomName: targetChannel })).status()).toBe(200); }); @@ -54,4 +63,33 @@ test.describe.serial('file-upload', () => { await expect(poHomeChannel.content.getFileDescription).toHaveText('lst_description'); await expect(poHomeChannel.content.lastMessageFileName).toContainText('lst-test.lst'); }); + + test('expect not to send drawio file when the "Reject unknown media types" setting is enabled', async ({ api, page }) => { + await setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', true); + + await page.reload(); + await poHomeChannel.content.sendFileMessage('diagram.drawio'); + await expect(poHomeChannel.content.btnModalConfirm).not.toBeVisible(); + }); + + test('expect send drawio file succesfully when the "Reject unknown media types" setting is disabled', async ({ api, page }) => { + await setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', false); + + await page.reload(); + await poHomeChannel.content.sendFileMessage('diagram.drawio'); + await poHomeChannel.content.descriptionInput.fill('drawio_description'); + await poHomeChannel.content.btnModalConfirm.click(); + + await expect(poHomeChannel.content.getFileDescription).toHaveText('drawio_description'); + await expect(poHomeChannel.content.lastMessageFileName).toContainText('diagram.drawio'); + }); + + test('expect not to send drawio file when the "Reject unknown media types" setting is disabled, but the default media type is blocked', async ({ api, page }) => { + await setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'application/octet-stream') + await setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', false); + + await page.reload(); + await poHomeChannel.content.sendFileMessage('diagram.drawio'); + await expect(poHomeChannel.content.btnModalConfirm).not.toBeVisible(); + }); }); diff --git a/apps/meteor/tests/e2e/fixtures/files/diagram.drawio b/apps/meteor/tests/e2e/fixtures/files/diagram.drawio new file mode 100644 index 000000000000..a86c2673ab98 --- /dev/null +++ b/apps/meteor/tests/e2e/fixtures/files/diagram.drawio @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From d267286be625342c1fe95c371bc80ae14d6b87f2 Mon Sep 17 00:00:00 2001 From: Matheus Barbosa Silva <36537004+matheusbsilva137@users.noreply.github.com> Date: Wed, 22 May 2024 18:02:11 -0300 Subject: [PATCH 03/13] Create changeset --- .changeset/breezy-pens-sing.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/breezy-pens-sing.md diff --git a/.changeset/breezy-pens-sing.md b/.changeset/breezy-pens-sing.md new file mode 100644 index 000000000000..be210ec20735 --- /dev/null +++ b/.changeset/breezy-pens-sing.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/i18n": minor +--- + +Added "Reject unknown media types" setting to control whether uploads with unknown media types (MIME types) should be accepted From 06b92b684cbf33c64588f6cb9b9ca4d7d3193238 Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Wed, 22 May 2024 18:07:43 -0300 Subject: [PATCH 04/13] feat: Improve error when uploading unknown media types --- .../room/modals/FileUploadModal/FileUploadModal.tsx | 9 +++++++++ packages/i18n/src/locales/en.i18n.json | 1 + 2 files changed, 10 insertions(+) diff --git a/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx b/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx index 312776397b32..d2a3b4ca32c5 100644 --- a/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx +++ b/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx @@ -64,6 +64,15 @@ const FileUploadModal = ({ }; useEffect(() => { + if (invalidContentType && !file.type) { + dispatchToastMessage({ + type: 'error', + message: t('FileUpload_MediaType_Unknown'), + }); + onClose(); + return; + } + if (invalidContentType) { dispatchToastMessage({ type: 'error', diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 24a5a622ec82..18ff61b3c953 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2369,6 +2369,7 @@ "FileUpload_MaxFileSize": "Maximum File Upload Size (in bytes)", "FileUpload_MaxFileSizeDescription": "Set it to -1 to remove the file size limitation.", "FileUpload_MediaType_NotAccepted__type__": "Media Type Not Accepted: {{type}}", + "FileUpload_MediaType_Unknown": "Unknown media type not accepted", "FileUpload_MediaType_NotAccepted": "Media Types Not Accepted", "FileUpload_MediaTypeBlackList": "Blocked Media Types", "FileUpload_MediaTypeBlackListDescription": "Comma-separated list of media types. This setting has priority over the Accepted Media Types.", From cd4113ca32cb91d828bbfc1c1f3aa28da39e1749 Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Fri, 24 May 2024 14:36:50 -0300 Subject: [PATCH 05/13] Update setting's name and description --- .../views/room/body/hooks/useFileUploadDropTarget.ts | 2 +- .../hooks/useFileUploadAction.ts | 2 +- apps/meteor/server/settings/file-upload.ts | 2 +- apps/meteor/tests/e2e/file-upload.spec.ts | 10 +++++----- packages/i18n/src/locales/en.i18n.json | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts index 214d8109dbfb..73631ea9ded2 100644 --- a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts +++ b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts @@ -30,7 +30,7 @@ export const useFileUploadDropTarget = (): readonly [ const t = useTranslation(); const fileUploadEnabled = useSetting('FileUpload_Enabled'); - const rejectUnknownMediaTypes = useSetting('FileUpload_RejectUnknownMediaTypes'); + const rejectUnknownMediaTypes = useSetting('FileUpload_UnknownMediaTypeProtection'); const user = useUser(); const fileUploadAllowedForUser = useReactiveValue( useCallback(() => !roomCoordinator.readOnly(room._id, { username: user?.username }), [room._id, user?.username]), diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts index d9487d454e88..09e50f8feb75 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts @@ -10,7 +10,7 @@ const fileInputProps = { type: 'file', multiple: true }; export const useFileUploadAction = (disabled: boolean): GenericMenuItemProps => { const t = useTranslation(); const fileUploadEnabled = useSetting('FileUpload_Enabled'); - const rejectUnknownMediaTypes = useSetting('FileUpload_RejectUnknownMediaTypes'); + const rejectUnknownMediaTypes = useSetting('FileUpload_UnknownMediaTypeProtection'); const fileInputRef = useFileInput(fileInputProps); const chat = useChat(); diff --git a/apps/meteor/server/settings/file-upload.ts b/apps/meteor/server/settings/file-upload.ts index 87d6d01e25b8..c27013295269 100644 --- a/apps/meteor/server/settings/file-upload.ts +++ b/apps/meteor/server/settings/file-upload.ts @@ -25,7 +25,7 @@ export const createFileUploadSettings = () => i18nDescription: 'FileUpload_MediaTypeBlackListDescription', }); - await this.add('FileUpload_RejectUnknownMediaTypes', true, { + await this.add('FileUpload_UnknownMediaTypeProtection', true, { type: 'boolean', public: true, }); diff --git a/apps/meteor/tests/e2e/file-upload.spec.ts b/apps/meteor/tests/e2e/file-upload.spec.ts index de86de5c2120..27745ceae9e8 100644 --- a/apps/meteor/tests/e2e/file-upload.spec.ts +++ b/apps/meteor/tests/e2e/file-upload.spec.ts @@ -12,7 +12,7 @@ test.describe.serial('file-upload', () => { test.beforeAll(async ({ api }) => { await Promise.all([ - setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', true), + setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', true), setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'), ]); targetChannel = await createTargetChannel(api); @@ -27,7 +27,7 @@ test.describe.serial('file-upload', () => { test.afterAll(async ({ api }) => { await Promise.all([ - setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', true), + setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', true), setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'), ]); expect((await api.post('/channels.delete', { roomName: targetChannel })).status()).toBe(200); @@ -65,7 +65,7 @@ test.describe.serial('file-upload', () => { }); test('expect not to send drawio file when the "Reject unknown media types" setting is enabled', async ({ api, page }) => { - await setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', true); + await setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', true); await page.reload(); await poHomeChannel.content.sendFileMessage('diagram.drawio'); @@ -73,7 +73,7 @@ test.describe.serial('file-upload', () => { }); test('expect send drawio file succesfully when the "Reject unknown media types" setting is disabled', async ({ api, page }) => { - await setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', false); + await setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', false); await page.reload(); await poHomeChannel.content.sendFileMessage('diagram.drawio'); @@ -86,7 +86,7 @@ test.describe.serial('file-upload', () => { test('expect not to send drawio file when the "Reject unknown media types" setting is disabled, but the default media type is blocked', async ({ api, page }) => { await setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'application/octet-stream') - await setSettingValueById(api, 'FileUpload_RejectUnknownMediaTypes', false); + await setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', false); await page.reload(); await poHomeChannel.content.sendFileMessage('diagram.drawio'); diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 18ff61b3c953..3882e9f22beb 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2378,8 +2378,8 @@ "FileUpload_ProtectFiles": "Protect Uploaded Files", "FileUpload_ProtectFilesDescription": "Only authenticated users will have access", "FileUpload_ProtectFilesEnabled_JWTNotSet": "Uploaded files are protected, but JWT access is not setup, this is required for Twilio to send media messages. Setup in Settings -> FileUpload", - "FileUpload_RejectUnknownMediaTypes": "Reject unknown media types", - "FileUpload_RejectUnknownMediaTypes_Description": "Uploading unknown media types is blocked by default. When this setting is disabled, the `application/octet-stream` MIME type will be assigned to files with unknown media types so that they can be uploaded.", + "FileUpload_UnknownMediaTypeProtection": "Unknown media type protection", + "FileUpload_UnknownMediaTypeProtection_Description": "If disabled, the `application/octet-stream` MIME type will be assigned to unknown file types for upload.", "FileUpload_RotateImages": "Rotate images on upload", "FileUpload_RotateImages_Description": "Enabling this setting may cause image quality loss", "FileUpload_S3_Acl": "Acl", From bf5d06eee512cbfe07d12524c2b7ff7dc087e345 Mon Sep 17 00:00:00 2001 From: Matheus Barbosa Silva <36537004+matheusbsilva137@users.noreply.github.com> Date: Fri, 24 May 2024 14:45:26 -0300 Subject: [PATCH 06/13] Update changeset --- .changeset/breezy-pens-sing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/breezy-pens-sing.md b/.changeset/breezy-pens-sing.md index be210ec20735..b7959078dde4 100644 --- a/.changeset/breezy-pens-sing.md +++ b/.changeset/breezy-pens-sing.md @@ -3,4 +3,4 @@ "@rocket.chat/i18n": minor --- -Added "Reject unknown media types" setting to control whether uploads with unknown media types (MIME types) should be accepted +Added "Unknown media type protection" setting to control whether uploads with unknown media types (MIME types) should be accepted From 57a36afcc86af60c2bf0ca6781ce877c77ee31a1 Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Fri, 24 May 2024 16:09:45 -0300 Subject: [PATCH 07/13] fix end-to-end tests --- apps/meteor/tests/end-to-end/api/09-rooms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/tests/end-to-end/api/09-rooms.js b/apps/meteor/tests/end-to-end/api/09-rooms.js index dc8a6a209300..b25d75d2aea7 100644 --- a/apps/meteor/tests/end-to-end/api/09-rooms.js +++ b/apps/meteor/tests/end-to-end/api/09-rooms.js @@ -201,7 +201,7 @@ describe('[Rooms]', function () { }); it('should not allow uploading a blocked media type to a room', async () => { - await updateSetting('FileUpload_MediaTypeBlackList', 'application/octet-stream'); + await updateSetting('FileUpload_MediaTypeBlackList', 'text/plain'); await request .post(api(`rooms.upload/${testChannel._id}`)) .set(credentials) From a85747959e64c96bba39fa79548e48a06deed9c9 Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Thu, 13 Jun 2024 13:54:55 -0300 Subject: [PATCH 08/13] improve: Remove setting and make application/octet-stream the default media type --- .changeset/breezy-pens-sing.md | 2 +- .../app/api/server/lib/getUploadFormData.ts | 4 +- .../body/hooks/useFileUploadDropTarget.ts | 3 +- .../hooks/useFileUploadAction.ts | 3 +- .../FileUploadModal/FileUploadModal.tsx | 9 ---- apps/meteor/server/settings/file-upload.ts | 5 --- apps/meteor/tests/data/interactions.ts | 1 + apps/meteor/tests/e2e/file-upload.spec.ts | 27 +++-------- apps/meteor/tests/end-to-end/api/09-rooms.js | 45 ++++++++++++++++--- packages/i18n/src/locales/en.i18n.json | 3 -- 10 files changed, 51 insertions(+), 51 deletions(-) diff --git a/.changeset/breezy-pens-sing.md b/.changeset/breezy-pens-sing.md index b7959078dde4..0725999ef62b 100644 --- a/.changeset/breezy-pens-sing.md +++ b/.changeset/breezy-pens-sing.md @@ -3,4 +3,4 @@ "@rocket.chat/i18n": minor --- -Added "Unknown media type protection" setting to control whether uploads with unknown media types (MIME types) should be accepted +Removed "Unknown media type" errors on the client side by using `application/octet-stream` as a fallback media type (MIME type) for all files diff --git a/apps/meteor/app/api/server/lib/getUploadFormData.ts b/apps/meteor/app/api/server/lib/getUploadFormData.ts index a8224d56cf57..a49369ff91ff 100644 --- a/apps/meteor/app/api/server/lib/getUploadFormData.ts +++ b/apps/meteor/app/api/server/lib/getUploadFormData.ts @@ -63,7 +63,7 @@ export async function getUploadFormData< function onFile( fieldname: string, file: Readable & { truncated: boolean }, - { filename, encoding, mimeType: mimetype }: { filename: string; encoding: string; mimeType: string }, + { filename, encoding, mimeType }: { filename: string; encoding: string; mimeType: string }, ) { if (options.field && fieldname !== options.field) { file.resume(); @@ -86,7 +86,7 @@ export async function getUploadFormData< file, filename, encoding, - mimetype: typeof mimeTypeFromFilename === 'string' ? mimeTypeFromFilename : mimetype, + mimetype: typeof mimeTypeFromFilename === 'string' ? mimeTypeFromFilename : mimeType, fieldname, fields, fileBuffer: Buffer.concat(fileChunks), diff --git a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts index 73631ea9ded2..832f9ac587c7 100644 --- a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts +++ b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts @@ -30,7 +30,6 @@ export const useFileUploadDropTarget = (): readonly [ const t = useTranslation(); const fileUploadEnabled = useSetting('FileUpload_Enabled'); - const rejectUnknownMediaTypes = useSetting('FileUpload_UnknownMediaTypeProtection'); const user = useUser(); const fileUploadAllowedForUser = useReactiveValue( useCallback(() => !roomCoordinator.readOnly(room._id, { username: user?.username }), [room._id, user?.username]), @@ -57,7 +56,7 @@ export const useFileUploadDropTarget = (): readonly [ const uploads = Array.from(uniqueFiles).map((file) => { const fileMimeType = mime.lookup(file.name); - Object.defineProperty(file, 'type', { value: fileMimeType ?? (rejectUnknownMediaTypes ? undefined : 'application/octet-stream') }); + Object.defineProperty(file, 'type', { value: typeof fileMimeType === 'string' ? fileMimeType : 'application/octet-stream' }); return file; }); diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts index 09e50f8feb75..a3b8e320ace0 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts @@ -10,7 +10,6 @@ const fileInputProps = { type: 'file', multiple: true }; export const useFileUploadAction = (disabled: boolean): GenericMenuItemProps => { const t = useTranslation(); const fileUploadEnabled = useSetting('FileUpload_Enabled'); - const rejectUnknownMediaTypes = useSetting('FileUpload_UnknownMediaTypeProtection'); const fileInputRef = useFileInput(fileInputProps); const chat = useChat(); @@ -28,7 +27,7 @@ export const useFileUploadAction = (disabled: boolean): GenericMenuItemProps => const filesToUpload = Array.from(fileInputRef?.current?.files ?? []).map((file) => { const fileMimeType = mime.lookup(file.name); Object.defineProperty(file, 'type', { - value: fileMimeType ?? (rejectUnknownMediaTypes ? undefined : 'application/octet-stream'), + value: typeof fileMimeType === 'string' ? fileMimeType : 'application/octet-stream', }); return file; }); diff --git a/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx b/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx index d2a3b4ca32c5..312776397b32 100644 --- a/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx +++ b/apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.tsx @@ -64,15 +64,6 @@ const FileUploadModal = ({ }; useEffect(() => { - if (invalidContentType && !file.type) { - dispatchToastMessage({ - type: 'error', - message: t('FileUpload_MediaType_Unknown'), - }); - onClose(); - return; - } - if (invalidContentType) { dispatchToastMessage({ type: 'error', diff --git a/apps/meteor/server/settings/file-upload.ts b/apps/meteor/server/settings/file-upload.ts index c27013295269..76e788cda0e2 100644 --- a/apps/meteor/server/settings/file-upload.ts +++ b/apps/meteor/server/settings/file-upload.ts @@ -25,11 +25,6 @@ export const createFileUploadSettings = () => i18nDescription: 'FileUpload_MediaTypeBlackListDescription', }); - await this.add('FileUpload_UnknownMediaTypeProtection', true, { - type: 'boolean', - public: true, - }); - await this.add('FileUpload_ProtectFiles', true, { type: 'boolean', public: true, diff --git a/apps/meteor/tests/data/interactions.ts b/apps/meteor/tests/data/interactions.ts index d14749181193..085d97d4ece3 100644 --- a/apps/meteor/tests/data/interactions.ts +++ b/apps/meteor/tests/data/interactions.ts @@ -1,5 +1,6 @@ export const targetUser = 'rocket.cat'; export const imgURL = './public/images/logo/1024x1024.png'; export const lstURL = './tests/e2e/fixtures/files/lst-test.lst'; +export const drawioURL = './tests/e2e/fixtures/files/diagram.drawio'; export const svgLogoURL = './public/images/logo/logo.svg'; export const svgLogoFileName = 'logo.svg'; diff --git a/apps/meteor/tests/e2e/file-upload.spec.ts b/apps/meteor/tests/e2e/file-upload.spec.ts index 27745ceae9e8..0a5d1cfd2512 100644 --- a/apps/meteor/tests/e2e/file-upload.spec.ts +++ b/apps/meteor/tests/e2e/file-upload.spec.ts @@ -11,10 +11,7 @@ test.describe.serial('file-upload', () => { let targetChannel: string; test.beforeAll(async ({ api }) => { - await Promise.all([ - setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', true), - setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'), - ]); + await setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'); targetChannel = await createTargetChannel(api); }); @@ -26,10 +23,7 @@ test.describe.serial('file-upload', () => { }); test.afterAll(async ({ api }) => { - await Promise.all([ - setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', true), - setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'), - ]); + await setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'image/svg+xml'); expect((await api.post('/channels.delete', { roomName: targetChannel })).status()).toBe(200); }); @@ -64,17 +58,7 @@ test.describe.serial('file-upload', () => { await expect(poHomeChannel.content.lastMessageFileName).toContainText('lst-test.lst'); }); - test('expect not to send drawio file when the "Reject unknown media types" setting is enabled', async ({ api, page }) => { - await setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', true); - - await page.reload(); - await poHomeChannel.content.sendFileMessage('diagram.drawio'); - await expect(poHomeChannel.content.btnModalConfirm).not.toBeVisible(); - }); - - test('expect send drawio file succesfully when the "Reject unknown media types" setting is disabled', async ({ api, page }) => { - await setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', false); - + test('expect send drawio (unknown media type) file succesfully', async ({ page }) => { await page.reload(); await poHomeChannel.content.sendFileMessage('diagram.drawio'); await poHomeChannel.content.descriptionInput.fill('drawio_description'); @@ -84,9 +68,8 @@ test.describe.serial('file-upload', () => { await expect(poHomeChannel.content.lastMessageFileName).toContainText('diagram.drawio'); }); - test('expect not to send drawio file when the "Reject unknown media types" setting is disabled, but the default media type is blocked', async ({ api, page }) => { - await setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'application/octet-stream') - await setSettingValueById(api, 'FileUpload_UnknownMediaTypeProtection', false); + test('expect not to send drawio file (unknown media type) when the default media type is blocked', async ({ api, page }) => { + await setSettingValueById(api, 'FileUpload_MediaTypeBlackList', 'application/octet-stream'); await page.reload(); await poHomeChannel.content.sendFileMessage('diagram.drawio'); diff --git a/apps/meteor/tests/end-to-end/api/09-rooms.js b/apps/meteor/tests/end-to-end/api/09-rooms.js index b25d75d2aea7..a7eb8815293e 100644 --- a/apps/meteor/tests/end-to-end/api/09-rooms.js +++ b/apps/meteor/tests/end-to-end/api/09-rooms.js @@ -7,7 +7,7 @@ import { after, afterEach, before, beforeEach, describe, it } from 'mocha'; import { sleep } from '../../../lib/utils/sleep'; import { getCredentials, api, request, credentials } from '../../data/api-data.js'; import { sendSimpleMessage, deleteMessage } from '../../data/chat.helper'; -import { imgURL, lstURL, svgLogoFileName, svgLogoURL } from '../../data/interactions'; +import { drawioURL, imgURL, lstURL, svgLogoFileName, svgLogoURL } from '../../data/interactions'; import { getSettingValueById, updateEEPermission, updatePermission, updateSetting } from '../../data/permissions.helper'; import { createRoom, deleteRoom } from '../../data/rooms.helper'; import { deleteTeam } from '../../data/teams.helper'; @@ -179,8 +179,8 @@ describe('[Rooms]', function () { }); }); - it('should upload a LST file to room', (done) => { - request + it('should upload a LST file to room', () => { + return request .post(api(`rooms.upload/${testChannel._id}`)) .set(credentials) .attach('file', lstURL) @@ -196,8 +196,29 @@ describe('[Rooms]', function () { expect(res.body.message).to.have.property('files'); expect(res.body.message.files).to.be.an('array').of.length(1); expect(res.body.message.files[0]).to.have.property('name', 'lst-test.lst'); - }) - .end(done); + expect(res.body.message.files[0]).to.have.property('type', 'text/plain'); + }); + }); + + it('should upload a DRAWIO file (unknown media type) to room', () => { + return request + .post(api(`rooms.upload/${testChannel._id}`)) + .set(credentials) + .attach('file', drawioURL) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('message'); + expect(res.body.message).to.have.property('attachments'); + expect(res.body.message.attachments).to.be.an('array').of.length(1); + expect(res.body.message.attachments[0]).to.have.property('format', 'DRAWIO'); + expect(res.body.message.attachments[0]).to.have.property('title', 'diagram.drawio'); + expect(res.body.message).to.have.property('files'); + expect(res.body.message.files).to.be.an('array').of.length(1); + expect(res.body.message.files[0]).to.have.property('name', 'diagram.drawio'); + expect(res.body.message.files[0]).to.have.property('type', 'application/octet-stream'); + }); }); it('should not allow uploading a blocked media type to a room', async () => { @@ -214,6 +235,20 @@ describe('[Rooms]', function () { }); }); + it('should not allow uploading an unknown media type to a room if the default one is blocked', async () => { + await updateSetting('FileUpload_MediaTypeBlackList', 'application/octet-stream'); + await request + .post(api(`rooms.upload/${testChannel._id}`)) + .set(credentials) + .attach('file', drawioURL) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('errorType', 'error-invalid-file-type'); + }); + }); + it('should be able to get the file', async () => { await request.get(fileNewUrl).set(credentials).expect('Content-Type', 'image/png').expect(200); await request.get(fileOldUrl).set(credentials).expect('Content-Type', 'image/png').expect(200); diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 3882e9f22beb..8647896b9ce3 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2369,9 +2369,6 @@ "FileUpload_MaxFileSize": "Maximum File Upload Size (in bytes)", "FileUpload_MaxFileSizeDescription": "Set it to -1 to remove the file size limitation.", "FileUpload_MediaType_NotAccepted__type__": "Media Type Not Accepted: {{type}}", - "FileUpload_MediaType_Unknown": "Unknown media type not accepted", - "FileUpload_MediaType_NotAccepted": "Media Types Not Accepted", - "FileUpload_MediaTypeBlackList": "Blocked Media Types", "FileUpload_MediaTypeBlackListDescription": "Comma-separated list of media types. This setting has priority over the Accepted Media Types.", "FileUpload_MediaTypeWhiteList": "Accepted Media Types", "FileUpload_MediaTypeWhiteListDescription": "Comma-separated list of media types. Leave it blank for accepting all media types.", From a35783ef06b65909202f51758e2307b8f8b54008 Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Thu, 13 Jun 2024 13:56:08 -0300 Subject: [PATCH 09/13] i18n: remove unused translation --- packages/i18n/src/locales/en.i18n.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 8647896b9ce3..1e22c9bad6b0 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2375,8 +2375,6 @@ "FileUpload_ProtectFiles": "Protect Uploaded Files", "FileUpload_ProtectFilesDescription": "Only authenticated users will have access", "FileUpload_ProtectFilesEnabled_JWTNotSet": "Uploaded files are protected, but JWT access is not setup, this is required for Twilio to send media messages. Setup in Settings -> FileUpload", - "FileUpload_UnknownMediaTypeProtection": "Unknown media type protection", - "FileUpload_UnknownMediaTypeProtection_Description": "If disabled, the `application/octet-stream` MIME type will be assigned to unknown file types for upload.", "FileUpload_RotateImages": "Rotate images on upload", "FileUpload_RotateImages_Description": "Enabling this setting may cause image quality loss", "FileUpload_S3_Acl": "Acl", From fcb6086ca6be06e1d1f0aa03f8b2e854bb6f911f Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Thu, 13 Jun 2024 15:25:35 -0300 Subject: [PATCH 10/13] i18n: re-add translations --- packages/i18n/src/locales/en.i18n.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 262b9039790d..e9d1894ef74e 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2378,6 +2378,8 @@ "FileUpload_MaxFileSize": "Maximum File Upload Size (in bytes)", "FileUpload_MaxFileSizeDescription": "Set it to -1 to remove the file size limitation.", "FileUpload_MediaType_NotAccepted__type__": "Media Type Not Accepted: {{type}}", + "FileUpload_MediaType_NotAccepted": "Media Types Not Accepted", + "FileUpload_MediaTypeBlackList": "Blocked Media Types", "FileUpload_MediaTypeBlackListDescription": "Comma-separated list of media types. This setting has priority over the Accepted Media Types.", "FileUpload_MediaTypeWhiteList": "Accepted Media Types", "FileUpload_MediaTypeWhiteListDescription": "Comma-separated list of media types. Leave it blank for accepting all media types.", From 49a553b70154337a695bb1eae4cbdb9eb4c03cc5 Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Thu, 13 Jun 2024 17:04:30 -0300 Subject: [PATCH 11/13] improve: Add alert to media type blocked list setting --- apps/meteor/server/settings/file-upload.ts | 1 + packages/i18n/src/locales/en.i18n.json | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/meteor/server/settings/file-upload.ts b/apps/meteor/server/settings/file-upload.ts index 76e788cda0e2..5fa09585fed6 100644 --- a/apps/meteor/server/settings/file-upload.ts +++ b/apps/meteor/server/settings/file-upload.ts @@ -23,6 +23,7 @@ export const createFileUploadSettings = () => type: 'string', public: true, i18nDescription: 'FileUpload_MediaTypeBlackListDescription', + alert: 'FileUpload_MediaTypeBlackList_Alert', }); await this.add('FileUpload_ProtectFiles', true, { diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index e9d1894ef74e..0594c65c89b9 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2381,6 +2381,7 @@ "FileUpload_MediaType_NotAccepted": "Media Types Not Accepted", "FileUpload_MediaTypeBlackList": "Blocked Media Types", "FileUpload_MediaTypeBlackListDescription": "Comma-separated list of media types. This setting has priority over the Accepted Media Types.", + "FileUpload_MediaTypeBlackList_Alert": "\"application/octet-stream\" is used as the default media type for all unknown file extensions. In order to allow uploading only known extensions, add it to the \"Blocked Media Types\" list.", "FileUpload_MediaTypeWhiteList": "Accepted Media Types", "FileUpload_MediaTypeWhiteListDescription": "Comma-separated list of media types. Leave it blank for accepting all media types.", "FileUpload_ProtectFiles": "Protect Uploaded Files", From e4d0a91f171a2e5e65dc87ee50a9721335797990 Mon Sep 17 00:00:00 2001 From: Matheus Barbosa Silva <36537004+matheusbsilva137@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:03:46 -0300 Subject: [PATCH 12/13] Update alert --- packages/i18n/src/locales/en.i18n.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 0594c65c89b9..d3e9d1aa0430 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -2381,7 +2381,7 @@ "FileUpload_MediaType_NotAccepted": "Media Types Not Accepted", "FileUpload_MediaTypeBlackList": "Blocked Media Types", "FileUpload_MediaTypeBlackListDescription": "Comma-separated list of media types. This setting has priority over the Accepted Media Types.", - "FileUpload_MediaTypeBlackList_Alert": "\"application/octet-stream\" is used as the default media type for all unknown file extensions. In order to allow uploading only known extensions, add it to the \"Blocked Media Types\" list.", + "FileUpload_MediaTypeBlackList_Alert": "The default media type for unknown file extensions is \"application/octet-stream\", to work only with known file extensions you can add it to the \"Blocked Media Types\" list.", "FileUpload_MediaTypeWhiteList": "Accepted Media Types", "FileUpload_MediaTypeWhiteListDescription": "Comma-separated list of media types. Leave it blank for accepting all media types.", "FileUpload_ProtectFiles": "Protect Uploaded Files", From 3f3e6ae78b1d788586cfecd87db87b9304df717b Mon Sep 17 00:00:00 2001 From: matheusbsilva137 Date: Mon, 17 Jun 2024 13:14:18 -0300 Subject: [PATCH 13/13] improve: Use helper function to get file MIME type --- apps/meteor/app/api/server/lib/getUploadFormData.ts | 7 +++---- apps/meteor/app/utils/lib/mimeTypes.ts | 7 ++++++- .../views/room/body/hooks/useFileUploadDropTarget.ts | 6 ++---- .../MessageBoxActionsToolbar/hooks/useFileUploadAction.ts | 5 ++--- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/meteor/app/api/server/lib/getUploadFormData.ts b/apps/meteor/app/api/server/lib/getUploadFormData.ts index a49369ff91ff..85fc0658542d 100644 --- a/apps/meteor/app/api/server/lib/getUploadFormData.ts +++ b/apps/meteor/app/api/server/lib/getUploadFormData.ts @@ -5,7 +5,7 @@ import type { ValidateFunction } from 'ajv'; import busboy from 'busboy'; import type { Request } from 'express'; -import { mime } from '../../../utils/lib/mimeTypes'; +import { getMimeType } from '../../../utils/lib/mimeTypes'; type UploadResult = { file: Readable & { truncated: boolean }; @@ -63,7 +63,7 @@ export async function getUploadFormData< function onFile( fieldname: string, file: Readable & { truncated: boolean }, - { filename, encoding, mimeType }: { filename: string; encoding: string; mimeType: string }, + { filename, encoding }: { filename: string; encoding: string }, ) { if (options.field && fieldname !== options.field) { file.resume(); @@ -80,13 +80,12 @@ export async function getUploadFormData< fileChunks.length = 0; return returnError(new MeteorError('error-file-too-large')); } - const mimeTypeFromFilename = mime.lookup(filename); uploadedFile = { file, filename, encoding, - mimetype: typeof mimeTypeFromFilename === 'string' ? mimeTypeFromFilename : mimeType, + mimetype: getMimeType(filename), fieldname, fields, fileBuffer: Buffer.concat(fileChunks), diff --git a/apps/meteor/app/utils/lib/mimeTypes.ts b/apps/meteor/app/utils/lib/mimeTypes.ts index f2da185f84ba..909a955d6724 100644 --- a/apps/meteor/app/utils/lib/mimeTypes.ts +++ b/apps/meteor/app/utils/lib/mimeTypes.ts @@ -12,4 +12,9 @@ const getExtension = (param: string): string => { return !extension || typeof extension === 'boolean' ? '' : extension; }; -export { mime, getExtension }; +const getMimeType = (fileName: string): string => { + const fileMimeType = mime.lookup(fileName); + return typeof fileMimeType === 'string' ? fileMimeType : 'application/octet-stream'; +}; + +export { mime, getExtension, getMimeType }; diff --git a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts index 832f9ac587c7..414b91c52493 100644 --- a/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts +++ b/apps/meteor/client/views/room/body/hooks/useFileUploadDropTarget.ts @@ -38,8 +38,7 @@ export const useFileUploadDropTarget = (): readonly [ const chat = useChat(); const onFileDrop = useMutableCallback(async (files: File[]) => { - const { mime } = await import('../../../../../app/utils/lib/mimeTypes'); - + const { getMimeType } = await import('../../../../../app/utils/lib/mimeTypes'); const getUniqueFiles = () => { const uniqueFiles: File[] = []; const st: Set = new Set(); @@ -55,8 +54,7 @@ export const useFileUploadDropTarget = (): readonly [ const uniqueFiles = getUniqueFiles(); const uploads = Array.from(uniqueFiles).map((file) => { - const fileMimeType = mime.lookup(file.name); - Object.defineProperty(file, 'type', { value: typeof fileMimeType === 'string' ? fileMimeType : 'application/octet-stream' }); + Object.defineProperty(file, 'type', { value: getMimeType(file.name) }); return file; }); diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts index a3b8e320ace0..03229c5dceb3 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBoxActionsToolbar/hooks/useFileUploadAction.ts @@ -23,11 +23,10 @@ export const useFileUploadAction = (disabled: boolean): GenericMenuItemProps => }; const handleUploadChange = async () => { - const { mime } = await import('../../../../../../../app/utils/lib/mimeTypes'); + const { getMimeType } = await import('../../../../../../../app/utils/lib/mimeTypes'); const filesToUpload = Array.from(fileInputRef?.current?.files ?? []).map((file) => { - const fileMimeType = mime.lookup(file.name); Object.defineProperty(file, 'type', { - value: typeof fileMimeType === 'string' ? fileMimeType : 'application/octet-stream', + value: getMimeType(file.name), }); return file; });