Upgrade to Django 2.1 (#710)

* Upgrade to Django 2.0

* more models

* i18n foo

* Update setup.py

* Fix Sentry exception PRETIXEU-JC

* Enforce slug uniqueness

* Import sorting

* Upgrade to Django 2.1

* Travis config

* Try to fix PostgreSQL failure

* Smaller test matrix

* staticfiles→static

* Include request in all authenticate() calls
This commit is contained in:
Raphael Michel
2018-08-06 12:48:46 +02:00
committed by GitHub
parent 0637490216
commit afd766999c
131 changed files with 491 additions and 263 deletions

View File

@@ -48,13 +48,13 @@ def login(request):
request.session['pretix_auth_2fa_user'] = form.user_cache.pk
request.session['pretix_auth_2fa_time'] = str(int(time.time()))
twofa_url = reverse('control:auth.login.2fa')
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
twofa_url += '?next=' + quote(request.GET.get('next'))
return redirect(twofa_url)
else:
auth_login(request, form.user_cache)
request.session['pretix_auth_login_time'] = int(time.time())
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
return redirect(reverse('control:index'))
else:
@@ -72,7 +72,7 @@ def logout(request):
auth_logout(request)
request.session['pretix_auth_login_time'] = 0
next = reverse('control:auth.login')
if 'next' in request.GET and is_safe_url(request.GET.get('next')):
if 'next' in request.GET and is_safe_url(request.GET.get('next'), allowed_hosts=None):
next += '?next=' + quote(request.GET.get('next'))
return redirect(next)
@@ -94,7 +94,7 @@ def register(request):
locale=request.LANGUAGE_CODE,
timezone=request.timezone if hasattr(request, 'timezone') else settings.TIME_ZONE
)
user = authenticate(email=user.email, password=form.cleaned_data['password'])
user = authenticate(request=request, email=user.email, password=form.cleaned_data['password'])
user.log_action('pretix.control.auth.user.created', user=user)
auth_login(request, user)
request.session['pretix_auth_login_time'] = int(time.time())
@@ -148,7 +148,7 @@ def invite(request, token):
locale=request.LANGUAGE_CODE,
timezone=request.timezone if hasattr(request, 'timezone') else settings.TIME_ZONE
)
user = authenticate(email=user.email, password=form.cleaned_data['password'])
user = authenticate(request=request, email=user.email, password=form.cleaned_data['password'])
user.log_action('pretix.control.auth.user.created', user=user)
auth_login(request, user)
request.session['pretix_auth_login_time'] = int(time.time())
@@ -329,7 +329,7 @@ class Login2FAView(TemplateView):
request.session['pretix_auth_login_time'] = int(time.time())
del request.session['pretix_auth_2fa_user']
del request.session['pretix_auth_2fa_time']
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
return redirect(reverse('control:index'))
else:

View File

@@ -1,10 +1,10 @@
import dateutil.parser
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Max, OuterRef, Subquery
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.timezone import is_aware, make_aware, now
from django.utils.translation import ugettext_lazy as _

View File

@@ -2,7 +2,6 @@ from decimal import Decimal
import pytz
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.db.models import (
Count, Exists, IntegerField, Max, Min, OuterRef, Q, Subquery, Sum,
)
@@ -10,6 +9,7 @@ from django.db.models.functions import Coalesce, Greatest
from django.dispatch import receiver
from django.shortcuts import render
from django.template.loader import get_template
from django.urls import reverse
from django.utils import formats
from django.utils.formats import date_format
from django.utils.html import escape

View File

@@ -9,7 +9,6 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.files import File
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import ProtectedError
from django.http import (
@@ -17,6 +16,7 @@ from django.http import (
JsonResponse,
)
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils import translation
from django.utils.formats import date_format
from django.utils.functional import cached_property

View File

@@ -2,12 +2,12 @@ import json
from django.contrib import messages
from django.core.files import File
from django.core.urlresolvers import resolve, reverse
from django.db import transaction
from django.db.models import Count, F, Q
from django.forms.models import inlineformset_factory
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import redirect
from django.urls import resolve, reverse
from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import ugettext, ugettext_lazy as _

View File

@@ -1,5 +1,4 @@
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import (
F, IntegerField, Max, Min, OuterRef, Prefetch, Subquery, Sum,
@@ -7,6 +6,7 @@ from django.db.models import (
from django.db.models.functions import Coalesce, Greatest
from django.http import JsonResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.translation import ugettext, ugettext_lazy as _

View File

@@ -10,11 +10,11 @@ import vat_moss.id
from django.conf import settings
from django.contrib import messages
from django.core.files import File
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Count
from django.http import FileResponse, Http404, HttpResponseNotAllowed
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils import formats
from django.utils.formats import date_format
from django.utils.functional import cached_property
@@ -275,7 +275,7 @@ class OrderRefundCancel(OrderView):
messages.success(self.request, _('The refund has been canceled.'))
else:
messages.error(self.request, _('This refund can not be canceled at the moment.'))
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next")):
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None):
return redirect(self.request.GET.get("next"))
return redirect(self.get_order_url())
@@ -310,7 +310,7 @@ class OrderRefundProcess(OrderView):
messages.success(self.request, _('The refund has been processed.'))
else:
messages.error(self.request, _('This refund can not be processed at the moment.'))
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next")):
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None):
return redirect(self.request.GET.get("next"))
return redirect(self.get_order_url())
@@ -336,7 +336,7 @@ class OrderRefundDone(OrderView):
messages.success(self.request, _('The refund has been marked as done.'))
else:
messages.error(self.request, _('This refund can not be processed at the moment.'))
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next")):
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None):
return redirect(self.request.GET.get("next"))
return redirect(self.get_order_url())

View File

@@ -2,11 +2,11 @@ from django import forms
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.core.files import File
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Count
from django.forms import inlineformset_factory
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (

View File

@@ -3,13 +3,13 @@ from datetime import datetime
from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule, rruleset
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import F, IntegerField, OuterRef, Prefetch, Subquery, Sum
from django.db.models.functions import Coalesce
from django.forms import inlineformset_factory
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.timezone import make_aware
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
@@ -424,7 +424,7 @@ class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateVi
kwargs = super().get_form_kwargs()
kwargs['event'] = self.request.event
if self.copy_from:
i = copy.copy(self.copy_from)
i = copy.deepcopy(self.copy_from)
i.pk = None
kwargs['instance'] = i
else:

View File

@@ -7,8 +7,8 @@ from urllib.parse import quote
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.http import is_safe_url
@@ -73,7 +73,7 @@ class ReauthView(TemplateView):
t = int(time.time())
request.session['pretix_auth_login_time'] = t
request.session['pretix_auth_last_used'] = t
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
return redirect(reverse('control:index'))
else:
@@ -544,7 +544,7 @@ class StartStaffSession(StaffMemberRequiredMixin, RecentAuthenticationRequiredMi
session_key=request.session.session_key
)
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
else:
return redirect(reverse("control:index"))

View File

@@ -1,13 +1,16 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import get_object_or_404, redirect
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, resolve_url
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.http import is_safe_url
from django.utils.translation import ugettext_lazy as _
from django.views import View
from django.views.generic import ListView
from hijack.helpers import login_user, release_hijack
from pretix.base.models import User
from pretix.base.services.mail import SendMailException
@@ -161,3 +164,78 @@ class UserCreateView(AdministratorPermissionRequiredMixin, RecentAuthenticationR
def form_valid(self, form):
messages.success(self.request, _('The new user has been created.'))
return super().form_valid(form)
# TODO: COMPAT methods: Remove after https://github.com/arteria/django-hijack/pull/178 is merged
def login_user(request, hijacked):
from hijack.helpers import (
check_hijack_authorization, get_used_backend, no_update_last_login, login,
hijack_started, hijack_settings
)
hijacker = request.user
hijack_history = [request.user._meta.pk.value_to_string(hijacker)]
if request.session.get('hijack_history'):
hijack_history = request.session['hijack_history'] + hijack_history
check_hijack_authorization(request, hijacked)
backend = get_used_backend(request)
hijacked.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
with no_update_last_login():
# Actually log user in
login(request, hijacked)
hijack_started.send(
sender=None, request=request,
hijacker=hijacker, hijacked=hijacked,
# send IDs for backward compatibility
hijacker_id=hijacker.pk, hijacked_id=hijacked.pk)
request.session['hijack_history'] = hijack_history
request.session['is_hijacked_user'] = True
request.session['display_hijack_warning'] = True
request.session.modified = True
return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGIN_REDIRECT_URL)
def redirect_to_next(request, default_url):
redirect_to = request.GET.get('next', '')
if not is_safe_url(redirect_to, allowed_hosts=None):
redirect_to = default_url
return HttpResponseRedirect(resolve_url(redirect_to))
def release_hijack(request):
from hijack.helpers import (
get_used_backend, no_update_last_login, login, hijack_ended, hijack_settings
)
hijack_history = request.session.get('hijack_history', False)
if not hijack_history:
raise PermissionDenied
hijacker = None
hijacked = None
if hijack_history:
hijacked = request.user
user_pk = hijack_history.pop()
hijacker = get_object_or_404(get_user_model(), pk=user_pk)
backend = get_used_backend(request)
hijacker.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
with no_update_last_login():
login(request, hijacker)
if hijack_history:
request.session['hijack_history'] = hijack_history
request.session['is_hijacked_user'] = True
request.session['display_hijack_warning'] = True
else:
request.session.pop('hijack_history', None)
request.session.pop('is_hijacked_user', None)
request.session.pop('display_hijack_warning', None)
request.session.modified = True
hijack_ended.send(
sender=None, request=request,
hijacker=hijacker, hijacked=hijacked,
# send IDs for backward compatibility
hijacker_id=hijacker.pk, hijacked_id=hijacked.pk)
return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGOUT_REDIRECT_URL)

View File

@@ -3,7 +3,6 @@ import io
from defusedcsv import csv
from django.conf import settings
from django.contrib import messages
from django.core.urlresolvers import resolve, reverse
from django.db import transaction
from django.db.models import Sum
from django.http import (
@@ -11,6 +10,7 @@ from django.http import (
JsonResponse,
)
from django.shortcuts import redirect
from django.urls import resolve, reverse
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (