summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Corey <alex.swansboro@gmail.com>2021-06-23 14:46:11 +0200
committerShane McDonald <me@shanemcd.com>2021-06-28 16:51:02 +0200
commit28a62ea774f82e8f1e90fad932209ef42e741ac3 (patch)
tree790218a4e47e83413d33acb519907a95cad91dbd
parentAdd link to project update job details on job details page. (diff)
downloadawx-28a62ea774f82e8f1e90fad932209ef42e741ac3.tar.xz
awx-28a62ea774f82e8f1e90fad932209ef42e741ac3.zip
properly validates credential password fields
-rw-r--r--awx/ui_next/src/components/FormField/PasswordInput.jsx12
-rw-r--r--awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx17
-rw-r--r--awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx28
3 files changed, 41 insertions, 16 deletions
diff --git a/awx/ui_next/src/components/FormField/PasswordInput.jsx b/awx/ui_next/src/components/FormField/PasswordInput.jsx
index 4747ef1319..0062ad4cb9 100644
--- a/awx/ui_next/src/components/FormField/PasswordInput.jsx
+++ b/awx/ui_next/src/components/FormField/PasswordInput.jsx
@@ -12,7 +12,15 @@ import {
import { EyeIcon, EyeSlashIcon } from '@patternfly/react-icons';
function PasswordInput(props) {
- const { autocomplete, id, name, validate, isRequired, isDisabled } = props;
+ const {
+ autocomplete,
+ id,
+ name,
+ validate,
+ isFieldGroupValid,
+ isRequired,
+ isDisabled,
+ } = props;
const [inputType, setInputType] = useState('password');
const [field, meta] = useField({ name, validate });
@@ -44,7 +52,7 @@ function PasswordInput(props) {
value={field.value === '$encrypted$' ? '' : field.value}
isDisabled={isDisabled}
isRequired={isRequired}
- validated={isValid ? 'default' : 'error'}
+ validated={isValid || isFieldGroupValid ? 'default' : 'error'}
type={inputType}
onChange={(_, event) => {
field.onChange(event);
diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx
index d7c579e2f3..2633da056a 100644
--- a/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx
+++ b/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx
@@ -26,7 +26,12 @@ const FileUpload = styled(PFFileUpload)`
flex-grow: 1;
`;
-function CredentialInput({ fieldOptions, credentialKind, ...rest }) {
+function CredentialInput({
+ fieldOptions,
+ isFieldGroupValid,
+ credentialKind,
+ ...rest
+}) {
const [fileName, setFileName] = useState('');
const [fileIsUploading, setFileIsUploading] = useState(false);
const [subFormField, meta, helpers] = useField(`inputs.${fieldOptions.id}`);
@@ -116,6 +121,7 @@ function CredentialInput({ fieldOptions, credentialKind, ...rest }) {
<>
{RevertReplaceButton}
<PasswordInput
+ isFieldGroupValid={isFieldGroupValid}
{...subFormField}
id={`credential-${fieldOptions.id}`}
{...rest}
@@ -169,7 +175,9 @@ function CredentialField({ credentialType, fieldOptions }) {
name: `inputs.${fieldOptions.id}`,
validate: validateField(),
});
- const isValid = !(meta.touched && meta.error);
+ const isValid =
+ !(meta.touched && meta.error) ||
+ formikValues.passwordPrompts[fieldOptions.id];
if (fieldOptions.choices) {
const selectOptions = fieldOptions.choices.map(choice => {
@@ -235,7 +243,10 @@ function CredentialField({ credentialType, fieldOptions }) {
isRequired={isRequired}
validated={isValid ? 'default' : 'error'}
>
- <CredentialInput fieldOptions={fieldOptions} />
+ <CredentialInput
+ isFieldGroupValid={isValid}
+ fieldOptions={fieldOptions}
+ />
</CredentialPluginField>
);
}
diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx
index 952eeb214a..8b37f241d3 100644
--- a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx
+++ b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx
@@ -98,15 +98,23 @@ function CredentialPluginField(props) {
const [, meta, helpers] = useField(`inputs.${fieldOptions.id}`);
const [passwordPromptField] = useField(`passwordPrompts.${fieldOptions.id}`);
- const invalidHelperTextToDisplay = meta.error && meta.touched && (
- <div
- className={css(styles.formHelperText, styles.modifiers.error)}
- id={`${fieldOptions.id}-helper`}
- aria-live="polite"
- >
- {meta.error}
- </div>
- );
+ let invalidHelperTextToDisplay;
+
+ if (meta.error && meta.touched) {
+ invalidHelperTextToDisplay = (
+ <div
+ className={css(styles.formHelperText, styles.modifiers.error)}
+ id={`${fieldOptions.id}-helper`}
+ aria-live="polite"
+ >
+ {meta.error}
+ </div>
+ );
+ }
+
+ if (fieldOptions.id === 'vault_password' && passwordPromptField.value) {
+ invalidHelperTextToDisplay = null;
+ }
useEffect(() => {
if (passwordPromptField.value) {
@@ -119,8 +127,6 @@ function CredentialPluginField(props) {
<>
{fieldOptions.ask_at_runtime ? (
<FieldWithPrompt
- fieldId={`credential-${fieldOptions.id}`}
- helperTextInvalid={meta.error}
isRequired={isRequired}
label={fieldOptions.label}
promptId={`credential-prompt-${fieldOptions.id}`}