mirror of
https://github.com/pretix/pretix.git
synced 2026-05-21 17:54:08 +00:00
Compare commits
2 Commits
system-not
...
pajowu/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4fdf85d46 | ||
|
|
82fc3627cc |
@@ -43,7 +43,7 @@ dependencies = [
|
||||
"django-countries==8.2.*",
|
||||
"django-filter==25.1",
|
||||
"django-formset-js-improved==0.5.0.5",
|
||||
"django-formtools==2.6.1",
|
||||
"django-formtools==2.5.1",
|
||||
"django-hierarkey==2.0.*,>=2.0.1",
|
||||
"django-hijack==3.7.*",
|
||||
"django-i18nfield==1.11.*",
|
||||
@@ -56,7 +56,7 @@ dependencies = [
|
||||
"django-redis==6.0.*",
|
||||
"django-scopes==2.0.*",
|
||||
"django-statici18n==2.7.*",
|
||||
"djangorestframework==3.17.*",
|
||||
"djangorestframework==3.16.*",
|
||||
"dnspython==2.8.*",
|
||||
"drf_ujson2==1.7.*",
|
||||
"geoip2==5.*",
|
||||
@@ -91,9 +91,9 @@ dependencies = [
|
||||
"pyuca",
|
||||
"qrcode==8.2",
|
||||
"redis==7.4.*",
|
||||
"reportlab==4.5.*",
|
||||
"reportlab==4.4.*",
|
||||
"requests==2.32.*",
|
||||
"sentry-sdk==2.60.*",
|
||||
"sentry-sdk==2.59.*",
|
||||
"sepaxml==2.7.*",
|
||||
"stripe==7.9.*",
|
||||
"text-unidecode==1.*",
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from io import BytesIO
|
||||
@@ -48,7 +47,9 @@ from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.core.validators import (
|
||||
MaxValueValidator, MinValueValidator, RegexValidator,
|
||||
)
|
||||
from django.db.models import QuerySet
|
||||
from django.forms import Select, widgets
|
||||
from django.forms.widgets import FILE_INPUT_CONTRADICTION
|
||||
@@ -219,6 +220,20 @@ class NamePartsFormField(forms.MultiValueField):
|
||||
defaults = {
|
||||
'widget': self.widget,
|
||||
'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.scheme_name = kwargs.pop('scheme')
|
||||
@@ -240,6 +255,7 @@ class NamePartsFormField(forms.MultiValueField):
|
||||
if fname == 'title' and self.scheme_titles:
|
||||
d = dict(defaults)
|
||||
d.pop('max_length', None)
|
||||
d.pop('validators', None)
|
||||
field = forms.ChoiceField(
|
||||
**d,
|
||||
choices=[('', '')] + [(d, d) for d in self.scheme_titles[1]]
|
||||
@@ -248,6 +264,7 @@ class NamePartsFormField(forms.MultiValueField):
|
||||
elif fname == 'salutation':
|
||||
d = dict(defaults)
|
||||
d.pop('max_length', None)
|
||||
d.pop('validators', None)
|
||||
field = forms.ChoiceField(
|
||||
**d,
|
||||
choices=[
|
||||
@@ -279,37 +296,6 @@ class NamePartsFormField(forms.MultiValueField):
|
||||
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')
|
||||
|
||||
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":
|
||||
value["salutation"] = ""
|
||||
|
||||
|
||||
@@ -55,12 +55,10 @@
|
||||
{% trans "You receive these emails based on your notification settings." %}<br>
|
||||
<a href="{{ settings_url }}">
|
||||
{% trans "Click here to view and change your notification settings" %}
|
||||
</a><br>
|
||||
<a href="{{ disable_url }}">
|
||||
{% trans "Click here disable all notifications immediately." %}
|
||||
</a>
|
||||
{% if disable_url %}<br>
|
||||
<a href="{{ disable_url }}">
|
||||
{% trans "Click here disable all notifications immediately." %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<!--[if gte mso 9]>
|
||||
</td></tr></table>
|
||||
|
||||
@@ -14,6 +14,5 @@
|
||||
{% trans "You receive these emails based on your notification settings." %}
|
||||
{% trans "Click here to view and change your notification settings:" %}
|
||||
{{ settings_url }}
|
||||
{% if disable_url %}{% trans "Click here disable all notifications immediately:" %}
|
||||
{% trans "Click here disable all notifications immediately:" %}
|
||||
{{ disable_url }}
|
||||
{% endif %}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def human_readable_locale(value):
|
||||
if not value:
|
||||
return ''
|
||||
return dict(settings.LANGUAGES).get(value, '')
|
||||
@@ -405,7 +405,7 @@ def process_banktransfers(self, job: int, data: list) -> None:
|
||||
# We need to sort prefixes by length with long ones first. In case we have an event with slug
|
||||
# "CONF" and one with slug "CONF2022", we want CONF2022 to match first, to avoid the parser
|
||||
# thinking "2022" is already the order code.
|
||||
"|".join(sorted([re.escape(p).replace("\\-", r"[\- ]*") for p in prefixes], key=lambda p: len(p), reverse=True)),
|
||||
"|".join([re.escape(p).replace("\\-", r"[\- ]*") for p in sorted(prefixes, key=lambda p: len(p), reverse=True)]),
|
||||
min(code_len_agg['min'] or 1, inr_len_agg['min'] or 1),
|
||||
max(code_len_agg['max'] or 5, inr_len_agg['max'] or 5)
|
||||
)
|
||||
|
||||
@@ -53,17 +53,7 @@ function async_task_on_success(data) {
|
||||
// hide waitingDialog when using browser's history back
|
||||
waitingDialog.hide();
|
||||
});
|
||||
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;
|
||||
}
|
||||
location.href = data.redirect;
|
||||
}
|
||||
$(this).trigger('pretix:async-task-success', data);
|
||||
}
|
||||
|
||||
@@ -65,4 +65,4 @@ if (itemsEl?.textContent) {
|
||||
|
||||
export const productSelectURL = ref(document.querySelector('#product-select2')?.textContent)
|
||||
export const variationSelectURL = ref(document.querySelector('#variations-select2')?.textContent)
|
||||
export const gateSelectURL = ref(document.querySelector('#gates-select2')?.textContent)
|
||||
export const gateSelectURL = ref(document.querySelector('#gate-select2')?.textContent)
|
||||
|
||||
@@ -43,7 +43,7 @@ RES_RULE = {
|
||||
"limit_products": [],
|
||||
"limit_variations": [],
|
||||
"all_payment_methods": True,
|
||||
"limit_payment_methods": [],
|
||||
"limit_payment_methods": set(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -834,3 +834,56 @@ def test_ambigious_date_with_region(env, job):
|
||||
|
||||
with scopes_disabled():
|
||||
assert env[2].payments.last().info_data["date"] == "2016-05-03"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_event_name_prefix_contains_dash(env, orga_job):
|
||||
event, user, o1, o2 = env
|
||||
slugs = ['dummy-2', 'dummy2345']
|
||||
for slug in slugs:
|
||||
event = Event.objects.create(
|
||||
organizer=event.organizer, name=slug.upper(), slug=slug,
|
||||
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'
|
||||
)
|
||||
with scopes_disabled():
|
||||
o1.event = Event.objects.get(slug="dummy2345")
|
||||
o1.save()
|
||||
process_banktransfers(orga_job, [{
|
||||
'payer': 'Karla Kundin',
|
||||
'reference': f'DUMMY2345-{o1.code}',
|
||||
'date': '2016-01-26',
|
||||
'amount': '23.00'
|
||||
}])
|
||||
with scopes_disabled():
|
||||
job = BankImportJob.objects.last()
|
||||
t = job.transactions.last()
|
||||
assert t.state == BankTransaction.STATE_VALID
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
@pytest.mark.django_db
|
||||
def test_event_name_prefix_multiple_dashes(env, orga_job):
|
||||
# We decided to ignore the case of multiple events where the event slugs only differ in dashes
|
||||
# for now. If we change that, switch this test case from xfail to regular test.
|
||||
|
||||
event, user, o1, o2 = env
|
||||
slugs = ['dummy-2', 'dummy--2', 'dummy2345']
|
||||
for slug in slugs:
|
||||
event = Event.objects.create(
|
||||
organizer=event.organizer, name=slug.upper(), slug=slug,
|
||||
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'
|
||||
)
|
||||
|
||||
with scopes_disabled():
|
||||
o1.event = Event.objects.get(slug="dummy-2")
|
||||
o1.save()
|
||||
process_banktransfers(orga_job, [{
|
||||
'payer': 'Karla Kundin',
|
||||
'reference': f'DUMMY2-{o1.code}',
|
||||
'date': '2016-01-26',
|
||||
'amount': '23.00'
|
||||
}])
|
||||
with scopes_disabled():
|
||||
job = BankImportJob.objects.last()
|
||||
t = job.transactions.last()
|
||||
assert t.state == BankTransaction.STATE_VALID
|
||||
|
||||
Reference in New Issue
Block a user