From e3eea58ac09dd23af2e987e3350ab4a16262f531 Mon Sep 17 00:00:00 2001 From: Brad Rogers Date: Wed, 7 Sep 2022 01:28:52 -0500 Subject: [PATCH 1/2] ROX-12343: unauthenticated email integration --- .../ToggledPopoverElement.tsx | 35 ++++++ .../Components/ToggledPopoverElement/index.ts | 1 + .../Forms/EmailIntegrationForm.tsx | 101 +++++++++++++++--- .../Reports/Form/EmailIntegrationForm.tsx | 82 ++++++++++++-- ui/apps/platform/src/types/notifier.proto.ts | 1 + 5 files changed, 195 insertions(+), 25 deletions(-) create mode 100644 ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx create mode 100644 ui/apps/platform/src/Components/ToggledPopoverElement/index.ts diff --git a/ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx b/ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx new file mode 100644 index 0000000000000..fe839d3c6be74 --- /dev/null +++ b/ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx @@ -0,0 +1,35 @@ +import React, { ReactElement, ReactNode } from 'react'; + +import { Popover } from '@patternfly/react-core'; + +export type ToggledPopoverElementProps = { + children: ReactNode; + popoverContent: string; + ariaLabel: string; + className: string; +}; + +/* + * Display children in a message box + * that is centered in the full height and width of its parent. + */ +const ToggledPopoverElement = ({ + children, + popoverContent, + ariaLabel, + className, +}: ToggledPopoverElementProps): ReactElement => ( + + + +); + +export default ToggledPopoverElement; diff --git a/ui/apps/platform/src/Components/ToggledPopoverElement/index.ts b/ui/apps/platform/src/Components/ToggledPopoverElement/index.ts new file mode 100644 index 0000000000000..460c0b7d9cf1c --- /dev/null +++ b/ui/apps/platform/src/Components/ToggledPopoverElement/index.ts @@ -0,0 +1 @@ +export { default } from './ToggledPopoverElement'; diff --git a/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx b/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx index b39d1fdc3c83c..7925106e84062 100644 --- a/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx +++ b/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx @@ -1,6 +1,15 @@ /* eslint-disable no-void */ -import React, { ReactElement } from 'react'; -import { Checkbox, Form, PageSection, SelectOption, TextInput } from '@patternfly/react-core'; +import React, { ReactElement, useState } from 'react'; +import { + Alert, + AlertVariant, + Checkbox, + Form, + PageSection, + SelectOption, + TextInput, +} from '@patternfly/react-core'; +import { HelpIcon } from '@patternfly/react-icons'; import * as yup from 'yup'; import { NotifierIntegrationBase } from 'services/NotifierIntegrationsService'; @@ -11,6 +20,7 @@ import FormMessage from 'Components/PatternFly/FormMessage'; import FormCancelButton from 'Components/PatternFly/FormCancelButton'; import FormTestButton from 'Components/PatternFly/FormTestButton'; import FormSaveButton from 'Components/PatternFly/FormSaveButton'; +import ToggledPopoverElement from 'Components/ToggledPopoverElement'; import useIntegrationForm from '../useIntegrationForm'; import { IntegrationFormProps } from '../integrationFormTypes'; @@ -27,6 +37,7 @@ export type EmailIntegration = { sender: string; disableTLS: boolean; startTLSAuthMethod: 'DISABLED' | 'PLAIN' | 'LOGIN'; + allowUnauthenticatedSmtp: boolean; }; type: 'email'; } & NotifierIntegrationBase; @@ -69,7 +80,11 @@ export const validationSchema = yup.object().shape({ .trim() .required('A server address is required') .matches(validHostnameRegex, 'Must be a valid server address'), - username: yup.string().trim().required('A username is required'), + allowUnauthenticatedSmtp: yup.boolean(), + username: yup.string().when('allowUnauthenticatedSmtp', { + is: false, + then: (usernameSchema) => usernameSchema.trim().required('A username is required'), + }), password: yup .string() .test( @@ -77,11 +92,9 @@ export const validationSchema = yup.object().shape({ 'A password is required', (value, context: yup.TestContext) => { const requirePasswordField = - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - context?.from[2]?.value?.updatePassword || false; + context?.from?.[2].value?.updatePassword || false; - if (!requirePasswordField) { + if (!requirePasswordField || context.parent.allowUnauthenticatedSmtp) { return true; } @@ -116,6 +129,7 @@ export const defaultValues: EmailIntegrationFormValues = { sender: '', disableTLS: false, startTLSAuthMethod: 'DISABLED', + allowUnauthenticatedSmtp: false, }, labelDefault: '', labelKey: '', @@ -130,6 +144,7 @@ function EmailIntegrationForm({ isEditable = false, }: IntegrationFormProps): ReactElement { const formInitialValues = { ...defaultValues, ...initialValues }; + const [storedUsername, setStoredUsername] = useState(''); if (initialValues) { formInitialValues.notifier = { ...formInitialValues.notifier, @@ -158,6 +173,7 @@ function EmailIntegrationForm({ validationSchema, }); const { isCreating } = usePageState(); + const { allowUnauthenticatedSmtp } = values.notifier.email; function onChange(value, event) { return setFieldValue(event.target.id, value); @@ -170,6 +186,17 @@ function EmailIntegrationForm({ } } + function onUpdateUnauthenticatedChange(isChecked) { + if (isChecked) { + setStoredUsername(values.notifier.email.username); + setFieldValue('notifier.email.username', ''); + setFieldValue('notifier.email.password', ''); + } else { + setFieldValue('notifier.email.username', storedUsername); + } + setFieldValue('notifier.email.allowUnauthenticatedSmtp', isChecked); + } + function onUpdateCredentialsChange(value, event) { setFieldValue('notifier.email.password', ''); return setFieldValue(event.target.id, value); @@ -216,25 +243,65 @@ function EmailIntegrationForm({ isDisabled={!isEditable} /> + + <> +
+ + + + +
+ {allowUnauthenticatedSmtp && ( + +

+ Unauthenticated SMTP is an insecure configuration and not + generally recommended. Please proceed with caution when + enabling this setting. +

+
+ )} + +
- {!isCreating && isEditable && ( + {!isCreating && isEditable && !allowUnauthenticatedSmtp && ( @@ -88,40 +111,81 @@ function EmailIntegrationForm({ onBlur={handleBlur} /> + + <> +
+ + + + +
+ {allowUnauthenticatedSmtp && ( + +

+ Unauthenticated SMTP is an insecure configuration and not + generally recommended. Please proceed with caution when + enabling this setting. +

+
+ )} + +
Date: Wed, 7 Sep 2022 11:01:53 -0500 Subject: [PATCH 2/2] ROX-12343: remove reusable popover button --- .../ToggledPopoverElement.tsx | 35 ------------------- .../Components/ToggledPopoverElement/index.ts | 1 - .../Forms/EmailIntegrationForm.tsx | 20 +++++++---- .../Reports/Form/EmailIntegrationForm.tsx | 20 +++++++---- 4 files changed, 26 insertions(+), 50 deletions(-) delete mode 100644 ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx delete mode 100644 ui/apps/platform/src/Components/ToggledPopoverElement/index.ts diff --git a/ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx b/ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx deleted file mode 100644 index fe839d3c6be74..0000000000000 --- a/ui/apps/platform/src/Components/ToggledPopoverElement/ToggledPopoverElement.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { ReactElement, ReactNode } from 'react'; - -import { Popover } from '@patternfly/react-core'; - -export type ToggledPopoverElementProps = { - children: ReactNode; - popoverContent: string; - ariaLabel: string; - className: string; -}; - -/* - * Display children in a message box - * that is centered in the full height and width of its parent. - */ -const ToggledPopoverElement = ({ - children, - popoverContent, - ariaLabel, - className, -}: ToggledPopoverElementProps): ReactElement => ( - - - -); - -export default ToggledPopoverElement; diff --git a/ui/apps/platform/src/Components/ToggledPopoverElement/index.ts b/ui/apps/platform/src/Components/ToggledPopoverElement/index.ts deleted file mode 100644 index 460c0b7d9cf1c..0000000000000 --- a/ui/apps/platform/src/Components/ToggledPopoverElement/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ToggledPopoverElement'; diff --git a/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx b/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx index 7925106e84062..4d4739211a666 100644 --- a/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx +++ b/ui/apps/platform/src/Containers/Integrations/IntegrationForm/Forms/EmailIntegrationForm.tsx @@ -8,6 +8,7 @@ import { PageSection, SelectOption, TextInput, + Popover, } from '@patternfly/react-core'; import { HelpIcon } from '@patternfly/react-icons'; import * as yup from 'yup'; @@ -20,7 +21,6 @@ import FormMessage from 'Components/PatternFly/FormMessage'; import FormCancelButton from 'Components/PatternFly/FormCancelButton'; import FormTestButton from 'Components/PatternFly/FormTestButton'; import FormSaveButton from 'Components/PatternFly/FormSaveButton'; -import ToggledPopoverElement from 'Components/ToggledPopoverElement'; import useIntegrationForm from '../useIntegrationForm'; import { IntegrationFormProps } from '../integrationFormTypes'; @@ -257,13 +257,19 @@ function EmailIntegrationForm({ onChange={onUpdateUnauthenticatedChange} onBlur={handleBlur} /> - - - + + {allowUnauthenticatedSmtp && ( - - - + + {allowUnauthenticatedSmtp && (