This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 5.0
in repository https://gitbox.apache.org/repos/asf/superset.git

commit aab564fa58eb16bf5f4b36eee2ea1dd628ced581
Author: Jillian <[email protected]>
AuthorDate: Wed Apr 16 02:16:06 2025 +0930

    fix(lang): patch FAB's LocaleView to redirect to previous page (#31692)
---
 superset/initialization/__init__.py       | 27 ++++++++++++++--
 tests/integration_tests/core_tests.py     | 51 +++++++++++++++++++++++++++++++
 tests/integration_tests/security_tests.py |  1 +
 3 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/superset/initialization/__init__.py 
b/superset/initialization/__init__.py
index 1a09d8b24c..1531d63b3f 100644
--- a/superset/initialization/__init__.py
+++ b/superset/initialization/__init__.py
@@ -24,9 +24,11 @@ from typing import Any, Callable, TYPE_CHECKING
 
 import wtforms_json
 from deprecation import deprecated
-from flask import Flask, redirect
+from flask import abort, Flask, redirect, request, session
 from flask_appbuilder import expose, IndexView
-from flask_babel import gettext as __
+from flask_appbuilder.api import safe
+from flask_appbuilder.utils.base import get_safe_redirect
+from flask_babel import gettext as __, refresh
 from flask_compress import Compress
 from flask_session import Session
 from werkzeug.middleware.proxy_fix import ProxyFix
@@ -693,3 +695,24 @@ class SupersetIndexView(IndexView):
     @expose("/")
     def index(self) -> FlaskResponse:
         return redirect("/superset/welcome/")
+
+    @expose("/lang/<string:locale>")
+    @safe
+    def patch_flask_locale(self, locale: str) -> FlaskResponse:
+        """
+        Change user's locale and redirect back to the previous page.
+
+        Overrides FAB's babel.views.LocaleView so we can use the request
+        Referrer as the redirect target, in case our previous page was actually
+        served by the frontend (and thus not added to the session's 
page_history
+        stack).
+        """
+        if locale not in self.appbuilder.bm.languages:
+            abort(404, description="Locale not supported.")
+        session["locale"] = locale
+        refresh()
+        self.update_redirect()
+
+        if redirect_to := request.headers.get("Referer"):
+            return redirect(get_safe_redirect(redirect_to))
+        return redirect(self.get_redirect())
diff --git a/tests/integration_tests/core_tests.py 
b/tests/integration_tests/core_tests.py
index dc01923e62..3f57f345ed 100644
--- a/tests/integration_tests/core_tests.py
+++ b/tests/integration_tests/core_tests.py
@@ -872,5 +872,56 @@ class TestCore(SupersetTestCase):
         assert resp.status_code == 302
 
 
+class TestLocalePatch(SupersetTestCase):
+    MOCK_LANGUAGES = (
+        "superset.views.filters.current_app.config",
+        {
+            "LANGUAGES": {
+                "es": {"flag": "es", "name": "EspaƱol"},
+            },
+        },
+    )
+
+    @mock.patch.dict(*MOCK_LANGUAGES)
+    def test_lang_redirect(self):
+        self.login(GAMMA_USERNAME)
+        referer_url = "http://localhost/explore/";
+        resp = self.client.get("/lang/es", headers={"Referer": referer_url})
+
+        assert resp.status_code == 302
+        assert resp.headers["Location"] == referer_url
+        with self.client.session_transaction() as session:
+            assert session["locale"] == "es"
+
+    @mock.patch.dict(*MOCK_LANGUAGES)
+    def test_lang_invalid_referer(self):
+        self.login(GAMMA_USERNAME)
+        referer_url = "http://someotherserver/explore/";
+        resp = self.client.get("/lang/es", headers={"Referer": referer_url})
+
+        assert resp.status_code == 302
+        assert resp.headers["Location"] == "/"
+        with self.client.session_transaction() as session:
+            assert session["locale"] == "es"
+
+    @mock.patch.dict(*MOCK_LANGUAGES)
+    def test_lang_no_referer(self):
+        self.login(GAMMA_USERNAME)
+        resp = self.client.get("/lang/es")
+
+        assert resp.status_code == 302
+        assert resp.headers["Location"] == "/"
+        with self.client.session_transaction() as session:
+            assert session["locale"] == "es"
+
+    def test_lang_invalid_locale(self):
+        self.login(GAMMA_USERNAME)
+        resp = self.client.get("/lang/es")
+
+        assert resp.status_code == 500
+        with self.client.session_transaction() as session:
+            assert session["locale"] == "en"
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests/integration_tests/security_tests.py 
b/tests/integration_tests/security_tests.py
index a89bb47af7..df97f8a5a0 100644
--- a/tests/integration_tests/security_tests.py
+++ b/tests/integration_tests/security_tests.py
@@ -1545,6 +1545,7 @@ class TestRolePermission(SupersetTestCase):
             ["SecurityApi", "login"],
             ["SecurityApi", "refresh"],
             ["SupersetIndexView", "index"],
+            ["SupersetIndexView", "patch_flask_locale"],
             ["DatabaseRestApi", "oauth2"],
         ]
         unsecured_views = []

Reply via email to