This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch tdd/issue-39296-sqllab-temp-dataset-owner-permission in repository https://gitbox.apache.org/repos/asf/superset.git
commit ccdf23ad6ddd1912240b7508977b77ff641e88b2 Author: Claude Code <[email protected]> AuthorDate: Wed Jul 29 16:33:42 2026 -0700 test(security): temp SQL Lab dataset permission check without owner (#39296) Closes #39296 Adds a regression test pinning the QUERY-path half of the asymmetry #39296 describes: exploring an unsaved SQL Lab query straight from "Create Chart" has no query-authorship bypass, unlike the "Save dataset" flow, which grants access via populate_owners()-assigned ownership. A user without catalog/schema/dataset-level datasource_access is denied here even though they just ran this exact query. Test-only PR, per the TDD-validation queue: if CI is green here, the denial is confirmed as intentional design (working as intended, not a bug), if red, something's changed since. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- tests/unit_tests/explore/utils_test.py | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/unit_tests/explore/utils_test.py b/tests/unit_tests/explore/utils_test.py index 54555d2814e..e9da9e96bda 100644 --- a/tests/unit_tests/explore/utils_test.py +++ b/tests/unit_tests/explore/utils_test.py @@ -362,3 +362,67 @@ def test_query_no_access(mocker: MockerFixture, client) -> None: datasource_id=1, datasource_type=DatasourceType.QUERY, ) + + +def test_unsaved_query_explore_allows_the_querys_own_author( + mocker: MockerFixture, client +) -> None: + """ + Regression for #39296: clicking "Create Chart" straight from a SQL Lab + query (no "Save dataset" step first) sends ``DatasourceType.QUERY`` into + ``CreateFormDataCommand``, which is the command backing that button (see + ``superset/commands/explore/form_data/create.py``). That command calls + this exact ``check_access`` function with ``chart_id=None``. + + Unlike the TABLE path (``check_access`` -> ``can_access_datasource`` -> + ``raise_for_access(datasource=...)``), which grants access to a + dataset's *owners* via ``is_editor`` regardless of catalog/schema/table + permissions, the QUERY path has no equivalent "you authored this" bypass: + ``raise_for_access``'s ``query=`` branch (``superset/security/manager.py``) + only ever checks catalog/schema/table-level ``datasource_access``, and + never looks at ``Query.user_id`` at all. So a user who just ran this + exact query in SQL Lab themselves (and therefore has execution rights on + the connection) but lacks that dataset-level permission is denied here, + even though the identical underlying data becomes explorable to them the + moment it's saved as a dataset, since ``populate_owners()`` + (``superset/commands/utils.py``) would make them an owner at that point. + That inconsistency, not a missing owner field, is the crux of #39296. + + This test sets the query's ``user_id`` to match the current user (i.e. + the user IS the query's own author) and asserts access should be + granted, the behavior a fix should produce. It's expected to currently + FAIL: no code path today grants a bypass for query authorship, so + ``raise_for_access`` denies even the query's own author. A red result + here is the TDD signal that the reported gap is real; a future fix + adding that bypass should turn this green. + """ + from superset.connectors.sqla.models import SqlaTable + from superset.explore.utils import check_access as check_chart_access + from superset.models.sql_lab import Query + + current_user = User(id=1) + + database = mocker.MagicMock() + database.get_default_catalog.return_value = None + database.get_default_schema_for_query.return_value = "public" + mocker.patch( + query_find_by_id, + return_value=Query( + database=database, sql="select * from foo", user_id=current_user.id + ), + ) + mocker.patch(query_datasources_by_name, return_value=[SqlaTable()]) + mocker.patch(is_admin, return_value=False) + mocker.patch(is_editor, return_value=False) + # No catalog/schema/dataset-level datasource_access grant of any kind: + # the only thing that should let this through is query authorship. + mocker.patch(can_access, return_value=False) + + with override_user(current_user): + # A user exploring a query they themselves just ran in SQL Lab + # should not be denied for lack of an unrelated dataset grant. + check_chart_access( + datasource_id=1, + chart_id=None, + datasource_type=DatasourceType.QUERY, + )
