[1.5.x] Fixed #19387 -- Preserved SafeData status in contrib.messages
Thanks Anton Baklanov for the report and the patch.
Backport of e277301c2
from master.
This commit is contained in:
parent
b7607003a5
commit
be10289d03
|
@ -4,6 +4,7 @@ from django.conf import settings
|
||||||
from django.contrib.messages.storage.base import BaseStorage, Message
|
from django.contrib.messages.storage.base import BaseStorage, Message
|
||||||
from django.http import SimpleCookie
|
from django.http import SimpleCookie
|
||||||
from django.utils.crypto import salted_hmac, constant_time_compare
|
from django.utils.crypto import salted_hmac, constant_time_compare
|
||||||
|
from django.utils.safestring import SafeData, mark_safe
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +16,9 @@ class MessageEncoder(json.JSONEncoder):
|
||||||
|
|
||||||
def default(self, obj):
|
def default(self, obj):
|
||||||
if isinstance(obj, Message):
|
if isinstance(obj, Message):
|
||||||
message = [self.message_key, obj.level, obj.message]
|
# Using 0/1 here instead of False/True to produce more compact json
|
||||||
|
is_safedata = 1 if isinstance(obj.message, SafeData) else 0
|
||||||
|
message = [self.message_key, is_safedata, obj.level, obj.message]
|
||||||
if obj.extra_tags:
|
if obj.extra_tags:
|
||||||
message.append(obj.extra_tags)
|
message.append(obj.extra_tags)
|
||||||
return message
|
return message
|
||||||
|
@ -30,7 +33,9 @@ class MessageDecoder(json.JSONDecoder):
|
||||||
def process_messages(self, obj):
|
def process_messages(self, obj):
|
||||||
if isinstance(obj, list) and obj:
|
if isinstance(obj, list) and obj:
|
||||||
if obj[0] == MessageEncoder.message_key:
|
if obj[0] == MessageEncoder.message_key:
|
||||||
return Message(*obj[1:])
|
if obj[1]:
|
||||||
|
obj[3] = mark_safe(obj[3])
|
||||||
|
return Message(*obj[2:])
|
||||||
return [self.process_messages(item) for item in obj]
|
return [self.process_messages(item) for item in obj]
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
return dict([(key, self.process_messages(value))
|
return dict([(key, self.process_messages(value))
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.contrib.messages.storage.cookie import (CookieStorage,
|
||||||
MessageEncoder, MessageDecoder)
|
MessageEncoder, MessageDecoder)
|
||||||
from django.contrib.messages.storage.base import Message
|
from django.contrib.messages.storage.base import Message
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
from django.utils.safestring import SafeData, mark_safe
|
||||||
|
|
||||||
|
|
||||||
def set_cookie_data(storage, messages, invalid=False, encode_empty=False):
|
def set_cookie_data(storage, messages, invalid=False, encode_empty=False):
|
||||||
|
@ -132,3 +133,21 @@ class CookieTest(BaseTest):
|
||||||
value = encoder.encode(messages)
|
value = encoder.encode(messages)
|
||||||
decoded_messages = json.loads(value, cls=MessageDecoder)
|
decoded_messages = json.loads(value, cls=MessageDecoder)
|
||||||
self.assertEqual(messages, decoded_messages)
|
self.assertEqual(messages, decoded_messages)
|
||||||
|
|
||||||
|
def test_safedata(self):
|
||||||
|
"""
|
||||||
|
Tests that a message containing SafeData is keeping its safe status when
|
||||||
|
retrieved from the message storage.
|
||||||
|
"""
|
||||||
|
def encode_decode(data):
|
||||||
|
message = Message(constants.DEBUG, data)
|
||||||
|
encoded = storage._encode(message)
|
||||||
|
decoded = storage._decode(encoded)
|
||||||
|
return decoded.message
|
||||||
|
|
||||||
|
storage = self.get_storage()
|
||||||
|
|
||||||
|
self.assertIsInstance(
|
||||||
|
encode_decode(mark_safe("<b>Hello Django!</b>")), SafeData)
|
||||||
|
self.assertNotIsInstance(
|
||||||
|
encode_decode("<b>Hello Django!</b>"), SafeData)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
from django.contrib.messages import constants
|
||||||
from django.contrib.messages.tests.base import BaseTest
|
from django.contrib.messages.tests.base import BaseTest
|
||||||
|
from django.contrib.messages.storage.base import Message
|
||||||
from django.contrib.messages.storage.session import SessionStorage
|
from django.contrib.messages.storage.session import SessionStorage
|
||||||
|
from django.utils.safestring import SafeData, mark_safe
|
||||||
|
|
||||||
|
|
||||||
def set_session_data(storage, messages):
|
def set_session_data(storage, messages):
|
||||||
|
@ -36,3 +39,14 @@ class SessionTest(BaseTest):
|
||||||
set_session_data(storage, example_messages)
|
set_session_data(storage, example_messages)
|
||||||
# Test that the message actually contains what we expect.
|
# Test that the message actually contains what we expect.
|
||||||
self.assertEqual(list(storage), example_messages)
|
self.assertEqual(list(storage), example_messages)
|
||||||
|
|
||||||
|
def test_safedata(self):
|
||||||
|
"""
|
||||||
|
Tests that a message containing SafeData is keeping its safe status when
|
||||||
|
retrieved from the message storage.
|
||||||
|
"""
|
||||||
|
storage = self.get_storage()
|
||||||
|
|
||||||
|
message = Message(constants.DEBUG, mark_safe("<b>Hello Django!</b>"))
|
||||||
|
set_session_data(storage, [message])
|
||||||
|
self.assertIsInstance(list(storage)[0].message, SafeData)
|
||||||
|
|
Loading…
Reference in New Issue