fix(ui): Add additional URL & email input validation (#843)

pull/848/head
TheCatLady 3 years ago committed by GitHub
parent b9d14a9fd0
commit 3f9bfeb01a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -14,13 +14,13 @@ const messages = defineMessages({
saving: 'Saving…',
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
validationWebhookUrlRequired: 'You must provide a webhook URL',
webhookUrlPlaceholder: 'Server Settings → Integrations → Webhooks',
discordsettingssaved: 'Discord notification settings saved!',
discordsettingsfailed: 'Discord notification settings failed to save.',
testsent: 'Test notification sent!',
test: 'Test',
notificationtypes: 'Notification Types',
validationWebhookUrl: 'You must provide a valid URL',
});
const NotificationsDiscord: React.FC = () => {
@ -31,9 +31,9 @@ const NotificationsDiscord: React.FC = () => {
);
const NotificationsDiscordSchema = Yup.object().shape({
webhookUrl: Yup.string().required(
intl.formatMessage(messages.validationWebhookUrlRequired)
),
webhookUrl: Yup.string()
.required(intl.formatMessage(messages.validationWebhookUrl))
.url(intl.formatMessage(messages.validationWebhookUrl)),
});
if (!data && !error) {

@ -12,7 +12,6 @@ import NotificationTypeSelector from '../../NotificationTypeSelector';
const messages = defineMessages({
save: 'Save Changes',
saving: 'Saving…',
validationFromRequired: 'You must provide a sender address',
validationSmtpHostRequired: 'You must provide an SMTP host',
validationSmtpPortRequired: 'You must provide an SMTP port',
agentenabled: 'Enable Agent',
@ -31,6 +30,7 @@ const messages = defineMessages({
'SSL should be disabled on standard TLS connections (port 587)',
senderName: 'Sender Name',
notificationtypes: 'Notification Types',
validationEmail: 'You must provide a valid email address',
});
const NotificationsEmail: React.FC = () => {
@ -41,9 +41,9 @@ const NotificationsEmail: React.FC = () => {
);
const NotificationsEmailSchema = Yup.object().shape({
emailFrom: Yup.string().required(
intl.formatMessage(messages.validationFromRequired)
),
emailFrom: Yup.string()
.required(intl.formatMessage(messages.validationEmail))
.email(intl.formatMessage(messages.validationEmail)),
smtpHost: Yup.string().required(
intl.formatMessage(messages.validationSmtpHostRequired)
),

@ -15,7 +15,6 @@ const messages = defineMessages({
saving: 'Saving…',
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
validationWebhookUrlRequired: 'You must provide a webhook URL',
webhookUrlPlaceholder: 'Webhook URL',
slacksettingssaved: 'Slack notification settings saved!',
slacksettingsfailed: 'Slack notification settings failed to save.',
@ -25,6 +24,7 @@ const messages = defineMessages({
settingupslackDescription:
'To use Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and use the provided webhook URL below.',
notificationtypes: 'Notification Types',
validationWebhookUrl: 'You must provide a valid URL',
});
const NotificationsSlack: React.FC = () => {
@ -35,9 +35,9 @@ const NotificationsSlack: React.FC = () => {
);
const NotificationsSlackSchema = Yup.object().shape({
webhookUrl: Yup.string().required(
intl.formatMessage(messages.validationWebhookUrlRequired)
),
webhookUrl: Yup.string()
.required(intl.formatMessage(messages.validationWebhookUrl))
.url(intl.formatMessage(messages.validationWebhookUrl)),
});
if (!data && !error) {

@ -37,7 +37,6 @@ const messages = defineMessages({
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
authheader: 'Authorization Header',
validationWebhookUrlRequired: 'You must provide a webhook URL',
validationJsonPayloadRequired: 'You must provide a JSON Payload',
webhookUrlPlaceholder: 'Remote webhook URL',
webhooksettingssaved: 'Webhook notification settings saved!',
@ -49,6 +48,7 @@ const messages = defineMessages({
resetPayloadSuccess: 'JSON reset to default payload.',
customJson: 'Custom JSON Payload',
templatevariablehelp: 'Template Variable Help',
validationWebhookUrl: 'You must provide a valid URL',
});
const NotificationsWebhook: React.FC = () => {
@ -59,9 +59,13 @@ const NotificationsWebhook: React.FC = () => {
);
const NotificationsWebhookSchema = Yup.object().shape({
webhookUrl: Yup.string().required(
intl.formatMessage(messages.validationWebhookUrlRequired)
),
webhookUrl: Yup.string()
.required(intl.formatMessage(messages.validationWebhookUrl))
.matches(
// eslint-disable-next-line
/^(https?:)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*)?([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/,
intl.formatMessage(messages.validationWebhookUrl)
),
jsonPayload: Yup.string()
.required(intl.formatMessage(messages.validationJsonPayloadRequired))
.test('validate-json', 'Invalid JSON', (value) => {

@ -52,6 +52,8 @@ const messages = defineMessages({
preventSearch: 'Disable Auto-Search',
validationApplicationUrl: 'You must provide a valid URL',
validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash',
validationBaseUrlLeadingSlash: 'Base URL must have a leading slash',
validationBaseUrlTrailingSlash: 'Base URL must not end in a trailing slash',
});
interface TestResponse {
@ -119,6 +121,27 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
return true;
}
),
baseUrl: Yup.string()
.test(
'leading-slash',
intl.formatMessage(messages.validationBaseUrlLeadingSlash),
(value) => {
if (value && value?.substr(0, 1) !== '/') {
return false;
}
return true;
}
)
.test(
'no-trailing-slash',
intl.formatMessage(messages.validationBaseUrlTrailingSlash),
(value) => {
if (value?.substr(value.length - 1) === '/') {
return false;
}
return true;
}
),
});
const testConnection = useCallback(

@ -52,6 +52,8 @@ const messages = defineMessages({
preventSearch: 'Disable Auto-Search',
validationApplicationUrl: 'You must provide a valid URL',
validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash',
validationBaseUrlLeadingSlash: 'Base URL must have a leading slash',
validationBaseUrlTrailingSlash: 'Base URL must not end in a trailing slash',
});
interface TestResponse {
@ -116,6 +118,27 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
return true;
}
),
baseUrl: Yup.string()
.test(
'leading-slash',
intl.formatMessage(messages.validationBaseUrlLeadingSlash),
(value) => {
if (value && value?.substr(0, 1) !== '/') {
return false;
}
return true;
}
)
.test(
'no-trailing-slash',
intl.formatMessage(messages.validationBaseUrlTrailingSlash),
(value) => {
if (value?.substr(value.length - 1) === '/') {
return false;
}
return true;
}
),
});
const testConnection = useCallback(

@ -11,6 +11,7 @@ import PermissionEdit from '../PermissionEdit';
import { Field, Form, Formik } from 'formik';
import { UserType } from '../../../server/constants/user';
import PageTitle from '../Common/PageTitle';
import * as Yup from 'yup';
export const messages = defineMessages({
edituser: 'Edit User',
@ -23,6 +24,7 @@ export const messages = defineMessages({
saving: 'Saving…',
usersaved: 'User saved!',
userfail: 'Something went wrong while saving the user.',
validationEmail: 'You must provide a valid email address',
});
const UserEdit: React.FC = () => {
@ -43,6 +45,12 @@ const UserEdit: React.FC = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user]);
const UserEditSchema = Yup.object().shape({
email: Yup.string()
.required(intl.formatMessage(messages.validationEmail))
.email(intl.formatMessage(messages.validationEmail)),
});
if (!user && !error) {
return <LoadingSpinner />;
}
@ -54,6 +62,7 @@ const UserEdit: React.FC = () => {
username: user?.username,
email: user?.email,
}}
validationSchema={UserEditSchema}
onSubmit={async (values) => {
try {
await axios.put(`/api/v1/user/${user?.id}`, {
@ -78,7 +87,7 @@ const UserEdit: React.FC = () => {
}
}}
>
{({ isSubmitting, handleSubmit }) => (
{({ errors, touched, isSubmitting, handleSubmit }) => (
<Form>
<PageTitle title={intl.formatMessage(messages.edituser)} />
<div>
@ -122,6 +131,9 @@ const UserEdit: React.FC = () => {
<div className="flex max-w-lg rounded-md shadow-sm">
<Field id="email" name="email" type="text" readOnly />
</div>
{errors.email && touched.email && (
<div className="error">{errors.email}</div>
)}
</div>
</div>
<div className="form-row">

@ -51,7 +51,6 @@ const messages = defineMessages({
createuser: 'Create User',
creating: 'Creating…',
create: 'Create',
validationemailrequired: 'Must enter a valid email address',
validationpasswordminchars:
'Password is too short; should be a minimum of 8 characters',
usercreatedfailed: 'Something went wrong while creating the user.',
@ -62,6 +61,7 @@ const messages = defineMessages({
passwordinfodescription:
'Email notifications need to be configured and enabled in order to automatically generate passwords.',
autogeneratepassword: 'Automatically generate password',
validationEmail: 'You must provide a valid email address',
});
const UserList: React.FC = () => {
@ -171,8 +171,8 @@ const UserList: React.FC = () => {
const CreateUserSchema = Yup.object().shape({
email: Yup.string()
.email()
.required(intl.formatMessage(messages.validationemailrequired)),
.required(intl.formatMessage(messages.validationEmail))
.email(intl.formatMessage(messages.validationEmail)),
password: Yup.lazy((value) =>
!value ? Yup.string() : Yup.string().min(8)
),

@ -237,7 +237,7 @@
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Slack notification settings saved!",
"components.Settings.Notifications.NotificationsSlack.test": "Test",
"components.Settings.Notifications.NotificationsSlack.testsent": "Test notification sent!",
"components.Settings.Notifications.NotificationsSlack.validationWebhookUrlRequired": "You must provide a webhook URL",
"components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "You must provide a valid URL",
"components.Settings.Notifications.NotificationsSlack.webhookUrl": "Webhook URL",
"components.Settings.Notifications.NotificationsSlack.webhookUrlPlaceholder": "Webhook URL",
"components.Settings.Notifications.NotificationsWebhook.agentenabled": "Enable Agent",
@ -252,7 +252,7 @@
"components.Settings.Notifications.NotificationsWebhook.test": "Test",
"components.Settings.Notifications.NotificationsWebhook.testsent": "Test notification sent!",
"components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "You must provide a JSON payload",
"components.Settings.Notifications.NotificationsWebhook.validationWebhookUrlRequired": "You must provide a webhook URL",
"components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "You must provide a valid URL",
"components.Settings.Notifications.NotificationsWebhook.webhookUrl": "Webhook URL",
"components.Settings.Notifications.NotificationsWebhook.webhookUrlPlaceholder": "Remote webhook URL",
"components.Settings.Notifications.NotificationsWebhook.webhooksettingsfailed": "Webhook notification settings failed to save.",
@ -284,10 +284,10 @@
"components.Settings.Notifications.testsent": "Test notification sent!",
"components.Settings.Notifications.validationBotAPIRequired": "You must provide a Bot API key",
"components.Settings.Notifications.validationChatIdRequired": "You must provide a Chat ID",
"components.Settings.Notifications.validationFromRequired": "You must provide a sender address",
"components.Settings.Notifications.validationEmail": "You must provide a valid email address",
"components.Settings.Notifications.validationSmtpHostRequired": "You must provide an SMTP host",
"components.Settings.Notifications.validationSmtpPortRequired": "You must provide an SMTP port",
"components.Settings.Notifications.validationWebhookUrlRequired": "You must provide a webhook URL",
"components.Settings.Notifications.validationWebhookUrl": "You must provide a valid URL",
"components.Settings.Notifications.webhookUrl": "Webhook URL",
"components.Settings.Notifications.webhookUrlPlaceholder": "Server Settings → Integrations → Webhooks",
"components.Settings.RadarrModal.add": "Add Server",
@ -327,6 +327,8 @@
"components.Settings.RadarrModal.validationApiKeyRequired": "You must provide an API key",
"components.Settings.RadarrModal.validationApplicationUrl": "You must provide a valid URL",
"components.Settings.RadarrModal.validationApplicationUrlTrailingSlash": "URL must not end in a trailing slash",
"components.Settings.RadarrModal.validationBaseUrlLeadingSlash": "Base URL must have a leading slash",
"components.Settings.RadarrModal.validationBaseUrlTrailingSlash": "Base URL must not end in a trailing slash",
"components.Settings.RadarrModal.validationHostnameRequired": "You must provide a hostname/IP",
"components.Settings.RadarrModal.validationMinimumAvailabilityRequired": "You must select a minimum availability",
"components.Settings.RadarrModal.validationNameRequired": "You must provide a server name",
@ -413,6 +415,8 @@
"components.Settings.SonarrModal.validationApiKeyRequired": "You must provide an API key",
"components.Settings.SonarrModal.validationApplicationUrl": "You must provide a valid URL",
"components.Settings.SonarrModal.validationApplicationUrlTrailingSlash": "URL must not end in a trailing slash",
"components.Settings.SonarrModal.validationBaseUrlLeadingSlash": "Base URL must have a leading slash",
"components.Settings.SonarrModal.validationBaseUrlTrailingSlash": "Base URL must not end in a trailing slash",
"components.Settings.SonarrModal.validationHostnameRequired": "You must provide a hostname/IP",
"components.Settings.SonarrModal.validationNameRequired": "You must provide a server name",
"components.Settings.SonarrModal.validationPortRequired": "You must provide a port",
@ -576,6 +580,7 @@
"components.UserEdit.userfail": "Something went wrong while saving the user.",
"components.UserEdit.username": "Display Name",
"components.UserEdit.usersaved": "User saved!",
"components.UserEdit.validationEmail": "You must provide a valid email address",
"components.UserList.admin": "Admin",
"components.UserList.autogeneratepassword": "Automatically generate password",
"components.UserList.bulkedit": "Bulk Edit",
@ -610,7 +615,7 @@
"components.UserList.users": "Users",
"components.UserList.userssaved": "Users saved!",
"components.UserList.usertype": "User Type",
"components.UserList.validationemailrequired": "Must enter a valid email address",
"components.UserList.validationEmail": "You must provide a valid email address",
"components.UserList.validationpasswordminchars": "Password is too short; should be a minimum of 8 characters",
"i18n.advanced": "Advanced",
"i18n.approve": "Approve",

Loading…
Cancel
Save