mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-27 10:44:33 +00:00
notification: Don't fail when formatting message strings
- When a notification's message contains unexpected formatting characters such
as '{}', showing the notification and consequently the entire FreedomBox web
interface fails. Prevent that by make sure that that message formatting never
fails.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
d8da0a41e5
commit
d69167bcfa
@ -1,10 +1,9 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""Module to provide API for showing notifications."""
|
||||||
Module to provide API for showing notifications.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
|
import string
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
@ -278,22 +277,22 @@ class Notification(models.StoredNotification):
|
|||||||
return Notification.objects.filter(*filters)[0:10]
|
return Notification.objects.filter(*filters)[0:10]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _translate(string, data=None):
|
def _translate(string_, data=None):
|
||||||
"""Translate a string for final display using data dict."""
|
"""Translate a string for final display using data dict."""
|
||||||
if not string:
|
if not string_:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
string = gettext(string)
|
string_ = gettext(string_)
|
||||||
try:
|
try:
|
||||||
string = str(string)
|
string_ = str(string_)
|
||||||
if data:
|
if data:
|
||||||
string = string.format(**data)
|
string_ = SafeFormatter().vformat(string_, [], data)
|
||||||
except KeyError as error:
|
except KeyError as error:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'Notification missing required key during translation: %s',
|
'Notification missing required key during translation: %s',
|
||||||
error)
|
error)
|
||||||
|
|
||||||
return string
|
return string_
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _translate_dict(data_dict, data=None):
|
def _translate_dict(data_dict, data=None):
|
||||||
@ -366,3 +365,14 @@ class Notification(models.StoredNotification):
|
|||||||
notes.append(note_context)
|
notes.append(note_context)
|
||||||
|
|
||||||
return {'notifications': notes, 'max_severity': max_severity}
|
return {'notifications': notes, 'max_severity': max_severity}
|
||||||
|
|
||||||
|
|
||||||
|
class SafeFormatter(string.Formatter):
|
||||||
|
"""A string.format() handler to deal with missing arguments."""
|
||||||
|
|
||||||
|
def get_value(self, key, args, kwargs):
|
||||||
|
"""Retrieve a given field value."""
|
||||||
|
try:
|
||||||
|
return super().get_value(key, args, kwargs)
|
||||||
|
except (IndexError, KeyError):
|
||||||
|
return f'?{key}?'
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import pytest
|
|||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from plinth.notification import Notification
|
from plinth.notification import Notification, SafeFormatter
|
||||||
|
|
||||||
pytestmark = pytest.mark.django_db
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
@ -413,3 +413,15 @@ def test_display_context_body_template(note, user, load_cfg, rf):
|
|||||||
context_note = context['notifications'][0]
|
context_note = context['notifications'][0]
|
||||||
assert context_note['body'].content == \
|
assert context_note['body'].content == \
|
||||||
b'Test notification body /plinth/help/about/\n'
|
b'Test notification body /plinth/help/about/\n'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('input_, output', (
|
||||||
|
(('', [], {}), ''),
|
||||||
|
(('{} {}', [10, 20], {}), '10 20'),
|
||||||
|
(('{1} {0} {key1}', [10, 20], dict(key1='value1')), '20 10 value1'),
|
||||||
|
(('{2} {1} {key1}', [10, 20], {}), '?2? 20 ?key1?'),
|
||||||
|
))
|
||||||
|
def test_safe_string_formatter(input_, output):
|
||||||
|
"""Test the safe string formatter."""
|
||||||
|
formatter = SafeFormatter()
|
||||||
|
assert output == formatter.vformat(*input_)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user