diff --git a/src/pretix/base/forms/__init__.py b/src/pretix/base/forms/__init__.py index 2060bbccdd..ead6a4bc81 100644 --- a/src/pretix/base/forms/__init__.py +++ b/src/pretix/base/forms/__init__.py @@ -1,9 +1,11 @@ import logging import i18nfield.forms +from django import forms from django.forms.models import ModelFormMetaclass from django.utils import six from django.utils.crypto import get_random_string +from formtools.wizard.views import SessionWizardView from hierarkey.forms import HierarkeyForm from pretix.base.models import Event @@ -71,3 +73,29 @@ class SettingsForm(i18nfield.forms.I18nFormMixin, HierarkeyForm): fname = '%s/%s.%s.%s' % (self.obj.slug, name, nonce, name.split('.')[-1]) # TODO: make sure pub is always correct return 'pub/' + fname + + +class PrefixForm(forms.Form): + prefix = forms.CharField(widget=forms.HiddenInput) + + +class SafeSessionWizardView(SessionWizardView): + def get_prefix(self, request, *args, **kwargs): + if hasattr(request, '_session_wizard_prefix'): + return request._session_wizard_prefix + prefix_form = PrefixForm(self.request.POST, prefix=super().get_prefix(request, *args, **kwargs)) + if not prefix_form.is_valid(): + request._session_wizard_prefix = get_random_string(length=24) + else: + request._session_wizard_prefix = prefix_form.cleaned_data['prefix'] + return request._session_wizard_prefix + + def get_context_data(self, form, **kwargs): + context = super().get_context_data(form=form, **kwargs) + context['wizard']['prefix_form'] = PrefixForm( + prefix=super().get_prefix(self.request), + initial={ + 'prefix': self.get_prefix(self.request) + } + ) + return context diff --git a/src/pretix/control/templates/pretixcontrol/events/create_base.html b/src/pretix/control/templates/pretixcontrol/events/create_base.html index 4e0fa772e9..642dca00b9 100644 --- a/src/pretix/control/templates/pretixcontrol/events/create_base.html +++ b/src/pretix/control/templates/pretixcontrol/events/create_base.html @@ -10,6 +10,7 @@
{% csrf_token %} {{ wizard.management_form }} + {{ wizard.prefix_form }} {% bootstrap_form_errors form %} {% block form %} {% endblock %} diff --git a/src/pretix/control/views/main.py b/src/pretix/control/views/main.py index 37110aa8dd..347b283287 100644 --- a/src/pretix/control/views/main.py +++ b/src/pretix/control/views/main.py @@ -12,9 +12,9 @@ from django.utils.functional import cached_property from django.utils.translation import ugettext, ugettext_lazy as _ from django.views import View from django.views.generic import ListView -from formtools.wizard.views import SessionWizardView from i18nfield.strings import LazyI18nString +from pretix.base.forms import SafeSessionWizardView from pretix.base.i18n import language from pretix.base.models import Event, Organizer, Quota, Team from pretix.control.forms.event import ( @@ -97,7 +97,7 @@ def condition_copy(wizard): return EventWizardCopyForm.copy_from_queryset(wizard.request.user).exists() -class EventWizard(SessionWizardView): +class EventWizard(SafeSessionWizardView): form_list = [ ('foundation', EventWizardFoundationForm), ('basics', EventWizardBasicsForm), diff --git a/src/tests/control/test_events.py b/src/tests/control/test_events.py index a1d3e7265b..153abd55b2 100644 --- a/src/tests/control/test_events.py +++ b/src/tests/control/test_events.py @@ -473,6 +473,7 @@ class EventsTest(SoupTest): def test_create_event_unauthorized(self): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga2.pk, 'foundation-locales': ('en', 'de') }) @@ -481,12 +482,14 @@ class EventsTest(SoupTest): def test_create_invalid_default_language(self): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga1.pk, 'foundation-locales': ('de',) }) doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-name_1': '33C3', 'basics-slug': '33c3', @@ -505,6 +508,7 @@ class EventsTest(SoupTest): def test_create_duplicate_slug(self): doc = self.post_doc('/control/events/add', { + 'event_wizard-prefix': 'event_wizard', 'event_wizard-current_step': 'foundation', 'foundation-organizer': self.orga1.pk, 'foundation-locales': ('de', 'en') @@ -512,6 +516,7 @@ class EventsTest(SoupTest): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-name_1': '33C3', 'basics-slug': '31c3', @@ -540,6 +545,7 @@ class EventsTest(SoupTest): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga1.pk, 'foundation-locales': ('en', 'de') }) @@ -548,6 +554,7 @@ class EventsTest(SoupTest): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-name_1': '33C3', 'basics-slug': '33c3', @@ -571,6 +578,7 @@ class EventsTest(SoupTest): self.post_doc('/control/events/add', { 'event_wizard-current_step': 'copy', + 'event_wizard-prefix': 'event_wizard', 'copy-copy_from_event': '' }) @@ -599,6 +607,7 @@ class EventsTest(SoupTest): self.assertNotIn("MRM", tabletext) doc = self.post_doc('/control/events/add', { + 'event_wizard-prefix': 'event_wizard', 'event_wizard-current_step': 'foundation', 'foundation-organizer': self.orga1.pk, 'foundation-locales': ('en', 'de'), @@ -606,6 +615,7 @@ class EventsTest(SoupTest): }) doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-name_1': '33C3', 'basics-slug': '33c3', @@ -626,6 +636,7 @@ class EventsTest(SoupTest): }) self.post_doc('/control/events/add', { 'event_wizard-current_step': 'copy', + 'event_wizard-prefix': 'event_wizard', 'copy-copy_from_event': '' }) ev = Event.objects.get(slug='33c3') @@ -649,6 +660,7 @@ class EventsTest(SoupTest): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga1.pk, 'foundation-locales': ('en', 'de') }) @@ -657,6 +669,7 @@ class EventsTest(SoupTest): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-name_1': '33C3', 'basics-slug': '33c3', @@ -680,6 +693,7 @@ class EventsTest(SoupTest): self.post_doc('/control/events/add', { 'event_wizard-current_step': 'copy', + 'event_wizard-prefix': 'event_wizard', 'copy-copy_from_event': self.event1.pk }) @@ -705,11 +719,13 @@ class EventsTest(SoupTest): # date_to, presale_start & presale_end are optional fields self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga1.pk, 'foundation-locales': 'en' }) self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-slug': '33c3', 'basics-date_from_0': '2016-12-27', @@ -728,6 +744,7 @@ class EventsTest(SoupTest): }) self.post_doc('/control/events/add', { 'event_wizard-current_step': 'copy', + 'event_wizard-prefix': 'event_wizard', 'copy-copy_from_event': '' }) @@ -749,11 +766,13 @@ class EventsTest(SoupTest): # date_from is mandatory self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga1.pk, 'foundation-locales': 'en' }) doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-slug': '33c3', 'basics-date_from_0': '', @@ -775,12 +794,14 @@ class EventsTest(SoupTest): def test_create_event_currency_symbol(self): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga1.pk, 'foundation-locales': 'en' }) doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-slug': '31c4', 'basics-date_from_0': '2016-12-27', @@ -802,12 +823,14 @@ class EventsTest(SoupTest): def test_create_event_non_iso_currency(self): doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'foundation', + 'event_wizard-prefix': 'event_wizard', 'foundation-organizer': self.orga1.pk, 'foundation-locales': 'en' }) doc = self.post_doc('/control/events/add', { 'event_wizard-current_step': 'basics', + 'event_wizard-prefix': 'event_wizard', 'basics-name_0': '33C3', 'basics-slug': '31c5', 'basics-date_from_0': '2016-12-27',