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:
Jon Dufresne 2018-10-01 18:18:04 -05:00 committed by Tim Graham
parent f3d3338e06
commit c82893cb8c
6 changed files with 21 additions and 10 deletions

View File

@ -284,7 +284,7 @@ class PasswordResetForm(forms.Form):
'email': email,
'domain': domain,
'site_name': site_name,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': token_generator.make_token(user),
'protocol': 'https' if use_https else 'http',

View File

@ -15,7 +15,6 @@ from urllib.parse import (
from django.core.exceptions import TooManyFieldsSent
from django.utils.datastructures import MultiValueDict
from django.utils.deprecation import RemovedInDjango30Warning
from django.utils.encoding import force_bytes
from django.utils.functional import keep_lazy_text
# based on RFC 7232, Appendix C
@ -220,10 +219,10 @@ def int_to_base36(i):
def urlsafe_base64_encode(s):
"""
Encode a bytestring in base64 for use in URLs. Strip any trailing equal
signs.
Encode a bytestring to a base64 string for use in URLs. Strip any trailing
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):
@ -231,7 +230,7 @@ def urlsafe_base64_decode(s):
Decode a base64 encoded string. Add back any trailing equal signs that
might have been stripped.
"""
s = force_bytes(s)
s = s.encode()
try:
return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b'='))
except (LookupError, BinasciiError) as e:

View File

@ -726,14 +726,22 @@ escaping HTML.
.. function:: urlsafe_base64_encode(s)
Encodes a bytestring in base64 for use in URLs, stripping any trailing
equal signs.
Encodes a bytestring to a base64 string for use in URLs, stripping any
trailing equal signs.
.. versionchanged:: 2.2
In older versions, it returns a bytestring instead of a string.
.. function:: urlsafe_base64_decode(s)
Decodes a base64 encoded string, adding back any trailing equal signs that
might have been stripped.
.. versionchanged:: 2.2
In older versions, ``s`` may be a bytestring.
``django.utils.module_loading``
===============================

View File

@ -298,6 +298,10 @@ Miscellaneous
* 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:
Features deprecated in 2.2

View File

@ -47,7 +47,7 @@ class AuthTemplateTests(TestCase):
client = PasswordResetConfirmClient()
default_token_generator = PasswordResetTokenGenerator()
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})
response = client.get(url)
self.assertContains(response, '<title>Enter new password</title>')

View File

@ -424,7 +424,7 @@ class UUIDUserPasswordResetTest(CustomUserPasswordResetTest):
def test_confirm_invalid_uuid(self):
"""A uidb64 that decodes to a non-UUID doesn't crash."""
_, 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('/')
response = self.client.get('/' + '/'.join((first, invalid_uidb64, second)) + '/')
self.assertContains(response, 'The password reset link was invalid')