From 89ba2da7e7260691fdb566adf32172fd55012cbc Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Thu, 17 Aug 2023 10:10:27 +0200 Subject: [PATCH] QR code generator for voucher URLs and general URLs (#3518) * QR code generator: Allow other URLs to be used (e.g. for plugins) * Add QR code to voucher URL view * Fix allowed_hosts --------- Co-authored-by: Richard Schreiber --- .../event/fragment_qr_dropdown.html | 27 +++++++++++++++++++ .../templates/pretixcontrol/event/index.html | 23 +--------------- .../pretixcontrol/vouchers/detail.html | 16 ++++++++--- src/pretix/control/views/event.py | 10 ++++++- src/pretix/control/views/vouchers.py | 9 +++++++ 5 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 src/pretix/control/templates/pretixcontrol/event/fragment_qr_dropdown.html diff --git a/src/pretix/control/templates/pretixcontrol/event/fragment_qr_dropdown.html b/src/pretix/control/templates/pretixcontrol/event/fragment_qr_dropdown.html new file mode 100644 index 0000000000..b139d6dfd3 --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/event/fragment_qr_dropdown.html @@ -0,0 +1,27 @@ +{% load i18n %} + diff --git a/src/pretix/control/templates/pretixcontrol/event/index.html b/src/pretix/control/templates/pretixcontrol/event/index.html index 88f5fd3748..d89bb08efa 100644 --- a/src/pretix/control/templates/pretixcontrol/event/index.html +++ b/src/pretix/control/templates/pretixcontrol/event/index.html @@ -27,28 +27,7 @@ - + {% include "pretixcontrol/event/fragment_qr_dropdown.html" with url=0 %}
diff --git a/src/pretix/control/templates/pretixcontrol/vouchers/detail.html b/src/pretix/control/templates/pretixcontrol/vouchers/detail.html index 612f216b63..7e3542fab1 100644 --- a/src/pretix/control/templates/pretixcontrol/vouchers/detail.html +++ b/src/pretix/control/templates/pretixcontrol/vouchers/detail.html @@ -42,10 +42,18 @@
- +
+ +
+ + {% include "pretixcontrol/event/fragment_qr_dropdown.html" with url=url %} +
+
{% endif %} diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 35bf3c8116..b81ea68efb 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -40,7 +40,7 @@ from collections import OrderedDict from decimal import Decimal from io import BytesIO from itertools import groupby -from urllib.parse import urlsplit +from urllib.parse import urlparse, urlsplit from zoneinfo import ZoneInfo import bleach @@ -50,6 +50,7 @@ from django.apps import apps from django.conf import settings from django.contrib import messages from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import PermissionDenied from django.core.files import File from django.db import transaction from django.db.models import ProtectedError @@ -61,6 +62,7 @@ from django.http import ( from django.shortcuts import get_object_or_404, redirect from django.urls import reverse from django.utils.functional import cached_property +from django.utils.http import url_has_allowed_host_and_scheme from django.utils.timezone import now from django.utils.translation import gettext, gettext_lazy as _, gettext_noop from django.views.generic import FormView, ListView @@ -1530,6 +1532,12 @@ class EventQRCode(EventPermissionRequiredMixin, View): def get(self, request, *args, filetype, **kwargs): url = build_absolute_uri(request.event, 'presale:event.index') + if "url" in request.GET: + if url_has_allowed_host_and_scheme(request.GET["url"], allowed_hosts=[urlparse(url).netloc]): + url = request.GET["url"] + else: + raise PermissionDenied("Untrusted URL") + qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_M, diff --git a/src/pretix/control/views/vouchers.py b/src/pretix/control/views/vouchers.py index d354a7fc36..1574a55587 100644 --- a/src/pretix/control/views/vouchers.py +++ b/src/pretix/control/views/vouchers.py @@ -34,6 +34,7 @@ # License for the specific language governing permissions and limitations under the License. import io +from urllib.parse import urlencode import bleach from defusedcsv import csv @@ -75,6 +76,7 @@ from pretix.control.views import PaginationMixin from pretix.helpers.compat import CompatDeleteView from pretix.helpers.format import format_map from pretix.helpers.models import modelcopy +from pretix.multidomain.urlreverse import build_absolute_uri class VoucherList(PaginationMixin, EventPermissionRequiredMixin, ListView): @@ -315,6 +317,13 @@ class VoucherUpdate(EventPermissionRequiredMixin, UpdateView): expires__gte=now() ).count() ctx['redeemed_in_carts'] = redeemed_in_carts + + url_params = { + 'voucher': self.object.code + } + if self.object.subevent_id: + url_params['subevent'] = self.object.subevent_id + ctx['url'] = build_absolute_uri(self.request.event, "presale:event.redeem") + "?" + urlencode(url_params) return ctx