Skip to content

Fix issue with Username being required for Shared server import config#9971

Open
KijongHan wants to merge 3 commits into
pgadmin-org:masterfrom
KijongHan:GH_9226
Open

Fix issue with Username being required for Shared server import config#9971
KijongHan wants to merge 3 commits into
pgadmin-org:masterfrom
KijongHan:GH_9226

Conversation

@KijongHan
Copy link
Copy Markdown
Contributor

@KijongHan KijongHan commented May 22, 2026

Resolves #9226

What does this PR do?

This PR resolves Username attribute not found for server 'shared_server' errors where server json import validation logic had a hard constraint on Username being required even when Shared was set to true. This PR introduces more coherent constraint validation logic for shared servers so that you are required to either provide SharedUsername or Username (for backwards compatibility). Furthermore, the underlying data model 'Username' property is set to 'SharedUsername' (for shared servers only) to align with UI behaviour for setting this fallback.

The UX also feels better as when after registering shared servers with only the SharedUsername set, when trying to connect to the server for the first time it prompts for the password (instead of showing an infinite loading spinner because the underlying Username is not set)

Summary of changes

add separate Username constraint validation logic for shared servers when importing servers.json
add fallback to set Username to SharedUsername for shared servers so that the UX flow matches the manual UI creation flow for registering new shared servers

Summary by CodeRabbit

  • Bug Fixes
    • Improved import and validation of shared database servers: shared servers are now skipped for non-admin users, username requirements are enforced conditionally (allowing a shared-specific username when appropriate), and the effective credential used for imported servers is computed reliably. This yields more accurate configuration, fewer import errors, and improved security when handling shared server entries.

KijongHan and others added 2 commits May 23, 2026 09:43
validate_json_data required Username for all non-Service connections,
rejecting legitimate JSON that only carried SharedUsername. Accept
either attribute when Shared is true; keep Username required for
non-shared servers.

Extract is_shared as a local while we're here — it's now referenced
twice in the loop body.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…d servers

When loading database servers from an import file, fall back to
SharedUsername for the underlying server.username when the server is
shared and no explicit Username is provided.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 45dc0386-3299-45fb-8b1d-bbd55eb4a975

📥 Commits

Reviewing files that changed from the base of the PR and between 177b57d and 034c8f2.

📒 Files selected for processing (1)
  • web/pgadmin/utils/__init__.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/pgadmin/utils/init.py

Walkthrough

Validation and loader functions in web/pgadmin/utils/init.py now derive an is_shared flag from input and compute an effective username (using SharedUsername when appropriate). Validation enforces username requirements conditionally for shared vs non-shared servers; the loader applies computed shared and username values to the server objects.

Changes

Shared Server Configuration and Validation

Layer / File(s) Summary
Shared server validation logic
web/pgadmin/utils/__init__.py
validate_json_data derives is_shared from input and uses it to gate non-admin shared-server imports. When Service is absent it validates Port first, then enforces username requirements: non-shared servers must have Username; shared servers must have Username or SharedUsername.
Load and apply computed server configuration
web/pgadmin/utils/__init__.py
load_database_servers computes is_shared and derives an effective username (falling back to SharedUsername when Username is missing for shared servers), then assigns new_server.username, new_server.shared, and new_server.shared_username from those computed values.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: fixing the issue where Username was incorrectly required for shared server imports, now allowing SharedUsername alone to satisfy the requirement.
Linked Issues check ✅ Passed The PR successfully implements the coding requirements from issue #9226: validation now accepts SharedUsername or Username for shared servers [#9226], and server.username is set to SharedUsername as fallback when missing [#9226].
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving issue #9226: validation logic adjustments and username fallback handling for shared servers, with no unrelated modifications present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.


is_shared = obj.get("Shared", None)
username = obj.get("Username", None)
if is_shared and not username:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi @KijongHan , In case where username is a empty string in json data, it will fall back to SharedUsername. If SharedUsername is also missing, the server imports silently with username = None. We can use username is None to only trigger the fallback when the key is genuinely absent.

I was able to reproduce this with following json

{
  "Servers": {
    "1": {
      "Group": "Servers",
      "Name": "Test",
      "Shared": true,
      "Username": "",
      "Host": "127.0.0.1",
      "Port": 5432,
      "MaintenanceDB": "postgres"
    }
  }
}

Copy link
Copy Markdown
Contributor Author

@KijongHan KijongHan Jun 3, 2026

Choose a reason for hiding this comment

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

Hey @hiteshjambhale thanks alot for checking this use case! I share your concern around an empty username string being considered a valid import, but I'm thinking that we should short-circuit the import process further up the validation chain (during JSON validation) here that way we handle the validation in the right place

From what I can see, an empty string username being considered valid has been there for some time, so I want to check with you @asheshv or @akshay-joshi and get your opinion on whether we should tighten the validation logic on the username property and not allow empty strings

Copy link
Copy Markdown

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

This PR updates pgAdmin’s servers.json import path to correctly handle shared servers by loosening validation so shared server definitions can provide SharedUsername instead of always requiring Username, and by applying a fallback so imported shared servers have an effective username consistent with the UI flow.

Changes:

  • Adjusted servers.json validation to accept either Username or SharedUsername for shared servers.
  • Updated server import to populate Server.username from SharedUsername when Username is not provided for shared servers.
  • Minor refactor to reuse computed is_shared during validation/import.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +736 to +740
is_shared = obj.get("Shared", None)
username = obj.get("Username", None)
if is_shared and not username:
username = obj.get("SharedUsername", None)

Copy link
Copy Markdown
Contributor Author

@KijongHan KijongHan Jun 3, 2026

Choose a reason for hiding this comment

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

the import currently prefers Username over SharedUsername when both are present

I think this Username override makes sense, so that SharedUsername is only the default value (this is how it is currently treated in the UI creation stage as well at the moment)

and it does not populate shared_username when only legacy Username is provided

I dont think we should be treating shared_username property value like a fallback. It should be "pure". This feels aligned to how username is used as a network login (so fallback seems reasonable) but shared_username is treated as the "default username for these shared servers" so it doesn't make sense to me to introduce a fallback here. Keen for your thoughts @asheshv

Comment thread web/pgadmin/utils/__init__.py
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.

Username is required even though SharedUsername is set

3 participants