chore: replace selenium user with fixed user (#31844)

This commit is contained in:
Ville Brofeldt
2025-01-22 12:46:06 -08:00
committed by GitHub
parent 1d6423e71f
commit 7482b20f7b
25 changed files with 304 additions and 215 deletions

View File

@@ -26,7 +26,7 @@ from pytest_mock import MockerFixture
from superset.commands.report.exceptions import AlertQueryError
from superset.reports.models import ReportCreationMethod, ReportScheduleType
from superset.tasks.types import ExecutorType
from superset.tasks.types import ExecutorType, FixedExecutor
from superset.utils.database import get_example_database
from tests.integration_tests.test_app import app
@@ -34,7 +34,7 @@ from tests.integration_tests.test_app import app
@pytest.mark.parametrize(
"owner_names,creator_name,config,expected_result",
[
(["gamma"], None, [ExecutorType.SELENIUM], "admin"),
(["gamma"], None, [FixedExecutor("admin")], "admin"),
(["gamma"], None, [ExecutorType.OWNER], "gamma"),
(
["alpha", "gamma"],
@@ -69,8 +69,8 @@ def test_execute_query_as_report_executor(
from superset.commands.report.alert import AlertCommand
from superset.reports.models import ReportSchedule
original_config = app.config["ALERT_REPORTS_EXECUTE_AS"]
app.config["ALERT_REPORTS_EXECUTE_AS"] = config
original_config = app.config["ALERT_REPORTS_EXECUTORS"]
app.config["ALERT_REPORTS_EXECUTORS"] = config
owners = [get_user(owner_name) for owner_name in owner_names]
report_schedule = ReportSchedule(
created_by=get_user(creator_name) if creator_name else None,
@@ -96,7 +96,7 @@ def test_execute_query_as_report_executor(
command.run()
assert override_user_mock.call_args[0][0].username == expected_result
app.config["ALERT_REPORTS_EXECUTE_AS"] = original_config
app.config["ALERT_REPORTS_EXECUTORS"] = original_config
def test_execute_query_mutate_query_enabled(
@@ -278,7 +278,7 @@ def test_get_alert_metadata_from_object(
from superset.commands.report.alert import AlertCommand
from superset.reports.models import ReportSchedule
app.config["ALERT_REPORTS_EXECUTE_AS"] = [ExecutorType.OWNER]
app.config["ALERT_REPORTS_EXECUTORS"] = [ExecutorType.OWNER]
mock_database = mocker.MagicMock()
mock_exec_id = uuid.uuid4()

View File

@@ -773,7 +773,7 @@ def test_email_chart_report_schedule_alpha_owner(
ExecuteReport Command: Test chart email report schedule with screenshot
executed as the chart owner
"""
config_key = "ALERT_REPORTS_EXECUTE_AS"
config_key = "ALERT_REPORTS_EXECUTORS"
original_config_value = app.config[config_key]
app.config[config_key] = [ExecutorType.OWNER]

View File

@@ -82,11 +82,15 @@ class TestCacheWarmUp(SupersetTestCase):
self.client.get(f"/superset/dashboard/{dash.id}/")
strategy = TopNDashboardsStrategy(1)
result = strategy.get_payloads()
result = strategy.get_tasks()
expected = [
{"chart_id": chart.id, "dashboard_id": dash.id} for chart in dash.slices
{
"payload": {"chart_id": chart.id, "dashboard_id": dash.id},
"username": "admin",
}
for chart in dash.slices
]
self.assertCountEqual(result, expected) # noqa: PT009
assert len(result) == len(expected)
def reset_tag(self, tag):
"""Remove associated object from tag, used to reset tests"""
@@ -104,34 +108,30 @@ class TestCacheWarmUp(SupersetTestCase):
self.reset_tag(tag1)
strategy = DashboardTagsStrategy(["tag1"])
result = strategy.get_payloads()
expected = []
assert result == expected
assert strategy.get_tasks() == []
# tag dashboard 'births' with `tag1`
tag1 = get_tag("tag1", db.session, TagType.custom)
dash = self.get_dash_by_slug("births")
tag1_urls = [{"chart_id": chart.id} for chart in dash.slices]
tag1_payloads = [{"chart_id": chart.id} for chart in dash.slices]
tagged_object = TaggedObject(
tag_id=tag1.id, object_id=dash.id, object_type=ObjectType.dashboard
)
db.session.add(tagged_object)
db.session.commit()
self.assertCountEqual(strategy.get_payloads(), tag1_urls) # noqa: PT009
assert len(strategy.get_tasks()) == len(tag1_payloads)
strategy = DashboardTagsStrategy(["tag2"])
tag2 = get_tag("tag2", db.session, TagType.custom)
self.reset_tag(tag2)
result = strategy.get_payloads()
expected = []
assert result == expected
assert strategy.get_tasks() == []
# tag first slice
dash = self.get_dash_by_slug("unicode-test")
chart = dash.slices[0]
tag2_urls = [{"chart_id": chart.id}]
tag2_payloads = [{"chart_id": chart.id}]
object_id = chart.id
tagged_object = TaggedObject(
tag_id=tag2.id, object_id=object_id, object_type=ObjectType.chart
@@ -139,11 +139,8 @@ class TestCacheWarmUp(SupersetTestCase):
db.session.add(tagged_object)
db.session.commit()
result = strategy.get_payloads()
self.assertCountEqual(result, tag2_urls) # noqa: PT009
assert len(strategy.get_tasks()) == len(tag2_payloads)
strategy = DashboardTagsStrategy(["tag1", "tag2"])
result = strategy.get_payloads()
expected = tag1_urls + tag2_urls
self.assertCountEqual(result, expected) # noqa: PT009
assert len(strategy.get_tasks()) == len(tag1_payloads + tag2_payloads)

View File

@@ -30,7 +30,7 @@ from superset import db, is_feature_enabled, security_manager
from superset.extensions import machine_auth_provider_factory
from superset.models.dashboard import Dashboard
from superset.models.slice import Slice
from superset.tasks.types import ExecutorType
from superset.tasks.types import ExecutorType, FixedExecutor
from superset.utils import json
from superset.utils.screenshots import ChartScreenshot, DashboardScreenshot
from superset.utils.urls import get_url_path
@@ -53,8 +53,8 @@ class TestThumbnailsSeleniumLive(LiveServerTestCase):
return app
def url_open_auth(self, username: str, url: str):
admin_user = security_manager.find_user(username=username)
cookies = machine_auth_provider_factory.instance.get_auth_cookies(admin_user)
user = security_manager.find_user(username=username)
cookies = machine_auth_provider_factory.instance.get_auth_cookies(user)
opener = urllib.request.build_opener()
opener.addheaders.append(("Cookie", f"session={cookies['session']}"))
return opener.open(f"{self.get_server_url()}/{url}")
@@ -70,7 +70,7 @@ class TestThumbnailsSeleniumLive(LiveServerTestCase):
thumbnail_url = resp["result"][0]["thumbnail_url"]
response = self.url_open_auth(
"admin",
ADMIN_USERNAME,
thumbnail_url,
)
assert response.getcode() == 202
@@ -84,9 +84,7 @@ class TestWebDriverScreenshotErrorDetector(SupersetTestCase):
self, mock_find_unexpected_errors, mock_firefox, mock_webdriver_wait
):
webdriver_proxy = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(
app.config["THUMBNAIL_SELENIUM_USER"]
)
user = security_manager.get_user_by_username(ADMIN_USERNAME)
url = get_url_path("Superset.dashboard", dashboard_id_or_slug=1)
webdriver_proxy.get_screenshot(url, "grid-container", user=user)
@@ -100,9 +98,7 @@ class TestWebDriverScreenshotErrorDetector(SupersetTestCase):
):
app.config["SCREENSHOT_REPLACE_UNEXPECTED_ERRORS"] = True
webdriver_proxy = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(
app.config["THUMBNAIL_SELENIUM_USER"]
)
user = security_manager.get_user_by_username(ADMIN_USERNAME)
url = get_url_path("Superset.dashboard", dashboard_id_or_slug=1)
webdriver_proxy.get_screenshot(url, "grid-container", user=user)
@@ -149,9 +145,7 @@ class TestWebDriverSelenium(SupersetTestCase):
self, mock_sleep, mock_webdriver, mock_webdriver_wait
):
webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(
app.config["THUMBNAIL_SELENIUM_USER"]
)
user = security_manager.get_user_by_username(ADMIN_USERNAME)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
app.config["SCREENSHOT_SELENIUM_HEADSTART"] = 5
webdriver.get_screenshot(url, "chart-container", user=user)
@@ -162,9 +156,7 @@ class TestWebDriverSelenium(SupersetTestCase):
def test_screenshot_selenium_locate_wait(self, mock_webdriver, mock_webdriver_wait):
app.config["SCREENSHOT_LOCATE_WAIT"] = 15
webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(
app.config["THUMBNAIL_SELENIUM_USER"]
)
user = security_manager.get_user_by_username(ADMIN_USERNAME)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
webdriver.get_screenshot(url, "chart-container", user=user)
assert mock_webdriver_wait.call_args_list[0] == call(ANY, 15)
@@ -174,9 +166,7 @@ class TestWebDriverSelenium(SupersetTestCase):
def test_screenshot_selenium_load_wait(self, mock_webdriver, mock_webdriver_wait):
app.config["SCREENSHOT_LOAD_WAIT"] = 15
webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(
app.config["THUMBNAIL_SELENIUM_USER"]
)
user = security_manager.get_user_by_username(ADMIN_USERNAME)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
webdriver.get_screenshot(url, "chart-container", user=user)
assert mock_webdriver_wait.call_args_list[2] == call(ANY, 15)
@@ -188,9 +178,7 @@ class TestWebDriverSelenium(SupersetTestCase):
self, mock_sleep, mock_webdriver, mock_webdriver_wait
):
webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(
app.config["THUMBNAIL_SELENIUM_USER"]
)
user = security_manager.get_user_by_username(ADMIN_USERNAME)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
app.config["SCREENSHOT_SELENIUM_ANIMATION_WAIT"] = 4
webdriver.get_screenshot(url, "chart-container", user=user)
@@ -232,7 +220,7 @@ class TestThumbnails(SupersetTestCase):
@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
@with_feature_flags(THUMBNAILS=True)
def test_get_async_dashboard_screenshot_as_selenium(self):
def test_get_async_dashboard_screenshot_as_fixed_user(self):
"""
Thumbnails: Simple get async dashboard screenshot as selenium user
"""
@@ -241,7 +229,7 @@ class TestThumbnails(SupersetTestCase):
patch.dict(
"superset.thumbnails.digest.current_app.config",
{
"THUMBNAIL_EXECUTE_AS": [ExecutorType.SELENIUM],
"THUMBNAIL_EXECUTORS": [FixedExecutor(ADMIN_USERNAME)],
},
),
patch(
@@ -251,8 +239,8 @@ class TestThumbnails(SupersetTestCase):
mock_adjust_string.return_value = self.digest_return_value
_, thumbnail_url = self._get_id_and_thumbnail_url(DASHBOARD_URL)
assert self.digest_hash in thumbnail_url
assert mock_adjust_string.call_args[0][1] == ExecutorType.SELENIUM
assert mock_adjust_string.call_args[0][2] == "admin"
assert mock_adjust_string.call_args[0][1] == ExecutorType.FIXED_USER
assert mock_adjust_string.call_args[0][2] == ADMIN_USERNAME
rv = self.client.get(thumbnail_url)
assert rv.status_code == 202
@@ -269,7 +257,7 @@ class TestThumbnails(SupersetTestCase):
patch.dict(
"superset.thumbnails.digest.current_app.config",
{
"THUMBNAIL_EXECUTE_AS": [ExecutorType.CURRENT_USER],
"THUMBNAIL_EXECUTORS": [ExecutorType.CURRENT_USER],
},
),
patch(
@@ -310,7 +298,7 @@ class TestThumbnails(SupersetTestCase):
@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
@with_feature_flags(THUMBNAILS=True)
def test_get_async_chart_screenshot_as_selenium(self):
def test_get_async_chart_screenshot_as_fixed_user(self):
"""
Thumbnails: Simple get async chart screenshot as selenium user
"""
@@ -319,7 +307,7 @@ class TestThumbnails(SupersetTestCase):
patch.dict(
"superset.thumbnails.digest.current_app.config",
{
"THUMBNAIL_EXECUTE_AS": [ExecutorType.SELENIUM],
"THUMBNAIL_EXECUTORS": [FixedExecutor(ADMIN_USERNAME)],
},
),
patch(
@@ -329,8 +317,8 @@ class TestThumbnails(SupersetTestCase):
mock_adjust_string.return_value = self.digest_return_value
_, thumbnail_url = self._get_id_and_thumbnail_url(CHART_URL)
assert self.digest_hash in thumbnail_url
assert mock_adjust_string.call_args[0][1] == ExecutorType.SELENIUM
assert mock_adjust_string.call_args[0][2] == "admin"
assert mock_adjust_string.call_args[0][1] == ExecutorType.FIXED_USER
assert mock_adjust_string.call_args[0][2] == ADMIN_USERNAME
rv = self.client.get(thumbnail_url)
assert rv.status_code == 202
@@ -347,7 +335,7 @@ class TestThumbnails(SupersetTestCase):
patch.dict(
"superset.thumbnails.digest.current_app.config",
{
"THUMBNAIL_EXECUTE_AS": [ExecutorType.CURRENT_USER],
"THUMBNAIL_EXECUTORS": [ExecutorType.CURRENT_USER],
},
),
patch(

View File

@@ -23,11 +23,11 @@ from typing import Any, Optional, Union
import pytest
from flask_appbuilder.security.sqla.models import User
from superset.tasks.exceptions import ExecutorNotFoundError
from superset.tasks.types import ExecutorType
from superset.tasks.exceptions import ExecutorNotFoundError, InvalidExecutorError
from superset.tasks.types import Executor, ExecutorType, FixedExecutor
SELENIUM_USER_ID = 1234
SELENIUM_USERNAME = "admin"
FIXED_USER_ID = 1234
FIXED_USERNAME = "admin"
def _get_users(
@@ -54,18 +54,18 @@ class ModelType(int, Enum):
@pytest.mark.parametrize(
"model_type,executor_types,model_config,current_user,expected_result",
"model_type,executors,model_config,current_user,expected_result",
[
(
ModelType.REPORT_SCHEDULE,
[ExecutorType.SELENIUM],
[FixedExecutor(FIXED_USERNAME)],
ModelConfig(
owners=[1, 2],
creator=3,
modifier=4,
),
None,
(ExecutorType.SELENIUM, SELENIUM_USER_ID),
(ExecutorType.FIXED_USER, FIXED_USER_ID),
),
(
ModelType.REPORT_SCHEDULE,
@@ -75,11 +75,11 @@ class ModelType(int, Enum):
ExecutorType.OWNER,
ExecutorType.MODIFIER,
ExecutorType.MODIFIER_OWNER,
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[]),
None,
(ExecutorType.SELENIUM, SELENIUM_USER_ID),
(ExecutorType.FIXED_USER, FIXED_USER_ID),
),
(
ModelType.REPORT_SCHEDULE,
@@ -89,7 +89,7 @@ class ModelType(int, Enum):
ExecutorType.OWNER,
ExecutorType.MODIFIER,
ExecutorType.MODIFIER_OWNER,
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[], modifier=1),
None,
@@ -103,7 +103,7 @@ class ModelType(int, Enum):
ExecutorType.OWNER,
ExecutorType.MODIFIER,
ExecutorType.MODIFIER_OWNER,
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[2], modifier=1),
None,
@@ -117,7 +117,7 @@ class ModelType(int, Enum):
ExecutorType.OWNER,
ExecutorType.MODIFIER,
ExecutorType.MODIFIER_OWNER,
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[2], creator=3, modifier=1),
None,
@@ -198,11 +198,11 @@ class ModelType(int, Enum):
(
ModelType.DASHBOARD,
[
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[1], creator=2, modifier=3),
4,
(ExecutorType.SELENIUM, SELENIUM_USER_ID),
(ExecutorType.FIXED_USER, FIXED_USER_ID),
),
(
ModelType.DASHBOARD,
@@ -219,11 +219,11 @@ class ModelType(int, Enum):
ExecutorType.CREATOR_OWNER,
ExecutorType.MODIFIER_OWNER,
ExecutorType.CURRENT_USER,
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[1], creator=2, modifier=3),
None,
(ExecutorType.SELENIUM, SELENIUM_USER_ID),
(ExecutorType.FIXED_USER, FIXED_USER_ID),
),
(
ModelType.CHART,
@@ -237,11 +237,11 @@ class ModelType(int, Enum):
(
ModelType.CHART,
[
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[1], creator=2, modifier=3),
4,
(ExecutorType.SELENIUM, SELENIUM_USER_ID),
(ExecutorType.FIXED_USER, FIXED_USER_ID),
),
(
ModelType.CHART,
@@ -252,26 +252,35 @@ class ModelType(int, Enum):
None,
ExecutorNotFoundError(),
),
(
ModelType.CHART,
[
ExecutorType.FIXED_USER,
],
ModelConfig(owners=[]),
None,
InvalidExecutorError(),
),
(
ModelType.CHART,
[
ExecutorType.CREATOR_OWNER,
ExecutorType.MODIFIER_OWNER,
ExecutorType.CURRENT_USER,
ExecutorType.SELENIUM,
FixedExecutor(FIXED_USERNAME),
],
ModelConfig(owners=[1], creator=2, modifier=3),
None,
(ExecutorType.SELENIUM, SELENIUM_USER_ID),
(ExecutorType.FIXED_USER, FIXED_USER_ID),
),
],
)
def test_get_executor(
model_type: ModelType,
executor_types: list[ExecutorType],
executors: list[Executor],
model_config: ModelConfig,
current_user: Optional[int],
expected_result: tuple[int, ExecutorNotFoundError],
expected_result: tuple[ExecutorType, int] | Exception,
) -> None:
from superset.models.dashboard import Dashboard
from superset.models.slice import Slice
@@ -308,14 +317,14 @@ def test_get_executor(
cm = nullcontext()
expected_executor_type = expected_result[0]
expected_executor = (
SELENIUM_USERNAME
if expected_executor_type == ExecutorType.SELENIUM
FIXED_USERNAME
if expected_executor_type == ExecutorType.FIXED_USER
else str(expected_result[1])
)
with cm:
executor_type, executor = get_executor(
executor_types=executor_types,
executors=executors,
model=obj,
current_user=str(current_user) if current_user else None,
)

View File

@@ -24,8 +24,8 @@ import pytest
from flask_appbuilder.security.sqla.models import User
from superset.connectors.sqla.models import BaseDatasource, SqlaTable
from superset.tasks.exceptions import ExecutorNotFoundError
from superset.tasks.types import ExecutorType
from superset.tasks.exceptions import InvalidExecutorError
from superset.tasks.types import Executor, ExecutorType, FixedExecutor
from superset.utils.core import DatasourceType, override_user
if TYPE_CHECKING:
@@ -81,7 +81,7 @@ def prepare_datasource_mock(
[
(
None,
[ExecutorType.SELENIUM],
[FixedExecutor("admin")],
False,
False,
[],
@@ -214,13 +214,21 @@ def prepare_datasource_mock(
False,
False,
[],
ExecutorNotFoundError(),
None,
),
(
None,
[ExecutorType.FIXED_USER],
False,
False,
[],
InvalidExecutorError(),
),
],
)
def test_dashboard_digest(
dashboard_overrides: dict[str, Any] | None,
execute_as: list[ExecutorType],
execute_as: list[Executor],
has_current_user: bool,
use_custom_digest: bool,
rls_datasources: list[dict[str, Any]],
@@ -255,7 +263,7 @@ def test_dashboard_digest(
patch.dict(
app.config,
{
"THUMBNAIL_EXECUTE_AS": execute_as,
"THUMBNAIL_EXECUTORS": execute_as,
"THUMBNAIL_DASHBOARD_DIGEST_FUNC": func,
},
),
@@ -282,7 +290,7 @@ def test_dashboard_digest(
[
(
None,
[ExecutorType.SELENIUM],
[FixedExecutor("admin")],
False,
False,
None,
@@ -345,13 +353,21 @@ def test_dashboard_digest(
False,
False,
None,
ExecutorNotFoundError(),
None,
),
(
None,
[ExecutorType.FIXED_USER],
False,
False,
None,
InvalidExecutorError(),
),
],
)
def test_chart_digest(
chart_overrides: dict[str, Any] | None,
execute_as: list[ExecutorType],
execute_as: list[Executor],
has_current_user: bool,
use_custom_digest: bool,
rls_datasource: dict[str, Any] | None,
@@ -383,7 +399,7 @@ def test_chart_digest(
patch.dict(
app.config,
{
"THUMBNAIL_EXECUTE_AS": execute_as,
"THUMBNAIL_EXECUTORS": execute_as,
"THUMBNAIL_CHART_DIGEST_FUNC": func,
},
),