From bd5337a2c2e296b7dfa0e24b8d26cb189f742fc7 Mon Sep 17 00:00:00 2001 From: Alexey Kislitsin Date: Fri, 14 Apr 2017 19:04:30 +0300 Subject: [PATCH] Fix #448 -- Add PlaceholderValidator (#465) * Integrated PlaceholderValidator to MailForm at plugins/sendmail * Integrated PlaceholderValidator to MailForm and MailSettingsForm * Typo --- src/pretix/base/forms/__init__.py | 1 + src/pretix/base/forms/validators.py | 31 ++++++++++++++++++++++++++++ src/pretix/control/forms/event.py | 27 ++++++++++++++++-------- src/pretix/plugins/sendmail/forms.py | 5 ++++- 4 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 src/pretix/base/forms/validators.py diff --git a/src/pretix/base/forms/__init__.py b/src/pretix/base/forms/__init__.py index 8bde46fcba..756f60f0dc 100644 --- a/src/pretix/base/forms/__init__.py +++ b/src/pretix/base/forms/__init__.py @@ -6,6 +6,7 @@ from django.utils import six from django.utils.crypto import get_random_string from hierarkey.forms import HierarkeyForm +from .validators import PlaceholderValidator from pretix.base.models import Event logger = logging.getLogger('pretix.plugins.ticketoutputpdf') diff --git a/src/pretix/base/forms/validators.py b/src/pretix/base/forms/validators.py new file mode 100644 index 0000000000..2e87623b73 --- /dev/null +++ b/src/pretix/base/forms/validators.py @@ -0,0 +1,31 @@ +import re +from django.core.exceptions import ValidationError +from django.core.validators import BaseValidator +from django.utils.translation import ugettext_lazy as _ + + +class PlaceholderValidator(BaseValidator): + """ + Takes list of allowed placeholders, + validates form field by checking for placeholders, + which are not presented in taken list. + """ + + def __init__(self, limit_value): + super().__init__(limit_value) + self.limit_value = limit_value + + def __call__(self, value): + data_placeholders = list(re.findall(r'({[\w\s]*})', value, re.X)) + invalid_placeholders = [] + for placeholder in data_placeholders: + if placeholder not in self.limit_value: + invalid_placeholders.append(placeholder) + if invalid_placeholders: + raise ValidationError( + _('Invalid placeholder(s): %(value)s'), + code='invalid', + params={'value': ", ".join(invalid_placeholders,)}) + + def clean(self, x): + return x diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py index e690261c1c..da66e04a0f 100644 --- a/src/pretix/control/forms/event.py +++ b/src/pretix/control/forms/event.py @@ -7,7 +7,7 @@ from django.utils.translation import ugettext_lazy as _ from i18nfield.forms import I18nFormField, I18nTextarea from pytz import common_timezones, timezone -from pretix.base.forms import I18nModelForm, SettingsForm +from pretix.base.forms import I18nModelForm, SettingsForm, PlaceholderValidator from pretix.base.models import Event, Organizer from pretix.control.forms import ExtFileField @@ -461,37 +461,44 @@ class MailSettingsForm(SettingsForm): required=False, widget=I18nTextarea, help_text=_("Available placeholders: {event}, {total}, {currency}, {date}, {paymentinfo}, {url}, " - "{invoice_name}, {invoice_company}") + "{invoice_name}, {invoice_company}"), + validators=[PlaceholderValidator(['{event}', '{total}', '{currency}', '{date}', '{paymentinfo}', + '{url}', '{invoice_name}', '{invoice_company}'])] ) mail_text_order_paid = I18nFormField( label=_("Text"), required=False, widget=I18nTextarea, - help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}, {payment_info}") + help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}, {payment_info}"), + validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}', '{payment_info}'])] ) mail_text_order_free = I18nFormField( label=_("Text"), required=False, widget=I18nTextarea, - help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}") + help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}"), + validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}'])] ) mail_text_order_changed = I18nFormField( label=_("Text"), required=False, widget=I18nTextarea, - help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}") + help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}"), + validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}'])] ) mail_text_resend_link = I18nFormField( label=_("Text (sent by admin)"), required=False, widget=I18nTextarea, - help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}") + help_text=_("Available placeholders: {event}, {url}, {invoice_name}, {invoice_company}"), + validators=[PlaceholderValidator(['{event}', '{url}', '{invoice_name}', '{invoice_company}'])] ) mail_text_resend_all_links = I18nFormField( label=_("Text (requested by user)"), required=False, widget=I18nTextarea, - help_text=_("Available placeholders: {event}, {orders}") + help_text=_("Available placeholders: {event}, {orders}"), + validators=[PlaceholderValidator(['{event}', '{orders}'])] ) mail_days_order_expire_warning = forms.IntegerField( label=_("Number of days"), @@ -504,13 +511,15 @@ class MailSettingsForm(SettingsForm): label=_("Text"), required=False, widget=I18nTextarea, - help_text=_("Available placeholders: {event}, {url}, {expire_date}, {invoice_name}, {invoice_company}") + help_text=_("Available placeholders: {event}, {url}, {expire_date}, {invoice_name}, {invoice_company}"), + validators=[PlaceholderValidator(['{event}', '{url}', '{expire_date}', '{invoice_name}', '{invoice_company}'])] ) mail_text_waiting_list = I18nFormField( label=_("Text"), required=False, widget=I18nTextarea, - help_text=_("Available placeholders: {event}, {url}, {product}, {hours}, {code}") + help_text=_("Available placeholders: {event}, {url}, {product}, {hours}, {code}"), + validators=[PlaceholderValidator(['{event}', '{url}', '{product}', '{hours}', '{code}'])] ) smtp_use_custom = forms.BooleanField( label=_("Use custom SMTP server"), diff --git a/src/pretix/plugins/sendmail/forms.py b/src/pretix/plugins/sendmail/forms.py index 597e10fb17..92fe19f1db 100644 --- a/src/pretix/plugins/sendmail/forms.py +++ b/src/pretix/plugins/sendmail/forms.py @@ -2,6 +2,7 @@ from django import forms from django.utils.translation import ugettext_lazy as _ from i18nfield.forms import I18nFormField, I18nTextarea, I18nTextInput +from pretix.base.forms import PlaceholderValidator from pretix.base.models import Order @@ -21,7 +22,9 @@ class MailForm(forms.Form): widget=I18nTextarea, required=True, locales=event.settings.get('locales'), help_text=_("Available placeholders: {due_date}, {event}, {order}, {order_date}, {order_url}, " - "{invoice_name}, {invoice_company}") + "{invoice_name}, {invoice_company}"), + validators=[PlaceholderValidator(['{due_date}', '{event}', '{order}', '{order_date}', '{order_url}', + '{invoice_name}', '{invoice_company}'])] ) choices = list(Order.STATUS_CHOICE) if not event.settings.get('payment_term_expire_automatically', as_type=bool):