Skip to content

Commit

Permalink
Widget: Fix language on first iframe request
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelm committed Jan 26, 2024
1 parent 734b376 commit eac88b5
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 21 deletions.
4 changes: 3 additions & 1 deletion src/pretix/api/auth/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
# <https://www.gnu.org/licenses/>.
#
from rest_framework import exceptions
from rest_framework.authentication import SessionAuthentication as BaseSessionAuthentication
from rest_framework.authentication import (
SessionAuthentication as BaseSessionAuthentication,
)

from pretix.multidomain.middlewares import CsrfViewMiddleware

Expand Down
38 changes: 24 additions & 14 deletions src/pretix/base/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@
_supported = None


def get_supported_language(requested_language, allowed_languages, default_language):
language = requested_language
if language not in allowed_languages:
firstpart = language.split('-')[0]
if firstpart in allowed_languages:
language = firstpart
else:
language = default_language
for lang in allowed_languages:
if lang.startswith(firstpart + '-'):
language = lang
break
if language not in allowed_languages:
# This seems redundant, but can happen in the rare edge case that settings.locale is (wrongfully)
# not part of settings.locales
language = allowed_languages[0]
return language


class LocaleMiddleware(MiddlewareMixin):

"""
Expand All @@ -65,20 +84,11 @@ def process_request(self, request: HttpRequest):
settings_holder = None

if settings_holder:
if language not in settings_holder.settings.locales:
firstpart = language.split('-')[0]
if firstpart in settings_holder.settings.locales:
language = firstpart
else:
language = settings_holder.settings.locale
for lang in settings_holder.settings.locales:
if lang.startswith(firstpart + '-'):
language = lang
break
if language not in settings_holder.settings.locales:
# This seems redundant, but can happen in the rare edge case that settings.locale is (wrongfully)
# not part of settings.locales
language = settings_holder.settings.locales[0]
language = get_supported_language(
language,
settings_holder.settings.locales,
settings_holder.settings.locale,
)
if '-' not in language and settings_holder.settings.region:
language += '-' + settings_holder.settings.region
else:
Expand Down
23 changes: 19 additions & 4 deletions src/pretix/presale/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@
from django.conf import settings
from django.contrib import messages
from django.db.models import Exists, OuterRef, Prefetch, Sum
from django.utils import translation
from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from django_scopes import scopes_disabled

from pretix.base.i18n import language
from pretix.base.i18n import get_language_without_region
from pretix.base.middleware import get_supported_language
from pretix.base.models import (
CartPosition, Customer, InvoiceAddress, ItemAddOn, Question,
QuestionAnswer, QuestionOption, TaxRule,
Expand Down Expand Up @@ -455,11 +457,24 @@ def wrapped_view(request, *args, **kwargs):

locale = request.GET.get('locale')
if locale and locale in [lc for lc, ll in settings.LANGUAGES]:
region = None
lng = locale
if hasattr(request, 'event'):
lng = get_supported_language(
lng,
request.event.settings.locales,
request.event.settings.locale,
)

region = request.event.settings.region
with language(locale, region):
resp = view_func(request, *args, **kwargs)
if '-' not in lng and region:
lng += '-' + region.lower()

# with language() is not good enough here – we really need to take the role of LocaleMiddleware and modify
# global state, because template rendering might be happening lazily.
translation.activate(lng)
request.LANGUAGE_CODE = get_language_without_region()
resp = view_func(request, *args, **kwargs)

max_age = 10 * 365 * 24 * 60 * 60
set_cookie_without_samesite(
request,
Expand Down
2 changes: 1 addition & 1 deletion src/tests/api/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
import pytest
from bs4 import BeautifulSoup
from django.test import Client
from tests.base import extract_form_fields

from pretix.base.models import Organizer
from tests.base import extract_form_fields


@pytest.mark.django_db
Expand Down
6 changes: 5 additions & 1 deletion src/tests/presale/test_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,13 @@ def setUp(self):
)

def test_iframe_entry_view_wrapper(self):
self.client.get('/%s/%s/?iframe=1&locale=de' % (self.orga.slug, self.event.slug))
self.event.settings.locales = ["de", "en"]
r = self.client.get('/%s/%s/?iframe=1&locale=de' % (self.orga.slug, self.event.slug), headers={
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
})
assert 'iframe_session' in self.client.session
assert self.client.cookies[settings.LANGUAGE_COOKIE_NAME].value == "de"
assert r.headers["Content-Language"] == "de"

def test_allow_frame_if_namespaced(self):
response = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
Expand Down

0 comments on commit eac88b5

Please sign in to comment.