Skip to content

fix(datasource): apply target-table access check on same-database repoint - #44080

Open
sha174n wants to merge 21 commits into
apache:masterfrom
sha174n:fix/datasource-save-repoint-access
Open

sha174n wants to merge 21 commits into
apache:masterfrom
sha174n:fix/datasource-save-repoint-access

Conversation

@sha174n

@sha174n sha174n commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

SUMMARY

The legacy Datasource.save view (POST /superset/datasource/save/) ran security_manager.raise_for_access(table=...) only inside the if database_id != orm_datasource.database_id: branch. A request that keeps the same database.id but changes table_name/schema/catalog also repoints the dataset (update_from_object applies whatever the request supplies), but skipped the target-table check, so it ran only for cross-database repoints.

This aligns the legacy view with the create/update paths: resolve the target database and table up front, and run the access check whenever either changes. A plain save that changes neither the database nor the table (a column/metric edit) still needs no recheck, since editorship already gates it.

TESTING INSTRUCTIONS

pytest tests/unit_tests/views/datasource/views_test.py

Adds test_save_rejects_same_database_repoint_to_table_without_access (same-DB repoint is now checked) and test_save_allows_unchanged_datasource_without_access_recheck (no behavior change for plain edits). Existing cross-database repoint tests still pass.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
  • Introduces new feature or API
  • Removes existing feature or API

@bito-code-review

bito-code-review Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #9c3488

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/views/datasource/views.py - 1
    • CWE-863: Authz target divergence · Line 130-134
      `requested_table` falls back to current `orm_datasource` values, but `update_from_object` (models.py:788-789) applies `obj.get(attr)`, setting a missing `table_name`/`schema`/`catalog` to `None`. So a request omitting these keys yields `table_changed=False`, skipping `raise_for_access`, while the dataset is actually repointed to `None`. Use plain `datasource_dict.get(...)` so the check target matches the applied target. ([CWE-863](https://cwe.mitre.org/data/definitions/863.html))
Review Details
  • Files reviewed - 2 · Commit Range: 0691a99..0691a99
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@codecov

codecov Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.85%. Comparing base (2918a7b) to head (5b3b211).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #44080   +/-   ##
=======================================
  Coverage   82.85%   82.85%           
=======================================
  Files        3017     3017           
  Lines      192923   192958   +35     
  Branches    44976    44985    +9     
=======================================
+ Hits       159845   159882   +37     
+ Misses      30038    30037    -1     
+ Partials     3040     3039    -1     
Flag Coverage Δ
hive 35.29% <11.36%> (-0.01%) ⬇️
mysql 53.71% <56.81%> (+<0.01%) ⬆️
postgres 53.72% <56.81%> (+<0.01%) ⬆️
presto 37.12% <11.36%> (-0.01%) ⬇️
python 86.50% <100.00%> (+<0.01%) ⬆️
sqlite 53.46% <56.81%> (+<0.01%) ⬆️
unit 80.15% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@sha174n
sha174n requested a review from rusackas September 9, 2026 16:24

@rusackas rusackas left a comment

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.

Good catch on the same-database repoint gap, and the tests are solid. One thing before this merges, though: bito's right that the fallback here doesn't match what actually gets applied. update_from_object (connectors/sqla/models.py:788) does setattr(self, attr, obj.get(attr)) with no default, so an omitted table_name/schema/catalog key gets set to None. But the check here falls back to the current value when the key is missing, so table_changed reads False and the new access check never runs, even though the dataset is about to get repointed (to None, in this case). Left a suggestion inline.

Comment thread superset/views/datasource/views.py Outdated
@rusackas

Copy link
Copy Markdown
Member

Heya, checking back in on this one — the suggestion above is still open. Should be a quick one whenever you get a chance.

@sha174n

sha174n commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas you and bito were right — update_from_object writes obj.get(attr) with no default, so an omitted table_name/schema/catalog lands as None and the fallback made that read as unchanged. Dropped the fallback in d16ddd8, with a test for the omitted-key path.

Removing the fallback surfaced two cases the stricter comparison would have caught wrongly, fixed in df17cab: a virtual dataset's table_name is a label rather than a pointer, so renaming one was getting gated on a physical table that doesn't exist (UpdateDatasetCommand skips the check there too, and a database repoint stays checked either way); and BaseDatasource.data emits an empty schema as None, so a dataset stored with schema="" round-tripped as a repoint. Both have regression tests.

@sha174n
sha174n requested a review from rusackas September 21, 2026 13:49
@sha174n

sha174n commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas one more in 96e2c48, from a self-review pass on the same block: the virtual-dataset skip needed a companion clause for the conversion case. Dropping sql binds the table_name label to a real table, so that save has to run the target-table check even when the label is unchanged, otherwise the label can be renamed under the skip and converted in a second save. UpdateDatasetCommand._validate_dataset_source has the equivalent clause; this ports it. Regression test added, and the mocks now set sql explicitly since an unset MagicMock attribute was making every physical fixture read as virtual.

Rest of the commit is cleanup: the source-binding comparison is field-by-field rather than Table.__eq__ (which compares the dotted rendering, so table="a.b" and schema="a", table="b" would read as the same target), the current database is only resolved on the branch that needs it instead of lazy-loading a row the repoint path throws away, and the update_from_object replace-semantics note moved into its docstring.

@bito-code-review

bito-code-review Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #ef0dce

Actionable Suggestions - 0
Review Details
  • Files reviewed - 3 · Commit Range: 0691a99..8b2ebe3
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
    • superset/connectors/sqla/models.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@bito-code-review

bito-code-review Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #eeb642

Actionable Suggestions - 0
Additional Suggestions - 1
  • tests/unit_tests/views/datasource/views_test.py - 1
    • duplicated test scaffolding · Line 629-687
      `test_save_checks_table_when_virtual_dataset_becomes_physical` duplicates the full body of `test_save_rejects_same_database_repoint_to_table_without_access` (same decorators, mock setup, request shape, `DatasetForbiddenError` expectation, and `raise_for_access` assertions), differing only in the initial `mock_orm.sql` value. Consider parametrizing on the initial `sql`/`table_name` so the two scenarios share one body.
Review Details
  • Files reviewed - 3 · Commit Range: 8b2ebe3..96e2c48
    • superset/connectors/sqla/models.py
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sha174n

sha174n commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas one tidy-up pass on top in 755e76d, no behaviour change to the rule you flagged: the two conversion clauses fold into a single condition, the requested schema/catalog are normalised at construction so the same value is compared and authorised, and the virtual test reuses the existing BaseDatasource.is_virtual property instead of re-deriving it from sql. Tests unchanged in substance and still green.

@netlify

netlify Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit a5aef64
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6ab3d3b6e375a600081dbe93
😎 Deploy Preview https://deploy-preview-44080--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@rusackas rusackas left a comment

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.

Thanks for the omitted-key fix, that reads right the way update_from_object actually applies it now.

One thing before this merges, though: the follow-up moved table_changed's computation above any type check, and it reads orm_datasource.table_name/.is_virtual unconditionally. Query, SavedQuery and SemanticView datasources don't have those attributes (Query only has tmp_table_name), so saving any non-table datasource through this endpoint now 500s, even one that never touches the database. Might be worth scoping the block to orm_datasource.type == DatasourceType.TABLE?

@sha174n

sha174n commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas quality pass in 4449a33, no change to the rule you flagged: the requested and current targets are now two Table values compared with dataclasses.astuple (Table.__eq__ compares the dotted rendering, which would conflate distinct targets), the gate reads as two named predicates instead of a negation nested in the condition, and the repeated per-test scaffolding moves into a dataset factory plus a save helper, with the three "must not re-check" cases folded into one parametrized test. Verified by mutating the gate both ways: forcing it on fails the skip cases, restricting it to database-only fails the repoint cases.

@bito-code-review

bito-code-review Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #edbae6

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 96e2c48..4449a33
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sha174n

sha174n commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas right, thanks — a query has tmp_table_name, not table_name, so reading the pointer unconditionally broke every non-dataset save. Fixed in 5ce70d6: the predicate moved into a _repoints_table helper behind an isinstance(orm_datasource, SqlaTable) guard, which also narrows the DatasourceDAO union so mypy is happy without a cast. Added test_save_of_non_dataset_datasource_skips_table_check, specced to a query's attribute surface so touching table_name/is_virtual raises rather than passing silently — it reproduces the AttributeError without the guard. Same pass drops the astuple deepcopy for a plain tuple compare and routes the remaining save tests through the shared _run_save helper.

@bito-code-review

bito-code-review Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #463827

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 4449a33..82d2a0a
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sha174n

sha174n commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas both points are in already: the omitted-key read in d16ddd8, and the non-dataset guard in 5ce70d6 (isinstance(orm_datasource, SqlaTable) short-circuits, so table_name/is_virtual are never read on a query or semantic view, covered by test_save_of_non_dataset_datasource_skips_table_check).

One follow-up in b05b995 from a tidy-up pass, no behaviour change: the "result is still virtual" skip moved out of the helper and into the caller's and chain, so _repoints_table takes two arguments and answers one question.

The red CI here is not from this branch: babel-extract and the check_pot_drift unit test both fail on messages.pot drift for strings in superset/dashboards/api.py and the report/screenshot paths, which reproduces on master. This PR adds no translatable strings. Everything else is green (17211 passed).

@sha174n

sha174n commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas both of your points were already in before your last pass, so nothing new was needed for them: the omitted-key read in d16ddd8, and the non-dataset guard in 5ce70d6, where isinstance(orm_datasource, SqlaTable) short-circuits ahead of table_name/is_virtual (covered by test_save_of_non_dataset_datasource_skips_table_check, whose mock is specced to a query's attribute surface so a regression raises rather than passing silently).

One docs-only commit on top in 7ecbbe4, no behaviour change: _repoints_table's virtual short-circuit is only sound because the caller has already established the result is physical, so the docstring now states that precondition instead of leaving it 60 lines away at the call site.

On the red CI: babel-extract and the check_pot_drift unit test (and the two required gates aggregating it) all fail on the same messages.pot drift, for strings in superset/dashboards/api.py and the alert/report paths. It reproduces on master and this branch adds no translatable strings, so it needs a separate regeneration PR rather than an unrelated .pot commit here.

@bito-code-review

bito-code-review Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #53995a

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 82d2a0a..7ecbbe4
    • superset/views/datasource/views.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sha174n

sha174n commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas no change to either rule you raised, but the guard you asked about moved in 0da560b: the datasource-type and still-virtual checks now live inside _repoints_table instead of in the caller's and chain, so the predicate is self-contained rather than relying on a precondition the caller has to enforce. The type check still short-circuits ahead of table_name/is_virtual, and test_save_of_non_dataset_datasource_skips_table_check still covers it. Same commit routes the last two save tests through the shared helper. 24 tests green, pre-commit clean.

Unrelated to this diff: the current red CI is messages.pot drift inherited from master (alert-retry and screenshot strings, one of which lives in superset/dashboards/api.py on master but not in the committed template). This branch touches no translatable strings, so I've left it for a separate branch rather than pulling catalog churn in here.

@bito-code-review

bito-code-review Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #85c0b7

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 7ecbbe4..0da560b
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@bito-code-review

bito-code-review Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #e92ffb

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 0da560b..bbb3e0a
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sha174n

sha174n commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas both points you raised are already in and unchanged: the omitted-key read in d16ddd8, and the non-dataset guard in 5ce70d6 (isinstance(orm_datasource, SqlaTable) short-circuits ahead of table_name/is_virtual).

Correction on my earlier CI note: the messages.pot drift was inherited from the commit this branch was based on, and master has since regenerated the template. Merged master in fb3678d and the drift check passes locally, so babel-extract and check_pot_drift should be green here without a separate branch.

One cleanup commit on top in 8448ff6, no behaviour change: the target database is resolved inside the branch that reads it rather than eagerly in an else, so a plain column/metric save no longer lazy-loads a Database row it discards, and six blank lines left behind by an earlier import move are dropped.

@bito-code-review

bito-code-review Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #f4a14c

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: bbb3e0a..9d474e5
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sha174n

sha174n commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas one commit on top in e9d4ad8, no behaviour change: comments trimmed where update_from_object's and _repoints_table's docstrings already carry the point, and the conversion parameter now states just what that clause covers, a conversion that changes the label in the same save. The sentence I dropped reasoned about a later save instead, which the clause cannot speak to: raise_for_access resolves the requested table through query_datasources_by_name, i.e. against the stored name rather than the one the request is about to write. UpdateDatasetCommand._validate_table_access resolves the same way, so nothing here diverges from it.

Both points you raised are unchanged and still in: the omitted-key read in d16ddd8, the non-dataset guard in 5ce70d6.

On the red CI, all four failures are one cause and it is not from this branch: babel-extract and check_pot_drift (plus the two gates aggregating it) fail on messages.pot drift for a string in superset/commands/database/exceptions.py. The template on this branch is byte-identical to master's and master's source carries the newer wording, so it reproduces on master and wants a regeneration PR rather than catalog churn here. 24 tests green, pre-commit clean.

@bito-code-review

bito-code-review Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #be25f0

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 9d474e5..e9d4ad8
    • tests/unit_tests/views/datasource/views_test.py
    • superset/views/datasource/views.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@sha174n

sha174n commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@rusackas correcting my last CI note: the messages.pot drift was not a master-side problem needing its own PR. Master had already regenerated the template in #44574; this branch was just based on the commit before it. Merged master in eadd783 and all four red checks (babel-extract, check_pot_drift, and the two gates aggregating it) pass locally.

Both points you raised remain in and unchanged: the omitted-key read in d16ddd8, the non-dataset guard in 5ce70d6. One cleanup commit on top in a5aef64, no behaviour change: three mock stubs that set return_value = None on calls nobody reads are dropped, and the comment above requested_table no longer restates update_from_object's docstring.

@bito-code-review

bito-code-review Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #8480cc

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: e9d4ad8..a5aef64
    • superset/views/datasource/views.py
    • tests/unit_tests/views/datasource/views_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

sha174n and others added 11 commits October 10, 2026 10:27
Move the datasource-type and still-virtual guards into _repoints_table so
the predicate is self-contained and no longer relies on a precondition the
caller has to enforce. Behaviour is unchanged: the type guard still
short-circuits ahead of table_name/is_virtual.

Also route the two remaining save tests through the shared _run_save helper.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
``_repoints_table`` took the whole request payload to read one key. Pass
the requested ``sql`` directly so the helper is not coupled to the
payload's key names, and trim the prose around it to the two points that
are not obvious from the code.

Also drops the function-local ``from flask import Flask`` lines in the
samples tests, redundant since the module-level import was added.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment-only in the view: the helper docstring owns the label-vs-pointer
rule, so the call site no longer restates it. Drops the test helper's
unused return value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…trized case

Quality pass, no behaviour change: the two "repoint allowed" tests differed
only in the requested table and the expected target, so they fold into a
single parametrized test; the module-level request app is built once; and the
comment above ``requested_table`` reads as a sentence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… save tests

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The view comment on `requested_table` and three test parameter comments
restated points already made in `update_from_object`'s docstring and in
`_repoints_table`'s. Point at those instead.

Also drops a clause on the conversion case that claimed more than the
check delivers: `raise_for_access` resolves the requested table through
`query_datasources_by_name` and accepts any match the caller can edit,
so an unchanged label resolves to the dataset under edit. The clause
still covers a conversion that changes the label in the same save, which
is what the parameter now says.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The save path only checked the table pointer, so a request supplying
``sql`` skipped the check entirely even though ``update_from_object``
applies it and ``is_virtual``/``kind`` derive from whether ``sql`` is
set. Ports ``UpdateDatasetCommand._validate_sql_access`` as a sibling
predicate, covering new SQL and unchanged SQL whose connection, catalog
or schema moves.

The two checks need separate ``raise_for_access`` calls, since passing
``sql`` builds an ephemeral query that supersedes ``table``.

Also folds the cross-database leg into ``_repoints_table`` so one
function owns the whole predicate, and restores the guard on the
``database_id`` write.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The save body is free-form JSON, so the target fields can arrive as any
type. The access checks parse `sql` and render `table_name`/`schema`/
`catalog`, neither of which survives a non-string, so validate the four
up front and answer 422 rather than failing inside the check.

Extracts the target parse and the access check into helpers, which keeps
`save` under the complexity limit, and drops a docstring clause that
described an attribute the function does not read.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The 422 for a non-string target field built its detail with an f-string
interpolated after `_()`, so only the outer sentence reached the catalog
and "must be a string" stayed English in every language. That outer
sentence also read "Dataset schema is invalid", which points at the
dataset's column schema rather than at the request body field that
actually failed the type check.

One msgid now carries the whole sentence with a `%(field)s` placeholder,
and the extraction template is regenerated so the string is translatable.
Same pass drops the dict `_requested_target` built only to read back by
key, and asserts the response names the offending field.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sha174n
sha174n force-pushed the fix/datasource-save-repoint-access branch from 0fc4493 to 5b3b211 Compare October 10, 2026 09:35
@github-actions github-actions Bot removed i18n:spanish Translation related to Spanish language i18n:italian Translation related to Italian language i18n:french Translation related to French language i18n:chinese Translation related to Chinese language i18n:japanese Translation related to Japanese language i18n:russian Translation related to Russian language i18n:korean Translation related to Korean language i18n:dutch i18n:slovak i18n:ukrainian i18n:portuguese i18n:brazilian i18n:traditional-chinese i18n:persian i18n:czech i18n:latvian labels Oct 10, 2026
@codeant-ai-for-open-source

Copy link
Copy Markdown
Contributor

CodeAnt PR Risk: Low Risk

  • The PR appears safe to merge; no concrete unresolved issue is evident in the changed authorization flow.
  • Dataset saves check access to the requested table or SQL target when repointing, including same-database and cross-database changes.
  • Focused tests cover repoint authorization, unchanged targets, malformed fields, and saves for non-dataset datasource types.

Assessed commit: 5b3b21136442

@github-actions github-actions Bot removed the requires:rebase Requires rebasing on top of current master label Oct 10, 2026

This branch has not been deployed

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

Labels

i18n Namespace | Anything related to localization size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants