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,
+        )

Reply via email to