diff --git a/superset-frontend/src/components/ListView/types.ts b/superset-frontend/src/components/ListView/types.ts index f8bff90f0..a0f495385 100644 --- a/superset-frontend/src/components/ListView/types.ts +++ b/superset-frontend/src/components/ListView/types.ts @@ -114,4 +114,6 @@ export enum FilterOperator { chartIsCertified = 'chart_is_certified', dashboardIsCertified = 'dashboard_is_certified', datasetIsCertified = 'dataset_is_certified', + dashboardHasCreatedBy = 'dashboard_has_created_by', + chartHasCreatedBy = 'chart_has_created_by', } diff --git a/superset/charts/api.py b/superset/charts/api.py index 09cc7352b..8a111b005 100644 --- a/superset/charts/api.py +++ b/superset/charts/api.py @@ -52,6 +52,7 @@ from superset.charts.filters import ( ChartCertifiedFilter, ChartFavoriteFilter, ChartFilter, + ChartHasCreatedByFilter, ) from superset.charts.schemas import ( CHART_SCHEMAS, @@ -205,6 +206,7 @@ class ChartRestApi(BaseSupersetModelRestApi): search_filters = { "id": [ChartFavoriteFilter, ChartCertifiedFilter], "slice_name": [ChartAllTextFilter], + "created_by": [ChartHasCreatedByFilter], } # Will just affect _info endpoint diff --git a/superset/charts/filters.py b/superset/charts/filters.py index c60d28594..625184df1 100644 --- a/superset/charts/filters.py +++ b/superset/charts/filters.py @@ -93,3 +93,19 @@ class ChartFilter(BaseFilter): # pylint: disable=too-few-public-methods models.SqlaTable.id.in_(owner_ids_query), ) ) + + +class ChartHasCreatedByFilter(BaseFilter): # pylint: disable=too-few-public-methods + """ + Custom filter for the GET list that filters all charts created by user + """ + + name = _("Has created by") + arg_name = "chart_has_created_by" + + def apply(self, query: Query, value: Any) -> Query: + if value is True: + return query.filter(and_(Slice.created_by_fk.isnot(None))) + if value is False: + return query.filter(and_(Slice.created_by_fk.is_(None))) + return query diff --git a/superset/dashboards/api.py b/superset/dashboards/api.py index be523446a..9f440566c 100644 --- a/superset/dashboards/api.py +++ b/superset/dashboards/api.py @@ -60,6 +60,7 @@ from superset.dashboards.filters import ( DashboardCertifiedFilter, DashboardCreatedByMeFilter, DashboardFavoriteFilter, + DashboardHasCreatedByFilter, DashboardTitleOrSlugFilter, FilterRelatedRoles, ) @@ -218,7 +219,7 @@ class DashboardRestApi(BaseSupersetModelRestApi): search_filters = { "dashboard_title": [DashboardTitleOrSlugFilter], "id": [DashboardFavoriteFilter, DashboardCertifiedFilter], - "created_by": [DashboardCreatedByMeFilter], + "created_by": [DashboardCreatedByMeFilter, DashboardHasCreatedByFilter], } base_order = ("changed_on", "desc") diff --git a/superset/dashboards/filters.py b/superset/dashboards/filters.py index 8b4b8fe52..eaac724ac 100644 --- a/superset/dashboards/filters.py +++ b/superset/dashboards/filters.py @@ -156,7 +156,6 @@ class DashboardAccessFilter(BaseFilter): # pylint: disable=too-few-public-metho if is_feature_enabled("EMBEDDED_SUPERSET") and security_manager.is_guest_user( g.user ): - guest_user: GuestUser = g.user embedded_dashboard_ids = [ r["id"] @@ -233,3 +232,19 @@ class DashboardCertifiedFilter(BaseFilter): # pylint: disable=too-few-public-me ) ) return query + + +class DashboardHasCreatedByFilter(BaseFilter): # pylint: disable=too-few-public-methods + """ + Custom filter for the GET list that filters all dashboards created by user + """ + + name = _("Has created by") + arg_name = "dashboard_has_created_by" + + def apply(self, query: Query, value: Any) -> Query: + if value is True: + return query.filter(and_(Dashboard.created_by_fk.isnot(None))) + if value is False: + return query.filter(and_(Dashboard.created_by_fk.is_(None))) + return query diff --git a/tests/integration_tests/charts/api_tests.py b/tests/integration_tests/charts/api_tests.py index c3546f32b..c0aaaa2c7 100644 --- a/tests/integration_tests/charts/api_tests.py +++ b/tests/integration_tests/charts/api_tests.py @@ -1357,3 +1357,31 @@ class TestChartApi(SupersetTestCase, ApiOwnersTestCaseMixin, InsertChartMixin): } ] } + + def test_gets_created_by_user_charts_filter(self): + arguments = { + "filters": [{"col": "id", "opr": "chart_has_created_by", "value": True}], + "keys": ["none"], + "columns": ["slice_name"], + } + self.login(username="admin") + + uri = f"api/v1/chart/?q={prison.dumps(arguments)}" + rv = self.get_assert_metric(uri, "get_list") + self.assertEqual(rv.status_code, 200) + data = json.loads(rv.data.decode("utf-8")) + self.assertEqual(data["count"], 8) + + def test_gets_not_created_by_user_charts_filter(self): + arguments = { + "filters": [{"col": "id", "opr": "chart_has_created_by", "value": False}], + "keys": ["none"], + "columns": ["slice_name"], + } + self.login(username="admin") + + uri = f"api/v1/chart/?q={prison.dumps(arguments)}" + rv = self.get_assert_metric(uri, "get_list") + self.assertEqual(rv.status_code, 200) + data = json.loads(rv.data.decode("utf-8")) + self.assertEqual(data["count"], 8) diff --git a/tests/integration_tests/dashboards/api_tests.py b/tests/integration_tests/dashboards/api_tests.py index d9b35680c..2c050538b 100644 --- a/tests/integration_tests/dashboards/api_tests.py +++ b/tests/integration_tests/dashboards/api_tests.py @@ -1836,3 +1836,39 @@ class TestDashboardApi(SupersetTestCase, ApiOwnersTestCaseMixin, InsertChartMixi # get returns 404 resp = self.get_assert_metric(uri, "get_embedded") self.assertEqual(resp.status_code, 404) + + @pytest.mark.usefixtures("create_created_by_admin_dashboards") + def test_gets_created_by_user_dashboards_filter(self): + arguments = { + "filters": [ + {"col": "id", "opr": "dashboard_has_created_by", "value": True} + ], + "keys": ["none"], + "columns": ["dashboard_title"], + } + self.login(username="admin") + + uri = f"api/v1/dashboard/?q={prison.dumps(arguments)}" + rv = self.get_assert_metric(uri, "get_list") + self.assertEqual(rv.status_code, 200) + data = json.loads(rv.data.decode("utf-8")) + self.assertEqual(data["count"], 7) + + def test_gets_not_created_by_user_dashboards_filter(self): + arguments = { + "filters": [ + {"col": "id", "opr": "dashboard_has_created_by", "value": False} + ], + "keys": ["none"], + "columns": ["dashboard_title"], + } + dashboard = self.insert_dashboard(f"title", f"slug", []) + self.login(username="admin") + + uri = f"api/v1/dashboard/?q={prison.dumps(arguments)}" + rv = self.get_assert_metric(uri, "get_list") + self.assertEqual(rv.status_code, 200) + data = json.loads(rv.data.decode("utf-8")) + self.assertEqual(data["count"], 6) + db.session.delete(dashboard) + db.session.commit()