Fix webhook pages in Settings (#10902)
## Context Some users were able to set an empty URL as webhook targetUrl, which was breaking the Webhook List and Detail pages ## Fix - Making sure to protect getHostNameOrThrow by isValidUrl - rework webhook form to prevent creation of invalid webhooks Fixes https://github.com/twentyhq/twenty/issues/10822
This commit is contained in:
@ -5,7 +5,7 @@ import { IconChevronRight } from 'twenty-ui';
|
||||
import { Webhook } from '@/settings/developers/types/webhook/Webhook';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { getUrlHostnameOrThrow } from 'twenty-shared';
|
||||
import { getUrlHostnameOrThrow, isValidUrl } from 'twenty-shared';
|
||||
|
||||
export const StyledApisFieldTableRow = styled(TableRow)`
|
||||
grid-template-columns: 1fr 28px;
|
||||
@ -39,7 +39,9 @@ export const SettingsDevelopersWebhookTableRow = ({
|
||||
return (
|
||||
<StyledApisFieldTableRow to={to}>
|
||||
<StyledUrlTableCell>
|
||||
{getUrlHostnameOrThrow(fieldItem.targetUrl)}
|
||||
{isValidUrl(fieldItem.targetUrl)
|
||||
? getUrlHostnameOrThrow(fieldItem.targetUrl)
|
||||
: fieldItem.targetUrl}
|
||||
</StyledUrlTableCell>
|
||||
<StyledIconTableCell>
|
||||
<StyledIconChevronRight
|
||||
|
||||
@ -35,7 +35,12 @@ export const useWebhookUpdateForm = ({
|
||||
const [formData, setFormData] = useState<WebhookFormData>({
|
||||
targetUrl: '',
|
||||
description: '',
|
||||
operations: [],
|
||||
operations: [
|
||||
{
|
||||
object: '*',
|
||||
action: '*',
|
||||
},
|
||||
],
|
||||
secret: '',
|
||||
});
|
||||
|
||||
@ -98,20 +103,35 @@ export const useWebhookUpdateForm = ({
|
||||
});
|
||||
}, 300);
|
||||
|
||||
const validateData = (data: Partial<WebhookFormData>) => {
|
||||
if (isDefined(data?.targetUrl)) {
|
||||
const trimmedUrl = data.targetUrl.trim();
|
||||
const isTargetUrlValid = isValidUrl(trimmedUrl);
|
||||
setIsTargetUrlValid(isTargetUrlValid);
|
||||
if (isTargetUrlValid) {
|
||||
setTitle(getUrlHostnameOrThrow(trimmedUrl) || 'New Webhook');
|
||||
const isFormValidAndSetErrors = () => {
|
||||
const { targetUrl } = formData;
|
||||
|
||||
if (isDefined(targetUrl)) {
|
||||
const trimmedUrl = targetUrl.trim();
|
||||
const isValid = isValidUrl(trimmedUrl);
|
||||
|
||||
if (!isValid) {
|
||||
setIsTargetUrlValid(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
setIsTargetUrlValid(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const updateWebhook = async (data: Partial<WebhookFormData>) => {
|
||||
validateData(data);
|
||||
setFormData((prev) => ({ ...prev, ...data }));
|
||||
|
||||
if (!isFormValidAndSetErrors()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(data?.targetUrl)) {
|
||||
setTitle(getUrlHostnameOrThrow(data.targetUrl) || 'New Webhook');
|
||||
}
|
||||
|
||||
await handleSave();
|
||||
};
|
||||
|
||||
@ -173,7 +193,10 @@ export const useWebhookUpdateForm = ({
|
||||
operations,
|
||||
secret: data.secret,
|
||||
});
|
||||
setTitle(getUrlHostnameOrThrow(data.targetUrl) || 'New Webhook');
|
||||
if (isValidUrl(data.targetUrl)) {
|
||||
setTitle(getUrlHostnameOrThrow(data.targetUrl));
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user