From c766ab177c4c4daccbfdb2812d79280bfd0d17d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Hovm=C3=B6ller?= Date: Tue, 30 Nov 2021 16:49:12 +0100 Subject: [PATCH] Fixed crash when auditing on binary data --- easyaudit/tests/test_app/tests.py | 25 +++++++++++++++++++++++++ easyaudit/utils.py | 12 ++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/easyaudit/tests/test_app/tests.py b/easyaudit/tests/test_app/tests.py index 96568a32..8fa043a7 100644 --- a/easyaudit/tests/test_app/tests.py +++ b/easyaudit/tests/test_app/tests.py @@ -4,6 +4,9 @@ from unittest import skip, skipIf import django +from django.db.models import BinaryField + +from easyaudit.utils import get_field_value asgi_views_supported = django.VERSION >= (3, 1) if asgi_views_supported: @@ -236,3 +239,25 @@ def test_request_event_admin_no_users(self): response = self.client.get(reverse('admin:easyaudit_requestevent_changelist')) self.assertEqual(200, response.status_code) filters = self._list_filters(response.content) + + +@override_settings(TEST=True) +class TestBinaryData(TestCase): + def test_binary_data(self): + class FakeObject: + pass + obj = FakeObject() + obj.binary_data = b'\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00' + binary_field = BinaryField() + binary_field.name = 'binary_data' + + # Small + actual = get_field_value(obj, binary_field) + expected = r"b'\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00'" + assert actual == expected + + # Large + obj.binary_data = b'\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00' * 100 + actual = get_field_value(obj, binary_field) + assert actual.startswith(expected[:-1]) + assert actual.endswith('[truncated 2000 bytes]') diff --git a/easyaudit/utils.py b/easyaudit/utils.py index 99dfec12..1d05d80a 100644 --- a/easyaudit/utils.py +++ b/easyaudit/utils.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -from uuid import UUID - from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.db.models import NOT_PROVIDED, DateTimeField @@ -19,18 +17,24 @@ def get_field_value(obj, field): :return: The value of the field as a string. :rtype: str """ + raw_value = getattr(obj, field.name, None) if isinstance(field, DateTimeField): # DateTimeFields are timezone-aware, so we need to convert the field # to its naive form before we can accuratly compare them for changes. try: - value = field.to_python(getattr(obj, field.name, None)) + value = field.to_python(raw_value) if value is not None and settings.USE_TZ and not timezone.is_naive(value): value = timezone.make_naive(value, timezone=timezone.utc) except ObjectDoesNotExist: value = field.default if field.default is not NOT_PROVIDED else None + elif isinstance(raw_value, bytes): + if len(raw_value) > 100: + return repr(raw_value[:100]) + '[truncated {} bytes]'.format(len(raw_value) - 100) + else: + return repr(raw_value) else: try: - value = smart_text(getattr(obj, field.name, None)) + value = smart_text(raw_value) except ObjectDoesNotExist: value = field.default if field.default is not NOT_PROVIDED else None