mirror of
https://github.com/apache/superset.git
synced 2026-04-19 16:14:52 +00:00
fix(keys): Unsafe dict access in get_native_filters_params() crashes execution (#38272)
This commit is contained in:
@@ -290,6 +290,10 @@ def test_get_dashboard_urls_with_multiple_tabs(
|
||||
"urlParams": None,
|
||||
}
|
||||
}
|
||||
mock_report_schedule.get_native_filters_params.return_value = ( # type: ignore
|
||||
"()",
|
||||
[],
|
||||
)
|
||||
|
||||
class_instance: BaseReportState = BaseReportState(
|
||||
mock_report_schedule, "January 1, 2021", "execution_id_example"
|
||||
@@ -333,6 +337,10 @@ def test_get_dashboard_urls_with_exporting_dashboard_only(
|
||||
"urlParams": None,
|
||||
}
|
||||
}
|
||||
mock_report_schedule.get_native_filters_params.return_value = ( # type: ignore
|
||||
"()",
|
||||
[],
|
||||
)
|
||||
mock_run.return_value = "url1"
|
||||
|
||||
class_instance: BaseReportState = BaseReportState(
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import pytest
|
||||
|
||||
from superset.reports.models import ReportSchedule
|
||||
|
||||
@@ -37,9 +36,14 @@ def test_get_native_filters_params():
|
||||
}
|
||||
}
|
||||
|
||||
assert report_schedule.get_native_filters_params() == (
|
||||
"(filter_id:(extraFormData:(filters:!((col:column_name,op:IN,val:!(value1,value2)))),filterState:(label:column_name,validateStatus:!f,value:!(value1,value2)),id:filter_id,ownState:()))"
|
||||
result, warnings = report_schedule.get_native_filters_params()
|
||||
expected = (
|
||||
"(filter_id:(extraFormData:(filters:!((col:column_name,op:IN,"
|
||||
"val:!(value1,value2)))),filterState:(label:column_name,"
|
||||
"validateStatus:!f,value:!(value1,value2)),id:filter_id,ownState:()))"
|
||||
)
|
||||
assert result == expected
|
||||
assert warnings == []
|
||||
|
||||
|
||||
def test_get_native_filters_params_multiple_filters():
|
||||
@@ -66,9 +70,17 @@ def test_get_native_filters_params_multiple_filters():
|
||||
}
|
||||
}
|
||||
|
||||
assert report_schedule.get_native_filters_params() == (
|
||||
"(filter_id_1:(extraFormData:(filters:!((col:column_name_1,op:IN,val:!(value1,value2)))),filterState:(label:column_name_1,validateStatus:!f,value:!(value1,value2)),id:filter_id_1,ownState:()),filter_id_2:(extraFormData:(filters:!((col:column_name_2,op:IN,val:!(value3,value4)))),filterState:(label:column_name_2,validateStatus:!f,value:!(value3,value4)),id:filter_id_2,ownState:()))"
|
||||
result, warnings = report_schedule.get_native_filters_params()
|
||||
expected = (
|
||||
"(filter_id_1:(extraFormData:(filters:!((col:column_name_1,op:IN,"
|
||||
"val:!(value1,value2)))),filterState:(label:column_name_1,"
|
||||
"validateStatus:!f,value:!(value1,value2)),id:filter_id_1,ownState:()),"
|
||||
"filter_id_2:(extraFormData:(filters:!((col:column_name_2,op:IN,"
|
||||
"val:!(value3,value4)))),filterState:(label:column_name_2,"
|
||||
"validateStatus:!f,value:!(value3,value4)),id:filter_id_2,ownState:()))"
|
||||
)
|
||||
assert result == expected
|
||||
assert warnings == []
|
||||
|
||||
|
||||
def test_report_generate_native_filter_no_values():
|
||||
@@ -99,9 +111,10 @@ def test_report_generate_native_filter_no_values():
|
||||
}
|
||||
|
||||
|
||||
def test_get_native_filters_params_invalid_structure():
|
||||
def test_get_native_filters_params_missing_filter_values():
|
||||
"""
|
||||
Test the ``get_native_filters_params`` method with invalid structure.
|
||||
Test the ``get_native_filters_params`` method with missing filterValues.
|
||||
Should handle gracefully by using empty list as default.
|
||||
"""
|
||||
report_schedule = ReportSchedule()
|
||||
report_schedule.extra = {
|
||||
@@ -111,29 +124,85 @@ def test_get_native_filters_params_invalid_structure():
|
||||
"nativeFilterId": "filter_id",
|
||||
"columnName": "column_name",
|
||||
"filterType": "filter_select",
|
||||
# Missing "filterValues" key
|
||||
# Missing "filterValues" key - should default to []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
with pytest.raises(KeyError, match="'filterValues'"):
|
||||
report_schedule.get_native_filters_params()
|
||||
# Should not raise, should handle gracefully with empty filterValues
|
||||
result, warnings = report_schedule.get_native_filters_params()
|
||||
assert "filter_id" in result
|
||||
assert "column_name" in result
|
||||
assert warnings == []
|
||||
|
||||
|
||||
# todo(hugh): how do we want to handle this case?
|
||||
# def test_report_generate_native_filter_invalid_filter_id():
|
||||
# """
|
||||
# Test the ``_generate_native_filter`` method with invalid filter id.
|
||||
# """
|
||||
# report_schedule = ReportSchedule()
|
||||
# native_filter_id = None
|
||||
# column_name = "column_name"
|
||||
# values = ["value1", "value2"]
|
||||
def test_get_native_filters_params_explicit_none_values():
|
||||
"""
|
||||
Test the ``get_native_filters_params`` method with explicit None values.
|
||||
Should handle gracefully by coercing None to empty string/list.
|
||||
"""
|
||||
report_schedule = ReportSchedule()
|
||||
report_schedule.extra = {
|
||||
"dashboard": {
|
||||
"nativeFilters": [
|
||||
{
|
||||
"nativeFilterId": "filter_id",
|
||||
"columnName": None, # Explicit None
|
||||
"filterType": "filter_select",
|
||||
"filterValues": None, # Explicit None
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# assert report_schedule._generate_native_filter(
|
||||
# native_filter_id, column_name, values
|
||||
# ) == {}
|
||||
# Should not raise TypeError, should handle gracefully
|
||||
result, warnings = report_schedule.get_native_filters_params()
|
||||
assert "filter_id" in result
|
||||
assert warnings == []
|
||||
|
||||
|
||||
def test_get_native_filters_params_missing_required_fields():
|
||||
"""
|
||||
Test the ``get_native_filters_params`` method with missing required fields.
|
||||
Filters missing nativeFilterId or filterType should be skipped.
|
||||
"""
|
||||
report_schedule = ReportSchedule()
|
||||
report_schedule.extra = {
|
||||
"dashboard": {
|
||||
"nativeFilters": [
|
||||
{
|
||||
# Missing nativeFilterId - should be skipped
|
||||
"filterType": "filter_select",
|
||||
"columnName": "column_name",
|
||||
"filterValues": ["value1"],
|
||||
},
|
||||
{
|
||||
# Missing filterType - should be skipped
|
||||
"nativeFilterId": "filter_2",
|
||||
"columnName": "column_name",
|
||||
"filterValues": ["value2"],
|
||||
},
|
||||
{
|
||||
# Valid filter - should be processed
|
||||
"nativeFilterId": "filter_3",
|
||||
"filterType": "filter_select",
|
||||
"columnName": "column_name",
|
||||
"filterValues": ["value3"],
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
result, warnings = report_schedule.get_native_filters_params()
|
||||
# Only the valid filter should be in the result
|
||||
assert "filter_3" in result
|
||||
assert "filter_2" not in result
|
||||
assert "value1" not in result
|
||||
assert "value3" in result
|
||||
# Two malformed filters should generate two warnings
|
||||
assert len(warnings) == 2
|
||||
assert all("Skipping malformed native filter" in w for w in warnings)
|
||||
|
||||
|
||||
def test_report_generate_native_filter():
|
||||
@@ -173,7 +242,9 @@ def test_get_native_filters_params_empty():
|
||||
report_schedule = ReportSchedule()
|
||||
report_schedule.extra = {}
|
||||
|
||||
assert report_schedule.get_native_filters_params() == "()"
|
||||
result, warnings = report_schedule.get_native_filters_params()
|
||||
assert result == "()"
|
||||
assert warnings == []
|
||||
|
||||
|
||||
def test_get_native_filters_params_no_native_filters():
|
||||
@@ -183,7 +254,9 @@ def test_get_native_filters_params_no_native_filters():
|
||||
report_schedule = ReportSchedule()
|
||||
report_schedule.extra = {"dashboard": {"nativeFilters": []}}
|
||||
|
||||
assert report_schedule.get_native_filters_params() == "()"
|
||||
result, warnings = report_schedule.get_native_filters_params()
|
||||
assert result == "()"
|
||||
assert warnings == []
|
||||
|
||||
|
||||
def test_report_generate_native_filter_empty_values():
|
||||
|
||||
Reference in New Issue
Block a user