| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| """Unit tests for Superset""" |
| from unittest import mock |
| |
| import pytest |
| |
| from tests.dashboards.dashboard_test_utils import * |
| from tests.dashboards.security.base_case import BaseTestDashboardSecurity |
| from tests.dashboards.superset_factory_util import ( |
| create_dashboard_to_db, |
| create_database_to_db, |
| create_datasource_table_to_db, |
| create_slice_to_db, |
| ) |
| from tests.fixtures.public_role import public_role_like_gamma |
| |
| |
| @mock.patch.dict( |
| "superset.extensions.feature_flag_manager._feature_flags", DASHBOARD_RBAC=True, |
| ) |
| class TestDashboardRoleBasedSecurity(BaseTestDashboardSecurity): |
| def test_get_dashboard_view__admin_can_access(self): |
| # arrange |
| dashboard_to_access = create_dashboard_to_db( |
| owners=[], slices=[create_slice_to_db()], published=False |
| ) |
| self.login("admin") |
| |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert_dashboard_view_response(response, dashboard_to_access) |
| |
| def test_get_dashboard_view__owner_can_access(self): |
| # arrange |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| owner = self.create_user_with_roles( |
| username, [new_role], should_create_roles=True |
| ) |
| dashboard_to_access = create_dashboard_to_db( |
| owners=[owner], slices=[create_slice_to_db()], published=False |
| ) |
| self.login(username) |
| |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert_dashboard_view_response(response, dashboard_to_access) |
| |
| def test_get_dashboard_view__user_can_not_access_without_permission(self): |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| self.create_user_with_roles(username, [new_role], should_create_roles=True) |
| dashboard_to_access = create_dashboard_to_db(published=True) |
| self.login(username) |
| |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert403(response) |
| |
| def test_get_dashboard_view__user_with_dashboard_permission_can_not_access_draft( |
| self, |
| ): |
| # arrange |
| dashboard_to_access = create_dashboard_to_db(published=False) |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| self.create_user_with_roles(username, [new_role], should_create_roles=True) |
| grant_access_to_dashboard(dashboard_to_access, new_role) |
| self.login(username) |
| |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert403(response) |
| |
| # post |
| revoke_access_to_dashboard(dashboard_to_access, new_role) |
| |
| def test_get_dashboard_view__user_access_with_dashboard_permission(self): |
| # arrange |
| |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| self.create_user_with_roles(username, [new_role], should_create_roles=True) |
| |
| dashboard_to_access = create_dashboard_to_db( |
| published=True, slices=[create_slice_to_db()] |
| ) |
| self.login(username) |
| grant_access_to_dashboard(dashboard_to_access, new_role) |
| |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert_dashboard_view_response(response, dashboard_to_access) |
| |
| # post |
| revoke_access_to_dashboard(dashboard_to_access, new_role) |
| |
| @pytest.mark.usefixtures("public_role_like_gamma") |
| def test_get_dashboard_view__public_user_can_not_access_without_permission(self): |
| dashboard_to_access = create_dashboard_to_db(published=True) |
| self.logout() |
| |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert403(response) |
| |
| @pytest.mark.usefixtures("public_role_like_gamma") |
| def test_get_dashboard_view__public_user_with_dashboard_permission_can_not_access_draft( |
| self, |
| ): |
| # arrange |
| dashboard_to_access = create_dashboard_to_db(published=False) |
| grant_access_to_dashboard(dashboard_to_access, "Public") |
| self.logout() |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert403(response) |
| |
| # post |
| revoke_access_to_dashboard(dashboard_to_access, "Public") |
| |
| @pytest.mark.usefixtures("public_role_like_gamma") |
| def test_get_dashboard_view__public_user_access_with_dashboard_permission(self): |
| # arrange |
| dashboard_to_access = create_dashboard_to_db( |
| published=True, slices=[create_slice_to_db()] |
| ) |
| grant_access_to_dashboard(dashboard_to_access, "Public") |
| |
| self.logout() |
| |
| # act |
| response = self.get_dashboard_view_response(dashboard_to_access) |
| |
| # assert |
| self.assert_dashboard_view_response(response, dashboard_to_access) |
| |
| # post |
| revoke_access_to_dashboard(dashboard_to_access, "Public") |
| |
| def test_get_dashboards_list__admin_get_all_dashboards(self): |
| # arrange |
| create_dashboard_to_db( |
| owners=[], slices=[create_slice_to_db()], published=False |
| ) |
| dashboard_counts = count_dashboards() |
| |
| self.login("admin") |
| |
| # act |
| response = self.get_dashboards_list_response() |
| |
| # assert |
| self.assert_dashboards_list_view_response(response, dashboard_counts) |
| |
| def test_get_dashboards_list__owner_get_all_owned_dashboards(self): |
| # arrange |
| ( |
| not_owned_dashboards, |
| owned_dashboards, |
| ) = self._create_sample_dashboards_with_owner_access() |
| |
| # act |
| response = self.get_dashboards_list_response() |
| |
| # assert |
| self.assert_dashboards_list_view_response( |
| response, 2, owned_dashboards, not_owned_dashboards |
| ) |
| |
| def _create_sample_dashboards_with_owner_access(self): |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| owner = self.create_user_with_roles( |
| username, [new_role], should_create_roles=True |
| ) |
| database = create_database_to_db() |
| table = create_datasource_table_to_db(db_id=database.id, owners=[owner]) |
| first_dash = create_dashboard_to_db( |
| owners=[owner], slices=[create_slice_to_db(datasource_id=table.id)] |
| ) |
| second_dash = create_dashboard_to_db( |
| owners=[owner], slices=[create_slice_to_db(datasource_id=table.id)] |
| ) |
| owned_dashboards = [first_dash, second_dash] |
| not_owned_dashboards = [ |
| create_dashboard_to_db( |
| slices=[create_slice_to_db(datasource_id=table.id)], published=True |
| ) |
| ] |
| self.login(username) |
| return not_owned_dashboards, owned_dashboards |
| |
| def test_get_dashboards_list__user_without_any_permissions_get_empty_list(self): |
| |
| # arrange |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| self.create_user_with_roles(username, [new_role], should_create_roles=True) |
| |
| create_dashboard_to_db(published=True) |
| self.login(username) |
| |
| # act |
| response = self.get_dashboards_list_response() |
| |
| # assert |
| self.assert_dashboards_list_view_response(response, 0) |
| |
| def test_get_dashboards_list__user_get_only_published_permitted_dashboards(self): |
| # arrange |
| ( |
| new_role, |
| draft_dashboards, |
| published_dashboards, |
| ) = self._create_sample_only_published_dashboard_with_roles() |
| |
| # act |
| response = self.get_dashboards_list_response() |
| |
| # assert |
| self.assert_dashboards_list_view_response( |
| response, len(published_dashboards), published_dashboards, draft_dashboards, |
| ) |
| |
| # post |
| for dash in published_dashboards + draft_dashboards: |
| revoke_access_to_dashboard(dash, new_role) |
| |
| def _create_sample_only_published_dashboard_with_roles(self): |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| self.create_user_with_roles(username, [new_role], should_create_roles=True) |
| published_dashboards = [ |
| create_dashboard_to_db(published=True), |
| create_dashboard_to_db(published=True), |
| ] |
| draft_dashboards = [ |
| create_dashboard_to_db(published=False), |
| create_dashboard_to_db(published=False), |
| ] |
| for dash in published_dashboards + draft_dashboards: |
| grant_access_to_dashboard(dash, new_role) |
| self.login(username) |
| return new_role, draft_dashboards, published_dashboards |
| |
| @pytest.mark.usefixtures("public_role_like_gamma") |
| def test_get_dashboards_list__public_user_without_any_permissions_get_empty_list( |
| self, |
| ): |
| create_dashboard_to_db(published=True) |
| |
| # act |
| response = self.get_dashboards_list_response() |
| |
| # assert |
| self.assert_dashboards_list_view_response(response, 0) |
| |
| @pytest.mark.usefixtures("public_role_like_gamma") |
| def test_get_dashboards_list__public_user_get_only_published_permitted_dashboards( |
| self, |
| ): |
| # arrange |
| published_dashboards = [ |
| create_dashboard_to_db(published=True), |
| create_dashboard_to_db(published=True), |
| ] |
| draft_dashboards = [ |
| create_dashboard_to_db(published=False), |
| create_dashboard_to_db(published=False), |
| ] |
| |
| for dash in published_dashboards + draft_dashboards: |
| grant_access_to_dashboard(dash, "Public") |
| |
| self.logout() |
| |
| # act |
| response = self.get_dashboards_list_response() |
| |
| # assert |
| self.assert_dashboards_list_view_response( |
| response, len(published_dashboards), published_dashboards, draft_dashboards, |
| ) |
| |
| # post |
| for dash in published_dashboards + draft_dashboards: |
| revoke_access_to_dashboard(dash, "Public") |
| |
| def test_get_dashboards_api__admin_get_all_dashboards(self): |
| # arrange |
| create_dashboard_to_db( |
| owners=[], slices=[create_slice_to_db()], published=False |
| ) |
| dashboard_counts = count_dashboards() |
| |
| self.login("admin") |
| |
| # act |
| response = self.get_dashboards_api_response() |
| |
| # assert |
| self.assert_dashboards_api_response(response, dashboard_counts) |
| |
| def test_get_dashboards_api__owner_get_all_owned_dashboards(self): |
| # arrange |
| ( |
| not_owned_dashboards, |
| owned_dashboards, |
| ) = self._create_sample_dashboards_with_owner_access() |
| |
| # act |
| response = self.get_dashboards_api_response() |
| |
| # assert |
| self.assert_dashboards_api_response( |
| response, 2, owned_dashboards, not_owned_dashboards |
| ) |
| |
| def test_get_dashboards_api__user_without_any_permissions_get_empty_list(self): |
| username = random_str() |
| new_role = f"role_{random_str()}" |
| self.create_user_with_roles(username, [new_role], should_create_roles=True) |
| create_dashboard_to_db(published=True) |
| self.login(username) |
| |
| # act |
| response = self.get_dashboards_api_response() |
| |
| # assert |
| self.assert_dashboards_api_response(response, 0) |
| |
| def test_get_dashboards_api__user_get_only_published_permitted_dashboards(self): |
| ( |
| new_role, |
| draft_dashboards, |
| published_dashboards, |
| ) = self._create_sample_only_published_dashboard_with_roles() |
| |
| # act |
| response = self.get_dashboards_api_response() |
| |
| # assert |
| self.assert_dashboards_api_response( |
| response, len(published_dashboards), published_dashboards, draft_dashboards, |
| ) |
| |
| # post |
| for dash in published_dashboards + draft_dashboards: |
| revoke_access_to_dashboard(dash, new_role) |
| |
| @pytest.mark.usefixtures("public_role_like_gamma") |
| def test_get_dashboards_api__public_user_without_any_permissions_get_empty_list( |
| self, |
| ): |
| create_dashboard_to_db(published=True) |
| self.logout() |
| |
| # act |
| response = self.get_dashboards_api_response() |
| |
| # assert |
| self.assert_dashboards_api_response(response, 0) |
| |
| @pytest.mark.usefixtures("public_role_like_gamma") |
| def test_get_dashboards_api__public_user_get_only_published_permitted_dashboards( |
| self, |
| ): |
| # arrange |
| published_dashboards = [ |
| create_dashboard_to_db(published=True), |
| create_dashboard_to_db(published=True), |
| ] |
| draft_dashboards = [ |
| create_dashboard_to_db(published=False), |
| create_dashboard_to_db(published=False), |
| ] |
| |
| for dash in published_dashboards + draft_dashboards: |
| grant_access_to_dashboard(dash, "Public") |
| |
| self.logout() |
| |
| # act |
| response = self.get_dashboards_api_response() |
| |
| # assert |
| self.assert_dashboards_api_response( |
| response, len(published_dashboards), published_dashboards, draft_dashboards, |
| ) |
| |
| # post |
| for dash in published_dashboards + draft_dashboards: |
| revoke_access_to_dashboard(dash, "Public") |