diff --git a/UPDATING.md b/UPDATING.md index dd95795550e0e..15669d0e25d05 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -24,6 +24,17 @@ assists people when migrating to a new version. ## 2.1.0 +- [22809](https://github.com/apache/superset/pull/22809): Migrated endpoint `/superset/sql_json` and `/superset/results/` to `/api/v1/sqllab/execute/` and `/api/v1/sqllab/results/` respectively. Corresponding permissions are `can sql_json on Superset` to `can execute on SQLLab`, `can results on Superset` to `can results on SQLLab`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22931](https://github.com/apache/superset/pull/22931): Migrated endpoint `/superset/get_or_create_table/` to `/api/v1/dataset/get_or_create/`. Corresponding permissions are `can get or create table on Superset` to `can get or create dataset on Dataset`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22882](https://github.com/apache/superset/pull/22882): Migrated endpoint `/superset/filter////` to `/api/v1/datasource///column//values/`. Corresponding permissions are `can filter on Superset` to `can get column values on Datasource`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22789](https://github.com/apache/superset/pull/22789): Migrated endpoint `/superset/recent_activity//` to `/api/v1/log/recent_activity//`. Corresponding permissions are `can recent activity on Superset` to `can recent activity on Log`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22913](https://github.com/apache/superset/pull/22913): Migrated endpoint `/superset/csv` to `/api/v1/sqllab/export/`. Corresponding permissions are `can csv on Superset` to `can export csv on SQLLab`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22496](https://github.com/apache/superset/pull/22496): Migrated endpoint `/superset/slice_json/` to `/api/v1/chart//data/`. Corresponding permissions are `can slice json on Superset` to `can read on Chart`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22496](https://github.com/apache/superset/pull/22496): Migrated endpoint `/superset/annotation_json/` to `/api/v1/chart//data/`. Corresponding permissions are `can annotation json on Superset` to `can read on Chart`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22624](https://github.com/apache/superset/pull/22624): Migrated endpoint `/superset/stop_query/` to `/api/v1/query/stop`. Corresponding permissions are `can stop query on Superset` to `can read on Query`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22579](https://github.com/apache/superset/pull/22579): Migrated endpoint `/superset/search_queries/` to `/api/v1/query/`. Corresponding permissions are `can search queries on Superset` to `can read on Query`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22501](https://github.com/apache/superset/pull/22501): Migrated endpoint `/superset/tables///` to `/api/v1/database//tables/`. Corresponding permissions are `can tables on Superset` to `can read on Database`. Make sure you add/replace the necessary permissions on any custom roles you may have. +- [22611](https://github.com/apache/superset/pull/22611): Migrated endpoint `/superset/queries/` to `api/v1/query/updated_since`. Corresponding permissions are `can queries on Superset` to `can read on Query`. Make sure you add/replace the necessary permissions on any custom roles you may have. - [23186](https://github.com/apache/superset/pull/23186): Superset will refuse to start if a default `SECRET_KEY` is detected on a non Flask debug setting. - [22022](https://github.com/apache/superset/pull/22022): HTTP API endpoints `/superset/approve` and `/superset/request_access` have been deprecated and their HTTP methods were changed from GET to POST - [20606](https://github.com/apache/superset/pull/20606): When user clicks on chart title or "Edit chart" button in Dashboard page, Explore opens in the same tab. Clicking while holding cmd/ctrl opens Explore in a new tab. To bring back the old behaviour (always opening Explore in a new tab), flip feature flag `DASHBOARD_EDIT_CHART_IN_NEW_TAB` to `True`. diff --git a/superset/views/base.py b/superset/views/base.py index 6e28745821ee2..ec74b8ccdb3a0 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -188,6 +188,7 @@ def generate_download_headers( def deprecated( eol_version: str = "3.0.0", + new_target: Optional[str] = None, ) -> Callable[[Callable[..., FlaskResponse]], Callable[..., FlaskResponse]]: """ A decorator to set an API endpoint from SupersetView has deprecated. @@ -196,13 +197,19 @@ def deprecated( def _deprecated(f: Callable[..., FlaskResponse]) -> Callable[..., FlaskResponse]: def wraps(self: "BaseSupersetView", *args: Any, **kwargs: Any) -> FlaskResponse: - logger.warning( + messsage = ( "%s.%s " - "This API endpoint is deprecated and will be removed in version %s", + "This API endpoint is deprecated and will be removed in version %s" + ) + logger_args = [ self.__class__.__name__, f.__name__, eol_version, - ) + ] + if new_target: + messsage += " . Use the following API endpoint instead: %s" + logger_args.append(new_target) + logger.warning(messsage, *logger_args) return f(self, *args, **kwargs) return functools.update_wrapper(wraps, f) diff --git a/superset/views/core.py b/superset/views/core.py index d3dfdb017cb48..f6ce1de3850a3 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -211,7 +211,7 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods @has_access_api @event_logger.log_this @expose("/datasources/") - @deprecated() + @deprecated(new_target="api/v1/dataset/") def datasources(self) -> FlaskResponse: return self.json_response( sorted( @@ -505,7 +505,7 @@ def generate_json( @expose("/slice_json/") @etag_cache() @check_resource_permissions(check_slice_perms) - @deprecated() + @deprecated(new_target="/api/v1/chart//data/") def slice_json(self, slice_id: int) -> FlaskResponse: form_data, slc = get_form_data(slice_id, use_slice_data=True) if not slc: @@ -529,7 +529,7 @@ def slice_json(self, slice_id: int) -> FlaskResponse: @has_access_api @event_logger.log_this @expose("/annotation_json/") - @deprecated() + @deprecated(new_target="/api/v1/chart//data/") def annotation_json( # pylint: disable=no-self-use self, layer_id: int ) -> FlaskResponse: @@ -999,7 +999,10 @@ def explore( @has_access_api @event_logger.log_this @expose("/filter////") - @deprecated() + @deprecated( + new_target="/api/v1/datasource//" + "/column//values/" + ) def filter( # pylint: disable=no-self-use self, datasource_type: str, datasource_id: int, column: str ) -> FlaskResponse: @@ -1143,7 +1146,7 @@ def save_or_overwrite_slice( @event_logger.log_this @expose("/tables///") @expose("/tables////") - @deprecated() + @deprecated(new_target="api/v1/database//tables/") def tables( # pylint: disable=no-self-use self, db_id: int, @@ -1352,7 +1355,7 @@ def add_slices( # pylint: disable=no-self-use @has_access_api @event_logger.log_this @expose("/testconn", methods=["POST", "GET"]) - @deprecated() + @deprecated(new_target="/api/v1/database/test_connection/") def testconn(self) -> FlaskResponse: # pylint: disable=no-self-use """Tests a sqla connection""" db_name = request.json.get("name") @@ -1441,7 +1444,7 @@ def get_user_activity_access_error(user_id: int) -> Optional[FlaskResponse]: @has_access_api @event_logger.log_this @expose("/recent_activity//", methods=["GET"]) - @deprecated() + @deprecated(new_target="/api/v1/log/recent_activity//") def recent_activity(self, user_id: int) -> FlaskResponse: """Recent activity (actions) for a given user""" error_obj = self.get_user_activity_access_error(user_id) @@ -1462,7 +1465,7 @@ def recent_activity(self, user_id: int) -> FlaskResponse: @has_access_api @event_logger.log_this @expose("/available_domains/", methods=["GET"]) - @deprecated() + @deprecated(new_target="/api/v1/available_domains/") def available_domains(self) -> FlaskResponse: # pylint: disable=no-self-use """ Returns the list of available Superset Webserver domains (if any) @@ -1477,7 +1480,7 @@ def available_domains(self) -> FlaskResponse: # pylint: disable=no-self-use @has_access_api @event_logger.log_this @expose("/fave_dashboards_by_username//", methods=["GET"]) - @deprecated() + @deprecated(new_target="api/v1/dashboard/favorite_status/") def fave_dashboards_by_username(self, username: str) -> FlaskResponse: """This lets us use a user's username to pull favourite dashboards""" user = security_manager.find_user(username=username) @@ -1487,7 +1490,7 @@ def fave_dashboards_by_username(self, username: str) -> FlaskResponse: @has_access_api @event_logger.log_this @expose("/fave_dashboards//", methods=["GET"]) - @deprecated() + @deprecated(new_target="api/v1/dashboard/favorite_status/") def fave_dashboards(self, user_id: int) -> FlaskResponse: error_obj = self.get_user_activity_access_error(user_id) if error_obj: @@ -1524,7 +1527,7 @@ def fave_dashboards(self, user_id: int) -> FlaskResponse: @has_access_api @event_logger.log_this @expose("/created_dashboards//", methods=["GET"]) - @deprecated() + @deprecated(new_target="api/v1/dashboard/") def created_dashboards(self, user_id: int) -> FlaskResponse: error_obj = self.get_user_activity_access_error(user_id) if error_obj: @@ -1609,7 +1612,7 @@ def user_slices(self, user_id: Optional[int] = None) -> FlaskResponse: @event_logger.log_this @expose("/created_slices", methods=["GET"]) @expose("/created_slices//", methods=["GET"]) - @deprecated() + @deprecated(new_target="api/v1/chart/") def created_slices(self, user_id: Optional[int] = None) -> FlaskResponse: """List of slices created by this user""" if not user_id: @@ -1926,7 +1929,7 @@ def log(self) -> FlaskResponse: # pylint: disable=no-self-use @has_access @expose("/get_or_create_table/", methods=["POST"]) @event_logger.log_this - @deprecated() + @deprecated(new_target="api/v1/dataset/get_or_create/") def sqllab_table_viz(self) -> FlaskResponse: # pylint: disable=no-self-use """Gets or creates a table object with attributes passed to the API. @@ -2041,7 +2044,9 @@ def sqllab_viz(self) -> FlaskResponse: # pylint: disable=no-self-use @has_access @expose("/extra_table_metadata////") @event_logger.log_this - @deprecated() + @deprecated( + new_target="api/v1/database//table_extra///" + ) def extra_table_metadata( # pylint: disable=no-self-use self, database_id: int, table_name: str, schema: str ) -> FlaskResponse: @@ -2099,7 +2104,7 @@ def theme(self) -> FlaskResponse: @has_access_api @expose("/results//") @event_logger.log_this - @deprecated() + @deprecated(new_target="/api/v1/sqllab/results/") def results(self, key: str) -> FlaskResponse: return self.results_exec(key) @@ -2221,7 +2226,7 @@ def results_exec(key: str) -> FlaskResponse: on_giveup=lambda details: db.session.rollback(), max_tries=5, ) - @deprecated() + @deprecated(new_target="/api/v1/query/stop") def stop_query(self) -> FlaskResponse: client_id = request.form.get("client_id") query = db.session.query(Query).filter_by(client_id=client_id).one() @@ -2250,7 +2255,7 @@ def stop_query(self) -> FlaskResponse: @has_access_api @event_logger.log_this @expose("/validate_sql_json/", methods=["POST", "GET"]) - @deprecated() + @deprecated(new_target="/api/v1/database//validate_sql/") def validate_sql_json( # pylint: disable=too-many-locals,no-self-use self, @@ -2323,7 +2328,7 @@ def validate_sql_json( @handle_api_exception @event_logger.log_this @expose("/sql_json/", methods=["POST"]) - @deprecated() + @deprecated(new_target="/api/v1/sqllab/execute/") def sql_json(self) -> FlaskResponse: errors = SqlJsonPayloadSchema().validate(request.json) if errors: @@ -2401,7 +2406,7 @@ def _create_response_from_execution_context( # pylint: disable=invalid-name, no @has_access @event_logger.log_this @expose("/csv/") - @deprecated() + @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) @@ -2475,7 +2480,7 @@ def csv(self, client_id: str) -> FlaskResponse: # pylint: disable=no-self-use @has_access @event_logger.log_this @expose("/fetch_datasource_metadata") - @deprecated() + @deprecated(new_target="api/v1/database//table///") def fetch_datasource_metadata(self) -> FlaskResponse: # pylint: disable=no-self-use """ Fetch the datasource metadata. @@ -2498,7 +2503,7 @@ def fetch_datasource_metadata(self) -> FlaskResponse: # pylint: disable=no-self @event_logger.log_this @expose("/queries/") @expose("/queries/") - @deprecated() + @deprecated(new_target="api/v1/query/updated_since") def queries(self, last_updated_ms: Union[float, int]) -> FlaskResponse: """ Get the updated queries. @@ -2530,7 +2535,7 @@ def queries_exec(last_updated_ms: Union[float, int]) -> FlaskResponse: @has_access @event_logger.log_this @expose("/search_queries") - @deprecated() + @deprecated(new_target="api/v1/query/") def search_queries(self) -> FlaskResponse: # pylint: disable=no-self-use """ Search for previously run sqllab queries. Used for Sqllab Query Search