refactor: Removes the deprecated redirect endpoint (#26377)

This commit is contained in:
Michael S. Molina 2024-01-19 11:39:04 -03:00 committed by GitHub
parent d9a3c3e1dd
commit a84d86fe26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 48 additions and 116 deletions

View File

@ -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 |

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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)

View File

@ -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"""

View File

@ -22,7 +22,6 @@ from . import (
css_templates,
dynamic_plugins,
health,
redirects,
sql_lab,
tags,
)

View File

@ -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("/")

View File

@ -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

View File

@ -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")

View File

@ -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]