From f5d115b6690f2d311deea747ed74585b8b3120ad Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Fri, 9 Jun 2023 12:03:15 -0300 Subject: [PATCH 1/4] feat: Convert ENABLE_BROAD_ACTIVITY_ACCESS and MENU_HIDE_USER_INFO into feature flags --- .../src/utils/featureFlags.ts | 1 + .../src/pages/ChartList/index.tsx | 5 +-- .../src/pages/DashboardList/index.tsx | 5 +-- superset/config.py | 12 +++---- superset/connectors/sqla/models.py | 5 ++- superset/models/dashboard.py | 5 ++- superset/models/filter_set.py | 7 ++-- superset/models/slice.py | 5 ++- superset/security/manager.py | 3 +- superset/views/base.py | 5 +-- superset/views/core.py | 2 +- tests/integration_tests/charts/api_tests.py | 9 ++--- tests/integration_tests/core_tests.py | 33 +++++++++---------- .../integration_tests/dashboards/api_tests.py | 9 ++--- tests/integration_tests/datasets/api_tests.py | 10 ++---- tests/integration_tests/log_api_tests.py | 5 ++- 16 files changed, 53 insertions(+), 68 deletions(-) diff --git a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts index 48e54d18416a8..138f21258bbd9 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts @@ -40,6 +40,7 @@ export enum FeatureFlag { EMBEDDABLE_CHARTS = 'EMBEDDABLE_CHARTS', EMBEDDED_SUPERSET = 'EMBEDDED_SUPERSET', ENABLE_ADVANCED_DATA_TYPES = 'ENABLE_ADVANCED_DATA_TYPES', + ENABLE_BROAD_ACTIVITY_ACCESS = 'ENABLE_BROAD_ACTIVITY_ACCESS', ENABLE_EXPLORE_DRAG_AND_DROP = 'ENABLE_EXPLORE_DRAG_AND_DROP', ENABLE_JAVASCRIPT_CONTROLS = 'ENABLE_JAVASCRIPT_CONTROLS', ENABLE_TEMPLATE_PROCESSING = 'ENABLE_TEMPLATE_PROCESSING', diff --git a/superset-frontend/src/pages/ChartList/index.tsx b/superset-frontend/src/pages/ChartList/index.tsx index 5a869e3c4fc66..9189e5d930435 100644 --- a/superset-frontend/src/pages/ChartList/index.tsx +++ b/superset-frontend/src/pages/ChartList/index.tsx @@ -234,8 +234,9 @@ function ChartList(props: ChartListProps) { const canExport = hasPerm('can_export') && isFeatureEnabled(FeatureFlag.VERSIONED_EXPORT); const initialSort = [{ id: 'changed_on_delta_humanized', desc: true }]; - const enableBroadUserAccess = - bootstrapData.common.conf.ENABLE_BROAD_ACTIVITY_ACCESS; + const enableBroadUserAccess = isFeatureEnabled( + FeatureFlag.ENABLE_BROAD_ACTIVITY_ACCESS, + ); const handleBulkChartExport = (chartsToExport: Chart[]) => { const ids = chartsToExport.map(({ id }) => id); handleResourceExport('chart', ids, () => { diff --git a/superset-frontend/src/pages/DashboardList/index.tsx b/superset-frontend/src/pages/DashboardList/index.tsx index 22e7b6c12fc19..362e6e2c14c95 100644 --- a/superset-frontend/src/pages/DashboardList/index.tsx +++ b/superset-frontend/src/pages/DashboardList/index.tsx @@ -143,8 +143,9 @@ function DashboardList(props: DashboardListProps) { const [importingDashboard, showImportModal] = useState(false); const [passwordFields, setPasswordFields] = useState([]); const [preparingExport, setPreparingExport] = useState(false); - const enableBroadUserAccess = - bootstrapData?.common?.conf?.ENABLE_BROAD_ACTIVITY_ACCESS; + const enableBroadUserAccess = isFeatureEnabled( + FeatureFlag.ENABLE_BROAD_ACTIVITY_ACCESS, + ); const [sshTunnelPasswordFields, setSSHTunnelPasswordFields] = useState< string[] >([]); diff --git a/superset/config.py b/superset/config.py index f9fdf3cdd5122..7b4684f2d2122 100644 --- a/superset/config.py +++ b/superset/config.py @@ -484,6 +484,11 @@ class D3Format(TypedDict, total=False): # otherwise enabling this flag won't have any effect on the DB. "SSH_TUNNELING": False, "AVOID_COLORS_COLLISION": True, + # Set to False to only allow viewing own recent activity + # or to disallow users from viewing other users profile page + "ENABLE_BROAD_ACTIVITY_ACCESS": False, + # Do not show user info or profile in the menu + "MENU_HIDE_USER_INFO": False, } # ------------------------------ @@ -1493,13 +1498,6 @@ def EMAIL_HEADER_MUTATOR( # pylint: disable=invalid-name,unused-argument # DATASET_HEALTH_CHECK: Callable[[SqlaTable], str] | None = None -# Do not show user info or profile in the menu -MENU_HIDE_USER_INFO = False - -# Set to False to only allow viewing own recent activity -# or to disallow users from viewing other users profile page -ENABLE_BROAD_ACTIVITY_ACCESS = True - # the advanced data type key should correspond to that set in the column metadata ADVANCED_DATA_TYPES: dict[str, AdvancedDataType] = { "internet_address": internet_address, diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index 41a9c89757891..20a382e80127b 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -594,9 +594,8 @@ def changed_by_name(self) -> str: @property def changed_by_url(self) -> str: - if ( - not self.changed_by - or not current_app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] + if not self.changed_by or not is_feature_enabled( + "ENABLE_BROAD_ACTIVITY_ACCESS" ): return "" return f"/superset/profile/{self.changed_by.username}" diff --git a/superset/models/dashboard.py b/superset/models/dashboard.py index f3b9c08794793..cdb0fd8a0de39 100644 --- a/superset/models/dashboard.py +++ b/superset/models/dashboard.py @@ -271,9 +271,8 @@ def changed_by_name(self) -> str: @property def changed_by_url(self) -> str: - if ( - not self.changed_by - or not current_app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] + if not self.changed_by or not is_feature_enabled( + "ENABLE_BROAD_ACTIVITY_ACCESS" ): return "" return f"/superset/profile/{self.changed_by.username}" diff --git a/superset/models/filter_set.py b/superset/models/filter_set.py index ac25b114ff0c1..2bc728c817f1d 100644 --- a/superset/models/filter_set.py +++ b/superset/models/filter_set.py @@ -26,7 +26,7 @@ from sqlalchemy.orm import relationship from sqlalchemy_utils import generic_relationship -from superset import app, db +from superset import app, db, is_feature_enabled from superset.models.helpers import AuditMixinNullable metadata = Model.metadata # pylint: disable=no-member @@ -68,9 +68,8 @@ def changed_by_name(self) -> str: @property def changed_by_url(self) -> str: - if ( - not self.changed_by - or not current_app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] + if not self.changed_by or not is_feature_enabled( + "ENABLE_BROAD_ACTIVITY_ACCESS" ): return "" return f"/superset/profile/{self.changed_by.username}" diff --git a/superset/models/slice.py b/superset/models/slice.py index 15dddfc7e1eaf..7754d745419ed 100644 --- a/superset/models/slice.py +++ b/superset/models/slice.py @@ -340,9 +340,8 @@ def created_by_url(self) -> str: @property def changed_by_url(self) -> str: - if ( - not self.changed_by - or not current_app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] + if not self.changed_by or not is_feature_enabled( + "ENABLE_BROAD_ACTIVITY_ACCESS" ): return "" return f"/superset/profile/{self.changed_by.username}" diff --git a/superset/security/manager.py b/superset/security/manager.py index 94a731a3ffdc0..e5fc323a56799 100644 --- a/superset/security/manager.py +++ b/superset/security/manager.py @@ -59,6 +59,7 @@ DatasetInvalidPermissionEvaluationException, SupersetSecurityException, ) +from superset.extensions import feature_flag_manager from superset.security.guest_token import ( GuestToken, GuestTokenResources, @@ -2005,7 +2006,7 @@ def get_rls_cache_key(self, datasource: "BaseDatasource") -> list[str]: @staticmethod def raise_for_user_activity_access(user_id: int) -> None: if not get_user_id() or ( - not current_app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] + not feature_flag_manager.is_feature_enabled("ENABLE_BROAD_ACTIVITY_ACCESS") and user_id != get_user_id() ): raise SupersetSecurityException( diff --git a/superset/views/base.py b/superset/views/base.py index 3a72096ac2fc1..793c7e31d4d6c 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -58,6 +58,7 @@ conf, db, get_feature_flags, + is_feature_enabled, security_manager, ) from superset.commands.exceptions import CommandException, CommandInvalidError @@ -383,12 +384,12 @@ def menu_data(user: User) -> dict[str, Any]: "show_language_picker": len(languages.keys()) > 1, "user_is_anonymous": user.is_anonymous, "user_info_url": None - if appbuilder.app.config["MENU_HIDE_USER_INFO"] + if is_feature_enabled("MENU_HIDE_USER_INFO") else appbuilder.get_url_for_userinfo, "user_logout_url": appbuilder.get_url_for_logout, "user_login_url": appbuilder.get_url_for_login, "user_profile_url": None - if user.is_anonymous or appbuilder.app.config["MENU_HIDE_USER_INFO"] + if user.is_anonymous or is_feature_enabled("MENU_HIDE_USER_INFO") else f"/superset/profile/{user.username}", "locale": session.get("locale", "en"), }, diff --git a/superset/views/core.py b/superset/views/core.py index 3b63eb74d81ad..6f0568fb0df60 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -2693,7 +2693,7 @@ def profile(self, username: str) -> FlaskResponse: # Prevent returning 404 when user is not found to prevent username scanning user_id = -1 if not user else user.id # Prevent unauthorized access to other user's profiles, - # unless configured to do so on with ENABLE_BROAD_ACTIVITY_ACCESS + # unless configured to do so with ENABLE_BROAD_ACTIVITY_ACCESS if error_obj := self.get_user_activity_access_error(user_id): return error_obj diff --git a/tests/integration_tests/charts/api_tests.py b/tests/integration_tests/charts/api_tests.py index fa09e56675547..202c7987d6761 100644 --- a/tests/integration_tests/charts/api_tests.py +++ b/tests/integration_tests/charts/api_tests.py @@ -34,6 +34,7 @@ from superset.models.slice import Slice from superset.utils.core import get_example_default_schema +from tests.integration_tests.conftest import with_feature_flags from tests.integration_tests.base_api_tests import ApiOwnersTestCaseMixin from tests.integration_tests.base_tests import SupersetTestCase from tests.integration_tests.fixtures.birth_names_dashboard import ( @@ -605,12 +606,11 @@ def test_update_chart(self): db.session.commit() @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=False) def test_chart_activity_access_disabled(self): """ Chart API: Test ENABLE_BROAD_ACTIVITY_ACCESS = False """ - access_flag = app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = False admin = self.get_user("admin") birth_names_table_id = SupersetTestCase.get_table(name="birth_names").id chart_id = self.insert_chart("title", [admin.id], birth_names_table_id).id @@ -626,17 +626,15 @@ def test_chart_activity_access_disabled(self): self.assertEqual(model.slice_name, new_name) self.assertEqual(model.changed_by_url, "") - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = access_flag db.session.delete(model) db.session.commit() @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=True) def test_chart_activity_access_enabled(self): """ Chart API: Test ENABLE_BROAD_ACTIVITY_ACCESS = True """ - access_flag = app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = True admin = self.get_user("admin") birth_names_table_id = SupersetTestCase.get_table(name="birth_names").id chart_id = self.insert_chart("title", [admin.id], birth_names_table_id).id @@ -652,7 +650,6 @@ def test_chart_activity_access_enabled(self): self.assertEqual(model.slice_name, new_name) self.assertEqual(model.changed_by_url, "/superset/profile/admin") - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = access_flag db.session.delete(model) db.session.commit() diff --git a/tests/integration_tests/core_tests.py b/tests/integration_tests/core_tests.py index f0c72b068036b..577bcdf41783e 100644 --- a/tests/integration_tests/core_tests.py +++ b/tests/integration_tests/core_tests.py @@ -831,39 +831,36 @@ def test_user_profile(self, username="admin"): data = self.get_json_resp(endpoint) self.assertNotIn("message", data) - def test_user_profile_optional_access(self): + def test_user_profile_default_access(self): self.login(username="gamma") resp = self.client.get(f"/superset/profile/admin/") - self.assertEqual(resp.status_code, 200) - - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = False - resp = self.client.get(f"/superset/profile/admin/") self.assertEqual(resp.status_code, 403) - # Restore config - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = True + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=True) + def test_user_profile_broad_access(self): + self.login(username="gamma") + resp = self.client.get(f"/superset/profile/admin/") + self.assertEqual(resp.status_code, 200) @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") - def test_user_activity_access(self, username="gamma"): + def test_user_activity_default_access(self, username="gamma"): self.login(username=username) - # accessing own and other users' activity is allowed by default for user in ("admin", "gamma"): for endpoint in self._get_user_activity_endpoints(user): resp = self.client.get(endpoint) - assert resp.status_code == 200 + expected_status_code = 200 if user == username else 403 + assert resp.status_code == expected_status_code + + @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=True) + def test_user_activity_broad_access(self, username="gamma"): + self.login(username=username) - # disabling flag will block access to other users' activity data - access_flag = app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = False for user in ("admin", "gamma"): for endpoint in self._get_user_activity_endpoints(user): resp = self.client.get(endpoint) - expected_status_code = 200 if user == username else 403 - assert resp.status_code == expected_status_code - - # restore flag - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = access_flag + assert resp.status_code == 200 @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") def test_slice_id_is_always_logged_correctly_on_web_request(self): diff --git a/tests/integration_tests/dashboards/api_tests.py b/tests/integration_tests/dashboards/api_tests.py index 49a6bbecbc85f..40bb2584ee3e6 100644 --- a/tests/integration_tests/dashboards/api_tests.py +++ b/tests/integration_tests/dashboards/api_tests.py @@ -39,6 +39,7 @@ from superset.utils.core import backend, override_user from superset.views.base import generate_download_headers +from tests.integration_tests.conftest import with_feature_flags from tests.integration_tests.base_api_tests import ApiOwnersTestCaseMixin from tests.integration_tests.base_tests import SupersetTestCase from tests.integration_tests.fixtures.importexport import ( @@ -1405,12 +1406,11 @@ def test_update_dashboard(self): db.session.delete(model) db.session.commit() + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=False) def test_dashboard_activity_access_disabled(self): """ Dashboard API: Test ENABLE_BROAD_ACTIVITY_ACCESS = False """ - access_flag = app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = False admin = self.get_user("admin") admin_role = self.get_role("Admin") dashboard_id = self.insert_dashboard( @@ -1426,16 +1426,14 @@ def test_dashboard_activity_access_disabled(self): self.assertEqual(model.dashboard_title, "title2") self.assertEqual(model.changed_by_url, "") - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = access_flag db.session.delete(model) db.session.commit() + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=True) def test_dashboard_activity_access_enabled(self): """ Dashboard API: Test ENABLE_BROAD_ACTIVITY_ACCESS = True """ - access_flag = app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = True admin = self.get_user("admin") admin_role = self.get_role("Admin") dashboard_id = self.insert_dashboard( @@ -1451,7 +1449,6 @@ def test_dashboard_activity_access_enabled(self): self.assertEqual(model.dashboard_title, "title2") self.assertEqual(model.changed_by_url, "/superset/profile/admin") - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = access_flag db.session.delete(model) db.session.commit() diff --git a/tests/integration_tests/datasets/api_tests.py b/tests/integration_tests/datasets/api_tests.py index 6c99efd358c93..2fc873b46f33e 100644 --- a/tests/integration_tests/datasets/api_tests.py +++ b/tests/integration_tests/datasets/api_tests.py @@ -43,7 +43,7 @@ from superset.utils.database import get_example_database, get_main_database from superset.utils.dict_import_export import export_to_dict from tests.integration_tests.base_tests import SupersetTestCase -from tests.integration_tests.conftest import CTAS_SCHEMA_NAME +from tests.integration_tests.conftest import CTAS_SCHEMA_NAME, with_feature_flags from tests.integration_tests.fixtures.birth_names_dashboard import ( load_birth_names_dashboard_with_slices, load_birth_names_data, @@ -1358,6 +1358,7 @@ def test_dataset_get_no_username(self): db.session.delete(dataset) db.session.commit() + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=True) def test_dataset_activity_access_enabled(self): """ Dataset API: Test ENABLE_BROAD_ACTIVITY_ACCESS = True @@ -1365,8 +1366,6 @@ def test_dataset_activity_access_enabled(self): if backend() == "sqlite": return - access_flag = app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = True dataset = self.insert_default_dataset() self.login(username="admin") table_data = {"description": "changed_description"} @@ -1381,10 +1380,10 @@ def test_dataset_activity_access_enabled(self): self.assertEqual(current_dataset["description"], "changed_description") self.assertEqual(current_dataset["changed_by_url"], "/superset/profile/admin") - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = access_flag db.session.delete(dataset) db.session.commit() + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=False) def test_dataset_activity_access_disabled(self): """ Dataset API: Test ENABLE_BROAD_ACTIVITY_ACCESS = Fase @@ -1392,8 +1391,6 @@ def test_dataset_activity_access_disabled(self): if backend() == "sqlite": return - access_flag = app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = False dataset = self.insert_default_dataset() self.login(username="admin") table_data = {"description": "changed_description"} @@ -1408,7 +1405,6 @@ def test_dataset_activity_access_disabled(self): self.assertEqual(current_dataset["description"], "changed_description") self.assertEqual(current_dataset["changed_by_url"], "") - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = access_flag db.session.delete(dataset) db.session.commit() diff --git a/tests/integration_tests/log_api_tests.py b/tests/integration_tests/log_api_tests.py index 83a7f5fd84b31..2555354d5f437 100644 --- a/tests/integration_tests/log_api_tests.py +++ b/tests/integration_tests/log_api_tests.py @@ -28,9 +28,9 @@ from superset import db from superset.models.core import Log from superset.views.log.api import LogRestApi +from tests.integration_tests.conftest import with_feature_flags from tests.integration_tests.dashboard_utils import create_dashboard from tests.integration_tests.test_app import app - from .base_tests import SupersetTestCase @@ -159,6 +159,7 @@ def test_update_log(self): db.session.delete(log) db.session.commit() + @with_feature_flags(ENABLE_BROAD_ACTIVITY_ACCESS=False) def test_get_recent_activity_no_broad_access(self): """ Log API: Test recent activity not visible for other users without @@ -166,12 +167,10 @@ def test_get_recent_activity_no_broad_access(self): """ admin_user = self.get_user("admin") self.login(username="admin") - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = False uri = f"api/v1/log/recent_activity/{admin_user.id + 1}/" rv = self.client.get(uri) self.assertEqual(rv.status_code, 403) - app.config["ENABLE_BROAD_ACTIVITY_ACCESS"] = True def test_get_recent_activity(self): """ From 4ddd593c6d37795fd55337a6ced5e5d7f8cce54e Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Fri, 9 Jun 2023 12:08:36 -0300 Subject: [PATCH 2/4] UPDATING.md --- UPDATING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPDATING.md b/UPDATING.md index e2f45f6937bc3..f1cce60914ca5 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -33,6 +33,7 @@ assists people when migrating to a new version. ### Breaking Changes +- [24345](https://github.com/apache/superset/pull/24345) Converts `ENABLE_BROAD_ACTIVITY_ACCESS` and `MENU_HIDE_USER_INFO` into feature flags and changes the value of `ENABLE_BROAD_ACTIVITY_ACCESS` to `False` as it's more secure. - [24330](https://github.com/apache/superset/pull/24330) Removes `getUiOverrideRegistry` from `ExtensionsRegistry`. - [23933](https://github.com/apache/superset/pull/23933) Removes the deprecated Multiple Line Charts. - [23741](https://github.com/apache/superset/pull/23741) Migrates the TreeMap chart and removes the legacy Treemap code. From 4c106d0efd65c19dce5004c646664b4ee0fbe600 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Fri, 9 Jun 2023 13:02:21 -0300 Subject: [PATCH 3/4] Fixes lint problems --- superset-frontend/src/pages/ChartList/index.tsx | 3 --- superset-frontend/src/pages/DashboardList/index.tsx | 3 --- superset/connectors/sqla/models.py | 2 +- superset/models/dashboard.py | 1 - superset/models/filter_set.py | 1 - superset/models/slice.py | 1 - superset/security/manager.py | 3 ++- 7 files changed, 3 insertions(+), 11 deletions(-) diff --git a/superset-frontend/src/pages/ChartList/index.tsx b/superset-frontend/src/pages/ChartList/index.tsx index 9189e5d930435..dbdfcebff4ae8 100644 --- a/superset-frontend/src/pages/ChartList/index.tsx +++ b/superset-frontend/src/pages/ChartList/index.tsx @@ -68,7 +68,6 @@ import setupPlugins from 'src/setup/setupPlugins'; import InfoTooltip from 'src/components/InfoTooltip'; import CertifiedBadge from 'src/components/CertifiedBadge'; import { GenericLink } from 'src/components/GenericLink/GenericLink'; -import getBootstrapData from 'src/utils/getBootstrapData'; import Owner from 'src/types/Owner'; import { loadTags } from 'src/components/Tags/utils'; import ChartCard from 'src/features/charts/ChartCard'; @@ -156,8 +155,6 @@ const StyledActions = styled.div` color: ${({ theme }) => theme.colors.grayscale.base}; `; -const bootstrapData = getBootstrapData(); - function ChartList(props: ChartListProps) { const { addDangerToast, diff --git a/superset-frontend/src/pages/DashboardList/index.tsx b/superset-frontend/src/pages/DashboardList/index.tsx index 362e6e2c14c95..1808573bea03d 100644 --- a/superset-frontend/src/pages/DashboardList/index.tsx +++ b/superset-frontend/src/pages/DashboardList/index.tsx @@ -54,7 +54,6 @@ import Dashboard from 'src/dashboard/containers/Dashboard'; import { Dashboard as CRUDDashboard } from 'src/views/CRUD/types'; import CertifiedBadge from 'src/components/CertifiedBadge'; import { loadTags } from 'src/components/Tags/utils'; -import getBootstrapData from 'src/utils/getBootstrapData'; import DashboardCard from 'src/features/dashboards/DashboardCard'; import { DashboardStatus } from 'src/features/dashboards/types'; @@ -101,8 +100,6 @@ const Actions = styled.div` color: ${({ theme }) => theme.colors.grayscale.base}; `; -const bootstrapData = getBootstrapData(); - function DashboardList(props: DashboardListProps) { const { addDangerToast, diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index 20a382e80127b..9e62b305416ea 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -32,7 +32,7 @@ import pandas as pd import sqlalchemy as sa import sqlparse -from flask import current_app, escape, Markup +from flask import escape, Markup from flask_appbuilder import Model from flask_babel import lazy_gettext as _ from jinja2.exceptions import TemplateError diff --git a/superset/models/dashboard.py b/superset/models/dashboard.py index cdb0fd8a0de39..8d690d7914804 100644 --- a/superset/models/dashboard.py +++ b/superset/models/dashboard.py @@ -24,7 +24,6 @@ from typing import Any, Callable import sqlalchemy as sqla -from flask import current_app from flask_appbuilder import Model from flask_appbuilder.models.decorators import renders from flask_appbuilder.security.sqla.models import User diff --git a/superset/models/filter_set.py b/superset/models/filter_set.py index 2bc728c817f1d..096935f99baee 100644 --- a/superset/models/filter_set.py +++ b/superset/models/filter_set.py @@ -20,7 +20,6 @@ import logging from typing import Any -from flask import current_app from flask_appbuilder import Model from sqlalchemy import Column, ForeignKey, Integer, MetaData, String, Text from sqlalchemy.orm import relationship diff --git a/superset/models/slice.py b/superset/models/slice.py index 7754d745419ed..7cf8fec3f7fc3 100644 --- a/superset/models/slice.py +++ b/superset/models/slice.py @@ -22,7 +22,6 @@ from urllib import parse import sqlalchemy as sqla -from flask import current_app from flask_appbuilder import Model from flask_appbuilder.models.decorators import renders from markupsafe import escape, Markup diff --git a/superset/security/manager.py b/superset/security/manager.py index e5fc323a56799..e84d6b3781850 100644 --- a/superset/security/manager.py +++ b/superset/security/manager.py @@ -59,7 +59,6 @@ DatasetInvalidPermissionEvaluationException, SupersetSecurityException, ) -from superset.extensions import feature_flag_manager from superset.security.guest_token import ( GuestToken, GuestTokenResources, @@ -2005,6 +2004,8 @@ def get_rls_cache_key(self, datasource: "BaseDatasource") -> list[str]: @staticmethod def raise_for_user_activity_access(user_id: int) -> None: + from superset.extensions import feature_flag_manager + if not get_user_id() or ( not feature_flag_manager.is_feature_enabled("ENABLE_BROAD_ACTIVITY_ACCESS") and user_id != get_user_id() From 689338a948123f33ffdeaec586eaf1dc50234ee2 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Fri, 9 Jun 2023 14:26:29 -0300 Subject: [PATCH 4/4] Ignores pylint error --- superset/security/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/superset/security/manager.py b/superset/security/manager.py index e84d6b3781850..0a792aad8023e 100644 --- a/superset/security/manager.py +++ b/superset/security/manager.py @@ -2004,6 +2004,7 @@ def get_rls_cache_key(self, datasource: "BaseDatasource") -> list[str]: @staticmethod def raise_for_user_activity_access(user_id: int) -> None: + # pylint: disable=import-outside-toplevel from superset.extensions import feature_flag_manager if not get_user_id() or (