From 729d873a0808c38808041ba3cff9213a9fd39064 Mon Sep 17 00:00:00 2001 From: MrKalyanKing Date: Fri, 7 Nov 2025 06:57:23 +0000 Subject: [PATCH 1/7] fix(integrations): Add validation for Avatar URL --- .../incoming/EditIncomingWebhook.tsx | 25 ++++++- .../incoming/IncomingWebhookForm.tsx | 66 +++++++++++++++++-- .../outgoing/EditOutgoingWebhook.tsx | 10 ++- 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx index 6c80c4e7828b7..a015fa7426f89 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx @@ -5,12 +5,18 @@ import { useSetModal, useTranslation, useRouter, useRouteParameter } from '@rock import { useId, useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +import { useErrorHandler } from '../../import/useErrorHandler'; + + import IncomingWebhookForm from './IncomingWebhookForm'; import { Page, PageHeader, PageScrollableContentWithShadow, PageFooter } from '../../../../components/Page'; import { useCreateIntegration } from '../hooks/useCreateIntegration'; import { useDeleteIntegration } from '../hooks/useDeleteIntegration'; import { useUpdateIntegration } from '../hooks/useUpdateIntegration'; +// +// import { useErrorHandler } from '../../import/useErrorHandler'; + export type EditIncomingWebhookFormData = { enabled: boolean; channel: string; @@ -51,6 +57,8 @@ const EditIncomingWebhook = ({ webhookData }: EditIncomingWebhookProps) => { const setModal = useSetModal(); const tab = useRouteParameter('type'); + const handleError = useErrorHandler(); + const deleteIntegration = useDeleteIntegration(INCOMING_TYPE); const updateIntegration = useUpdateIntegration(INCOMING_TYPE); const createIntegration = useCreateIntegration(INCOMING_TYPE); @@ -63,6 +71,21 @@ const EditIncomingWebhook = ({ webhookData }: EditIncomingWebhookProps) => { formState: { isDirty }, } = methods; + + + // + const handleInvalid = (errors: { + avatar?: { message?: string }; + emoji?: { message?: string }; + }) => { + // This will check for your two new bug messages and pop-up a toast + if (errors.avatar && errors.avatar.message) { + handleError(errors.avatar.message); + } else if (errors.emoji && errors.emoji.message) { + handleError(errors.emoji.message); + } + }; + // const handleDeleteIntegration = useCallback(() => { const onDelete = async () => { if (!webhookData?._id) { @@ -113,7 +136,7 @@ const EditIncomingWebhook = ({ webhookData }: EditIncomingWebhookProps) => { )} - + diff --git a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx index aa8e77f5b2746..9aea4f8f2b47b 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx @@ -32,6 +32,31 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized { + if (!value) return true; // Not required, so empty is fine + try { + new URL(value); // Use the built-in URL constructor + return true; + } catch (error) { + // If it fails, return the error message for the parent to catch + return t('The_URL_is_invalid', { url: value }); + } + }; + + const validateEmoji = (value: string) => { + if (!value) return true; // Not required, so empty is fine + // Check if it's in :emoji: format + if (/^:.+:$/.test(value)) { + return true; + } + // If not, return an error for the parent to catch + return t('Invalid_emoji_format_Must_be_in_colon_format', { example: ':ghost:' }); + }; + + // + const { control, watch, @@ -239,7 +264,7 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized {t('Avatar_URL')} - ( @@ -250,7 +275,24 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized} /> )} - /> + /> */} + + ( + } + // This line links the error state for accessibility + aria-invalid={Boolean(fieldState.error)} + /> + )} + /> {t('You_can_change_a_different_avatar_too')} {t('Should_be_a_URL_of_an_image')} @@ -258,7 +300,7 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized {t('Emoji')} - ( @@ -269,7 +311,23 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized} /> )} - /> + /> */} + ( + } + // This line links the error state for accessibility + aria-invalid={Boolean(fieldState.error)} + /> + )} + /> {t('You_can_use_an_emoji_as_avatar')} { const t = useTranslation(); + // + const handleError = useErrorHandler(); + // const setModal = useSetModal(); const router = useRouter(); @@ -87,6 +93,8 @@ const EditOutgoingWebhook = ({ webhookData }: EditOutgoingWebhookProps) => { const createIntegration = useCreateIntegration(OUTGOING_TYPE); const updateIntegration = useUpdateIntegration(OUTGOING_TYPE); + + const handleDeleteIntegration = useCallback(() => { const onDelete = async () => { deleteIntegration.mutate({ type: OUTGOING_TYPE, integrationId: webhookData?._id }); @@ -151,7 +159,7 @@ const EditOutgoingWebhook = ({ webhookData }: EditOutgoingWebhookProps) => { )} - + From 42559f904b5659591074ecdfc5cdd551def7baf9 Mon Sep 17 00:00:00 2001 From: MrKalyanKing Date: Fri, 7 Nov 2025 07:04:50 +0000 Subject: [PATCH 2/7] fix(integrations): Add validation for Avatar URL --- .../incoming/EditIncomingWebhook.tsx | 5 +- .../incoming/IncomingWebhookForm.tsx | 71 +++++++------------ 2 files changed, 26 insertions(+), 50 deletions(-) diff --git a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx index a015fa7426f89..4d955b18cd6e6 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx @@ -14,8 +14,7 @@ import { useCreateIntegration } from '../hooks/useCreateIntegration'; import { useDeleteIntegration } from '../hooks/useDeleteIntegration'; import { useUpdateIntegration } from '../hooks/useUpdateIntegration'; -// -// import { useErrorHandler } from '../../import/useErrorHandler'; + export type EditIncomingWebhookFormData = { enabled: boolean; @@ -78,7 +77,7 @@ const EditIncomingWebhook = ({ webhookData }: EditIncomingWebhookProps) => { avatar?: { message?: string }; emoji?: { message?: string }; }) => { - // This will check for your two new bug messages and pop-up a toast + if (errors.avatar && errors.avatar.message) { handleError(errors.avatar.message); } else if (errors.emoji && errors.emoji.message) { diff --git a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx index 9aea4f8f2b47b..fbe7e50454a00 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx @@ -32,26 +32,26 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized { - if (!value) return true; // Not required, so empty is fine + const validateAvatarUrl = (value: string) => { + if (!value) return true; try { - new URL(value); // Use the built-in URL constructor + new URL(value); return true; } catch (error) { - // If it fails, return the error message for the parent to catch + return t('The_URL_is_invalid', { url: value }); } }; const validateEmoji = (value: string) => { - if (!value) return true; // Not required, so empty is fine - // Check if it's in :emoji: format + if (!value) return true; + if (/^:.+:$/.test(value)) { return true; } - // If not, return an error for the parent to catch + return t('Invalid_emoji_format_Must_be_in_colon_format', { example: ':ghost:' }); }; @@ -264,35 +264,23 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized {t('Avatar_URL')} - {/* ( + + rules={{ validate: validateAvatarUrl }} + render={({ field, fieldState }) => ( } + + aria-invalid={Boolean(fieldState.error)} /> )} - /> */} - - ( - } - // This line links the error state for accessibility - aria-invalid={Boolean(fieldState.error)} - /> - )} - /> + /> {t('You_can_change_a_different_avatar_too')} {t('Should_be_a_URL_of_an_image')} @@ -300,34 +288,23 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized {t('Emoji')} - {/* ( + + rules={{ validate: validateEmoji }} + render={({ field, fieldState }) => ( } + + aria-invalid={Boolean(fieldState.error)} /> )} - /> */} - ( - } - // This line links the error state for accessibility - aria-invalid={Boolean(fieldState.error)} - /> - )} - /> + /> {t('You_can_use_an_emoji_as_avatar')} Date: Fri, 7 Nov 2025 17:18:19 +0000 Subject: [PATCH 3/7] fix(integrations): Add validation for Avatar --- .changeset/funny-islands-run.md | 5 ++ .changeset/light-singers-join.md | 5 ++ .../incoming/EditIncomingWebhook.tsx | 18 ++----- .../incoming/IncomingWebhookForm.tsx | 48 +++++++++++-------- 4 files changed, 40 insertions(+), 36 deletions(-) create mode 100644 .changeset/funny-islands-run.md create mode 100644 .changeset/light-singers-join.md diff --git a/.changeset/funny-islands-run.md b/.changeset/funny-islands-run.md new file mode 100644 index 0000000000000..67523184d7222 --- /dev/null +++ b/.changeset/funny-islands-run.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': major +--- + +fix(integrations): Add validation for Incoming Webhook Avatar diff --git a/.changeset/light-singers-join.md b/.changeset/light-singers-join.md new file mode 100644 index 0000000000000..87ee18ec55aa0 --- /dev/null +++ b/.changeset/light-singers-join.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +fix(integrations): Add validation for Incoming Webhook Avatar diff --git a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx index 4d955b18cd6e6..5e9586750c0d9 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/EditIncomingWebhook.tsx @@ -5,7 +5,7 @@ import { useSetModal, useTranslation, useRouter, useRouteParameter } from '@rock import { useId, useCallback } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { useErrorHandler } from '../../import/useErrorHandler'; + import IncomingWebhookForm from './IncomingWebhookForm'; @@ -56,7 +56,7 @@ const EditIncomingWebhook = ({ webhookData }: EditIncomingWebhookProps) => { const setModal = useSetModal(); const tab = useRouteParameter('type'); - const handleError = useErrorHandler(); + const deleteIntegration = useDeleteIntegration(INCOMING_TYPE); const updateIntegration = useUpdateIntegration(INCOMING_TYPE); @@ -72,19 +72,7 @@ const EditIncomingWebhook = ({ webhookData }: EditIncomingWebhookProps) => { - // - const handleInvalid = (errors: { - avatar?: { message?: string }; - emoji?: { message?: string }; - }) => { - if (errors.avatar && errors.avatar.message) { - handleError(errors.avatar.message); - } else if (errors.emoji && errors.emoji.message) { - handleError(errors.emoji.message); - } - }; - // const handleDeleteIntegration = useCallback(() => { const onDelete = async () => { if (!webhookData?._id) { @@ -135,7 +123,7 @@ const EditIncomingWebhook = ({ webhookData }: EditIncomingWebhookProps) => { )} - + diff --git a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx index fbe7e50454a00..e66202f1b658a 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx @@ -32,31 +32,26 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized { - if (!value) return true; + if (!value) return true; try { new URL(value); return true; } catch (error) { - return t('The_URL_is_invalid', { url: value }); } }; const validateEmoji = (value: string) => { - if (!value) return true; - + if (!value) return true; + if (/^:.+:$/.test(value)) { return true; } - + return t('Invalid_emoji_format_Must_be_in_colon_format', { example: ':ghost:' }); }; - // - const { control, watch, @@ -261,57 +256,68 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized {t('Choose_the_alias_that_will_appear_before_the_username_in_messages')} + + {t('Avatar_URL')} - ( + render={({ field, fieldState: { error } }) => ( } - - aria-invalid={Boolean(fieldState.error)} + aria-invalid={Boolean(error)} /> )} /> + {errors?.avatar && ( + + {errors.avatar.message} + + )} + {t('You_can_change_a_different_avatar_too')} {t('Should_be_a_URL_of_an_image')} + {t('Emoji')} - ( + render={({ field, fieldState: { error } }) => ( } - - aria-invalid={Boolean(fieldState.error)} + aria-invalid={Boolean(error)} /> )} /> + + {errors?.emoji && ( + + {errors.emoji.message} + + )} + {t('You_can_use_an_emoji_as_avatar')} + {t('Override_Destination_Channel')} From 3bcbd464a2a33e0a78a93c2c68ae8b2ee381b43b Mon Sep 17 00:00:00 2001 From: MrKalyanKing Date: Fri, 7 Nov 2025 17:26:30 +0000 Subject: [PATCH 4/7] fix(integrations): Add validation for Avatar --- .../admin/integrations/incoming/IncomingWebhookForm.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx index e66202f1b658a..92f418b21508c 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx @@ -35,7 +35,10 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized { if (!value) return true; try { - new URL(value); + const url = new URL(value); + if (url.protocol !== 'http:' && url.protocol !== 'https:') { + return t('The_URL_is_invalid', { url: value }); + } return true; } catch (error) { return t('The_URL_is_invalid', { url: value }); @@ -256,7 +259,6 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized {t('Choose_the_alias_that_will_appear_before_the_username_in_messages')} - {t('Avatar_URL')} From 7ad4f5cef1fe680bae9b973894fc428d25fab4f1 Mon Sep 17 00:00:00 2001 From: MrKalyanKing Date: Sun, 9 Nov 2025 12:31:39 +0000 Subject: [PATCH 5/7] fix(integrations): Add Emoji validation to Incoming webhook form --- .changeset/mighty-queens-hug.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/mighty-queens-hug.md diff --git a/.changeset/mighty-queens-hug.md b/.changeset/mighty-queens-hug.md new file mode 100644 index 0000000000000..e1e0b93c66a10 --- /dev/null +++ b/.changeset/mighty-queens-hug.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +fix(Integration):Incoming webhook form Emoji validation From bd95e5b0f5d6e9d5b818708a6ace2c0b449c5d4f Mon Sep 17 00:00:00 2001 From: MrKalyanKing Date: Sun, 9 Nov 2025 12:49:19 +0000 Subject: [PATCH 6/7] fix(integrations): Add Emoji validation to Incoming webhook form --- .../integrations/incoming/IncomingWebhookForm.tsx | 10 +++++++--- .../integrations/outgoing/EditOutgoingWebhook.tsx | 4 +--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx index 92f418b21508c..6067897c0219c 100644 --- a/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx +++ b/apps/meteor/client/views/admin/integrations/incoming/IncomingWebhookForm.tsx @@ -49,10 +49,14 @@ const IncomingWebhookForm = ({ webhookData }: { webhookData?: Serialized { const t = useTranslation(); - // - const handleError = useErrorHandler(); - // + const setModal = useSetModal(); const router = useRouter(); From cc0a7754d3671f26ee2909c359564f8c599cb68f Mon Sep 17 00:00:00 2001 From: MrKalyanKing Date: Sun, 9 Nov 2025 12:50:46 +0000 Subject: [PATCH 7/7] fix(integrations): Add Emoji validation to Incoming webhook form --- .changeset/mighty-queens-hug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/mighty-queens-hug.md b/.changeset/mighty-queens-hug.md index e1e0b93c66a10..a03e97c78f44d 100644 --- a/.changeset/mighty-queens-hug.md +++ b/.changeset/mighty-queens-hug.md @@ -2,4 +2,4 @@ '@rocket.chat/meteor': patch --- -fix(Integration):Incoming webhook form Emoji validation +fix(integrations): Add validation for Incoming Webhook Emoji field format