Skip to content

Fixes #27536: Allow removing optional password fields in connection edit form#27589

Open
miantalha45 wants to merge 20 commits intoopen-metadata:mainfrom
miantalha45:fix/password-field-remove-ux
Open

Fixes #27536: Allow removing optional password fields in connection edit form#27589
miantalha45 wants to merge 20 commits intoopen-metadata:mainfrom
miantalha45:fix/password-field-remove-ux

Conversation

@miantalha45
Copy link
Copy Markdown
Contributor

@miantalha45 miantalha45 commented Apr 21, 2026

Problem

Password fields in the connection edit form don't return values from the API (expected, for security). However, this meant users had no way to:

  • Know whether a password was previously saved (the field appeared empty)
  • Remove an optional password field (e.g. Snowflake private key) to delete the secret from Secrets Manager

Fixes #27536

Solution

When a password field contains a masked value (*********) from the API, instead of showing a confusing empty input, we now show a saved password indicator with explicit actions:

  • "Password is saved" indicator — makes it clear a secret exists
  • Update — switches to edit mode to enter a new password
  • Remove (non-required fields only) — explicitly clears the field, signaling the backend to remove the secret from Secrets Manager
  • Cancel — reverts back to the saved indicator without submitting changes

Changes

  • PasswordWidget.tsx — new saved/edit/remove state machine for masked password fields
  • password-widget.less — styles for the saved password indicator
  • en-us.json + all 17 locale files — new message.password-saved i18n key
  • PasswordWidget.test.tsx — updated and expanded tests (9 → 13 tests)

Recording

Screen.Recording.2026-04-22.at.5.00.45.PM.mov

Type of change:

  • Bug fix

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • I have commented on my code, particularly in hard-to-understand areas.

Summary by Gitar

  • Backend secret management:
    • Updated SecretsManager to handle null password values as explicit removal requests.
    • Modified ExternalSecretsManager and DBSecretsManager to delete existing secrets when an empty string is provided.
  • Testing updates:
    • Added comprehensive unit tests in DBSecretsManagerTest and KubernetesSecretsManagerTest to verify secret removal logic.

This will update automatically on new commits.

@miantalha45 miantalha45 requested a review from a team as a code owner April 21, 2026 12:14
Copilot AI review requested due to automatic review settings April 21, 2026 12:14
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

1 similar comment
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Comment thread openmetadata-ui/src/main/resources/ui/src/locale/languages/ar-sa.json Outdated
@ulixius9
Copy link
Copy Markdown
Member

@miantalha45 can you please also upload a screen recording of the fix

@miantalha45
Copy link
Copy Markdown
Contributor Author

sure @ulixius9 let me share it.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Member

@aniketkatkar97 aniketkatkar97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @miantalha45, Thanks for the contribution. Can you please

  1. Address the comments from Gitar-bot?
  2. Add playwright e2e coverage for the new scenarios? You can use the existing ServiceForm.spec.ts to add the test case
  3. Attach the screen recording for the changes

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@miantalha45
Copy link
Copy Markdown
Contributor Author

sure @aniketkatkar97 Let me do all these changes. I will let you know once I have done.

Copilot AI review requested due to automatic review settings April 22, 2026 05:31
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.

Comment on lines +35 to +42
const isMaskedValue = useMemo(
() => ALL_ASTERISKS_REGEX.test(props.value),
[props.value]
);

const wasOriginallyMasked = useRef(isMaskedValue);

const [isEditing, setIsEditing] = useState(!isMaskedValue);
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wasOriginallyMasked is initialized only on first render. If props.value is populated asynchronously (e.g., from undefined to a masked value) this widget will never enter the saved-indicator state. Consider updating the ref when isMaskedValue becomes true (e.g., wasOriginallyMasked.current ||= isMaskedValue) so the indicator reliably appears once a masked value arrives.

Copilot uses AI. Check for mistakes.
Comment on lines +105 to +121
<Button
data-testid={`password-update-btn-${props.id}`}
size="small"
type="link"
onClick={handleUpdate}>
{t('label.update')}
</Button>
{!props.required && (
<Button
danger
data-testid={`password-remove-btn-${props.id}`}
icon={<CloseCircleOutlined />}
size="small"
type="link"
onClick={handleRemove}>
{t('label.remove')}
</Button>
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The saved-indicator actions ignore disabled/readonly: users can click Update/Remove even when the widget is disabled/read-only, which still flips local state (and Remove triggers onChange). The action buttons should be disabled (or hidden) when props.disabled or props.readonly is true, and the handlers should no-op in that case.

Copilot uses AI. Check for mistakes.
"passed-x-checks": "Passed {{count}} checks",
"password-error-message": "Password must be a minimum of 8 and a maximum of 56 characters long and contain at least one uppercase character (A-Z), one lowercase character (a-z), one number, and one special character (such as !, %, @, or #)",
"password-pattern-error": "Password must be of minimum 8 and maximum 56 characters, with one special , one upper, one lower case character",
"password-saved": "Password is saved. Enter a new value to update or remove it.",
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helper text says users can "update or remove" the saved password, but the Remove action is intentionally hidden when the field is required. Please adjust the message to avoid promising an unavailable action (e.g., make it conditional based on required, or use wording that only mentions Update).

Suggested change
"password-saved": "Password is saved. Enter a new value to update or remove it.",
"password-saved": "Password is saved. Enter a new value to update it.",

Copilot uses AI. Check for mistakes.
Comment on lines +88 to +96
it('Should return to saved indicator after clicking Cancel', async () => {
render(<PasswordWidget {...mockProps} />);

const passwordInput = screen.getByTestId(
'password-input-widget-root/password'
);
fireEvent.click(screen.getByTestId('password-update-btn-root/password'));
fireEvent.click(screen.getByTestId('password-cancel-edit-btn-root/password'));

fireEvent.focus(passwordInput);
expect(screen.getByTestId('password-update-btn-root/password')).toBeInTheDocument();
expect(screen.queryByTestId('password-input-widget-root/password')).not.toBeInTheDocument();
});
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage doesn’t currently validate the core Cancel semantics after an edit/remove (i.e., that the edited value is reverted in form state, not just that the indicator is shown again). Add a test that: click Update, type a new value, click Cancel, and assert the original masked value is restored (and/or onChange is called with the original value as appropriate).

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +72
const handleRemove = useCallback(() => {
props.onChange('');
setIsEditing(true);
}, [props]);

const handleUpdate = useCallback(() => {
setIsEditing(true);
}, []);

const handleCancelEdit = useCallback(() => {
setIsEditing(false);
props.onChange(props.value);
}, [props]);
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleCancelEdit does not restore the original masked value when the user has typed a new value (or clicked Remove). Since props.value will already be the edited value by the time Cancel is clicked, calling props.onChange(props.value) keeps the edited value in the form state while hiding the input again. Store the original value (e.g., in a ref when entering edit mode) and restore that on Cancel (or avoid mutating form state until the user confirms).

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copilot AI review requested due to automatic review settings April 22, 2026 12:04
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

1 similar comment
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copilot AI review requested due to automatic review settings April 23, 2026 17:20
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copilot AI review requested due to automatic review settings April 24, 2026 02:44
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copilot AI review requested due to automatic review settings April 25, 2026 09:11
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented Apr 25, 2026

Code Review ✅ Approved 4 resolved / 4 findings

Enables removal of optional password fields in the connection edit form while resolving state mismatch issues, improper secret deletion handling, and stale commented code. Locale keys have also been updated to ensure proper translation support.

✅ 4 resolved
Bug: Cancel does not revert form value, causing UI/state mismatch

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Form/JSONSchema/JsonSchemaWidgets/PasswordWidget.tsx:69-72
When a user clicks Update, types a new password (e.g., newpassword), then clicks Cancel, handleCancelEdit calls props.onChange(props.value) — but props.value is already newpassword at that point (because typing triggered onChange). So the call is a no-op.

The UI switches back to the "Password is saved" indicator, but the form state still holds newpassword. If the user submits the form, the new password gets sent to the backend even though the UI indicated the original secret was unchanged. This is a data integrity issue — the user thinks they cancelled, but actually submitted a password change.

Edge Case: deleteSecretInternal may throw on non-existent secrets (AWS/GCP/Azure)

📄 openmetadata-service/src/main/java/org/openmetadata/service/secrets/ExternalSecretsManager.java:36-41
In ExternalSecretsManager.storeValue (line 38), when the value is null/empty and store=true, deleteSecretInternal is called. However, AWSSecretsManager, GCPSecretsManager, and AzureKVSecretsManager do not handle the case where the secret doesn't exist — AWS will throw ResourceNotFoundException, GCP will throw a not-found gRPC error, and Azure will throw from beginDeleteSecret.

While the obj != null guard at SecretsManager.java:407 prevents truly null fields from reaching this path, an empty-string password field that was never previously stored as a secret (e.g., a user submitting a form without ever setting an optional password) would still trigger a delete call for a non-existent secret.

The KubernetesSecretsManager already handles this correctly by catching 404 errors in its deleteSecretInternal.

Quality: Commented-out code should be removed, not left in place

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Form/JSONSchema/JsonSchemaWidgets/PasswordWidget.tsx:99
The LockOutlined icon is commented out rather than removed. If the icon is no longer needed, delete the line entirely. Commented-out code adds noise and can confuse future contributors about intent.

Quality: Locale files use untranslated English for password-saved key

📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/ar-sa.json:3058
All 18 non-English locale files (ar-sa, de-de, ja-jp, zh-cn, etc.) have the English string "Password is saved. Enter a new value to update or remove it." instead of a translated version. While this is a common pattern for initial PRs, it means non-English users will see an English sentence in an otherwise localized UI.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Copilot AI review requested due to automatic review settings April 26, 2026 07:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Review UX for removing password fields in connection form

5 participants