You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2024/03/07 18:21:34 UTC

(superset) 01/06: fix: improve explore REST api validations (#27395)

This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 4.0
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 94aeef5f827eda424edd5b212651b3e263e96571
Author: Daniel Vaz Gaspar <da...@gmail.com>
AuthorDate: Tue Mar 5 17:44:51 2024 +0000

    fix: improve explore REST api validations (#27395)
    
    (cherry picked from commit a3d2e0bf447fad5d4495eea97529118b562f4e3c)
---
 superset/commands/explore/get.py             | 11 +++++++++--
 tests/integration_tests/explore/api_tests.py | 20 +++++++++++++++++++-
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/superset/commands/explore/get.py b/superset/commands/explore/get.py
index 9d715bd63d..a0ff176109 100644
--- a/superset/commands/explore/get.py
+++ b/superset/commands/explore/get.py
@@ -37,6 +37,7 @@ from superset.daos.exceptions import DatasourceNotFound
 from superset.exceptions import SupersetException
 from superset.explore.exceptions import WrongEndpointError
 from superset.explore.permalink.exceptions import ExplorePermalinkGetFailedError
+from superset.extensions import security_manager
 from superset.utils import core as utils
 from superset.views.utils import (
     get_datasource_info,
@@ -61,7 +62,6 @@ class GetExploreCommand(BaseCommand, ABC):
     # pylint: disable=too-many-locals,too-many-branches,too-many-statements
     def run(self) -> Optional[dict[str, Any]]:
         initial_form_data = {}
-
         if self._permalink_key is not None:
             command = GetExplorePermalinkCommand(self._permalink_key)
             permalink_value = command.run()
@@ -110,12 +110,19 @@ class GetExploreCommand(BaseCommand, ABC):
             self._datasource_type = SqlaTable.type
 
         datasource: Optional[BaseDatasource] = None
+
         if self._datasource_id is not None:
             with contextlib.suppress(DatasourceNotFound):
                 datasource = DatasourceDAO.get_datasource(
                     cast(str, self._datasource_type), self._datasource_id
                 )
-        datasource_name = datasource.name if datasource else _("[Missing Dataset]")
+
+        datasource_name = _("[Missing Dataset]")
+
+        if datasource:
+            datasource_name = datasource.name
+            security_manager.can_access_datasource(datasource)
+
         viz_type = form_data.get("viz_type")
         if not viz_type and datasource and datasource.default_endpoint:
             raise WrongEndpointError(redirect=datasource.default_endpoint)
diff --git a/tests/integration_tests/explore/api_tests.py b/tests/integration_tests/explore/api_tests.py
index c0b7f5fcd4..6d33f1c916 100644
--- a/tests/integration_tests/explore/api_tests.py
+++ b/tests/integration_tests/explore/api_tests.py
@@ -197,7 +197,7 @@ def test_get_from_permalink_unknown_key(test_client, login_as_admin):
 
 
 @patch("superset.security.SupersetSecurityManager.can_access_datasource")
-def test_get_dataset_access_denied(
+def test_get_dataset_access_denied_with_form_data_key(
     mock_can_access_datasource, test_client, login_as_admin, dataset
 ):
     message = "Dataset access denied"
@@ -214,6 +214,24 @@ def test_get_dataset_access_denied(
     assert data["message"] == message
 
 
+@patch("superset.security.SupersetSecurityManager.can_access_datasource")
+def test_get_dataset_access_denied(
+    mock_can_access_datasource, test_client, login_as_admin, dataset
+):
+    message = "Dataset access denied"
+    mock_can_access_datasource.side_effect = DatasetAccessDeniedError(
+        message=message, datasource_id=dataset.id, datasource_type=dataset.type
+    )
+    resp = test_client.get(
+        f"api/v1/explore/?datasource_id={dataset.id}&datasource_type={dataset.type}"
+    )
+    data = json.loads(resp.data.decode("utf-8"))
+    assert resp.status_code == 403
+    assert data["datasource_id"] == dataset.id
+    assert data["datasource_type"] == dataset.type
+    assert data["message"] == message
+
+
 @patch("superset.daos.datasource.DatasourceDAO.get_datasource")
 def test_wrong_endpoint(mock_get_datasource, test_client, login_as_admin, dataset):
     dataset.default_endpoint = "another_endpoint"