Skip to content

Fixes #27536: allow clearing masked password fields in connection edit form - #32945

Merged
Rohit0301 merged 9 commits into
mainfrom
fix-issue-27536-with-tests
Sep 10, 2026
Merged

Fixes #27536: allow clearing masked password fields in connection edit form#32945
Rohit0301 merged 9 commits into
mainfrom
fix-issue-27536-with-tests

Conversation

@Rohit0301

Copy link
Copy Markdown
Contributor

Describe your changes:

Fixes #27536

Password fields in the connection edit form were hidden (shown as empty) when the API returned a masked sentinel value (*****). This prevented users from knowing a secret was stored, and made it impossible to clear an optional password field — clearing the field would send replace/'' in the PATCH, overwriting the secret with an empty string instead of removing it.

Changes made:

  • PasswordWidget.tsx: Removed the useMemo that converted the masked sentinel to undefined; the masked value now flows to the input and displays as password dots so users can see a secret is stored. Added allowClear button to Ant Design Input.Password. Added handleChange that converts ''undefined (or emptyValue from RJSF options) so clearing the field produces a proper JSON Patch remove op instead of replace/''.
  • PasswordWidget.test.tsx: Added 3 new tests covering masked-value display, clear→undefined conversion, and post-clear re-render.
  • PasswordFieldClear.spec.ts (new): Playwright E2E spec with 4 scenarios — masked dots visible in edit form, PATCH does not contain replace/'' after clearing, round-trip shows empty after save, and regression guard that untouched password generates no patch op.

Type of change:

  • Bug fix

High-level design:

N/A — small change.

Tests:

Use cases covered

  • Masked password field shows as filled dots in the connection edit form (user knows a secret is stored)
  • Clicking the × clear button and saving does not send replace/'' in the PATCH request
  • After clearing and saving, re-opening the form shows an empty password field
  • Saving without touching the password field generates no patch op for it (regression guard)

Unit tests

  • I added unit tests for the new/changed logic.
  • Files added/updated: openmetadata-ui/src/main/resources/ui/src/components/common/Form/JSONSchema/JsonSchemaWidgets/PasswordWidget.test.tsx
  • Coverage on PasswordWidget.tsx: 100% Statements, 91.66% Branches, 100% Functions, 100% Lines (11 tests pass)

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • I added Playwright E2E tests under openmetadata-ui/.../ui/playwright/ for UI changes.
  • Files added/updated: openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PasswordFieldClear.spec.ts

Manual testing performed

  • Reviewed the component logic and unit test output confirms correct behaviour for all scenarios.

UI screen recording / screenshots:

Not applicable — the visual change (masked dots vs empty field) is verified via Playwright assertions on toHaveValue.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • My PR is linked to a GitHub issue via Fixes #27536 above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.
  • For UI changes: I attached a screen recording and/or screenshots above.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.
  • I have added a test that covers the exact scenario we are fixing.

…t form

Show the masked sentinel as password dots (not blank) so users know a secret
is stored, and convert empty-string onChange to undefined so the RJSF patch
does not write replace/'' to the backend. Adds allowClear button, 3 new unit
tests (100% stmt/func/line coverage on PasswordWidget), and a Playwright
E2E spec covering the masked-dots UX, clear-then-save PATCH guard, and
round-trip behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added the UI UI specific issues label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

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!

@Rohit0301 Rohit0301 self-assigned this Sep 8, 2026
@Rohit0301 Rohit0301 added the safe to test Add this label to run secure Github workflows on PRs label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 70%
70.39% (95036/134999) 54.9% (56206/102373) 56.3% (18770/33336)

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit 808a3d094874e6503ed20fdc99e3ae3beaf44c5f in Playwright run 34335379261, attempt 2.

✅ 4492 passed · ❌ 0 failed · 🟡 5 flaky · ⏭️ 1 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ✅ met · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 4h 4m 33s

⏱️ Max setup 5m 17s · max shard execution 21m 33s · max shard-job elapsed before upload 24m 32s · reporting 21s

🌐 217.36 requests/attempt · 2.30 app boots/UI scenario · 38.44% common-shard skew

Optimization targets still in progress:

  • Common shard skew was 38.44% (convergence target: at most 15%).
  • Browser traffic was 217.36 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 2.3 per UI scenario (10927 boots / 4742 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard advanced-search-01 130 0 0 0 0 0
✅ Shard chromium-01 192 0 0 0 0 0
✅ Shard chromium-02 165 0 0 0 0 0
✅ Shard chromium-03 185 0 0 0 0 0
🟡 Shard chromium-04 155 0 1 0 0 0
✅ Shard chromium-05 197 0 0 0 0 0
✅ Shard chromium-06 150 0 0 0 0 0
✅ Shard chromium-07 190 0 0 0 0 0
✅ Shard chromium-08 192 0 0 0 0 0
🟡 Shard chromium-09 158 0 1 0 0 0
✅ Shard chromium-10 186 0 0 0 0 0
✅ Shard chromium-11 179 0 0 0 0 0
✅ Shard chromium-12 196 0 0 1 0 0
✅ Shard chromium-13 154 0 0 0 0 0
🟡 Shard chromium-14 169 0 1 0 0 0
🟡 Shard chromium-15 222 0 2 0 0 0
✅ Shard chromium-16 180 0 0 0 0 0
✅ Shard chromium-17 169 0 0 0 0 0
✅ Shard chromium-18 212 0 0 0 0 0
✅ Shard chromium-19 138 0 0 0 0 0
✅ Shard chromium-20 189 0 0 0 0 0
✅ Shard chromium-21 185 0 0 0 0 0
✅ Shard chromium-22 170 0 0 0 0 0
✅ Shard data-asset-rules-01 65 0 0 0 0 0
✅ Shard domain-isolation-01 16 0 0 0 0 0
✅ Shard global-state-01 34 0 0 0 0 0
✅ Shard import-export-01 80 0 0 0 0 0
✅ Shard import-export-02 70 0 0 0 0 0
✅ Shard ingestion-01 54 0 0 0 0 0
✅ Shard ingestion-02 41 0 0 0 0 0
✅ Shard reindex-01 28 0 0 0 0 0
✅ Shard search-01 12 0 0 0 0 0
✅ Shard search-rbac-01 29 0 0 0 0 0
🟡 5 flaky test(s) (passed on retry)
  • Pages/CustomProperties.spec.tsDate Time (shard chromium-04, 1 retry)
  • Pages/TasksUIFlow.spec.tsCreate and resolve description task for Pipeline via UI (shard chromium-09, 1 retry)
  • Pages/Entity.spec.tsUser as Owner with unsorted list (shard chromium-14, 1 retry)
  • Pages/GlossaryTermRelationSettings.spec.tscreates a custom relation type via the drawer (shard chromium-15, 1 retry)
  • Pages/InputOutputPorts.spec.tsOutput ports section collapse/expand (shard chromium-15, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

Comment on lines -34 to -36
if (ALL_ASTERISKS_REGEX.test(props.value)) {
return undefined; // Do not show the password if it is masked
} else {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This was needed since when people go to edit we don't have actual password, so we are not seding it back to avoid overrride to some static value, please check PR with this change before modifying it

…rvices

Extends PasswordFieldClear.spec.ts to cover:
- MySQL database service (authType/password): masked dots UX, no replace/''
  on clear, and regression guard that untouched password generates no patch op.
- Superset dashboard service (connection/password): same three scenarios.

Also makes navigateToEditConnection accept a serviceType parameter (defaulting
to Messaging) so all three service types share the same navigation helper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rohit0301 and others added 2 commits September 9, 2026 12:45
…test

In both the database and dashboard describe blocks the regression guard
(saving without touching the password should produce no patch op) was
running after the clearing test that had already removed the password,
making the guard trivially pass. Moved it before the clearing test so it
runs while the stored password is still present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rohit0301 and others added 2 commits September 9, 2026 13:49
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gitar-bot

gitar-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 resolved / 4 findings

Fixes password field masking in the connection edit form by displaying masked values as dots, adding a clear button, and converting empty input to undefined to generate proper JSON Patch remove operations. Resolved issues with sentinel value corruption on typing, E2E assertion precision, and test ordering for the regression guard. Unit and Playwright tests provide comprehensive coverage across all scenarios. No issues found.

✅ 4 resolved
Bug: Typing into masked field appends to sentinel, corrupting saved password

📄 openmetadata-ui/src/main/resources/ui/src/components/common/Form/JSONSchema/JsonSchemaWidgets/PasswordWidget.tsx:49 📄 openmetadata-ui/src/main/resources/ui/src/components/common/Form/JSONSchema/JsonSchemaWidgets/PasswordWidget.tsx:51
By removing the useMemo that converted the masked sentinel to undefined, the input now holds the literal masked value ('*********') as its value, and there is no onFocus select-all or clear-on-focus behavior. If a user wants to change the password and simply clicks into the field and types (without first using the allowClear ×), the new characters are appended to the sentinel, so the value saved becomes e.g. '*********newpass' — corrupting the secret. Before this change, the field was empty so typing produced a clean value. Consider clearing/selecting the masked value on focus, or only appending when the current value is not the masked sentinel.

Quality: E2E comment contradicts the assertion it documents

📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PasswordFieldClear.spec.ts:164-168
The comment states 'Re-opening shows the masked value' but the assertion immediately below checks toHaveValue(''). The misleading comment (and the reference to 'CorePasswordWidget', which does not exist in this widget) will confuse future readers about the expected round-trip behavior. Align the comment with the actual assertion.

Quality: Password clear E2E assertion is a no-op when op is absent

📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PasswordFieldClear.spec.ts:118-124
The 'saving after clearing' test only asserts passwordOp.value !== '' when passwordOp is defined; if the clear produces no op at all (passwordOp undefined) the test passes without verifying anything meaningful about the clear behavior. Consider asserting the expected op explicitly (e.g. a remove op for /saslPassword, or no op) so the regression guard cannot pass vacuously.

Quality: Regression guard runs after password already cleared, weakening it

📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PasswordFieldClear.spec.ts:264-278 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PasswordFieldClear.spec.ts:308-322 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PasswordFieldClear.spec.ts:390-404 📄 openmetadata-ui/src/main/resources/ui/playwright/e2e/Flow/PasswordFieldClear.spec.ts:436-450
In both the database and dashboard describes the tests share one service (created in beforeAll) and run in declaration order: the "saving after clearing" test clears the password and saves (producing a remove op that deletes the stored secret), then the "saving without clearing preserves the password" regression guard runs against a service whose password is already gone. The guard therefore no longer verifies that an existing stored password is preserved — its assertion (no /password op when only hostPort changes) passes trivially. Reorder so the regression guard runs before the clearing test, or create a dedicated service for it.

Options

Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@sonarqubecloud

sonarqubecloud Bot commented Sep 9, 2026

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-09-10T01:53:29Z)

Blocked the queue: playwright-summary

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

Labels

safe to test Add this label to run secure Github workflows on PRs UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Review UX for removing password fields in connection form

2 participants