This is an automated email from the ASF dual-hosted git repository. michaelsmolina pushed a commit to branch 5.0 in repository https://gitbox.apache.org/repos/asf/superset.git
commit 2c6cdfe7ad3caa491ba8353dcb11f9cad371e00c Author: Luke Hart <[email protected]> AuthorDate: Fri Mar 28 06:01:14 2025 +1300 fix: use role_model from security manager (#32873) (cherry picked from commit 103fedaf922292567d7082f3febe24d46b1516d3) --- superset/security/manager.py | 4 +- tests/unit_tests/commands/dashboard/__init__.py | 16 ++++ tests/unit_tests/commands/dashboard/create_test.py | 98 ++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/superset/security/manager.py b/superset/security/manager.py index 450265ccb9..a48aadb5fe 100644 --- a/superset/security/manager.py +++ b/superset/security/manager.py @@ -1110,7 +1110,9 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods """ Find a List of models by a list of ids, if defined applies `base_filter` """ - query = self.get_session.query(Role).filter(Role.id.in_(role_ids)) + query = self.get_session.query(self.role_model).filter( + self.role_model.id.in_(role_ids) + ) return query.all() def copy_role( diff --git a/tests/unit_tests/commands/dashboard/__init__.py b/tests/unit_tests/commands/dashboard/__init__.py new file mode 100644 index 0000000000..13a83393a9 --- /dev/null +++ b/tests/unit_tests/commands/dashboard/__init__.py @@ -0,0 +1,16 @@ +# 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. diff --git a/tests/unit_tests/commands/dashboard/create_test.py b/tests/unit_tests/commands/dashboard/create_test.py new file mode 100644 index 0000000000..9bb0cff9ab --- /dev/null +++ b/tests/unit_tests/commands/dashboard/create_test.py @@ -0,0 +1,98 @@ +# 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. +from __future__ import annotations + +import pytest +from flask_appbuilder.security.sqla.models import Role, User +from pytest_mock import MockerFixture + +from superset.commands.dashboard.create import CreateDashboardCommand +from superset.extensions import security_manager +from tests.unit_tests.fixtures.common import admin_user, after_each # noqa: F401 + + +def test_validate_custom_role_class( + mocker: MockerFixture, + monkeypatch: pytest.MonkeyPatch, + admin_user: User, # noqa: F811 + after_each: None, # noqa: F811 +) -> None: + class CustomRoleModel(Role): + __tablename__ = "ab_role" + + monkeypatch.setattr(security_manager, "role_model", CustomRoleModel) + mocker.patch.object(security_manager, "is_admin", return_value=True) + + owner_ids = [admin_user.id] + role_ids = [role.id for role in admin_user.roles] + + command = CreateDashboardCommand(data={"owners": owner_ids, "roles": role_ids}) + command.validate() + + for role in command._properties["roles"]: + assert isinstance(role, CustomRoleModel) + + +def test_validate_custom_user_class( + mocker: MockerFixture, + monkeypatch: pytest.MonkeyPatch, + admin_user: User, # noqa: F811 + after_each: None, # noqa: F811 +) -> None: + class CustomUserModel(User): + __tablename__ = "ab_user" + + monkeypatch.setattr(security_manager, "user_model", CustomUserModel) + mocker.patch.object(security_manager, "is_admin", return_value=True) + + owner_ids = [admin_user.id] + role_ids = [role.id for role in admin_user.roles] + + command = CreateDashboardCommand(data={"owners": owner_ids, "roles": role_ids}) + command.validate() + + for owner in command._properties["owners"]: + assert isinstance(owner, CustomUserModel) + + +def test_validate_custom_role_and_user_class( + mocker: MockerFixture, + monkeypatch: pytest.MonkeyPatch, + admin_user: User, # noqa: F811 + after_each: None, # noqa: F811 +) -> None: + class CustomRoleModel(Role): + __tablename__ = "ab_role" + + class CustomUserModel(User): + __tablename__ = "ab_user" + + monkeypatch.setattr(security_manager, "role_model", CustomRoleModel) + monkeypatch.setattr(security_manager, "user_model", CustomUserModel) + mocker.patch.object(security_manager, "is_admin", return_value=True) + + owner_ids = [admin_user.id] + role_ids = [role.id for role in admin_user.roles] + + command = CreateDashboardCommand(data={"owners": owner_ids, "roles": role_ids}) + command.validate() + + for role in command._properties["roles"]: + assert isinstance(role, CustomRoleModel) + + for owner in command._properties["owners"]: + assert isinstance(owner, CustomUserModel)
