Refs #27795 -- Removed force_bytes() usage from django/utils/http.py.
django.utils.http.urlsafe_base64_encode() now returns a string, not a bytestring. Since URLs are represented as strings, urlsafe_base64_encode() should return a string. All uses immediately decoded the bytestring to a string anyway. As the inverse operation, urlsafe_base64_decode() accepts a string.
This commit is contained in:
parent
f3d3338e06
commit
c82893cb8c
|
@ -284,7 +284,7 @@ class PasswordResetForm(forms.Form):
|
||||||
'email': email,
|
'email': email,
|
||||||
'domain': domain,
|
'domain': domain,
|
||||||
'site_name': site_name,
|
'site_name': site_name,
|
||||||
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
|
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
|
||||||
'user': user,
|
'user': user,
|
||||||
'token': token_generator.make_token(user),
|
'token': token_generator.make_token(user),
|
||||||
'protocol': 'https' if use_https else 'http',
|
'protocol': 'https' if use_https else 'http',
|
||||||
|
|
|
@ -15,7 +15,6 @@ from urllib.parse import (
|
||||||
from django.core.exceptions import TooManyFieldsSent
|
from django.core.exceptions import TooManyFieldsSent
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.deprecation import RemovedInDjango30Warning
|
from django.utils.deprecation import RemovedInDjango30Warning
|
||||||
from django.utils.encoding import force_bytes
|
|
||||||
from django.utils.functional import keep_lazy_text
|
from django.utils.functional import keep_lazy_text
|
||||||
|
|
||||||
# based on RFC 7232, Appendix C
|
# based on RFC 7232, Appendix C
|
||||||
|
@ -220,10 +219,10 @@ def int_to_base36(i):
|
||||||
|
|
||||||
def urlsafe_base64_encode(s):
|
def urlsafe_base64_encode(s):
|
||||||
"""
|
"""
|
||||||
Encode a bytestring in base64 for use in URLs. Strip any trailing equal
|
Encode a bytestring to a base64 string for use in URLs. Strip any trailing
|
||||||
signs.
|
equal signs.
|
||||||
"""
|
"""
|
||||||
return base64.urlsafe_b64encode(s).rstrip(b'\n=')
|
return base64.urlsafe_b64encode(s).rstrip(b'\n=').decode('ascii')
|
||||||
|
|
||||||
|
|
||||||
def urlsafe_base64_decode(s):
|
def urlsafe_base64_decode(s):
|
||||||
|
@ -231,7 +230,7 @@ def urlsafe_base64_decode(s):
|
||||||
Decode a base64 encoded string. Add back any trailing equal signs that
|
Decode a base64 encoded string. Add back any trailing equal signs that
|
||||||
might have been stripped.
|
might have been stripped.
|
||||||
"""
|
"""
|
||||||
s = force_bytes(s)
|
s = s.encode()
|
||||||
try:
|
try:
|
||||||
return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b'='))
|
return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b'='))
|
||||||
except (LookupError, BinasciiError) as e:
|
except (LookupError, BinasciiError) as e:
|
||||||
|
|
|
@ -726,14 +726,22 @@ escaping HTML.
|
||||||
|
|
||||||
.. function:: urlsafe_base64_encode(s)
|
.. function:: urlsafe_base64_encode(s)
|
||||||
|
|
||||||
Encodes a bytestring in base64 for use in URLs, stripping any trailing
|
Encodes a bytestring to a base64 string for use in URLs, stripping any
|
||||||
equal signs.
|
trailing equal signs.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.2
|
||||||
|
|
||||||
|
In older versions, it returns a bytestring instead of a string.
|
||||||
|
|
||||||
.. function:: urlsafe_base64_decode(s)
|
.. function:: urlsafe_base64_decode(s)
|
||||||
|
|
||||||
Decodes a base64 encoded string, adding back any trailing equal signs that
|
Decodes a base64 encoded string, adding back any trailing equal signs that
|
||||||
might have been stripped.
|
might have been stripped.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.2
|
||||||
|
|
||||||
|
In older versions, ``s`` may be a bytestring.
|
||||||
|
|
||||||
``django.utils.module_loading``
|
``django.utils.module_loading``
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
|
|
|
@ -298,6 +298,10 @@ Miscellaneous
|
||||||
|
|
||||||
* Support for bytestring paths in the template filesystem loader is removed.
|
* Support for bytestring paths in the template filesystem loader is removed.
|
||||||
|
|
||||||
|
* :func:`django.utils.http.urlsafe_base64_encode` now returns a string instead
|
||||||
|
of a bytestring, and :func:`django.utils.http.urlsafe_base64_decode` may no
|
||||||
|
longer be passed a bytestring.
|
||||||
|
|
||||||
.. _deprecated-features-2.2:
|
.. _deprecated-features-2.2:
|
||||||
|
|
||||||
Features deprecated in 2.2
|
Features deprecated in 2.2
|
||||||
|
|
|
@ -47,7 +47,7 @@ class AuthTemplateTests(TestCase):
|
||||||
client = PasswordResetConfirmClient()
|
client = PasswordResetConfirmClient()
|
||||||
default_token_generator = PasswordResetTokenGenerator()
|
default_token_generator = PasswordResetTokenGenerator()
|
||||||
token = default_token_generator.make_token(self.user)
|
token = default_token_generator.make_token(self.user)
|
||||||
uidb64 = urlsafe_base64_encode(str(self.user.pk).encode()).decode()
|
uidb64 = urlsafe_base64_encode(str(self.user.pk).encode())
|
||||||
url = reverse('password_reset_confirm', kwargs={'uidb64': uidb64, 'token': token})
|
url = reverse('password_reset_confirm', kwargs={'uidb64': uidb64, 'token': token})
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
self.assertContains(response, '<title>Enter new password</title>')
|
self.assertContains(response, '<title>Enter new password</title>')
|
||||||
|
|
|
@ -424,7 +424,7 @@ class UUIDUserPasswordResetTest(CustomUserPasswordResetTest):
|
||||||
def test_confirm_invalid_uuid(self):
|
def test_confirm_invalid_uuid(self):
|
||||||
"""A uidb64 that decodes to a non-UUID doesn't crash."""
|
"""A uidb64 that decodes to a non-UUID doesn't crash."""
|
||||||
_, path = self._test_confirm_start()
|
_, path = self._test_confirm_start()
|
||||||
invalid_uidb64 = urlsafe_base64_encode('INVALID_UUID'.encode()).decode()
|
invalid_uidb64 = urlsafe_base64_encode('INVALID_UUID'.encode())
|
||||||
first, _uuidb64_, second = path.strip('/').split('/')
|
first, _uuidb64_, second = path.strip('/').split('/')
|
||||||
response = self.client.get('/' + '/'.join((first, invalid_uidb64, second)) + '/')
|
response = self.client.get('/' + '/'.join((first, invalid_uidb64, second)) + '/')
|
||||||
self.assertContains(response, 'The password reset link was invalid')
|
self.assertContains(response, 'The password reset link was invalid')
|
||||||
|
|
Loading…
Reference in New Issue