Compare commits

...

8 Commits

Author SHA1 Message Date
robbi5
2f792c52a3 Show device name on order print log 2026-05-20 09:33:23 +02:00
Martin Gross
412a5adf8f Control: Fix typo in gateSelectURL 2026-05-19 22:03:35 +02:00
dependabot[bot]
e4da2e5e03 Update reportlab requirement from ==4.4.* to ==4.5.* (#6138)
Updates the requirements on [reportlab](https://www.reportlab.com/) to permit the latest version.

---
updated-dependencies:
- dependency-name: reportlab
  dependency-version: 4.5.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 18:03:32 +02:00
Richard Schreiber
9d7038b127 Force async_task_is_download to be downloaded if in iframe (Z#23234427) (#6194)
* Force async_task_is_download to be downloaded if in iframe (Z#23234427)

* Update src/pretix/static/pretixbase/js/asynctask.js

Co-authored-by: luelista <weller@rami.io>

---------

Co-authored-by: luelista <weller@rami.io>
2026-05-19 17:07:54 +02:00
Richard Schreiber
ce5af572cc Improve error messages for name-parts inputs (Z#23234440) (#6187)
* Improve error messages for name-parts inputs (Z#23234440)

* fix isort after flake8

* correct spelling of .med in user-provided title/name

* fix search instead of match
2026-05-19 15:23:30 +02:00
dependabot[bot]
6d293e544e Bump django-formtools from 2.5.1 to 2.6.1 (#6191)
Bumps [django-formtools](https://github.com/jazzband/django-formtools) from 2.5.1 to 2.6.1.
- [Changelog](https://github.com/jazzband/django-formtools/blob/master/docs/changelog.rst)
- [Commits](https://github.com/jazzband/django-formtools/compare/2.5.1...2.6.1)

---
updated-dependencies:
- dependency-name: django-formtools
  dependency-version: 2.6.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 11:36:49 +02:00
dependabot[bot]
28a8032adf Update sentry-sdk requirement from ==2.59.* to ==2.60.* (#6190)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.59.0a1...2.60.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.60.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 11:36:25 +02:00
dependabot[bot]
d765a89139 Update djangorestframework requirement from ==3.16.* to ==3.17.* (#6013)
* Update djangorestframework requirement from ==3.16.* to ==3.17.*

Updates the requirements on [djangorestframework](https://github.com/encode/django-rest-framework) to permit the latest version.
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.16.0...3.17.0)

---
updated-dependencies:
- dependency-name: djangorestframework
  dependency-version: 3.17.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix failing test

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Raphael Michel <michel@rami.io>
2026-05-18 17:58:43 +02:00
6 changed files with 51 additions and 27 deletions

View File

@@ -43,7 +43,7 @@ dependencies = [
"django-countries==8.2.*", "django-countries==8.2.*",
"django-filter==25.1", "django-filter==25.1",
"django-formset-js-improved==0.5.0.5", "django-formset-js-improved==0.5.0.5",
"django-formtools==2.5.1", "django-formtools==2.6.1",
"django-hierarkey==2.0.*,>=2.0.1", "django-hierarkey==2.0.*,>=2.0.1",
"django-hijack==3.7.*", "django-hijack==3.7.*",
"django-i18nfield==1.11.*", "django-i18nfield==1.11.*",
@@ -56,7 +56,7 @@ dependencies = [
"django-redis==6.0.*", "django-redis==6.0.*",
"django-scopes==2.0.*", "django-scopes==2.0.*",
"django-statici18n==2.7.*", "django-statici18n==2.7.*",
"djangorestframework==3.16.*", "djangorestframework==3.17.*",
"dnspython==2.8.*", "dnspython==2.8.*",
"drf_ujson2==1.7.*", "drf_ujson2==1.7.*",
"geoip2==5.*", "geoip2==5.*",
@@ -91,9 +91,9 @@ dependencies = [
"pyuca", "pyuca",
"qrcode==8.2", "qrcode==8.2",
"redis==7.4.*", "redis==7.4.*",
"reportlab==4.4.*", "reportlab==4.5.*",
"requests==2.32.*", "requests==2.32.*",
"sentry-sdk==2.59.*", "sentry-sdk==2.60.*",
"sepaxml==2.7.*", "sepaxml==2.7.*",
"stripe==7.9.*", "stripe==7.9.*",
"text-unidecode==1.*", "text-unidecode==1.*",

View File

@@ -35,6 +35,7 @@
import copy import copy
import json import json
import logging import logging
import re
from datetime import timedelta from datetime import timedelta
from decimal import Decimal from decimal import Decimal
from io import BytesIO from io import BytesIO
@@ -47,9 +48,7 @@ from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.validators import ( from django.core.validators import MaxValueValidator, MinValueValidator
MaxValueValidator, MinValueValidator, RegexValidator,
)
from django.db.models import QuerySet from django.db.models import QuerySet
from django.forms import Select, widgets from django.forms import Select, widgets
from django.forms.widgets import FILE_INPUT_CONTRADICTION from django.forms.widgets import FILE_INPUT_CONTRADICTION
@@ -220,20 +219,6 @@ class NamePartsFormField(forms.MultiValueField):
defaults = { defaults = {
'widget': self.widget, 'widget': self.widget,
'max_length': kwargs.pop('max_length', None), 'max_length': kwargs.pop('max_length', None),
'validators': [
RegexValidator(
# The following characters should never appear in a name anywhere of
# the world. However, they commonly appear in inputs generated by spam
# bots.
r'^[^$€/%§{}<>~]*$',
message=_('Please do not use special characters in names.')
),
RegexValidator(
URL_RE,
inverse_match=True,
message=_('Please do not use special characters in names.')
)
]
} }
self.max_length = defaults['max_length'] self.max_length = defaults['max_length']
self.scheme_name = kwargs.pop('scheme') self.scheme_name = kwargs.pop('scheme')
@@ -255,7 +240,6 @@ class NamePartsFormField(forms.MultiValueField):
if fname == 'title' and self.scheme_titles: if fname == 'title' and self.scheme_titles:
d = dict(defaults) d = dict(defaults)
d.pop('max_length', None) d.pop('max_length', None)
d.pop('validators', None)
field = forms.ChoiceField( field = forms.ChoiceField(
**d, **d,
choices=[('', '')] + [(d, d) for d in self.scheme_titles[1]] choices=[('', '')] + [(d, d) for d in self.scheme_titles[1]]
@@ -264,7 +248,6 @@ class NamePartsFormField(forms.MultiValueField):
elif fname == 'salutation': elif fname == 'salutation':
d = dict(defaults) d = dict(defaults)
d.pop('max_length', None) d.pop('max_length', None)
d.pop('validators', None)
field = forms.ChoiceField( field = forms.ChoiceField(
**d, **d,
choices=[ choices=[
@@ -296,6 +279,37 @@ class NamePartsFormField(forms.MultiValueField):
if sum(len(v) for v in value.values() if v) > (self.max_length or 250): if sum(len(v) for v in value.values() if v) > (self.max_length or 250):
raise forms.ValidationError(_('Please enter a shorter name.'), code='max_length') raise forms.ValidationError(_('Please enter a shorter name.'), code='max_length')
for fname, label, size in self.scheme['fields']:
if fname == 'salutation' or (fname == 'title' and self.scheme_titles):
continue
v = value.get(fname)
if not v:
continue
special_chars = re.findall('[$€/%§{}<>~]', v)
if special_chars:
raise forms.ValidationError(
_('The field "%(label)s" may not contain special characters such as "%(chars)s".'),
code='name_special_chars',
params={
"label": label,
"chars": "".join(special_chars),
},
)
# URL_RE checks for valid domain names, including one special TLD med, which can be part of a title
if ".med" in v:
v = v.replace(".med", ". med")
value[fname] = v
url_matched = URL_RE.search(v)
if url_matched:
raise forms.ValidationError(
_('The field "%(label)s" may not contain an URL (%(url)s).'),
code='url_in_title',
params={
"label": label,
"url": url_matched.group(0),
}
)
if value.get("salutation") == "empty": if value.get("salutation") == "empty":
value["salutation"] = "" value["salutation"] = ""

View File

@@ -553,7 +553,7 @@
<span class="fa fa-print"></span> <span class="fa fa-print"></span>
{{ pl.datetime|date:"SHORT_DATETIME_FORMAT" }} {{ pl.datetime|date:"SHORT_DATETIME_FORMAT" }}
{{ pl.get_type_display }} {{ pl.get_type_display }}
({{ pl.source }}{% if pl.device %}, #{{ pl.device.device_id }}{% endif %}) ({{ pl.source }}{% if pl.device %}, {{ pl.device.name }} - #{{ pl.device.device_id }}{% endif %})
{% if not pl.successful %}<span class="fa fa-warning fa-fw"></span>{% endif %} {% if not pl.successful %}<span class="fa fa-warning fa-fw"></span>{% endif %}
<br> <br>
{% endfor %} {% endfor %}

View File

@@ -53,7 +53,17 @@ function async_task_on_success(data) {
// hide waitingDialog when using browser's history back // hide waitingDialog when using browser's history back
waitingDialog.hide(); waitingDialog.hide();
}); });
location.href = data.redirect; if (async_task_is_download && window.self !== window.top) {
// if in an iframe, force to download an async_task_is_download
// e.g. pretix-reseller embeds order-page in iframe, which would cause ticket-PDFs to be displayed inline
var a = document.createElement("a");
a.href = data.redirect;
a.download = "";
a.target = "_blank";
a.click();
} else {
location.href = data.redirect;
}
} }
$(this).trigger('pretix:async-task-success', data); $(this).trigger('pretix:async-task-success', data);
} }

View File

@@ -65,4 +65,4 @@ if (itemsEl?.textContent) {
export const productSelectURL = ref(document.querySelector('#product-select2')?.textContent) export const productSelectURL = ref(document.querySelector('#product-select2')?.textContent)
export const variationSelectURL = ref(document.querySelector('#variations-select2')?.textContent) export const variationSelectURL = ref(document.querySelector('#variations-select2')?.textContent)
export const gateSelectURL = ref(document.querySelector('#gate-select2')?.textContent) export const gateSelectURL = ref(document.querySelector('#gates-select2')?.textContent)

View File

@@ -43,7 +43,7 @@ RES_RULE = {
"limit_products": [], "limit_products": [],
"limit_variations": [], "limit_variations": [],
"all_payment_methods": True, "all_payment_methods": True,
"limit_payment_methods": set(), "limit_payment_methods": [],
} }