diff --git a/client/src/Pages/Notifications/create/index.jsx b/client/src/Pages/Notifications/create/index.jsx index de5ee39b9..b78f9a40a 100644 --- a/client/src/Pages/Notifications/create/index.jsx +++ b/client/src/Pages/Notifications/create/index.jsx @@ -65,12 +65,19 @@ const CreateNotifications = () => { const [isOpen, setIsOpen] = useState(false); + const getNotificationTypeValue = (typeId) => { + return NOTIFICATION_TYPES.find((type) => type._id === typeId)?.value || "email"; + }; + + const extractError = (error, field) => + error?.details.find((d) => d.path.includes(field))?.message; + // handlers const onSubmit = (e) => { e.preventDefault(); const form = { ...notification, - type: NOTIFICATION_TYPES.find((type) => type._id === notification.type).value, + type: getNotificationTypeValue(notification.type), }; let error = null; @@ -84,7 +91,7 @@ const CreateNotifications = () => { }); console.log(JSON.stringify(newErrors)); console.log(JSON.stringify(form, null, 2)); - createToast({ body: "Please check the form for errors." }); + createToast({ body: Object.values(newErrors)[0] }); setErrors(newErrors); return; } @@ -98,22 +105,32 @@ const CreateNotifications = () => { const onChange = (e) => { const { name, value } = e.target; + let rawNotification = { ...notification, [name]: value }; + let newNotification = { + ...rawNotification, + type: getNotificationTypeValue(rawNotification.type), + }; - const newNotification = { ...notification, [name]: value }; + const { error } = notificationValidation.validate(newNotification, { + abortEarly: false, + }); + let validationError = { ...errors }; - const { error } = notificationValidation.extract(name).validate(value); - setErrors((prev) => ({ - ...prev, - [name]: error?.message, - })); + if (name === "type") { + validationError["type"] = extractError(error, "type"); + validationError["address"] = extractError(error, "address"); + } else { + validationError[name] = extractError(error, name); + } - setNotification(newNotification); + setNotification(rawNotification); + setErrors(validationError); }; const onTestNotification = () => { const form = { ...notification, - type: NOTIFICATION_TYPES.find((type) => type._id === notification.type).value, + type: getNotificationTypeValue(notification.type), }; let error = null; @@ -125,7 +142,7 @@ const CreateNotifications = () => { error.details.forEach((err) => { newErrors[err.path[0]] = err.message; }); - createToast({ body: "Please check the form for errors." }); + createToast({ body: Object.values(newErrors)[0] }); setErrors(newErrors); return; } @@ -139,7 +156,7 @@ const CreateNotifications = () => { } }; - const type = NOTIFICATION_TYPES.find((type) => type._id === notification.type).value; + const type = getNotificationTypeValue(notification.type); return ( diff --git a/client/src/Validation/validation.js b/client/src/Validation/validation.js index d86bbd556..b2fe7de71 100644 --- a/client/src/Validation/validation.js +++ b/client/src/Validation/validation.js @@ -410,14 +410,33 @@ const notificationValidation = joi.object({ "string.empty": "Notification name is required", "any.required": "Notification name is required", }), - address: joi.string().required().messages({ - "string.empty": "This field cannot be empty", - "string.base": "This field must be a string", - "any.required": "This field is required", - }), - type: joi.string().required().messages({ - "string.empty": "This field is required", - "any.required": "This field is required", + + type: joi + .string() + .valid("email", "webhook", "slack", "discord", "pager_duty") + .required() + .messages({ + "string.empty": "Notification type is required", + "any.required": "Notification type is required", + "any.only": "Notification type must be email, webhook, or pager_duty", + }), + + address: joi.when("type", { + is: "email", + then: joi + .string() + .email({ tlds: { allow: false } }) + .required() + .messages({ + "string.empty": "E-mail address cannot be empty", + "any.required": "E-mail address is required", + "string.email": "Please enter a valid e-mail address", + }), + otherwise: joi.string().uri().required().messages({ + "string.empty": "Webhook URL cannot be empty", + "any.required": "Webhook URL is required", + "string.uri": "Please enter a valid Webhook URL", + }), }), }); diff --git a/server/validation/joi.js b/server/validation/joi.js index d44bb14eb..f555756eb 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -577,14 +577,7 @@ const createNotificationBodyValidation = joi.object({ "string.empty": "Notification name is required", "any.required": "Notification name is required", }), - address: joi.when("type", { - is: "email", - then: joi.string().email().required().messages({ - "string.empty": "E-mail address cannot be empty", - "any.required": "E-mail address is required", - "string.email": "Please enter a valid e-mail address", - }), - }), + type: joi .string() .valid("email", "webhook", "slack", "discord", "pager_duty") @@ -594,6 +587,20 @@ const createNotificationBodyValidation = joi.object({ "any.required": "Notification type is required", "any.only": "Notification type must be email, webhook, or pager_duty", }), + + address: joi.when("type", { + is: "email", + then: joi.string().email().required().messages({ + "string.empty": "E-mail address cannot be empty", + "any.required": "E-mail address is required", + "string.email": "Please enter a valid e-mail address", + }), + otherwise: joi.string().uri().required().messages({ + "string.empty": "Webhook URL cannot be empty", + "any.required": "Webhook URL is required", + "string.uri": "Please enter a valid Webhook URL", + }), + }), }); //****************************************