Skip to content

Keep the setup wizard closed when a configured database is unreachable#6333

Open
dkayiwa wants to merge 1 commit into
openmrs:masterfrom
dkayiwa:security/setup-not-reopened-on-db-failure
Open

Keep the setup wizard closed when a configured database is unreachable#6333
dkayiwa wants to merge 1 commit into
openmrs:masterfrom
dkayiwa:security/setup-not-reopened-on-db-failure

Conversation

@dkayiwa

@dkayiwa dkayiwa commented Jul 15, 2026

Copy link
Copy Markdown
Member

Summary

DatabaseDetective.isDatabaseEmpty(Properties) treated any exception while connecting as "the database is empty" (catch (Exception e) { return true; }). Both callers, Listener at startup and InitializationFilter, use that to decide whether to show the unauthenticated setup wizard. So on an already-configured deployment, a database-connectivity failure at startup (a DB outage or restart) made the instance report itself empty and reopen the unauthenticated setup wizard, which renders the stored DB credentials and lets an unauthenticated user reconfigure the instance and persist their own settings back to openmrs-runtime.properties.

Change

On a connection failure, only treat the instance as empty when it is genuinely unconfigured (no connection.url). A configured instance that cannot be reached is reported as not empty, so startup fails with a connection error instead of reopening setup. Unconfigured/fresh installs (null or empty properties) still return empty, so the normal first-run wizard is unaffected. Also removed the return true inside the finally block's close() handler, which could otherwise override a non-empty result.

Tests

DatabaseDetectiveTest.shouldNotReportConfiguredButUnreachableDatabaseAsEmpty: a configured instance whose database is unreachable is not reported as empty. The existing null-properties and empty-properties cases (still empty) continue to pass.

Addresses GHSA-jqhq-p753-2hwj. This is the reopen root cause; it is distinct from #6152, which fixes credential wiping mid-flow (TRUNK-6645).

DatabaseDetective.isDatabaseEmpty caught any connection failure and
reported the database as empty. Both callers, Listener startup and
InitializationFilter, use that result to decide whether to present the
unauthenticated setup wizard, so a database-connectivity failure on an
already-configured deployment reopened the wizard, exposing the stored
database credentials in the rendered form and letting an unauthenticated
user reconfigure and persist their own settings.

Only a genuinely unconfigured instance (no connection URL) is now treated
as empty on a connection failure; a configured instance that cannot be
reached is reported as not empty, so it fails startup with a connection
error instead of reopening setup. Also stop the finally block from
returning inside a close() failure, which could otherwise flip a
non-empty result to empty.

Adds a regression test that a configured but unreachable database is not
reported as empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 25.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.48%. Comparing base (d8fe136) to head (389a795).

Files with missing lines Patch % Lines
...s/web/filter/initialization/DatabaseDetective.java 25.00% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #6333      +/-   ##
============================================
+ Coverage     59.47%   59.48%   +0.01%     
- Complexity     9541     9544       +3     
============================================
  Files           731      731              
  Lines         38323    38323              
  Branches       5587     5588       +1     
============================================
+ Hits          22794    22798       +4     
+ Misses        13489    13485       -4     
  Partials       2040     2040              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

// already-configured deployment during a database outage, so only a genuinely
// unconfigured instance (no connection URL) counts as empty.
String url = props.getProperty(CONNECTION_URL);
return url == null || url.trim().isEmpty();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

isBlank() exists and is better than .trim().isEmpty() for this purpose since it doesn't need to allocate a new string.

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.

3 participants