mirror of https://github.com/apache/superset.git
refactor: Removes the deprecated redirect endpoint (#26377)
This commit is contained in:
parent
d9a3c3e1dd
commit
a84d86fe26
|
@ -57,7 +57,6 @@
|
|||
| can external metadata on Datasource | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O |
|
||||
| can save on Datasource | :heavy_check_mark: | :heavy_check_mark: | O | O |
|
||||
| can get on Datasource | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O |
|
||||
| can shortner on R | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O |
|
||||
| can my queries on SqlLab | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| can log on Superset | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O |
|
||||
| can schemas access for csv upload on Superset | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | O |
|
||||
|
|
|
@ -41,6 +41,7 @@ assists people when migrating to a new version.
|
|||
- [26636](https://github.com/apache/superset/issues/26636): Sets the `DASHBOARD_VIRTUALIZATION` feature flag to `True` by default. This feature was introduced by [21438](https://github.com/apache/superset/pull/21438) and will enable virtualization when rendering a dashboard's charts in an attempt to reduce the number of elements (DOM nodes) rendered at once. This is especially useful for large dashboards.
|
||||
- [26637](https://github.com/apache/superset/issues/26637): Sets the `DRILL_BY` feature flag to `True` by default given that the feature has been tested for a while and reached a stable state.
|
||||
- [26462](https://github.com/apache/superset/issues/26462): Removes the Profile feature given that it's not actively maintained and not widely used.
|
||||
- [26377](https://github.com/apache/superset/pull/26377): Removes the deprecated Redirect API that supported short URLs used before the permalink feature.
|
||||
|
||||
### Potential Downtime
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import { HTML5Backend } from 'react-dnd-html5-backend';
|
|||
|
||||
import { LineEditableTabs } from 'src/components/Tabs';
|
||||
import { AntdModal } from 'src/components';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
|
||||
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
|
||||
|
@ -40,8 +39,6 @@ import { nativeFilters } from 'spec/fixtures/mockNativeFilters';
|
|||
import { initialState } from 'src/SqlLab/fixtures';
|
||||
|
||||
describe('Tabs', () => {
|
||||
fetchMock.post('glob:*/r/shortener/', {});
|
||||
|
||||
const props = {
|
||||
id: 'TABS_ID',
|
||||
parentId: DASHBOARD_ROOT_ID,
|
||||
|
|
|
@ -183,7 +183,6 @@ class SupersetAppInitializer: # pylint: disable=too-many-public-methods
|
|||
from superset.views.key_value import KV
|
||||
from superset.views.log.api import LogRestApi
|
||||
from superset.views.log.views import LogModelView
|
||||
from superset.views.redirects import R
|
||||
from superset.views.sql_lab.views import (
|
||||
SavedQueryView,
|
||||
SavedQueryViewApi,
|
||||
|
@ -309,7 +308,6 @@ class SupersetAppInitializer: # pylint: disable=too-many-public-methods
|
|||
appbuilder.add_view_no_menu(ExploreView)
|
||||
appbuilder.add_view_no_menu(ExplorePermalinkView)
|
||||
appbuilder.add_view_no_menu(KV)
|
||||
appbuilder.add_view_no_menu(R)
|
||||
appbuilder.add_view_no_menu(SavedQueryView)
|
||||
appbuilder.add_view_no_menu(SavedQueryViewApi)
|
||||
appbuilder.add_view_no_menu(SliceAsync)
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# 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.
|
||||
"""drop_url_table
|
||||
|
||||
Revision ID: e863403c0c50
|
||||
Revises: 214f580d09c9
|
||||
Create Date: 2023-12-28 16:03:31.691033
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "e863403c0c50"
|
||||
down_revision = "214f580d09c9"
|
||||
|
||||
from importlib import import_module
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
module = import_module("superset.migrations.versions.2016-01-13_20-24_8e80a26a31db_")
|
||||
|
||||
|
||||
def upgrade():
|
||||
module.downgrade()
|
||||
|
||||
|
||||
def downgrade():
|
||||
module.upgrade()
|
||||
op.alter_column("url", "changed_on", existing_type=sa.DATETIME(), nullable=True)
|
||||
op.alter_column("url", "created_on", existing_type=sa.DATETIME(), nullable=True)
|
|
@ -90,14 +90,6 @@ if TYPE_CHECKING:
|
|||
DB_CONNECTION_MUTATOR = config["DB_CONNECTION_MUTATOR"]
|
||||
|
||||
|
||||
class Url(Model, AuditMixinNullable):
|
||||
"""Used for the short url feature"""
|
||||
|
||||
__tablename__ = "url"
|
||||
id = Column(Integer, primary_key=True)
|
||||
url = Column(Text)
|
||||
|
||||
|
||||
class KeyValue(Model): # pylint: disable=too-few-public-methods
|
||||
|
||||
"""Used for any type of key-value store"""
|
||||
|
|
|
@ -22,7 +22,6 @@ from . import (
|
|||
css_templates,
|
||||
dynamic_plugins,
|
||||
health,
|
||||
redirects,
|
||||
sql_lab,
|
||||
tags,
|
||||
)
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
# 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.
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from flask import flash
|
||||
from flask_appbuilder import expose
|
||||
from werkzeug.utils import redirect
|
||||
|
||||
from superset import db, event_logger
|
||||
from superset.models import core as models
|
||||
from superset.superset_typing import FlaskResponse
|
||||
from superset.views.base import BaseSupersetView
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class R(BaseSupersetView): # pylint: disable=invalid-name
|
||||
|
||||
"""used for short urls"""
|
||||
|
||||
@staticmethod
|
||||
def _validate_explore_url(url: str) -> Optional[str]:
|
||||
if url.startswith("//superset/explore/p/"):
|
||||
return url
|
||||
|
||||
if url.startswith("//superset/explore"):
|
||||
return "/" + url[10:] # Remove /superset from old Explore URLs
|
||||
|
||||
if url.startswith("//explore"):
|
||||
return url
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _validate_dashboard_url(url: str) -> Optional[str]:
|
||||
if url.startswith("//superset/dashboard/"):
|
||||
return url
|
||||
|
||||
return None
|
||||
|
||||
@event_logger.log_this
|
||||
@expose("/<int:url_id>")
|
||||
def index(self, url_id: int) -> FlaskResponse:
|
||||
url = db.session.query(models.Url).get(url_id)
|
||||
if url and url.url:
|
||||
explore_url = self._validate_explore_url(url.url)
|
||||
if explore_url:
|
||||
if explore_url.startswith("//explore/?"):
|
||||
explore_url = f"//explore/?r={url_id}"
|
||||
return redirect(explore_url[1:])
|
||||
|
||||
dashboard_url = self._validate_dashboard_url(url.url)
|
||||
if dashboard_url:
|
||||
return redirect(dashboard_url[1:])
|
||||
|
||||
return redirect("/")
|
||||
|
||||
flash("URL to nowhere...", "danger")
|
||||
return redirect("/")
|
|
@ -19,7 +19,6 @@ import logging
|
|||
from collections import defaultdict
|
||||
from functools import wraps
|
||||
from typing import Any, Callable, DefaultDict, Optional, Union
|
||||
from urllib import parse
|
||||
|
||||
import msgpack
|
||||
import pyarrow as pa
|
||||
|
@ -31,7 +30,6 @@ from flask_babel import _
|
|||
from sqlalchemy.exc import NoResultFound
|
||||
from werkzeug.wrappers.response import Response
|
||||
|
||||
import superset.models.core as models
|
||||
from superset import app, dataframe, db, result_set, viz
|
||||
from superset.common.db_query_status import QueryStatus
|
||||
from superset.daos.datasource import DatasourceDAO
|
||||
|
@ -145,7 +143,7 @@ def loads_request_json(request_json_data: str) -> dict[Any, Any]:
|
|||
return {}
|
||||
|
||||
|
||||
def get_form_data( # pylint: disable=too-many-locals
|
||||
def get_form_data(
|
||||
slice_id: Optional[int] = None,
|
||||
use_slice_data: bool = False,
|
||||
initial_form_data: Optional[dict[str, Any]] = None,
|
||||
|
@ -185,19 +183,6 @@ def get_form_data( # pylint: disable=too-many-locals
|
|||
json_data = form_data["queries"][0] if "queries" in form_data else {}
|
||||
form_data.update(json_data)
|
||||
|
||||
if has_request_context():
|
||||
url_id = request.args.get("r")
|
||||
if url_id:
|
||||
saved_url = db.session.query(models.Url).filter_by(id=url_id).first()
|
||||
if saved_url:
|
||||
url_str = parse.unquote_plus(
|
||||
saved_url.url.split("?")[1][10:], encoding="utf-8"
|
||||
)
|
||||
url_form_data = loads_request_json(url_str)
|
||||
# allow form_date in request override saved url
|
||||
url_form_data.update(form_data)
|
||||
form_data = url_form_data
|
||||
|
||||
form_data = {k: v for k, v in form_data.items() if k not in REJECTED_FORM_DATA_KEYS}
|
||||
|
||||
# When a slice_id is present, load from DB and override
|
||||
|
|
|
@ -413,17 +413,6 @@ class TestCore(SupersetTestCase):
|
|||
db.session.delete(ck)
|
||||
app.config["STORE_CACHE_KEYS_IN_METADATA_DB"] = store_cache_keys
|
||||
|
||||
def test_redirect_invalid(self):
|
||||
model_url = models.Url(url="hhttp://invalid.com")
|
||||
db.session.add(model_url)
|
||||
db.session.commit()
|
||||
|
||||
self.login(username="admin")
|
||||
response = self.client.get(f"/r/{model_url.id}")
|
||||
assert response.headers["Location"] == "/"
|
||||
db.session.delete(model_url)
|
||||
db.session.commit()
|
||||
|
||||
@with_feature_flags(KV_STORE=False)
|
||||
def test_kv_disabled(self):
|
||||
self.login(username="admin")
|
||||
|
|
|
@ -112,6 +112,7 @@ class TestDeleteTagsCommand(SupersetTestCase):
|
|||
TaggedObject.object_id == example_dashboard.id,
|
||||
Tag.type == TagType.custom,
|
||||
)
|
||||
.order_by(Tag.name)
|
||||
.all()
|
||||
)
|
||||
assert example_tags == [tag.name for tag in created_tags]
|
||||
|
|
Loading…
Reference in New Issue