diff --git a/RESOURCES/STANDARD_ROLES.md b/RESOURCES/STANDARD_ROLES.md index 7e804ca75..f01135d10 100644 --- a/RESOURCES/STANDARD_ROLES.md +++ b/RESOURCES/STANDARD_ROLES.md @@ -63,7 +63,6 @@ |can schemas access for csv upload on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can user slices on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can favstar on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| -|can estimate query cost on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can import dashboards on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can search queries on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| |can sqllab viz on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| @@ -73,7 +72,6 @@ |can publish on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can csv on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| |can fave dashboards by username on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| -|can sql json on Superset|:heavy_check_mark:|O|O|:heavy_check_mark:| |can slice on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can sync druid source on Superset|:heavy_check_mark:|O|O|O| |can explore on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| @@ -104,7 +102,6 @@ |can stop query on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| |can request access on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can dashboard on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| -|can results on Superset|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can post on TableSchemaView|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can expanded on TableSchemaView|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| |can delete on TableSchemaView|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O| diff --git a/UPDATING.md b/UPDATING.md index 7ec7a2651..7fca883ec 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -34,6 +34,7 @@ assists people when migrating to a new version. ### Breaking Changes +- [24359](https://github.com/apache/superset/pull/24359): Removed deprecated APIs `/superset/estimate_query_cost/..`, `/superset/results/..`, `/superset/sql_json/..`, `/superset/csv/..` - [24345](https://github.com/apache/superset/pull/24345) Converts `ENABLE_BROAD_ACTIVITY_ACCESS` and `MENU_HIDE_USER_INFO` into feature flags and changes the value of `ENABLE_BROAD_ACTIVITY_ACCESS` to `False` as it's more secure. - [24342](https://github.com/apache/superset/pull/24342): Removed deprecated API `/superset/tables///...` - [24335](https://github.com/apache/superset/pull/24335): Removed deprecated API `/superset/filter////` diff --git a/superset-frontend/src/profile/components/fixtures.tsx b/superset-frontend/src/profile/components/fixtures.tsx index e721b6dfa..d4a3612df 100644 --- a/superset-frontend/src/profile/components/fixtures.tsx +++ b/superset-frontend/src/profile/components/fixtures.tsx @@ -29,7 +29,6 @@ export const user: UserWithPermissionsAndRoles = { ], sql_lab: [ ['menu_access', 'SQL Lab'], - ['can_sql_json', 'Superset'], ['can_search_queries', 'Superset'], ['can_csv', 'Superset'], ], diff --git a/superset/security/manager.py b/superset/security/manager.py index 0df9ad03f..10f24450a 100644 --- a/superset/security/manager.py +++ b/superset/security/manager.py @@ -235,7 +235,6 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods ("can_execute_sql_query", "SQLLab"), ("can_estimate_query_cost", "SQL Lab"), ("can_export_csv", "SQLLab"), - ("can_sql_json", "Superset"), # Deprecated permission remove on 3.0.0 ("can_sqllab_history", "Superset"), ("can_sqllab_viz", "Superset"), ("can_sqllab_table_viz", "Superset"), # Deprecated permission remove on 3.0.0 @@ -713,6 +712,7 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods self.add_permission_view_menu("all_datasource_access", "all_datasource_access") self.add_permission_view_menu("all_database_access", "all_database_access") self.add_permission_view_menu("all_query_access", "all_query_access") + self.add_permission_view_menu("can_csv", "Superset") self.add_permission_view_menu("can_share_dashboard", "Superset") self.add_permission_view_menu("can_share_chart", "Superset") diff --git a/superset/views/core.py b/superset/views/core.py index d9f9fd61b..65386adee 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -21,11 +21,10 @@ import logging import re from contextlib import closing from datetime import datetime -from typing import Any, Callable, cast, Optional +from typing import Any, Callable, cast from urllib import parse import backoff -import pandas as pd import simplejson as json from flask import abort, flash, g, redirect, render_template, request, Response from flask_appbuilder import expose @@ -46,8 +45,6 @@ from superset import ( db, event_logger, is_feature_enabled, - results_backend, - results_backend_use_msgpack, security_manager, sql_lab, viz, @@ -79,13 +76,11 @@ from superset.exceptions import ( CacheLoadError, CertificateException, DatabaseNotFound, - SerializationError, SupersetCancelQueryException, SupersetErrorException, SupersetException, SupersetGenericErrorException, SupersetSecurityException, - SupersetTimeoutException, ) from superset.explore.form_data.commands.create import CreateFormDataCommand from superset.explore.form_data.commands.get import GetFormDataCommand @@ -93,37 +88,17 @@ from superset.explore.form_data.commands.parameters import CommandParameters from superset.explore.permalink.commands.get import GetExplorePermalinkCommand from superset.explore.permalink.exceptions import ExplorePermalinkGetFailedError from superset.extensions import async_query_manager, cache_manager -from superset.jinja_context import get_template_processor from superset.models.core import Database, FavStar from superset.models.dashboard import Dashboard from superset.models.slice import Slice from superset.models.sql_lab import Query, TabState from superset.models.user_attributes import UserAttribute -from superset.queries.dao import QueryDAO from superset.security.analytics_db_safety import check_sqlalchemy_uri -from superset.sql_lab import get_sql_results from superset.sql_parse import ParsedQuery from superset.sql_validators import get_validator_by_name -from superset.sqllab.command_status import SqlJsonExecutionStatus -from superset.sqllab.commands.execute import CommandResult, ExecuteSqlCommand -from superset.sqllab.exceptions import ( - QueryIsForbiddenToAccessException, - SqlLabException, -) -from superset.sqllab.execution_context_convertor import ExecutionContextConvertor -from superset.sqllab.limiting_factor import LimitingFactor -from superset.sqllab.query_render import SqlQueryRenderImpl -from superset.sqllab.sql_json_executer import ( - ASynchronousSqlJsonExecutor, - SqlJsonExecutor, - SynchronousSqlJsonExecutor, -) -from superset.sqllab.sqllab_execution_context import SqlJsonExecutionContext -from superset.sqllab.utils import apply_display_max_row_configuration_if_require -from superset.sqllab.validators import CanAccessQueryValidatorImpl from superset.superset_typing import FlaskResponse from superset.tasks.async_queries import load_explore_json_into_cache -from superset.utils import core as utils, csv +from superset.utils import core as utils from superset.utils.async_query_manager import AsyncQueryTokenException from superset.utils.cache import etag_cache from superset.utils.core import DatasourceType, get_user_id, ReservedUrlParameters @@ -144,9 +119,7 @@ from superset.views.base import ( validate_sqlatable, ) from superset.views.log.dao import LogDAO -from superset.views.sql_lab.schemas import SqlJsonPayloadSchema from superset.views.utils import ( - _deserialize_results_payload, bootstrap_user_data, check_datasource_perms, check_explore_cache_perms, @@ -738,7 +711,6 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods bootstrap_data = { "can_add": slice_add_perm, - "can_download": slice_download_perm, "datasource": sanitize_datasource_data(datasource_data), "form_data": form_data, "datasource_id": datasource_id, @@ -1696,162 +1668,10 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods ) return json_success(json.dumps(payload)) - @has_access_api - @expose("/estimate_query_cost//", methods=("POST",)) - @expose("/estimate_query_cost///", methods=("POST",)) - @event_logger.log_this - @deprecated(new_target="api/v1/sqllab/estimate/") - def estimate_query_cost( # pylint: disable=no-self-use - self, database_id: int, schema: str | None = None - ) -> FlaskResponse: - mydb = db.session.query(Database).get(database_id) - - sql = json.loads(request.form.get("sql", '""')) - if template_params := json.loads(request.form.get("templateParams") or "{}"): - template_processor = get_template_processor(mydb) - sql = template_processor.process_template(sql, **template_params) - - timeout = SQLLAB_QUERY_COST_ESTIMATE_TIMEOUT - timeout_msg = f"The estimation exceeded the {timeout} seconds timeout." - try: - with utils.timeout(seconds=timeout, error_message=timeout_msg): - cost = mydb.db_engine_spec.estimate_query_cost( - mydb, schema, sql, utils.QuerySource.SQL_LAB - ) - except SupersetTimeoutException as ex: - logger.exception(ex) - return json_errors_response([ex.error]) - except Exception as ex: # pylint: disable=broad-except - return json_error_response(utils.error_msg_from_exception(ex)) - - spec = mydb.db_engine_spec - query_cost_formatters: dict[str, Any] = app.config[ - "QUERY_COST_FORMATTERS_BY_ENGINE" - ] - query_cost_formatter = query_cost_formatters.get( - spec.engine, spec.query_cost_formatter - ) - cost = query_cost_formatter(cost) - - return json_success(json.dumps(cost)) - @expose("/theme/") def theme(self) -> FlaskResponse: return self.render_template("superset/theme.html") - @has_access_api - @expose("/results//") - @event_logger.log_this - @deprecated(new_target="api/v1/sqllab/results/") - def results(self, key: str) -> FlaskResponse: - return self.results_exec(key) - - @staticmethod - def results_exec(key: str) -> FlaskResponse: - """Serves a key off of the results backend - - It is possible to pass the `rows` query argument to limit the number - of rows returned. - """ - if not results_backend: - raise SupersetErrorException( - SupersetError( - message=__("Results backend is not configured."), - error_type=SupersetErrorType.RESULTS_BACKEND_NOT_CONFIGURED_ERROR, - level=ErrorLevel.ERROR, - ) - ) - - read_from_results_backend_start = now_as_float() - blob = results_backend.get(key) - stats_logger.timing( - "sqllab.query.results_backend_read", - now_as_float() - read_from_results_backend_start, - ) - if not blob: - raise SupersetErrorException( - SupersetError( - message=__( - "Data could not be retrieved from the results backend. You " - "need to re-run the original query." - ), - error_type=SupersetErrorType.RESULTS_BACKEND_ERROR, - level=ErrorLevel.ERROR, - ), - status=410, - ) - - query = db.session.query(Query).filter_by(results_key=key).one_or_none() - if query is None: - raise SupersetErrorException( - SupersetError( - message=__( - "The query associated with these results could not be found. " - "You need to re-run the original query." - ), - error_type=SupersetErrorType.RESULTS_BACKEND_ERROR, - level=ErrorLevel.ERROR, - ), - status=404, - ) - - try: - query.raise_for_access() - except SupersetSecurityException as ex: - raise SupersetErrorException( - SupersetError( - message=__( - "You are not authorized to see this query. If you think this " - "is an error, please reach out to your administrator." - ), - error_type=SupersetErrorType.QUERY_SECURITY_ACCESS_ERROR, - level=ErrorLevel.ERROR, - ), - status=403, - ) from ex - - payload = utils.zlib_decompress(blob, decode=not results_backend_use_msgpack) - try: - obj = _deserialize_results_payload( - payload, query, cast(bool, results_backend_use_msgpack) - ) - except SerializationError as ex: - raise SupersetErrorException( - SupersetError( - message=__( - "Data could not be deserialized from the results backend. The " - "storage format might have changed, rendering the old data " - "stake. You need to re-run the original query." - ), - error_type=SupersetErrorType.RESULTS_BACKEND_ERROR, - level=ErrorLevel.ERROR, - ), - status=404, - ) from ex - - if "rows" in request.args: - try: - rows = int(request.args["rows"]) - except ValueError as ex: - raise SupersetErrorException( - SupersetError( - message=__( - "The provided `rows` argument is not a valid integer." - ), - error_type=SupersetErrorType.INVALID_PAYLOAD_SCHEMA_ERROR, - level=ErrorLevel.ERROR, - ), - status=400, - ) from ex - - obj = apply_display_max_row_configuration_if_require(obj, rows) - - return json_success( - json.dumps( - obj, default=utils.json_iso_dttm_ser, ignore_nan=True, encoding=None - ) - ) - @has_access_api @handle_api_exception @expose("/stop_query/", methods=("POST",)) @@ -1968,155 +1788,6 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods return json_error_response(f"{msg}", status=400) return json_error_response(f"{msg}") - @has_access_api - @handle_api_exception - @event_logger.log_this - @expose("/sql_json/", methods=("POST",)) - @deprecated(new_target="/api/v1/sqllab/execute/") - def sql_json(self) -> FlaskResponse: - if errors := SqlJsonPayloadSchema().validate(request.json): - return json_error_response(status=400, payload=errors) - - try: - log_params = { - "user_agent": cast(Optional[str], request.headers.get("USER_AGENT")) - } - execution_context = SqlJsonExecutionContext(request.json) - command = self._create_sql_json_command(execution_context, log_params) - command_result: CommandResult = command.run() - return self._create_response_from_execution_context(command_result) - except SqlLabException as ex: - logger.error(ex.message) - self._set_http_status_into_Sql_lab_exception(ex) - payload = {"errors": [ex.to_dict()]} - return json_error_response(status=ex.status, payload=payload) - - @staticmethod - def _create_sql_json_command( - execution_context: SqlJsonExecutionContext, log_params: dict[str, Any] | None - ) -> ExecuteSqlCommand: - query_dao = QueryDAO() - sql_json_executor = Superset._create_sql_json_executor( - execution_context, query_dao - ) - execution_context_convertor = ExecutionContextConvertor() - execution_context_convertor.set_max_row_in_display( - int(config.get("DISPLAY_MAX_ROW")) - ) - return ExecuteSqlCommand( - execution_context, - query_dao, - DatabaseDAO(), - CanAccessQueryValidatorImpl(), - SqlQueryRenderImpl(get_template_processor), - sql_json_executor, - execution_context_convertor, - config["SQLLAB_CTAS_NO_LIMIT"], - log_params, - ) - - @staticmethod - def _create_sql_json_executor( - execution_context: SqlJsonExecutionContext, query_dao: QueryDAO - ) -> SqlJsonExecutor: - sql_json_executor: SqlJsonExecutor - if execution_context.is_run_asynchronous(): - sql_json_executor = ASynchronousSqlJsonExecutor(query_dao, get_sql_results) - else: - sql_json_executor = SynchronousSqlJsonExecutor( - query_dao, - get_sql_results, - config.get("SQLLAB_TIMEOUT"), - is_feature_enabled("SQLLAB_BACKEND_PERSISTENCE"), - ) - return sql_json_executor - - @staticmethod - def _set_http_status_into_Sql_lab_exception(ex: SqlLabException) -> None: - if isinstance(ex, QueryIsForbiddenToAccessException): - ex.status = 403 - - def _create_response_from_execution_context( # pylint: disable=invalid-name, no-self-use - self, - command_result: CommandResult, - ) -> FlaskResponse: - status_code = 200 - if command_result["status"] == SqlJsonExecutionStatus.QUERY_IS_RUNNING: - status_code = 202 - return json_success(command_result["payload"], status_code) - - @has_access - @event_logger.log_this - @expose("/csv/") - @deprecated(new_target="api/v1/sqllab/export/") - def csv(self, client_id: str) -> FlaskResponse: # pylint: disable=no-self-use - """Download the query results as csv.""" - logger.info("Exporting CSV file [%s]", client_id) - query = db.session.query(Query).filter_by(client_id=client_id).one() - - try: - query.raise_for_access() - except SupersetSecurityException as ex: - flash(ex.error.message) - return redirect("/") - - blob = None - if results_backend and query.results_key: - logger.info("Fetching CSV from results backend [%s]", query.results_key) - blob = results_backend.get(query.results_key) - if blob: - logger.info("Decompressing") - payload = utils.zlib_decompress( - blob, decode=not results_backend_use_msgpack - ) - obj = _deserialize_results_payload( - payload, query, cast(bool, results_backend_use_msgpack) - ) - - df = pd.DataFrame( - data=obj["data"], - dtype=object, - columns=[c["name"] for c in obj["columns"]], - ) - - logger.info("Using pandas to convert to CSV") - else: - logger.info("Running a query to turn into CSV") - if query.select_sql: - sql = query.select_sql - limit = None - else: - sql = query.executed_sql - limit = ParsedQuery(sql).limit - if limit is not None and query.limiting_factor in { - LimitingFactor.QUERY, - LimitingFactor.DROPDOWN, - LimitingFactor.QUERY_AND_DROPDOWN, - }: - # remove extra row from `increased_limit` - limit -= 1 - df = query.database.get_df(sql, query.schema)[:limit] - - csv_data = csv.df_to_escaped_csv(df, index=False, **config["CSV_EXPORT"]) - quoted_csv_name = parse.quote(query.name) - response = CsvResponse( - csv_data, headers=generate_download_headers("csv", quoted_csv_name) - ) - event_info = { - "event_type": "data_export", - "client_id": client_id, - "row_count": len(df.index), - "database": query.database.name, - "schema": query.schema, - "sql": query.sql, - "exported_format": "csv", - } - event_rep = repr(event_info) - logger.debug( - "CSV exported: %s", event_rep, extra={"superset_event": event_info} - ) - return response - @api @handle_api_exception @has_access diff --git a/tests/integration_tests/core_tests.py b/tests/integration_tests/core_tests.py index 392771659..91af621c9 100644 --- a/tests/integration_tests/core_tests.py +++ b/tests/integration_tests/core_tests.py @@ -16,11 +16,9 @@ # under the License. # isort:skip_file """Unit tests for Superset""" -import csv import datetime import doctest import html -import io import json import logging from urllib.parse import quote @@ -553,40 +551,6 @@ class TestCore(SupersetTestCase): assert "Charts" in self.get_resp("/chart/list/") assert "Dashboards" in self.get_resp("/dashboard/list/") - @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") - def test_csv_endpoint(self): - self.login() - client_id = f"{random.getrandbits(64)}"[:10] - get_name_sql = """ - SELECT name - FROM birth_names - LIMIT 1 - """ - resp = self.run_sql(get_name_sql, client_id, raise_on_error=True) - name = resp["data"][0]["name"] - sql = f""" - SELECT name - FROM birth_names - WHERE name = '{name}' - LIMIT 1 - """ - client_id = f"{random.getrandbits(64)}"[:10] - self.run_sql(sql, client_id, raise_on_error=True) - - resp = self.get_resp(f"/superset/csv/{client_id}") - data = csv.reader(io.StringIO(resp)) - expected_data = csv.reader(io.StringIO(f"name\n{name}\n")) - - client_id = f"{random.getrandbits(64)}"[:10] - self.run_sql(sql, client_id, raise_on_error=True) - - resp = self.get_resp(f"/superset/csv/{client_id}") - data = csv.reader(io.StringIO(resp)) - expected_data = csv.reader(io.StringIO(f"name\n{name}\n")) - - self.assertEqual(list(expected_data), list(data)) - self.logout() - @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") def test_extra_table_metadata(self): self.login() @@ -596,52 +560,6 @@ class TestCore(SupersetTestCase): f"/superset/extra_table_metadata/{example_db.id}/birth_names/{schema}/" ) - def test_required_params_in_sql_json(self): - self.login() - client_id = f"{random.getrandbits(64)}"[:10] - - data = {"client_id": client_id} - rv = self.client.post( - "/superset/sql_json/", - json=data, - ) - failed_resp = { - "sql": ["Missing data for required field."], - "database_id": ["Missing data for required field."], - } - resp_data = json.loads(rv.data.decode("utf-8")) - self.assertDictEqual(resp_data, failed_resp) - self.assertEqual(rv.status_code, 400) - - data = {"sql": "SELECT 1", "client_id": client_id} - rv = self.client.post( - "/superset/sql_json/", - json=data, - ) - failed_resp = {"database_id": ["Missing data for required field."]} - resp_data = json.loads(rv.data.decode("utf-8")) - self.assertDictEqual(resp_data, failed_resp) - self.assertEqual(rv.status_code, 400) - - data = {"database_id": 1, "client_id": client_id} - rv = self.client.post( - "/superset/sql_json/", - json=data, - ) - failed_resp = {"sql": ["Missing data for required field."]} - resp_data = json.loads(rv.data.decode("utf-8")) - self.assertDictEqual(resp_data, failed_resp) - self.assertEqual(rv.status_code, 400) - - data = {"sql": "SELECT 1", "database_id": 1, "client_id": client_id} - rv = self.client.post( - "/superset/sql_json/", - json=data, - ) - resp_data = json.loads(rv.data.decode("utf-8")) - self.assertEqual(resp_data.get("status"), "success") - self.assertEqual(rv.status_code, 200) - def test_templated_sql_json(self): if superset.utils.database.get_example_database().backend == "presto": # TODO: make it work for presto @@ -651,32 +569,6 @@ class TestCore(SupersetTestCase): data = self.run_sql(sql, "fdaklj3ws") self.assertEqual(data["data"][0]["test"], "2") - @mock.patch( - "tests.integration_tests.superset_test_custom_template_processors.datetime" - ) - @mock.patch("superset.views.core.get_sql_results") - def test_custom_templated_sql_json(self, sql_lab_mock, mock_dt) -> None: - """Test sqllab receives macros expanded query.""" - mock_dt.utcnow = mock.Mock(return_value=datetime.datetime(1970, 1, 1)) - self.login() - sql = "SELECT '$DATE()' as test" - resp = { - "status": QueryStatus.SUCCESS, - "query": {"rows": 1}, - "data": [{"test": "'1970-01-01'"}], - } - sql_lab_mock.return_value = resp - - dbobj = self.create_fake_db_for_macros() - json_payload = dict(database_id=dbobj.id, sql=sql) - self.get_json_resp( - "/superset/sql_json/", raise_on_error=False, json_=json_payload - ) - assert sql_lab_mock.called - self.assertEqual(sql_lab_mock.call_args[0][1], "SELECT '1970-01-01' as test") - - self.delete_fake_db_for_macros() - def test_fetch_datasource_metadata(self): self.login(username="admin") url = "/superset/fetch_datasource_metadata?" "datasourceKey=1__table" @@ -1126,54 +1018,6 @@ class TestCore(SupersetTestCase): assert data == ["this_schema_is_allowed_too"] self.delete_fake_db() - @mock.patch("superset.views.core.results_backend_use_msgpack", False) - def test_display_limit(self): - from superset.views import core - - core.results_backend = mock.Mock() - self.login() - - data = [{"col_0": i} for i in range(100)] - payload = { - "status": QueryStatus.SUCCESS, - "query": {"rows": 100}, - "data": data, - } - # limit results to 1 - expected_key = {"status": "success", "query": {"rows": 100}, "data": data} - limited_data = data[:1] - expected_limited = { - "status": "success", - "query": {"rows": 100}, - "data": limited_data, - "displayLimitReached": True, - } - - query_mock = mock.Mock() - query_mock.sql = "SELECT *" - query_mock.database = 1 - query_mock.schema = "superset" - - # do not apply msgpack serialization - use_msgpack = app.config["RESULTS_BACKEND_USE_MSGPACK"] - app.config["RESULTS_BACKEND_USE_MSGPACK"] = False - serialized_payload = sql_lab._serialize_payload(payload, False) - compressed = utils.zlib_compress(serialized_payload) - core.results_backend.get.return_value = compressed - - with mock.patch("superset.views.core.db") as mock_superset_db: - mock_superset_db.session.query().filter_by().one_or_none.return_value = ( - query_mock - ) - # get all results - result_key = json.loads(self.get_resp("/superset/results/key/")) - result_limited = json.loads(self.get_resp("/superset/results/key/?rows=1")) - - self.assertEqual(result_key, expected_key) - self.assertEqual(result_limited, expected_limited) - - app.config["RESULTS_BACKEND_USE_MSGPACK"] = use_msgpack - def test_results_default_deserialization(self): use_new_deserialization = False data = [("a", 4, 4.0, "2019-08-18T16:39:16.660000")] diff --git a/tests/integration_tests/security_tests.py b/tests/integration_tests/security_tests.py index ec1654138..a4b228a17 100644 --- a/tests/integration_tests/security_tests.py +++ b/tests/integration_tests/security_tests.py @@ -1500,7 +1500,6 @@ class TestRolePermission(SupersetTestCase): self.assertIn(("can_csv", "Superset"), sql_lab_set) self.assertIn(("can_read", "Database"), sql_lab_set) self.assertIn(("can_read", "SavedQuery"), sql_lab_set) - self.assertIn(("can_sql_json", "Superset"), sql_lab_set) self.assertIn(("can_sqllab_viz", "Superset"), sql_lab_set) self.assertIn(("can_sqllab_table_viz", "Superset"), sql_lab_set) self.assertIn(("can_sqllab", "Superset"), sql_lab_set)