Files
pretix_cgo/src/pretix/presale/utils.py
2019-06-17 22:59:45 +02:00

187 lines
7.6 KiB
Python

import warnings
from importlib import import_module
from urllib.parse import urljoin
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.urls import resolve
from django.utils.translation import ugettext_lazy as _
from django_scopes import scope
from pretix.base.middleware import LocaleMiddleware
from pretix.base.models import Event, Organizer
from pretix.multidomain.urlreverse import get_domain
from pretix.presale.signals import process_request, process_response
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
@scope(organizer=None)
def _detect_event(request, require_live=True, require_plugin=None):
if hasattr(request, '_event_detected'):
return
db = 'default'
if request.method == 'GET':
db = settings.DATABASE_REPLICA
url = resolve(request.path_info)
try:
if hasattr(request, 'organizer_domain'):
# We are on an organizer's custom domain
if 'organizer' in url.kwargs and url.kwargs['organizer']:
if url.kwargs['organizer'] != request.organizer.slug:
raise Http404(_('The selected event was not found.'))
path = "/" + request.get_full_path().split("/", 2)[-1]
return redirect(path)
request.event = request.organizer.events.using(db).get(
slug=url.kwargs['event'],
organizer=request.organizer,
)
request.organizer = request.organizer
else:
# We are on our main domain
if 'event' in url.kwargs and 'organizer' in url.kwargs:
request.event = Event.objects\
.select_related('organizer')\
.using(db)\
.get(
slug=url.kwargs['event'],
organizer__slug=url.kwargs['organizer']
)
request.organizer = request.event.organizer
elif 'organizer' in url.kwargs:
request.organizer = Organizer.objects.using(db).get(
slug=url.kwargs['organizer']
)
else:
raise Http404()
# If this organizer has a custom domain, send the user there
domain = get_domain(request.organizer)
if domain:
if request.port and request.port not in (80, 443):
domain = '%s:%d' % (domain, request.port)
path = request.get_full_path().split("/", 2)[-1]
r = redirect(urljoin('%s://%s' % (request.scheme, domain), path))
r['Access-Control-Allow-Origin'] = '*'
return r
if hasattr(request, 'event'):
# Restrict locales to the ones available for this event
LocaleMiddleware().process_request(request)
if require_live and 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)))
try:
parentdata = sparent.load()
except:
pass
else:
can_access = 'event_access' in parentdata
if not can_access:
raise PermissionDenied(_('The selected ticket shop is currently not available.'))
if require_plugin:
is_core = any(require_plugin.startswith(m) for m in settings.CORE_MODULES)
if require_plugin not in request.event.get_plugins() and not is_core:
raise Http404(_('This feature is not enabled.'))
if not hasattr(request, 'sales_channel'):
# The environ lookup is only relevant during unit testing
request.sales_channel = request.environ.get('PRETIX_SALES_CHANNEL', 'web')
for receiver, response in process_request.send(request.event, request=request):
if response:
return response
except Event.DoesNotExist:
try:
if hasattr(request, 'organizer_domain'):
event = request.organizer.events.get(
slug__iexact=url.kwargs['event'],
organizer=request.organizer,
)
pathparts = request.get_full_path().split('/')
pathparts[1] = event.slug
return redirect('/'.join(pathparts))
else:
if 'event' in url.kwargs and 'organizer' in url.kwargs:
event = Event.objects.select_related('organizer').get(
slug__iexact=url.kwargs['event'],
organizer__slug__iexact=url.kwargs['organizer']
)
pathparts = request.get_full_path().split('/')
pathparts[1] = event.organizer.slug
pathparts[2] = event.slug
return redirect('/'.join(pathparts))
except Event.DoesNotExist:
raise Http404(_('The selected event was not found.'))
raise Http404(_('The selected event was not found.'))
except Organizer.DoesNotExist:
if 'organizer' in url.kwargs:
try:
organizer = Organizer.objects.get(
slug__iexact=url.kwargs['organizer']
)
except Organizer.DoesNotExist:
raise Http404(_('The selected organizer was not found.'))
pathparts = request.get_full_path().split('/')
pathparts[1] = organizer.slug
return redirect('/'.join(pathparts))
raise Http404(_('The selected organizer was not found.'))
request._event_detected = True
def _event_view(function=None, require_live=True, require_plugin=None):
def event_view_wrapper(func, require_live=require_live):
def wrap(request, *args, **kwargs):
ret = _detect_event(request, require_live=require_live, require_plugin=require_plugin)
if ret:
return ret
else:
with scope(organizer=getattr(request, 'organizer', None)):
response = func(request=request, *args, **kwargs)
for receiver, r in process_response.send(request.event, request=request, response=response):
response = r
if isinstance(response, TemplateResponse):
response = response.render()
return response
for attrname in dir(func):
# Preserve flags like csrf_exempt
if not attrname.startswith('__'):
setattr(wrap, attrname, getattr(func, attrname))
return wrap
if function:
return event_view_wrapper(function, require_live=require_live)
return event_view_wrapper
def event_view(function=None, require_live=True):
warnings.warn('The event_view decorator is deprecated since it will be automatically applied by the URL routing '
'layer when you use event_urls.',
DeprecationWarning)
def noop(fn):
return fn
return function or noop