Compare commits

...
Author SHA1 Message Date
Mira Weller 3badcfcccb Update signal docstrings 2026-07-09 17:22:15 +02:00
Mira Weller a61609a89d Use SafeStrings for event_live_issues 2026-07-03 14:22:48 +02:00
Mira Weller 8ec1b83d25 Use SafeStrings for plugin signals returning HTML that should be rendered 2026-07-03 14:04:17 +02:00
943b319557 use cookieretry only on presale event pages (Z#23236752) (#6297)
* use cookieretry only on presale event pages

* use csrfcookieretry only on event index page

* include static tag

* include csrfcookieretry in order.html as well

* Update src/pretix/static/pretixpresale/js/csrfcookieretry.js

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>

---------

Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2026-07-03 13:56:47 +02:00
Richard SchreiberandGitHub 28b13667ce Widget: add beta-flag to URL (#6338) 2026-07-03 12:04:54 +02:00
Raphael MichelandGitHub b00d1c9156 Bump django-querytagger 2026-07-03 11:53:34 +02:00
12 changed files with 67 additions and 32 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ dependencies = [
"django-oauth-toolkit==2.3.*", "django-oauth-toolkit==2.3.*",
"django-otp==1.7.*", "django-otp==1.7.*",
"django-phonenumber-field==8.4.*", "django-phonenumber-field==8.4.*",
"django-querytagger==0.0.2", "django-querytagger==0.0.3",
"django-redis==6.0.*", "django-redis==6.0.*",
"django-scopes==2.0.*", "django-scopes==2.0.*",
"django-statici18n==2.7.*", "django-statici18n==2.7.*",
+6 -9
View File
@@ -1403,15 +1403,12 @@ class Event(EventMixin, LoggedModel):
for mp in self.organizer.meta_properties.all(): for mp in self.organizer.meta_properties.all():
if mp.required and not self.meta_data.get(mp.name): if mp.required and not self.meta_data.get(mp.name):
issues.append( issues.append(format_html(
('<a {a_attr}>' + gettext('You need to fill the meta parameter "{property}".') + '</a>').format( '<a href="{href}{href_hash}">{text}</a>',
property=mp.name, text=gettext('You need to fill the meta parameter "{property}".').format(property=mp.name),
a_attr='href="%s#id_prop-%d-value"' % ( href=reverse('control:event.settings', kwargs={'organizer': self.organizer.slug, 'event': self.slug}),
reverse('control:event.settings', kwargs={'organizer': self.organizer.slug, 'event': self.slug}), href_hash=f'#id_prop-{mp.pk}-value',
mp.pk ))
)
)
)
responses = event_live_issues.send(self) responses = event_live_issues.send(self)
for receiver, response in sorted(responses, key=lambda r: str(r[0])): for receiver, response in sorted(responses, key=lambda r: str(r[0])):
+3 -2
View File
@@ -535,8 +535,9 @@ EventPluginRegistry = PluginAwareRegistry # for backwards compatibility
event_live_issues = EventPluginSignal() event_live_issues = EventPluginSignal()
""" """
This signal is sent out to determine whether an event can be taken live. If you want to This signal is sent out to determine whether an event can be taken live. If you want to
prevent the event from going live, return a string that will be displayed to the user prevent the event from going live, return an error message to display to the user (either
as the error message. If you don't, your receiver should return ``None``. as a SafeString containing HTML, or a string that will be HTML-escaped). If you don't,
your receiver should return ``None``.
As with all event-plugin signals, the ``sender`` keyword argument will contain the event. As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
""" """
+3 -2
View File
@@ -22,6 +22,7 @@
import importlib import importlib
from django import template from django import template
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from pretix.base.models import Event from pretix.base.models import Event
@@ -44,7 +45,7 @@ def eventsignal(event: Event, signame: str, **kwargs):
_html = [] _html = []
for receiver, response in signal.send(event, **kwargs): for receiver, response in signal.send(event, **kwargs):
if response: if response:
_html.append(response) _html.append(conditional_escape(response))
return mark_safe("".join(_html)) return mark_safe("".join(_html))
@@ -63,5 +64,5 @@ def signal(signame: str, request, **kwargs):
_html = [] _html = []
for receiver, response in signal.send(request, **kwargs): for receiver, response in signal.send(request, **kwargs):
if response: if response:
_html.append(response) _html.append(conditional_escape(response))
return mark_safe("".join(_html)) return mark_safe("".join(_html))
+12 -4
View File
@@ -39,7 +39,8 @@ from pretix.base.signals import (
html_page_start = GlobalSignal() html_page_start = GlobalSignal()
""" """
This signal allows you to put code in the beginning of the main page for every This signal allows you to put code in the beginning of the main page for every
page in the backend. You are expected to return HTML. page in the backend. You are expected to return a SafeString containing HTML, or
a string that will be HTML-escaped.
The ``sender`` keyword argument will contain the request. The ``sender`` keyword argument will contain the request.
""" """
@@ -129,7 +130,7 @@ event_dashboard_top = EventPluginSignal()
Arguments: 'request' Arguments: 'request'
This signal is sent out to include custom HTML in the top part of the the event dashboard. This signal is sent out to include custom HTML in the top part of the the event dashboard.
Receivers should return HTML. Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
An additional keyword argument ``subevent`` *can* contain a sub-event. An additional keyword argument ``subevent`` *can* contain a sub-event.
@@ -172,6 +173,7 @@ Arguments: 'form'
This signal allows you to add additional HTML to the form that is used for modifying vouchers. This signal allows you to add additional HTML to the form that is used for modifying vouchers.
You receive the form object in the ``form`` keyword argument. You receive the form object in the ``form`` keyword argument.
Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -209,6 +211,7 @@ Arguments: 'quota'
This signal allows you to append HTML to a Quota's detail view. You receive the This signal allows you to append HTML to a Quota's detail view. You receive the
quota as argument in the ``quota`` keyword argument. quota as argument in the ``quota`` keyword argument.
Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -219,6 +222,7 @@ Arguments: 'subevent'
This signal allows you to append HTML to a SubEvent's detail view. You receive the This signal allows you to append HTML to a SubEvent's detail view. You receive the
subevent as argument in the ``subevent`` keyword argument. subevent as argument in the ``subevent`` keyword argument.
Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -265,7 +269,8 @@ order_info = EventPluginSignal()
""" """
Arguments: ``order``, ``request`` Arguments: ``order``, ``request``
This signal is sent out to display additional information on the order detail page This signal is sent out to display additional information on the order detail page.
Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
Additionally, the argument ``order`` and ``request`` are available. Additionally, the argument ``order`` and ``request`` are available.
@@ -275,7 +280,8 @@ order_approve_info = EventPluginSignal()
""" """
Arguments: ``order``, ``request`` Arguments: ``order``, ``request``
This signal is sent out to display additional information on the order approve page This signal is sent out to display additional information on the order approve page.
Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
Additionally, the argument ``order`` and ``request`` are available. Additionally, the argument ``order`` and ``request`` are available.
@@ -286,6 +292,7 @@ order_position_buttons = EventPluginSignal()
Arguments: ``order``, ``position``, ``request`` Arguments: ``order``, ``position``, ``request``
This signal is sent out to display additional buttons for a single position of an order. This signal is sent out to display additional buttons for a single position of an order.
Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
Additionally, the argument ``order`` and ``request`` are available. Additionally, the argument ``order`` and ``request`` are available.
@@ -315,6 +322,7 @@ Arguments: 'request'
This signal is sent out to include template snippets on the settings page of an event This signal is sent out to include template snippets on the settings page of an event
that allows generating a pretix Widget code. that allows generating a pretix Widget code.
Receivers should return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
A second keyword argument ``request`` will contain the request object. A second keyword argument ``request`` will contain the request object.
@@ -19,7 +19,7 @@
</p> </p>
<ul> <ul>
{% for issue in issues %} {% for issue in issues %}
<li>{{ issue|safe }}</li> <li>{{ issue }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@@ -42,7 +42,7 @@
</p> </p>
<ul> <ul>
{% for issue in issues %} {% for issue in issues %}
<li>{{ issue|safe }}</li> <li>{{ issue }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
+16 -10
View File
@@ -161,7 +161,8 @@ voucher_redeem_info = EventPluginSignal()
""" """
Arguments: ``voucher`` Arguments: ``voucher``
This signal is sent out to display additional information on the "redeem a voucher" page This signal is sent out to display additional information on the "redeem a voucher" page.
You are expected to return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -194,6 +195,7 @@ Arguments: ``request``
This signals allows you to add HTML content to the confirmation page that is presented at the This signals allows you to add HTML content to the confirmation page that is presented at the
end of the checkout process, just before the order is being created. end of the checkout process, just before the order is being created.
You are expected to return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. A ``request`` As with all event plugin signals, the ``sender`` keyword argument will contain the event. A ``request``
argument will contain the request object. argument will contain the request object.
@@ -276,7 +278,8 @@ order_info = EventPluginSignal()
""" """
Arguments: ``order``, ``request`` Arguments: ``order``, ``request``
This signal is sent out to display additional information on the order detail page This signal is sent out to display additional information on the order detail page.
Return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -285,7 +288,8 @@ position_info = EventPluginSignal()
""" """
Arguments: ``order``, ``position``, ``request`` Arguments: ``order``, ``position``, ``request``
This signal is sent out to display additional information on the position detail page This signal is sent out to display additional information on the position detail page.
Return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -294,7 +298,8 @@ order_info_top = EventPluginSignal()
""" """
Arguments: ``order``, ``request`` Arguments: ``order``, ``request``
This signal is sent out to display additional information on top of the order detail page This signal is sent out to display additional information on top of the order detail page.
Return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -303,7 +308,8 @@ position_info_top = EventPluginSignal()
""" """
Arguments: ``order``, ``position``, ``request`` Arguments: ``order``, ``position``, ``request``
This signal is sent out to display additional information on top of the position detail page This signal is sent out to display additional information on top of the position detail page.
Return a SafeString containing HTML, or a string that will be HTML-escaped.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. As with all event plugin signals, the ``sender`` keyword argument will contain the event.
""" """
@@ -349,7 +355,7 @@ This signal is sent out to display additional information on the frontpage above
of products and but below a custom frontpage text. of products and but below a custom frontpage text.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. The As with all event plugin signals, the ``sender`` keyword argument will contain the event. The
receivers are expected to return HTML. receivers are expected to return a SafeString containing HTML, or a string that will be HTML-escaped.
""" """
render_seating_plan = EventPluginSignal() render_seating_plan = EventPluginSignal()
@@ -361,7 +367,7 @@ You will be passed the ``request`` as a keyword argument. If applicable, a ``sub
``voucher`` argument might be given. ``voucher`` argument might be given.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. The As with all event plugin signals, the ``sender`` keyword argument will contain the event. The
receivers are expected to return HTML. receivers are expected to return a SafeString containing HTML, or a string that will be HTML-escaped.
""" """
front_page_bottom = EventPluginSignal() front_page_bottom = EventPluginSignal()
@@ -372,7 +378,7 @@ This signal is sent out to display additional information on the frontpage below
of products. of products.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. The As with all event plugin signals, the ``sender`` keyword argument will contain the event. The
receivers are expected to return HTML. receivers are expected to return a SafeString containing HTML, or a string that will be HTML-escaped.
""" """
front_page_bottom_widget = EventPluginSignal() front_page_bottom_widget = EventPluginSignal()
@@ -383,7 +389,7 @@ This signal is sent out to display additional information on the frontpage below
of products if the front page is shown in the widget. of products if the front page is shown in the widget.
As with all event plugin signals, the ``sender`` keyword argument will contain the event. The As with all event plugin signals, the ``sender`` keyword argument will contain the event. The
receivers are expected to return HTML. receivers are expected to return a SafeString containing HTML, or a string that will be HTML-escaped.
""" """
checkout_all_optional = EventPluginSignal() checkout_all_optional = EventPluginSignal()
@@ -403,7 +409,7 @@ Arguments: ``item``, ``variation``, ``subevent``
This signal is sent out when the description of an item or variation is rendered and allows you to append This signal is sent out when the description of an item or variation is rendered and allows you to append
additional text to the description. You are passed the ``item``, ``variation`` and ``subevent``. You are additional text to the description. You are passed the ``item``, ``variation`` and ``subevent``. You are
expected to return HTML. expected to return markdown.
""" """
register_cookie_providers = EventPluginSignal() register_cookie_providers = EventPluginSignal()
@@ -9,7 +9,7 @@
{% load anonymize_email %} {% load anonymize_email %}
{% block thetitle %} {% block thetitle %}
{% if messages %} {% if messages %}
{{ messages|join:" " }} :: {{ messages|join:" " }} ::
{% endif %} {% endif %}
{% block title %}{% endblock %}{% if request.resolver_match.url_name != "event.index" %} :: {% endif %}{{ event.name }} {% block title %}{% endblock %}{% if request.resolver_match.url_name != "event.index" %} :: {% endif %}{{ event.name }}
{% endblock %} {% endblock %}
@@ -1,6 +1,7 @@
{% extends "pretixpresale/event/base.html" %} {% extends "pretixpresale/event/base.html" %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
{% load static %}
{% load eventurl %} {% load eventurl %}
{% load cache_large %} {% load cache_large %}
{% load money %} {% load money %}
@@ -39,6 +40,7 @@
{% else %} {% else %}
<meta property="og:url" content="{% abseventurl request.event "presale:event.index" %}" /> <meta property="og:url" content="{% abseventurl request.event "presale:event.index" %}" />
{% endif %} {% endif %}
<script type="text/javascript" src="{% static "pretixpresale/js/csrfcookieretry.js" %}"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@@ -6,6 +6,7 @@
{% load money %} {% load money %}
{% load expiresformat %} {% load expiresformat %}
{% load eventurl %} {% load eventurl %}
{% load static %}
{% load phone_format %} {% load phone_format %}
{% load rich_text %} {% load rich_text %}
{% load getitem %} {% load getitem %}
@@ -22,6 +23,10 @@
{% endif %} {% endif %}
{% trans "Order details" %} {% trans "Order details" %}
{% endblock %} {% endblock %}
{% block custom_header %}
{{ block.super }}
<script type="text/javascript" src="{% static "pretixpresale/js/csrfcookieretry.js" %}"></script>
{% endblock %}
{% block content %} {% block content %}
{% if "thanks" in request.GET or "paid" in request.GET %} {% if "thanks" in request.GET or "paid" in request.GET %}
<div class="thank-you"> <div class="thank-you">
+1 -1
View File
@@ -123,7 +123,7 @@ def widget_css_etag(request, version, **kwargs):
def _use_vite(request): def _use_vite(request):
if getattr(settings, 'PRETIX_WIDGET_VITE', False): if getattr(settings, 'PRETIX_WIDGET_VITE', False) or "beta" in request.GET:
return True return True
origin = request.META.get('HTTP_ORIGIN', '') origin = request.META.get('HTTP_ORIGIN', '')
gs = GlobalSettingsObject() gs = GlobalSettingsObject()
@@ -0,0 +1,15 @@
document.addEventListener("DOMContentLoaded", () => {
const COOKIE_NAME = "__Host-pretix_csrftoken";
const RELOAD_FLAG = "csrfReloadPerformed";
const hasCookie = document.cookie
.split("; ")
.some((c) => c.startsWith(COOKIE_NAME + "="));
if (!hasCookie && !sessionStorage.getItem(RELOAD_FLAG)) {
sessionStorage.setItem(RELOAD_FLAG, "1");
location.reload();
} else if (hasCookie && sessionStorage.getItem(RELOAD_FLAG)) {
sessionStorage.removeItem(RELOAD_FLAG);
}
});