mirror of
https://github.com/pretix/pretix.git
synced 2026-05-08 15:44:02 +00:00
Time machine mode [Z#23129725] (#3961)
Allows organizers to test their shop as if it were a different date and time. Implemented using a time_machine_now() function which is used instead of regular now(), which can overlay the real date time with a value from a ContextVar, assigned from a session value in EventMiddleware. For more information, see doc/development/implementation/timemachine.rst --------- Co-authored-by: Richard Schreiber <schreiber@rami.io> Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
@@ -38,6 +38,9 @@ from importlib import import_module
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import (
|
||||
BACKEND_SESSION_KEY, SESSION_KEY, get_user_model, load_backend,
|
||||
)
|
||||
from django.db.models import Q
|
||||
from django.http import Http404, HttpResponseForbidden
|
||||
from django.middleware.csrf import rotate_token
|
||||
@@ -52,6 +55,7 @@ from django_scopes import scope
|
||||
|
||||
from pretix.base.middleware import LocaleMiddleware
|
||||
from pretix.base.models import Customer, Event, Organizer
|
||||
from pretix.base.timemachine import time_machine_now_assigned_from_request
|
||||
from pretix.helpers.http import redirect_to_url
|
||||
from pretix.multidomain.urlreverse import (
|
||||
get_event_domain, get_organizer_domain,
|
||||
@@ -218,6 +222,17 @@ def customer_logout(request):
|
||||
request._cached_customer = None
|
||||
|
||||
|
||||
def _get_user_from_session_data(sessiondata):
|
||||
if SESSION_KEY not in sessiondata:
|
||||
return None
|
||||
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)
|
||||
return user
|
||||
|
||||
|
||||
@scope(organizer=None)
|
||||
def _detect_event(request, require_live=True, require_plugin=None):
|
||||
|
||||
@@ -303,14 +318,13 @@ def _detect_event(request, require_live=True, require_plugin=None):
|
||||
# Restrict locales to the ones available for this event
|
||||
LocaleMiddleware(NotImplementedError).process_request(request)
|
||||
|
||||
if require_live and not request.event.live:
|
||||
if require_live and (request.event.testmode or not request.event.live):
|
||||
can_access = (
|
||||
url.url_name == 'event.auth'
|
||||
or (
|
||||
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)))
|
||||
@@ -319,9 +333,12 @@ def _detect_event(request, require_live=True, require_plugin=None):
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
can_access = 'event_access' in parentdata
|
||||
user = _get_user_from_session_data(parentdata)
|
||||
if user and 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:
|
||||
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
|
||||
# don't want it to show in our log files.
|
||||
template = loader.get_template("pretixpresale/event/offline.html")
|
||||
@@ -393,7 +410,8 @@ def _event_view(function=None, require_live=True, require_plugin=None):
|
||||
if ret:
|
||||
return ret
|
||||
else:
|
||||
with scope(organizer=getattr(request, 'organizer', None)):
|
||||
with scope(organizer=getattr(request, 'organizer', None)), \
|
||||
time_machine_now_assigned_from_request(request):
|
||||
response = func(request=request, *args, **kwargs)
|
||||
if getattr(request, 'event', None):
|
||||
for receiver, r in process_response.send(request.event, request=request, response=response):
|
||||
|
||||
Reference in New Issue
Block a user