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=(