diff --git a/src/pretix/api/urls.py b/src/pretix/api/urls.py index 1ad42a60e0..f5e96f1ed1 100644 --- a/src/pretix/api/urls.py +++ b/src/pretix/api/urls.py @@ -35,7 +35,8 @@ import importlib from django.apps import apps -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from rest_framework import routers from pretix.api.views import cart diff --git a/src/pretix/base/views/redirect.py b/src/pretix/base/views/redirect.py index 533144f99e..c5b65cd1eb 100644 --- a/src/pretix/base/views/redirect.py +++ b/src/pretix/base/views/redirect.py @@ -28,7 +28,7 @@ from django.urls import reverse def _is_samesite_referer(request): - referer = request.META.get('HTTP_REFERER') + referer = request.headers.get('referer') if referer is None: return False diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 4bfdc24951..a3ece0290a 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -33,7 +33,8 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under the License. -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from django.views.generic.base import RedirectView from pretix.control.views import ( diff --git a/src/pretix/control/views/dashboards.py b/src/pretix/control/views/dashboards.py index 66446a33aa..50746d131d 100644 --- a/src/pretix/control/views/dashboards.py +++ b/src/pretix/control/views/dashboards.py @@ -51,7 +51,7 @@ from django.utils import formats from django.utils.formats import date_format from django.utils.html import escape from django.utils.timezone import now -from django.utils.translation import gettext_lazy as _, pgettext, ungettext +from django.utils.translation import gettext_lazy as _, ngettext, pgettext from pretix.base.decimal import round_decimal from pretix.base.models import ( @@ -555,7 +555,7 @@ def widgets_for_event_qs(request, qs, user, nmax, lazy=False): 'event': event.slug, 'organizer': event.organizer.slug }), - orders_text=ungettext('{num} order', '{num} orders', event.order_count or 0).format( + orders_text=ngettext('{num} order', '{num} orders', event.order_count or 0).format( num=event.order_count or 0 ) ) if user.has_active_staff_session(request.session.session_key) or event.pk in events_with_orders else '' diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 631231c736..fddca01036 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -62,7 +62,7 @@ from django.urls import reverse from django.utils import formats from django.utils.formats import date_format, get_format from django.utils.functional import cached_property -from django.utils.http import is_safe_url +from django.utils.http import url_has_allowed_host_and_scheme from django.utils.timezone import make_aware, now from django.utils.translation import gettext, gettext_lazy as _, ngettext from django.views.generic import ( @@ -680,7 +680,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"), allowed_hosts=None): + if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None): return redirect(self.request.GET.get("next")) return redirect(self.get_order_url()) @@ -716,7 +716,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"), allowed_hosts=None): + if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None): return redirect(self.request.GET.get("next")) return redirect(self.get_order_url()) @@ -742,7 +742,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"), allowed_hosts=None): + if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None): return redirect(self.request.GET.get("next")) return redirect(self.get_order_url()) diff --git a/src/pretix/control/views/waitinglist.py b/src/pretix/control/views/waitinglist.py index 4881aba7a1..ee775665cb 100644 --- a/src/pretix/control/views/waitinglist.py +++ b/src/pretix/control/views/waitinglist.py @@ -43,7 +43,7 @@ from django.http import Http404, HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.functional import cached_property -from django.utils.http import is_safe_url +from django.utils.http import url_has_allowed_host_and_scheme from django.utils.timezone import now from django.utils.translation import gettext_lazy as _, pgettext from django.views import View @@ -144,7 +144,7 @@ class WaitingListActionView(EventPermissionRequiredMixin, WaitingListQuerySetMix permission = 'can_change_orders' def _redirect_back(self): - if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None): + if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None): return redirect(self.request.GET.get("next")) return redirect(reverse('control:event.orders.waitinglist', kwargs={ 'event': self.request.event.slug, @@ -360,7 +360,7 @@ class EntryDelete(EventPermissionRequiredMixin, DeleteView): self.object.log_action('pretix.event.orders.waitinglist.deleted', user=self.request.user) self.object.delete() messages.success(self.request, _('The selected entry has been deleted.')) - if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None): + if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None): return redirect(self.request.GET.get("next")) return HttpResponseRedirect(success_url) diff --git a/src/pretix/helpers/http.py b/src/pretix/helpers/http.py index eec2b437c5..47f5752b99 100644 --- a/src/pretix/helpers/http.py +++ b/src/pretix/helpers/http.py @@ -38,7 +38,7 @@ class ChunkBasedFileResponse(StreamingHttpResponse): def get_client_ip(request): ip = request.META.get('REMOTE_ADDR') if settings.TRUST_X_FORWARDED_FOR: - x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + x_forwarded_for = request.headers.get('x-forwarded-for') if x_forwarded_for: ip = x_forwarded_for.split(',')[0] return ip diff --git a/src/pretix/multidomain/event_domain_urlconf.py b/src/pretix/multidomain/event_domain_urlconf.py index 2aea8ca743..29987671c6 100644 --- a/src/pretix/multidomain/event_domain_urlconf.py +++ b/src/pretix/multidomain/event_domain_urlconf.py @@ -22,7 +22,8 @@ import importlib.util from django.apps import apps -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from pretix.multidomain.plugin_handler import plugin_event_urls from pretix.presale.urls import event_patterns, locale_patterns diff --git a/src/pretix/multidomain/maindomain_urlconf.py b/src/pretix/multidomain/maindomain_urlconf.py index 61f8980f5e..b03dbfce6b 100644 --- a/src/pretix/multidomain/maindomain_urlconf.py +++ b/src/pretix/multidomain/maindomain_urlconf.py @@ -35,7 +35,8 @@ import importlib.util from django.apps import apps -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from django.views.generic import TemplateView from pretix.multidomain.plugin_handler import plugin_event_urls diff --git a/src/pretix/multidomain/organizer_domain_urlconf.py b/src/pretix/multidomain/organizer_domain_urlconf.py index 65e8708842..e7098096a1 100644 --- a/src/pretix/multidomain/organizer_domain_urlconf.py +++ b/src/pretix/multidomain/organizer_domain_urlconf.py @@ -22,7 +22,8 @@ import importlib.util from django.apps import apps -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from pretix.multidomain.plugin_handler import plugin_event_urls from pretix.presale.urls import ( diff --git a/src/pretix/plugins/paypal/urls.py b/src/pretix/plugins/paypal/urls.py index cb373ddf25..0a29004270 100644 --- a/src/pretix/plugins/paypal/urls.py +++ b/src/pretix/plugins/paypal/urls.py @@ -19,7 +19,8 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from .views import abort, oauth_disconnect, redirect_view, success diff --git a/src/pretix/plugins/paypal2/urls.py b/src/pretix/plugins/paypal2/urls.py index e49ca964ae..f85b71864b 100644 --- a/src/pretix/plugins/paypal2/urls.py +++ b/src/pretix/plugins/paypal2/urls.py @@ -19,7 +19,8 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from .views import ( PayView, XHRView, abort, isu_disconnect, isu_return, redirect_view, diff --git a/src/pretix/plugins/stripe/urls.py b/src/pretix/plugins/stripe/urls.py index 011a3cf98a..dbcf9d45c9 100644 --- a/src/pretix/plugins/stripe/urls.py +++ b/src/pretix/plugins/stripe/urls.py @@ -19,7 +19,8 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from pretix.multidomain import event_url diff --git a/src/pretix/presale/urls.py b/src/pretix/presale/urls.py index 0a63c61704..2d8b0ad476 100644 --- a/src/pretix/presale/urls.py +++ b/src/pretix/presale/urls.py @@ -32,7 +32,8 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under the License. -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from django.views.decorators.csrf import csrf_exempt import pretix.presale.views.cart diff --git a/src/pretix/presale/views/cart.py b/src/pretix/presale/views/cart.py index 5650c65312..3f287b7f02 100644 --- a/src/pretix/presale/views/cart.py +++ b/src/pretix/presale/views/cart.py @@ -48,7 +48,7 @@ from django.utils import translation from django.utils.crypto import get_random_string from django.utils.decorators import method_decorator from django.utils.functional import cached_property -from django.utils.http import is_safe_url, url_has_allowed_host_and_scheme +from django.utils.http import url_has_allowed_host_and_scheme from django.utils.timezone import now from django.utils.translation import gettext as _, pgettext from django.views.decorators.clickjacking import xframe_options_exempt @@ -83,7 +83,7 @@ except: class CartActionMixin: def get_next_url(self): - if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None): + if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None): u = self.request.GET.get('next') else: kwargs = {} @@ -106,7 +106,7 @@ class CartActionMixin: return self.get_next_url() def get_error_url(self): - if "next_error" in self.request.GET and is_safe_url(self.request.GET.get("next_error"), allowed_hosts=None): + if "next_error" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next_error"), allowed_hosts=None): u = self.request.GET.get('next_error') if '?' in u: u += '&require_cookie=true' diff --git a/src/pretix/urls.py b/src/pretix/urls.py index 3d6d96d645..3fd42ea801 100644 --- a/src/pretix/urls.py +++ b/src/pretix/urls.py @@ -33,7 +33,8 @@ # License for the specific language governing permissions and limitations under the License. from django.conf import settings -from django.conf.urls import include, re_path +from django.conf.urls import re_path +from django.urls import include from django.views.generic import RedirectView import pretix.control.urls diff --git a/src/tests/api/test_checkin.py b/src/tests/api/test_checkin.py index 6ef20442e4..9132e9af89 100644 --- a/src/tests/api/test_checkin.py +++ b/src/tests/api/test_checkin.py @@ -23,8 +23,6 @@ import datetime import time from decimal import Decimal from unittest import mock -# deprecated: from django.utils.http import urlquote -# use urlib instead from urllib.parse import quote as urlquote import pytest diff --git a/src/tests/testdummy/__init__.py b/src/tests/testdummy/__init__.py index 7bff28a9a5..9fd5bdc500 100644 --- a/src/tests/testdummy/__init__.py +++ b/src/tests/testdummy/__init__.py @@ -19,19 +19,3 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # -from django.apps import AppConfig - - -class TestDummyApp(AppConfig): - name = 'tests.testdummy' - verbose_name = '.testdummy' - - class PretixPluginMeta: - name = '.testdummy' - version = '1.0.0' - - def ready(self): - from tests.testdummy import signals # noqa - - -default_app_config = 'tests.testdummy.TestDummyApp' diff --git a/src/tests/testdummy/apps.py b/src/tests/testdummy/apps.py new file mode 100644 index 0000000000..ea89f7ce8b --- /dev/null +++ b/src/tests/testdummy/apps.py @@ -0,0 +1,34 @@ +# +# This file is part of pretix (Community Edition). +# +# Copyright (C) 2014-2020 Raphael Michel and contributors +# Copyright (C) 2020-2021 rami.io GmbH and contributors +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General +# Public License as published by the Free Software Foundation in version 3 of the License. +# +# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are +# applicable granting you additional permissions and placing additional restrictions on your usage of this software. +# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive +# this file, see . +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along with this program. If not, see +# . +# +from django.apps import AppConfig + + +class TestDummyApp(AppConfig): + name = 'tests.testdummy' + verbose_name = '.testdummy' + + class PretixPluginMeta: + name = '.testdummy' + version = '1.0.0' + + def ready(self): + from tests.testdummy import signals # noqa