Skip to content
Merged
27 changes: 25 additions & 2 deletions superset/initialization/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@

import wtforms_json
from deprecation import deprecated
from flask import Flask, redirect, url_for
from flask import abort, Flask, redirect, request, session, url_for
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
Expand Down Expand Up @@ -708,3 +710,24 @@
@expose("/")
def index(self) -> FlaskResponse:
return redirect(url_for("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()

Check warning on line 729 in superset/initialization/__init__.py

View check run for this annotation

Codecov / codecov/patch

superset/initialization/__init__.py#L725-L729

Added lines #L725 - L729 were not covered by tests

if redirect_to := request.headers.get("Referer"):
return redirect(get_safe_redirect(redirect_to))
return redirect(self.get_redirect())

Check warning on line 733 in superset/initialization/__init__.py

View check run for this annotation

Codecov / codecov/patch

superset/initialization/__init__.py#L731-L733

Added lines #L731 - L733 were not covered by tests
51 changes: 51 additions & 0 deletions tests/integration_tests/core_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -872,5 +872,56 @@ def test_dashboard_permalink(self, get_dashboard_permalink_mock, request_mock):
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()
1 change: 1 addition & 0 deletions tests/integration_tests/security_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,7 @@ def test_views_are_secured(self):
["SecurityApi", "login"],
["SecurityApi", "refresh"],
["SupersetIndexView", "index"],
["SupersetIndexView", "patch_flask_locale"],
["DatabaseRestApi", "oauth2"],
]
unsecured_views = []
Expand Down
Loading