Skip to content

feat: add system-wide default for Geometry Viewer custom tile provider#10198

Open
asheshv wants to merge 3 commits into
pgadmin-org:masterfrom
asheshv:feat/geometry-viewer-system-default-provider
Open

feat: add system-wide default for Geometry Viewer custom tile provider#10198
asheshv wants to merge 3 commits into
pgadmin-org:masterfrom
asheshv:feat/geometry-viewer-system-default-provider

Conversation

@asheshv

@asheshv asheshv commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #10142. Geometry Viewer's custom tile provider was only configurable per-user (Preferences), with no way for an administrator to set an organization-wide default (e.g. an internal tile server) that applies to every user out of the box.

Design

config.DEFAULT_GEOMETRY_VIEWER_PROVIDER is a plain dict, and the five custom_tile_* preference defaults (url, name, crs, attribution, max_zoom) are sourced from it instead of hardcoded literals. Preference.get() only reads a per-user DB row if the user has explicitly saved one, otherwise it falls back to this default — so this is override semantics: a user's own saved preference always wins, there is only ever one active provider (no second/competing entry), and no naming-conflict surface is introduced.

An administrator sets it in config_local.py/config_distro.py (or PGADMIN_CONFIG_DEFAULT_GEOMETRY_VIEWER_PROVIDER as a Python-dict-literal string, same mechanism already used for DEFAULT_BINARY_PATHS).

Safety

config_local.py/config_distro.py/PGADMIN_CONFIG_* replace this config variable wholesale, not merged key-by-key. A naive DEFAULT_GEOMETRY_VIEWER_PROVIDER['name'] would KeyError-crash preference registration (and thus app startup) on any partial admin override, or AttributeError if the admin sets the wrong type entirely (e.g. a string instead of a dict).

resolve_geometry_viewer_provider_defaults() guards against this: falls back per-field on missing/wrong-type values, validates crs against the 3 supported choices, and validates max_zoom is a non-bool int in [0, 25] — degrading to the original hardcoded defaults instead of crashing.

Security

No new attacker-reachable surface: DEFAULT_GEOMETRY_VIEWER_PROVIDER is filesystem/deployment-level admin config, same trust boundary as DEFAULT_BINARY_PATHS/OAUTH2_CONFIG. The existing DOMPurify sanitization on name/attribution and the http(s):// + {x}/{y}/{z} URL validation in GeometryViewerUtils.js (from #10142) apply uniformly to config-sourced and per-user values alike — same code path, no bypass. Per-user preference isolation (user_id-keyed) is untouched.

Testing

  • test_geometry_viewer_provider_defaults.py — 9 scenarios (fully valid, partial override, non-dict, invalid CRS, out-of-range/non-int/bool max_zoom, non-string fields, empty dict), run via regression/runtests.py --pkg tools.sqleditor — all pass.
  • pycodestyle --config=.pycodestyle clean (the exact make check-pep8 invocation).
  • Docs built via Sphinx (make docs equivalent) — 0 new warnings, new preferences.rst paragraph renders correctly, config_py ref resolves.

Known minor nit (not fixed here, low risk)

The 3 supported CRS values are listed twice — once in GEOMETRY_VIEWER_CRS_CHOICES (validation) and once in the preference's options=[...] list (UI labels, from #10142). If a 4th CRS is ever added, both need updating in sync. Pre-existing pattern, not introduced by this PR; flagging for awareness.

Summary by CodeRabbit

  • New Features

    • Added system-wide default settings for Geometry Viewer custom tile provider fields.
    • Administrators can configure default URL, name, CRS, attribution, and max zoom.
    • Existing saved user preferences continue to override the system defaults.
  • Documentation

    • Documented how the system default applies and when user preferences take precedence.
  • Tests

    • Added test coverage for default resolution, including partial overrides and validation of invalid values.

asheshv added 2 commits July 24, 2026 22:20
Follow-up to pgadmin-org#10142. Geometry Viewer's custom tile provider was
only configurable per-user, with no way for an administrator to
set an organization-wide default (e.g. an internal tile server)
that applies to every user out of the box.

Add DEFAULT_GEOMETRY_VIEWER_PROVIDER to config.py and source the
five custom_tile_* preference defaults from it instead of hardcoded
literals. Preference.get() only reads a per-user DB row if the user
has explicitly saved one, otherwise falling back to this default -
so this is pure override semantics: a user's own saved preference
always wins, and there is no second/competing provider entry, so no
naming-conflict surface is introduced.
…rrides

DEFAULT_GEOMETRY_VIEWER_PROVIDER is replaced wholesale by
config_local.py/config_distro.py/PGADMIN_CONFIG_*, not merged
key-by-key. Direct dict indexing crashed preference registration on
any partial override (KeyError) or non-dict value (AttributeError),
and an out-of-range/wrong-type crs or max_zoom would have reached
the frontend unvalidated.

Move the defaulting logic into
resolve_geometry_viewer_provider_defaults(), computed fresh each
time register_query_tool_preferences() runs (previously computed
once at import time, which also made it unmockable in tests):
falls back per-field for missing/wrong-type values, validates crs
against the 3 supported choices, and validates max_zoom is a
non-bool int in [0, 25].

Adds test_geometry_viewer_provider_defaults.py covering fully valid,
partial, non-dict, invalid crs, out-of-range/non-int/bool max_zoom,
and non-string field scenarios - run via the project's actual
regression harness (not just an ad hoc script).
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds a configurable system-wide default for Geometry Viewer custom tile provider preferences, validates configured values, applies them during preference registration, tests fallback behavior, and documents precedence over saved user preferences.

Changes

Geometry Viewer defaults

Layer / File(s) Summary
Provider default contract and validation
web/config.py, web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py, web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.py
Defines DEFAULT_GEOMETRY_VIEWER_PROVIDER, validates CRS, zoom, and string fields, and tests valid, partial, malformed, and out-of-range configurations.
Preference registration and precedence
web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py, docs/en_US/preferences.rst
Uses resolved values for Geometry Viewer tile preferences and documents that saved user preferences override system defaults.

Estimated code review effort: 2 (Simple) | ~10 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 clearly and concisely describes the main change: a system-wide default for the Geometry Viewer custom tile provider.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.py`:
- Line 59: Correct the continuation indentation in the geometry viewer provider
defaults test, specifically the closing `}))` lines at the repeated locations,
so they comply with pycodestyle E126. Align each continuation consistently with
its surrounding call structure without changing the test logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0dd7b056-2f8a-41c7-9c04-bb1df8388d29

📥 Commits

Reviewing files that changed from the base of the PR and between 108797d and a4ff44c.

📒 Files selected for processing (4)
  • docs/en_US/preferences.rst
  • web/config.py
  • web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.py
  • web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py

Comment thread web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.py Outdated
Factor the repeated fallback-defaults dict into _ALL_FALLBACK instead
of fighting hanging-indent rules on deeply nested inline literals -
CI's pycodestyle run caught E126 (over-indented) on the original
nested dicts; a same-style de-indent then hit E123 (closing bracket
mismatch), since this repo's .pycodestyle ignore list overrides
pycodestyle's implicit defaults and leaves both checks active.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.py (1)

36-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Address the RUF012 mutable class attributes.

_ALL_FALLBACK and _partial_override_expected are mutable dictionaries stored on the test class, which Ruff flags under RUF012. Add from typing import ClassVar and annotate these shared fixtures: _ALL_FALLBACK: ClassVar = {...} and _partial_override_expected: ClassVar = dict(_ALL_FALLBACK).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.py`
around lines 36 - 41, In the test class, import ClassVar from typing and
annotate both shared dictionary fixtures, _ALL_FALLBACK and
_partial_override_expected, as ClassVar while preserving their existing values
and initialization.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.py`:
- Around line 36-41: In the test class, import ClassVar from typing and annotate
both shared dictionary fixtures, _ALL_FALLBACK and _partial_override_expected,
as ClassVar while preserving their existing values and initialization.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bbdda73c-ac55-434b-a050-4007107bcf15

📥 Commits

Reviewing files that changed from the base of the PR and between a4ff44c and b7b09ee.

📒 Files selected for processing (1)
  • web/pgadmin/tools/sqleditor/tests/test_geometry_viewer_provider_defaults.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.

1 participant