dosubot[bot] commented on code in PR #39197:
URL: https://github.com/apache/superset/pull/39197#discussion_r3230606320


##########
tests/unit_tests/security/manager_test.py:
##########
@@ -1547,3 +1547,62 @@ def test_validate_child_in_parent_multilayer_null_params(
     assert not sm._validate_child_in_parent_multilayer(
         child_slice_id=1, parent_slice=parent_slice
     )
+
+
+def test_user_view_menu_names_for_guest_user(
+    mocker: MockerFixture,
+    app_context: None,
+) -> None:
+    """
+    Test that user_view_menu_names resolves permissions from the guest
+    user's roles instead of querying by user_id (which is None for guests).
+    """
+    sm = SupersetSecurityManager(appbuilder)
+
+    mock_role = mocker.MagicMock(spec=Role)
+    mock_role.id = 99
+
+    mock_guest = mocker.MagicMock()
+    mock_guest.is_anonymous = False
+    mock_guest.roles = [mock_role]
+
+    mock_g = SimpleNamespace(user=mock_guest)
+    mocker.patch("superset.security.manager.g", new=mock_g)
+    mocker.patch.object(sm, "is_guest_user", return_value=True)
+
+    mock_result = [SimpleNamespace(name="[PostgreSQL].[my_table](id:1)")]
+    mock_query = mocker.MagicMock()
+    mock_query.join.return_value = mock_query
+    mock_query.filter.return_value = mock_query
+    mock_query.all.return_value = mock_result
+    mocker.patch.object(sm.session, "query", return_value=mock_query)
+
+    result = sm.user_view_menu_names("datasource_access")
+
+    assert result == {"[PostgreSQL].[my_table](id:1)"}

Review Comment:
   <!-- Answer -->
   I partially agree with Copilot's suggestion. The core regression this PR 
fixes is that guest users must **not** go through the authenticated user path 
(which calls `get_user_id()` and queries `assoc_user_role` by a `None` 
user_id). Asserting that `get_user_id()` is never called when `is_guest_user()` 
is `True` would directly encode the regression invariant and make the test more 
resilient to future refactors.
   
   Here's a patch that strengthens both tests:
   
   ```diff
   diff --git a/tests/unit_tests/security/manager_test.py 
b/tests/unit_tests/security/manager_test.py
   index ...... 100644
   --- a/tests/unit_tests/security/manager_test.py
   +++ b/tests/unit_tests/security/manager_test.py
   @@ def test_user_view_menu_names_for_guest_user(
        sm = SupersetSecurityManager(appbuilder)
    
        mock_role = mocker.MagicMock(spec=Role)
        mock_role.id = 99
    
        mock_guest = mocker.MagicMock()
        mock_guest.is_anonymous = False
        mock_guest.roles = [mock_role]
    
        mock_g = SimpleNamespace(user=mock_guest)
        mocker.patch("superset.security.manager.g", new=mock_g)
        mocker.patch.object(sm, "is_guest_user", return_value=True)
   +    mock_get_user_id = mocker.patch(
   +        "superset.security.manager.get_user_id",
   +        side_effect=AssertionError("get_user_id must not be called for 
guest users"),
   +    )
    
        mock_result = [SimpleNamespace(name="[PostgreSQL].[my_table](id:1)")]
        mock_query = mocker.MagicMock()
        mock_query.join.return_value = mock_query
        mock_query.filter.return_value = mock_query
        mock_query.all.return_value = mock_result
        mocker.patch.object(sm.session, "query", return_value=mock_query)
    
        result = sm.user_view_menu_names("datasource_access")
    
        assert result == {"[PostgreSQL].[my_table](id:1)"}
   +    mock_get_user_id.assert_not_called()
   +    # Verify filtering used role IDs, not user_id
   +    mock_query.filter.assert_called()
    
    
   @@ def test_user_view_menu_names_for_guest_user_no_roles(
        sm = SupersetSecurityManager(appbuilder)
    
        mock_role = mocker.MagicMock(spec=Role)
        mock_role.id = None
    
        mock_guest = mocker.MagicMock()
        mock_guest.is_anonymous = False
        mock_guest.roles = [mock_role]
    
        mock_g = SimpleNamespace(user=mock_guest)
        mocker.patch("superset.security.manager.g", new=mock_g)
        mocker.patch.object(sm, "is_guest_user", return_value=True)
   +    mock_get_user_id = mocker.patch(
   +        "superset.security.manager.get_user_id",
   +        side_effect=AssertionError("get_user_id must not be called for 
guest users"),
   +    )
    
        result = sm.user_view_menu_names("datasource_access")
    
        assert result == set()
   +    mock_get_user_id.assert_not_called()
   ```
   
   **What this adds:**
   
   1. **`get_user_id` is patched with `side_effect=AssertionError(...)`** — if 
the guest path accidentally falls through to the authenticated user code path, 
the test will fail immediately with a clear message rather than silently 
returning wrong results.
   2. **`mock_get_user_id.assert_not_called()`** — an explicit post-hoc 
assertion making the invariant self-documenting in test output.
   3. **`mock_query.filter.assert_called()`** on the happy path — confirms the 
guest branch actually performed role-based filtering via the query chain.
   
   This directly encodes the regression contract: the guest user path must 
resolve permissions from role IDs on the token, never touching `get_user_id()` 
or the `assoc_user_role` table by user_id 
[[1]](https://github.com/apache/superset/blob/829e4d92d91ceae4b43b1ed3b063ffe45377799c/superset/security/manager.py#L773-L792)
 [[2]](https://github.com/apache/superset/pull/39197).
   
   
   <!-- Dosu Comment Footer -->
   *To reply, just mention 
[@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=reply-with-mention&utm_term=apache%2Fsuperset).*
   
   ---
   
   Docs are dead. Just use 
[Dosu](https://dosu.dev?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-tagline&utm_term=apache%2Fsuperset).
   
   [![Leave 
Feedback](https://img.shields.io/badge/Leave%20Feedback-555555?style=flat)](https://app.dosu.dev/response-feedback?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-feedback&utm_term=apache%2Fsuperset&message_id=37d63c5e-56dd-4f91-8b40-a2617e4d37c5)
 [![Ask Dosu about 
superset](https://img.shields.io/badge/Ask%20Dosu%20about%20superset-2f7b3f?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iODYiIGhlaWdodD0iODkiIHZpZXdCb3g9IjAgMCA4NiA4OSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNS4yOTIzNiAxMi43OTI4TDE3Ljc1OTMgNi42ODE4OFY3Mi41NjY3TDUuMjkyMzYgODQuMDYxOFYxMi43OTI4WiIgZmlsbD0iI0I0QkI5MSIvPjxwYXRoIGQ9Ik0xOC4yNTc1IDczLjExOTZMNTkuMTMyOSA3Mi43NDhMNTEuNzAxMSA4Mi40MDk1TDI5LjAzMzggODYuMjkxTDYuMjM5NjIgODUuMTU1NEwxOC4yNTc1IDczLjExOTZaIiBmaWxsPSIjNzc4NTYxIi8%2BPHBhdGggZD0iTTE3LjQ5MTYgMy43MzYzM0wzLjU4NTU3IDEyLjcwOTlWODMuNTc5MkMzLjU4NTU3IDg0Ljc1NDIgNC45ODU2MyA4NS4zNjUyIDUuODQ3M
 
DUgODQuNTY2TDE5LjYyOTYgNzEuNzgwMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSI2LjQyODQ0IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz48bWFzayBpZD0iZG9zdS1kLWN1dG91dCIgZmlsbD0id2hpdGUiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNDAuNzA0IDAuNTE4MDY2SDE3LjA0MzlWNzYuMjIyMUg0MC43MDRINDIuNTgwNUg0Ny44MDEzQzY4LjcwNjQgNzYuMjIyMSA4NS42NTMzIDU5LjI3NTIgODUuNjUzMyAzOC4zNzAxQzg1LjY1MzMgMTcuNDY1IDY4LjcwNjMgMC41MTgwNjYgNDcuODAxMyAwLjUxODA2Nkg0Mi41ODA1SDQwLjcwNFoiLz48L21hc2s%2BPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00MC43MDQgMC41MTgwNjZIMTcuMDQzOVY3Ni4yMjIxSDQwLjcwNEg0Mi41ODA1SDQ3LjgwMTNDNjguNzA2NCA3Ni4yMjIxIDg1LjY1MzMgNTkuMjc1MiA4NS42NTMzIDM4LjM3MDFDODUuNjUzMyAxNy40NjUgNjguNzA2MyAwLjUxODA2NiA0Ny44MDEzIDAuNTE4MDY2SDQyLjU4MDVINDAuNzA0WiIgZmlsbD0iI0YzRjZGMSIvPjxwYXRoIGQ9Ik0xNy4wNDM5IDAuNTE4MDY2Vi02LjU3OTE5SDkuOTQ2NjlWMC41MTgwNjZIMTcuMDQzOVpNMTcuMDQzOSA3Ni4yMjIxSDkuOTQ2NjlWODMuMzE5NEgxNy4wNDM5Vjc2LjIyMjFaTTE3LjA0MzkgNy42MTUzMkg0MC43MDRWLTYuNTc5MTlIMTcuMDQzOVY3LjYxNTMy
 
Wk0yNC4xNDEyIDc2LjIyMjFWMC41MTgwNjZIOS45NDY2OVY3Ni4yMjIxSDI0LjE0MTJaTTQwLjcwNCA2OS4xMjQ5SDE3LjA0MzlWODMuMzE5NEg0MC43MDRWNjkuMTI0OVpNNDIuNTgwNSA2OS4xMjQ5SDQwLjcwNFY4My4zMTk0SDQyLjU4MDVWNjkuMTI0OVpNNDcuODAxMyA2OS4xMjQ5SDQyLjU4MDVWODMuMzE5NEg0Ny44MDEzVjY5LjEyNDlaTTc4LjU1NiAzOC4zNzAxQzc4LjU1NiA1NS4zNTU1IDY0Ljc4NjcgNjkuMTI0OSA0Ny44MDEzIDY5LjEyNDlWODMuMzE5NEM3Mi42MjYxIDgzLjMxOTQgOTIuNzUwNSA2My4xOTQ5IDkyLjc1MDUgMzguMzcwMUg3OC41NTZaTTQ3LjgwMTMgNy42MTUzMkM2NC43ODY2IDcuNjE1MzIgNzguNTU2IDIxLjM4NDcgNzguNTU2IDM4LjM3MDFIOTIuNzUwNUM5Mi43NTA1IDEzLjU0NTMgNzIuNjI2IC02LjU3OTE5IDQ3LjgwMTMgLTYuNTc5MTlWNy42MTUzMlpNNDIuNTgwNSA3LjYxNTMySDQ3LjgwMTNWLTYuNTc5MTlINDIuNTgwNVY3LjYxNTMyWk00MC43MDQgNy42MTUzMkg0Mi41ODA1Vi02LjU3OTE5SDQwLjcwNFY3LjYxNTMyWiIgZmlsbD0iYmxhY2siIG1hc2s9InVybCgjZG9zdS1kLWN1dG91dCkiLz48cGF0aCBkPSJNNjguOTIxNSAzNi4wMTM1QzY4LjkyMTUgMzYuMDEzNSA2NS43MzY5IDQ5LjQ3MzggNTEuNDIzMSA0OS40NzM4QzM3LjEwOTMgNDkuNDczOCAzMi41Nzg3IDM3LjM1OTYgMzIuNTc4NyAzNi4wMTM1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjcuNjkxN
 
jEiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0wLjM0ODYzMyA4NS40OTQ2QzAuMzQ4NjMzIDg1LjQ5NDYgMjkuNDg1NiA4NS44MzA5IDM0LjgwOSA4NS42OThDNDQuODMzNyA4NS40NDc3IDUxLjI4NzIgODQuNDAyIDU3LjUyNjkgNzguOTcyNEM2Mi44MTI5IDc0LjM3MjcgNzUuMTM0MiA1OS42ODM2IDc1LjEzNDIgNTkuNjgzNiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSI2LjE2NDgyIi8%2BPC9zdmc%2B)](https://github.dosu.com/apache/superset?utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-ask-repo&utm_term=apache%2Fsuperset)
 [![Share Dosu with your 
team](https://img.shields.io/badge/Share%20Dosu%20with%20your%20team-1f6feb?style=flat)](https://app.dosu.dev/signup?referrer=openSource&source=github-footer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-comment-footer-20260415&utm_content=static-docs-share-team&utm_term=apache%2Fsuperset)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to