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 2023/12/08 14:04:59 UTC
(superset) 01/08: fix(embedded): Hide sensitive payload data from guest users (#25878)
This is an automated email from the ASF dual-hosted git repository.
michaelsmolina pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/superset.git
commit b9e8cc958a57dc7594c114fd914d7d7039d7e842
Author: Jack Fragassi <jf...@gmail.com>
AuthorDate: Mon Dec 4 14:52:59 2023 -0800
fix(embedded): Hide sensitive payload data from guest users (#25878)
(cherry picked from commit 386d4e0541872984bf2c473f06343a51dc3cf9e1)
---
.../src/hooks/apiResources/dashboards.ts | 1 +
superset/dashboards/schemas.py | 20 +++++++++-
tests/integration_tests/dashboards/api_tests.py | 43 ++++++++++++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/superset-frontend/src/hooks/apiResources/dashboards.ts b/superset-frontend/src/hooks/apiResources/dashboards.ts
index b21cc668c0..61896ba130 100644
--- a/superset-frontend/src/hooks/apiResources/dashboards.ts
+++ b/superset-frontend/src/hooks/apiResources/dashboards.ts
@@ -31,6 +31,7 @@ export const useDashboard = (idOrSlug: string | number) =>
(dashboard.json_metadata && JSON.parse(dashboard.json_metadata)) || {},
position_data:
dashboard.position_json && JSON.parse(dashboard.position_json),
+ owners: dashboard.owners || [],
}),
);
diff --git a/superset/dashboards/schemas.py b/superset/dashboards/schemas.py
index f72aeae582..9a6bcfb456 100644
--- a/superset/dashboards/schemas.py
+++ b/superset/dashboards/schemas.py
@@ -18,9 +18,10 @@ import json
import re
from typing import Any, Union
-from marshmallow import fields, post_load, pre_load, Schema
+from marshmallow import fields, post_dump, post_load, pre_load, Schema
from marshmallow.validate import Length, ValidationError
+from superset import security_manager
from superset.exceptions import SupersetException
from superset.tags.models import TagTypes
from superset.utils import core as utils
@@ -202,6 +203,15 @@ class DashboardGetResponseSchema(Schema):
changed_on_humanized = fields.String(data_key="changed_on_delta_humanized")
is_managed_externally = fields.Boolean(allow_none=True, dump_default=False)
+ # pylint: disable=unused-argument
+ @post_dump()
+ def post_dump(self, serialized: dict[str, Any], **kwargs: Any) -> dict[str, Any]:
+ if security_manager.is_guest_user():
+ del serialized["owners"]
+ del serialized["changed_by_name"]
+ del serialized["changed_by"]
+ return serialized
+
class DatabaseSchema(Schema):
id = fields.Int()
@@ -250,6 +260,14 @@ class DashboardDatasetSchema(Schema):
granularity_sqla = fields.List(fields.List(fields.Str()))
normalize_columns = fields.Bool()
+ # pylint: disable=unused-argument
+ @post_dump()
+ def post_dump(self, serialized: dict[str, Any], **kwargs: Any) -> dict[str, Any]:
+ if security_manager.is_guest_user():
+ del serialized["owners"]
+ del serialized["database"]
+ return serialized
+
class BaseDashboardSchema(Schema):
# pylint: disable=no-self-use,unused-argument
diff --git a/tests/integration_tests/dashboards/api_tests.py b/tests/integration_tests/dashboards/api_tests.py
index cc7bc109b4..a5c44f9f08 100644
--- a/tests/integration_tests/dashboards/api_tests.py
+++ b/tests/integration_tests/dashboards/api_tests.py
@@ -176,6 +176,26 @@ class TestDashboardApi(SupersetTestCase, ApiOwnersTestCaseMixin, InsertChartMixi
expected_values = [0, 1] if backend() == "presto" else [0, 1, 2]
self.assertEqual(result[0]["column_types"], expected_values)
+ @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices")
+ @patch("superset.dashboards.schemas.security_manager.has_guest_access")
+ @patch("superset.dashboards.schemas.security_manager.is_guest_user")
+ def test_get_dashboard_datasets_as_guest(self, is_guest_user, has_guest_access):
+ self.login(username="admin")
+ uri = "api/v1/dashboard/world_health/datasets"
+ is_guest_user = True
+ has_guest_access = True
+ response = self.get_assert_metric(uri, "get_datasets")
+ self.assertEqual(response.status_code, 200)
+ data = json.loads(response.data.decode("utf-8"))
+ dashboard = Dashboard.get("world_health")
+ expected_dataset_ids = {s.datasource_id for s in dashboard.slices}
+ result = data["result"]
+ actual_dataset_ids = {dataset["id"] for dataset in result}
+ self.assertEqual(actual_dataset_ids, expected_dataset_ids)
+ for dataset in result:
+ for excluded_key in ["database", "owners"]:
+ assert excluded_key not in dataset
+
@pytest.mark.usefixtures("load_world_bank_dashboard_with_slices")
def test_get_dashboard_datasets_not_found(self):
self.login(username="alpha")
@@ -409,6 +429,29 @@ class TestDashboardApi(SupersetTestCase, ApiOwnersTestCaseMixin, InsertChartMixi
db.session.delete(dashboard)
db.session.commit()
+ @patch("superset.dashboards.schemas.security_manager.has_guest_access")
+ @patch("superset.dashboards.schemas.security_manager.is_guest_user")
+ def test_get_dashboard_as_guest(self, is_guest_user, has_guest_access):
+ """
+ Dashboard API: Test get dashboard as guest
+ """
+ admin = self.get_user("admin")
+ dashboard = self.insert_dashboard(
+ "title", "slug1", [admin.id], created_by=admin
+ )
+ is_guest_user.return_value = True
+ has_guest_access.return_value = True
+ self.login(username="admin")
+ uri = f"api/v1/dashboard/{dashboard.id}"
+ rv = self.get_assert_metric(uri, "get")
+ self.assertEqual(rv.status_code, 200)
+ data = json.loads(rv.data.decode("utf-8"))
+ for excluded_key in ["changed_by", "changed_by_name", "owners"]:
+ assert excluded_key not in data["result"]
+ # rollback changes
+ db.session.delete(dashboard)
+ db.session.commit()
+
def test_info_dashboard(self):
"""
Dashboard API: Test info