From d5ecfbb90147b7c22c816470e40e7b390f6ce65b Mon Sep 17 00:00:00 2001 From: Usiel Riedl Date: Thu, 12 Jan 2023 17:48:01 +0800 Subject: [PATCH] fix(embed): fix server error due to breaking change on flask-login (#22462) Co-authored-by: Usiel Riedl --- superset/embedded/view.py | 7 +- superset/views/dashboard/views.py | 5 +- tests/integration_tests/embedded/test_view.py | 72 +++++++++++++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 tests/integration_tests/embedded/test_view.py diff --git a/superset/embedded/view.py b/superset/embedded/view.py index c3c6c39ba25a..8dd383aadafe 100644 --- a/superset/embedded/view.py +++ b/superset/embedded/view.py @@ -19,10 +19,10 @@ from flask import abort, g, request from flask_appbuilder import expose -from flask_login import AnonymousUserMixin, LoginManager +from flask_login import AnonymousUserMixin, login_user from flask_wtf.csrf import same_origin -from superset import event_logger, is_feature_enabled, security_manager +from superset import event_logger, is_feature_enabled from superset.embedded.dao import EmbeddedDAO from superset.superset_typing import FlaskResponse from superset.utils import core as utils @@ -68,8 +68,7 @@ def embedded( # Log in as an anonymous user, just for this view. # This view needs to be visible to all users, # and building the page fails if g.user and/or ctx.user aren't present. - login_manager: LoginManager = security_manager.lm - login_manager.reload_user(AnonymousUserMixin()) + login_user(AnonymousUserMixin(), force=True) add_extra_log_payload( embedded_dashboard_id=uuid, diff --git a/superset/views/dashboard/views.py b/superset/views/dashboard/views.py index 32f0189d7046..52cb2da82e91 100644 --- a/superset/views/dashboard/views.py +++ b/superset/views/dashboard/views.py @@ -24,7 +24,7 @@ from flask_appbuilder.models.sqla.interface import SQLAInterface from flask_appbuilder.security.decorators import has_access from flask_babel import gettext as __, lazy_gettext as _ -from flask_login import AnonymousUserMixin, LoginManager +from flask_login import AnonymousUserMixin, login_user from superset import db, event_logger, is_feature_enabled, security_manager from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod @@ -149,8 +149,7 @@ def embedded( # Log in as an anonymous user, just for this view. # This view needs to be visible to all users, # and building the page fails if g.user and/or ctx.user aren't present. - login_manager: LoginManager = security_manager.lm - login_manager.reload_user(AnonymousUserMixin()) + login_user(AnonymousUserMixin(), force=True) add_extra_log_payload( dashboard_id=dashboard_id_or_slug, diff --git a/tests/integration_tests/embedded/test_view.py b/tests/integration_tests/embedded/test_view.py new file mode 100644 index 000000000000..9f524e9c09e2 --- /dev/null +++ b/tests/integration_tests/embedded/test_view.py @@ -0,0 +1,72 @@ +# 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. +from __future__ import annotations + +from typing import TYPE_CHECKING +from unittest import mock + +import pytest + +from superset import db +from superset.embedded.dao import EmbeddedDAO +from superset.models.dashboard import Dashboard +from tests.integration_tests.fixtures.birth_names_dashboard import ( + load_birth_names_dashboard_with_slices, + load_birth_names_data, +) +from tests.integration_tests.fixtures.client import client + +if TYPE_CHECKING: + from typing import Any + + from flask.testing import FlaskClient + + +@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") +@mock.patch.dict( + "superset.extensions.feature_flag_manager._feature_flags", + EMBEDDED_SUPERSET=True, +) +def test_get_embedded_dashboard(client: FlaskClient[Any]): + dash = db.session.query(Dashboard).filter_by(slug="births").first() + embedded = EmbeddedDAO.upsert(dash, []) + uri = f"embedded/{embedded.uuid}" + response = client.get(uri) + assert response.status_code == 200 + + +@pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") +@mock.patch.dict( + "superset.extensions.feature_flag_manager._feature_flags", + EMBEDDED_SUPERSET=True, +) +def test_get_embedded_dashboard_referrer_not_allowed(client: FlaskClient[Any]): + dash = db.session.query(Dashboard).filter_by(slug="births").first() + embedded = EmbeddedDAO.upsert(dash, ["test.example.com"]) + uri = f"embedded/{embedded.uuid}" + response = client.get(uri) + assert response.status_code == 403 + + +@mock.patch.dict( + "superset.extensions.feature_flag_manager._feature_flags", + EMBEDDED_SUPERSET=True, +) +def test_get_embedded_dashboard_non_found(client: FlaskClient[Any]): + uri = f"embedded/bad-uuid" + response = client.get(uri) + assert response.status_code == 404