diff --git a/src/pretix/base/timemachine.py b/src/pretix/base/timemachine.py
index 68b6200475..d13a4a6ee4 100644
--- a/src/pretix/base/timemachine.py
+++ b/src/pretix/base/timemachine.py
@@ -31,8 +31,7 @@ timemachine_now_var = contextvars.ContextVar('timemachine_now', default=None)
@contextmanager
def time_machine_now_assigned_from_request(request):
if hasattr(request, 'event') and 'timemachine_now_dt' in request.session and \
- request.event.testmode and request.user.is_authenticated and \
- request.user.has_event_permission(request.organizer, request.event, 'can_change_event_settings', request):
+ request.event.testmode and has_time_machine_permission(request, request.event):
request.now_dt = parse(request.session['timemachine_now_dt'])
request.now_dt_is_fake = True
else:
@@ -60,3 +59,16 @@ def time_machine_now_assigned(now_dt):
yield
finally:
timemachine_now_var.set(None)
+
+
+def has_time_machine_permission(request, event):
+ permission = 'can_change_event_settings'
+
+ return (
+ request.user.is_authenticated and
+ request.user.has_event_permission(request.organizer, request.event, permission, request=request)
+ ) or (
+ getattr(request, 'event_access_user', None) and
+ request.event_access_user.is_authenticated and
+ request.event_access_user.has_event_permission(request.organizer, request.event, permission, request=request)
+ )
diff --git a/src/pretix/control/context.py b/src/pretix/control/context.py
index 55849e0e32..13eb1d2054 100644
--- a/src/pretix/control/context.py
+++ b/src/pretix/control/context.py
@@ -46,11 +46,11 @@ from pretix.base.settings import GlobalSettingsObject
from pretix.control.navigation import (
get_event_navigation, get_global_navigation, get_organizer_navigation,
)
-
-from ..helpers.i18n import (
+from pretix.helpers.i18n import (
get_javascript_format, get_javascript_output_format, get_moment_locale,
)
-from ..multidomain.urlreverse import get_event_domain
+from pretix.multidomain.urlreverse import get_event_domain
+
from .signals import html_head, nav_topbar
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
@@ -114,10 +114,8 @@ def _default_context(request):
s.create()
ctx['new_session'] = s.session_key
request.session['child_session_{}'.format(request.event.pk)] = s.session_key
- request.session['event_access'] = True
else:
ctx['new_session'] = child_sess
- request.session['event_access'] = True
if request.GET.get('subevent', ''):
# Do not use .get() for lazy evaluation
diff --git a/src/pretix/presale/templates/pretixpresale/event/base.html b/src/pretix/presale/templates/pretixpresale/event/base.html
index c1c7f6d863..2d660bde36 100644
--- a/src/pretix/presale/templates/pretixpresale/event/base.html
+++ b/src/pretix/presale/templates/pretixpresale/event/base.html
@@ -126,7 +126,7 @@
{% if request.event.testmode %}
{% if request.sales_channel.testmode_supported %}
- {% if request.user.is_authenticated %}
+ {% if request.user.is_authenticated or request.event_access_user.is_authenticated %}
diff --git a/src/pretix/presale/utils.py b/src/pretix/presale/utils.py
index a091159df9..929975dc2a 100644
--- a/src/pretix/presale/utils.py
+++ b/src/pretix/presale/utils.py
@@ -222,13 +222,13 @@ def customer_logout(request):
request._cached_customer = None
-def _apply_user_from_session_data(request, sessiondata):
+def _get_user_from_session_data(sessiondata):
user_id = get_user_model()._meta.pk.to_python(sessiondata[SESSION_KEY])
backend_path = sessiondata[BACKEND_SESSION_KEY]
if backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
user = backend.get_user(user_id)
- request.user = user
+ return user
@scope(organizer=None)
@@ -323,7 +323,6 @@ def _detect_event(request, require_live=True, require_plugin=None):
request.user.is_authenticated
and request.user.has_event_permission(request.organizer, request.event, request=request)
)
-
)
if not can_access and 'pretix_event_access_{}'.format(request.event.pk) in request.session:
sparent = SessionStore(request.session.get('pretix_event_access_{}'.format(request.event.pk)))
@@ -332,9 +331,10 @@ def _detect_event(request, require_live=True, require_plugin=None):
except:
pass
else:
- can_access = 'event_access' in parentdata
- if can_access:
- _apply_user_from_session_data(request, parentdata)
+ user = _get_user_from_session_data(parentdata)
+ if user.is_authenticated and user.has_event_permission(request.organizer, request.event, request=request):
+ can_access = True
+ request.event_access_user = user
if not can_access and not request.event.live:
# Directly construct view instead of just calling `raise` since this case is so common that we
diff --git a/src/pretix/presale/views/event.py b/src/pretix/presale/views/event.py
index 69deaaf56d..bc31b2d987 100644
--- a/src/pretix/presale/views/event.py
+++ b/src/pretix/presale/views/event.py
@@ -63,6 +63,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.generic import TemplateView
from pretix.base.channels import get_all_sales_channels
+from pretix.base.forms.widgets import SplitDateTimePickerWidget
from pretix.base.models import (
ItemVariation, Quota, SeatCategoryMapping, Voucher,
)
@@ -72,7 +73,12 @@ from pretix.base.models.items import (
)
from pretix.base.services.placeholders import PlaceholderContext
from pretix.base.services.quotas import QuotaAvailability
+from pretix.base.timemachine import has_time_machine_permission
from pretix.helpers.compat import date_fromisocalendar
+from pretix.helpers.formats.en.formats import (
+ SHORT_MONTH_DAY_FORMAT, WEEK_FORMAT,
+)
+from pretix.helpers.http import redirect_to_url
from pretix.multidomain.urlreverse import eventreverse
from pretix.presale.ical import get_public_ical
from pretix.presale.signals import item_description
@@ -81,10 +87,6 @@ from pretix.presale.views.organizer import (
filter_qs_by_attr, has_before_after, weeks_for_template,
)
-from ...base.forms.widgets import SplitDateTimePickerWidget
-from ...control.permissions import EventPermissionRequiredMixin
-from ...helpers.formats.en.formats import SHORT_MONTH_DAY_FORMAT, WEEK_FORMAT
-from ...helpers.http import redirect_to_url
from . import (
CartMixin, EventViewMixin, allow_frame_if_namespaced, get_cart,
iframe_entry_view_wrapper,
@@ -918,7 +920,7 @@ class EventAuth(View):
except:
raise PermissionDenied(_('Please go back and try again.'))
else:
- if 'event_access' not in parentdata:
+ if 'child_session_{}'.format(request.event.pk) not in parentdata:
raise PermissionDenied(_('Please go back and try again.'))
request.session['pretix_event_access_{}'.format(request.event.pk)] = parent
@@ -933,12 +935,13 @@ class TimemachineForm(forms.Form):
)
-class EventTimeMachine(EventViewMixin, EventPermissionRequiredMixin, TemplateView):
- permission = 'can_change_event_settings'
+class EventTimeMachine(EventViewMixin, TemplateView):
template_name = 'pretixpresale/event/timemachine.html'
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
+ if not has_time_machine_permission(request, request.event):
+ raise PermissionDenied(_('You are not allowed to access time machine mode.'))
self.timemachine_form = TimemachineForm(
data=request.method == 'POST' and request.POST or None,
initial=(