mirror of
https://github.com/pretix/pretix.git
synced 2026-03-04 11:02:27 +00:00
Compare commits
4 Commits
fix-empty-
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
959e926a67 | ||
|
|
876ddf1321 | ||
|
|
005b1d54d3 | ||
|
|
2066471086 |
@@ -19,6 +19,7 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
# 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/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from collections import Counter, defaultdict
|
from collections import Counter, defaultdict
|
||||||
@@ -1215,6 +1216,18 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
raise ValidationError('The given payment provider is not known.')
|
raise ValidationError('The given payment provider is not known.')
|
||||||
return pp
|
return pp
|
||||||
|
|
||||||
|
def validate_payment_info(self, info):
|
||||||
|
if info:
|
||||||
|
try:
|
||||||
|
obj = json.loads(info)
|
||||||
|
except ValueError:
|
||||||
|
raise ValidationError('payment_info must be valid JSON.')
|
||||||
|
|
||||||
|
if not isinstance(obj, dict):
|
||||||
|
# only objects are allowed
|
||||||
|
raise ValidationError('payment_info must be a JSON object.')
|
||||||
|
return info
|
||||||
|
|
||||||
def validate_expires(self, expires):
|
def validate_expires(self, expires):
|
||||||
if expires < now():
|
if expires < now():
|
||||||
raise ValidationError('Expiration date must be in the future.')
|
raise ValidationError('Expiration date must be in the future.')
|
||||||
|
|||||||
34
src/pretix/base/templatetags/anonymize_email.py
Normal file
34
src/pretix/base/templatetags/anonymize_email.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# 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.utils.html import mark_safe
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter("anon_email")
|
||||||
|
def anon_email(value):
|
||||||
|
"""Replaces @ with [at] and . with [dot] for anonymization."""
|
||||||
|
if not isinstance(value, str):
|
||||||
|
return value
|
||||||
|
value = value.replace("@", "[at]").replace(".", "[dot]")
|
||||||
|
return mark_safe(''.join(['&#{0};'.format(ord(char)) for char in value]))
|
||||||
@@ -518,6 +518,7 @@ def pretixcontrol_orderposition_blocked_display(sender: Event, orderposition, bl
|
|||||||
'The order requires approval before it can continue to be processed.'),
|
'The order requires approval before it can continue to be processed.'),
|
||||||
'pretix.event.order.approved': _('The order has been approved.'),
|
'pretix.event.order.approved': _('The order has been approved.'),
|
||||||
'pretix.event.order.denied': _('The order has been denied (comment: "{comment}").'),
|
'pretix.event.order.denied': _('The order has been denied (comment: "{comment}").'),
|
||||||
|
'pretix.event.order.vatid.validated': _('The customer VAT ID has been verified.'),
|
||||||
'pretix.event.order.contact.changed': _('The email address has been changed from "{old_email}" '
|
'pretix.event.order.contact.changed': _('The email address has been changed from "{old_email}" '
|
||||||
'to "{new_email}".'),
|
'to "{new_email}".'),
|
||||||
'pretix.event.order.contact.confirmed': _(
|
'pretix.event.order.contact.confirmed': _(
|
||||||
|
|||||||
@@ -1641,9 +1641,17 @@ class OrderCheckVATID(OrderView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
normalized_id = validate_vat_id(ia.vat_id, str(ia.country))
|
normalized_id = validate_vat_id(ia.vat_id, str(ia.country))
|
||||||
ia.vat_id_validated = True
|
with transaction.atomic():
|
||||||
ia.vat_id = normalized_id
|
ia.vat_id_validated = True
|
||||||
ia.save()
|
ia.vat_id = normalized_id
|
||||||
|
ia.save()
|
||||||
|
self.order.log_action(
|
||||||
|
'pretix.event.order.vatid.validated',
|
||||||
|
data={
|
||||||
|
'vat_id': normalized_id,
|
||||||
|
},
|
||||||
|
user=self.request.user,
|
||||||
|
)
|
||||||
except VATIDFinalError as e:
|
except VATIDFinalError as e:
|
||||||
messages.error(self.request, e.message)
|
messages.error(self.request, e.message)
|
||||||
except VATIDTemporaryError:
|
except VATIDTemporaryError:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
{% load eventurl %}
|
{% load eventurl %}
|
||||||
{% load safelink %}
|
{% load safelink %}
|
||||||
{% load rich_text %}
|
{% load rich_text %}
|
||||||
|
{% load anonymize_email %}
|
||||||
{% block thetitle %}
|
{% block thetitle %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
{{ messages|join:" " }} ::
|
{{ messages|join:" " }} ::
|
||||||
@@ -219,7 +220,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block footernav %}
|
{% block footernav %}
|
||||||
{% if request.event.settings.contact_mail %}
|
{% if request.event.settings.contact_mail %}
|
||||||
<li><a href="mailto:{{ request.event.settings.contact_mail }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
<li><a href="{{ 'mailto:'|add:request.event.settings.contact_mail|anon_email }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if request.event.settings.privacy_url %}
|
{% if request.event.settings.privacy_url %}
|
||||||
<li><a href="{% safelink request.event.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>
|
<li><a href="{% safelink request.event.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>
|
||||||
|
|||||||
@@ -21,4 +21,5 @@
|
|||||||
<script type="text/javascript" src="{% static "pretixpresale/js/ui/cart.js" %}"></script>
|
<script type="text/javascript" src="{% static "pretixpresale/js/ui/cart.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "pretixpresale/js/ui/iframe.js" %}"></script>
|
<script type="text/javascript" src="{% static "pretixpresale/js/ui/iframe.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "pretixbase/js/addressform.js" %}"></script>
|
<script type="text/javascript" src="{% static "pretixbase/js/addressform.js" %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static "pretixbase/js/deanonymize_email.js" %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
{% load thumb %}
|
{% load thumb %}
|
||||||
{% load eventurl %}
|
{% load eventurl %}
|
||||||
{% load safelink %}
|
{% load safelink %}
|
||||||
|
{% load anonymize_email %}
|
||||||
{% block thetitle %}
|
{% block thetitle %}
|
||||||
{% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }}
|
{% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -97,7 +98,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block footernav %}
|
{% block footernav %}
|
||||||
{% if not request.event and request.organizer.settings.contact_mail %}
|
{% if not request.event and request.organizer.settings.contact_mail %}
|
||||||
<li><a href="mailto:{{ request.organizer.settings.contact_mail }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
<li><a href="{{ 'mailto:'|add:request.organizer.settings.contact_mail|anon_email }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not request.event and request.organizer.settings.privacy_url %}
|
{% if not request.event and request.organizer.settings.privacy_url %}
|
||||||
<li><a href="{% safelink request.organizer.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>
|
<li><a href="{% safelink request.organizer.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>
|
||||||
|
|||||||
7
src/pretix/static/pretixbase/js/deanonymize_email.js
Normal file
7
src/pretix/static/pretixbase/js/deanonymize_email.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
document.querySelectorAll('a[href^="mailto:"]').forEach(function(link) {
|
||||||
|
// Replace [at] with @ and the [dot] with . in both the href and the displayed text (if needed)
|
||||||
|
link.href = link.href.replace('[at]', '@').replace('[dot]', '.');
|
||||||
|
link.textContent = link.textContent.replace('[at]', '@').replace('[dot]', '.');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -895,6 +895,41 @@ def test_order_create_payment_info_optional(token_client, organizer, event, item
|
|||||||
assert json.loads(p.info) == res['payment_info']
|
assert json.loads(p.info) == res['payment_info']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_order_create_payment_info_valid_object(token_client, organizer, event, item, quota, question):
|
||||||
|
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
|
||||||
|
res['positions'][0]['item'] = item.pk
|
||||||
|
res['positions'][0]['answers'][0]['question'] = question.pk
|
||||||
|
|
||||||
|
res["payment_info"] = [{"should": "fail"}]
|
||||||
|
resp = token_client.post(
|
||||||
|
'/api/v1/organizers/{}/events/{}/orders/'.format(
|
||||||
|
organizer.slug, event.slug
|
||||||
|
), format='json', data=res
|
||||||
|
)
|
||||||
|
assert resp.status_code == 400
|
||||||
|
|
||||||
|
res['payment_info'] = {
|
||||||
|
'foo': {
|
||||||
|
'bar': [1, 2],
|
||||||
|
'test': False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp = token_client.post(
|
||||||
|
'/api/v1/organizers/{}/events/{}/orders/'.format(
|
||||||
|
organizer.slug, event.slug
|
||||||
|
), format='json', data=res
|
||||||
|
)
|
||||||
|
assert resp.status_code == 201
|
||||||
|
with scopes_disabled():
|
||||||
|
o = Order.objects.get(code=resp.data['code'])
|
||||||
|
|
||||||
|
p = o.payments.first()
|
||||||
|
assert p.provider == "banktransfer"
|
||||||
|
assert p.amount == o.total
|
||||||
|
assert json.loads(p.info) == res['payment_info']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_order_create_position_secret_optional(token_client, organizer, event, item, quota, question):
|
def test_order_create_position_secret_optional(token_client, organizer, event, item, quota, question):
|
||||||
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
|
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
|
||||||
|
|||||||
Reference in New Issue
Block a user