Refs #32508 -- Raised ImproperlyConfigured/TypeError instead of using "assert" in various code.

This commit is contained in:
Mateo Radman 2021-06-20 20:16:33 +02:00 committed by Mariusz Felisiak
parent 64839512a6
commit 8a7ac78b70
7 changed files with 36 additions and 11 deletions

View File

@ -12,7 +12,7 @@ from django.contrib.auth.forms import (
) )
from django.contrib.auth.tokens import default_token_generator from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import ValidationError from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.http import HttpResponseRedirect, QueryDict from django.http import HttpResponseRedirect, QueryDict
from django.shortcuts import resolve_url from django.shortcuts import resolve_url
from django.urls import reverse_lazy from django.urls import reverse_lazy
@ -261,7 +261,10 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
@method_decorator(sensitive_post_parameters()) @method_decorator(sensitive_post_parameters())
@method_decorator(never_cache) @method_decorator(never_cache)
def dispatch(self, *args, **kwargs): def dispatch(self, *args, **kwargs):
assert 'uidb64' in kwargs and 'token' in kwargs if 'uidb64' not in kwargs or 'token' not in kwargs:
raise ImproperlyConfigured(
"The URL path must contain 'uidb64' and 'token' parameters."
)
self.validlink = False self.validlink = False
self.user = self.get_user(kwargs['uidb64']) self.user = self.get_user(kwargs['uidb64'])

View File

@ -80,8 +80,8 @@ class Signal:
# If DEBUG is on, check that we got a good receiver # If DEBUG is on, check that we got a good receiver
if settings.configured and settings.DEBUG: if settings.configured and settings.DEBUG:
assert callable(receiver), "Signal receivers must be callable." if not callable(receiver):
raise TypeError('Signal receivers must be callable.')
# Check for **kwargs # Check for **kwargs
if not func_accepts_kwargs(receiver): if not func_accepts_kwargs(receiver):
raise ValueError("Signal receivers must accept keyword arguments (**kwargs).") raise ValueError("Signal receivers must accept keyword arguments (**kwargs).")

View File

@ -77,11 +77,12 @@ def sensitive_post_parameters(*parameters):
def decorator(view): def decorator(view):
@functools.wraps(view) @functools.wraps(view)
def sensitive_post_parameters_wrapper(request, *args, **kwargs): def sensitive_post_parameters_wrapper(request, *args, **kwargs):
assert isinstance(request, HttpRequest), ( if not isinstance(request, HttpRequest):
"sensitive_post_parameters didn't receive an HttpRequest. " raise TypeError(
"If you are decorating a classmethod, be sure to use " "sensitive_post_parameters didn't receive an HttpRequest "
"@method_decorator." "object. If you are decorating a classmethod, make sure "
) "to use @method_decorator."
)
if parameters: if parameters:
request.sensitive_post_parameters = parameters request.sensitive_post_parameters = parameters
else: else:

View File

@ -23,6 +23,7 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.middleware import SessionMiddleware from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.sites.requests import RequestSite from django.contrib.sites.requests import RequestSite
from django.core import mail from django.core import mail
from django.core.exceptions import ImproperlyConfigured
from django.db import connection from django.db import connection
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.middleware.csrf import CsrfViewMiddleware, get_token from django.middleware.csrf import CsrfViewMiddleware, get_token
@ -386,6 +387,11 @@ class PasswordResetTest(AuthViewsTestCase):
response = Client().get('/reset/%s/set-password/' % uuidb64) response = Client().get('/reset/%s/set-password/' % uuidb64)
self.assertContains(response, 'The password reset link was invalid') self.assertContains(response, 'The password reset link was invalid')
def test_missing_kwargs(self):
msg = "The URL path must contain 'uidb64' and 'token' parameters."
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/reset/missing_parameters/')
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUser') @override_settings(AUTH_USER_MODEL='auth_tests.CustomUser')
class CustomUserPasswordResetTest(AuthViewsTestCase): class CustomUserPasswordResetTest(AuthViewsTestCase):

View File

@ -133,6 +133,7 @@ urlpatterns = auth_urlpatterns + [
post_reset_login_backend='django.contrib.auth.backends.AllowAllUsersModelBackend', post_reset_login_backend='django.contrib.auth.backends.AllowAllUsersModelBackend',
), ),
), ),
path('reset/missing_parameters/', views.PasswordResetConfirmView.as_view()),
path('password_change/custom/', path('password_change/custom/',
views.PasswordChangeView.as_view(success_url='/custom/')), views.PasswordChangeView.as_view(success_url='/custom/')),
path('password_change/custom/named/', path('password_change/custom/named/',

View File

@ -58,7 +58,7 @@ class DispatcherTests(SimpleTestCase):
@override_settings(DEBUG=True) @override_settings(DEBUG=True)
def test_cannot_connect_non_callable(self): def test_cannot_connect_non_callable(self):
msg = 'Signal receivers must be callable.' msg = 'Signal receivers must be callable.'
with self.assertRaisesMessage(AssertionError, msg): with self.assertRaisesMessage(TypeError, msg):
a_signal.connect(object()) a_signal.connect(object())
self.assertTestIsClean(a_signal) self.assertTestIsClean(a_signal)

View File

@ -12,7 +12,7 @@ from unittest import mock
from django.core import mail from django.core import mail
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.db import DatabaseError, connection from django.db import DatabaseError, connection
from django.http import Http404 from django.http import Http404, HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from django.template import TemplateDoesNotExist from django.template import TemplateDoesNotExist
from django.test import RequestFactory, SimpleTestCase, override_settings from django.test import RequestFactory, SimpleTestCase, override_settings
@ -1635,3 +1635,17 @@ class DecoratorsTests(SimpleTestCase):
@sensitive_post_parameters @sensitive_post_parameters
def test_func(request): def test_func(request):
return index_page(request) return index_page(request)
def test_sensitive_post_parameters_http_request(self):
class MyClass:
@sensitive_post_parameters()
def a_view(self, request):
return HttpResponse()
msg = (
"sensitive_post_parameters didn't receive an HttpRequest object. "
"If you are decorating a classmethod, make sure to use "
"@method_decorator."
)
with self.assertRaisesMessage(TypeError, msg):
MyClass().a_view(HttpRequest())