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
|
||||
"""
|
||||
Module to provide API for showing notifications.
|
||||
"""
|
||||
"""Module to provide API for showing notifications."""
|
||||
|
||||
import copy
|
||||
import logging
|
||||
import string
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Q
|
||||
@ -278,22 +277,22 @@ class Notification(models.StoredNotification):
|
||||
return Notification.objects.filter(*filters)[0:10]
|
||||
|
||||
@staticmethod
|
||||
def _translate(string, data=None):
|
||||
def _translate(string_, data=None):
|
||||
"""Translate a string for final display using data dict."""
|
||||
if not string:
|
||||
if not string_:
|
||||
return None
|
||||
|
||||
string = gettext(string)
|
||||
string_ = gettext(string_)
|
||||
try:
|
||||
string = str(string)
|
||||
string_ = str(string_)
|
||||
if data:
|
||||
string = string.format(**data)
|
||||
string_ = SafeFormatter().vformat(string_, [], data)
|
||||
except KeyError as error:
|
||||
logger.warning(
|
||||
'Notification missing required key during translation: %s',
|
||||
error)
|
||||
|
||||
return string
|
||||
return string_
|
||||
|
||||
@staticmethod
|
||||
def _translate_dict(data_dict, data=None):
|
||||
@ -366,3 +365,14 @@ class Notification(models.StoredNotification):
|
||||
notes.append(note_context)
|
||||
|
||||
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.core.exceptions import ValidationError
|
||||
|
||||
from plinth.notification import Notification
|
||||
from plinth.notification import Notification, SafeFormatter
|
||||
|
||||
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]
|
||||
assert context_note['body'].content == \
|
||||
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