raise validation error on bad lang request values (#20438)

* escape (incorrect) lang request values in the response

* raise validation error for a bad locale code

* different test for flat translation reponses

* return bad lang value without escaping

* Update overview.rst
This commit is contained in:
Andrew Williamson 2023-03-09 15:24:24 +00:00 коммит произвёл GitHub
Родитель 11d492f881
Коммит 906739fd38
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 34 добавлений и 3 удалений

Просмотреть файл

@ -193,6 +193,11 @@ For example, for a request ``?lang=de``:
}
}
.. warning::
``lang`` must only contains alphanumeric characters (plus ``-`` and ``_``).
For ``POST``, ``PATCH`` and ``PUT`` requests you submit an object containing
translations for any languages needing to be updated/saved. Any language not
in the object is not updated, but is not removed.
@ -452,7 +457,7 @@ These are `v5` specific changes - `v4` changes apply also.
* 2023-03-02: added specific HTTP 409 status code for add-on/version submissions that already exist
* 2023-03-02: added support for calling the version detail endpoint using a version number instead of an ``id``.
* 2023-03-09: added ``is_disabled`` to version detail and update endpoints, for authenticated developers and revieweers. https://github.com/mozilla/addons-server/issues/20142
* 2023-03-08: restricted ``lang`` parameter to only alphanumeric, ``_``, ``-``. https://github.com/mozilla/addons-server/issues/20452
.. _`#11380`: https://github.com/mozilla/addons-server/issues/11380/
.. _`#11379`: https://github.com/mozilla/addons-server/issues/11379/

Просмотреть файл

@ -16,6 +16,9 @@ from olympia.translations.models import Translation
from olympia.translations.utils import default_locale
LANGUAGE_CODE_REGEX = r'[\w-]+'
class ReverseChoiceField(fields.ChoiceField):
"""
A ChoiceField that exposes the "human-readable" values of its choices,
@ -108,8 +111,10 @@ class TranslationSerializerField(fields.CharField):
def get_requested_language(self):
request = self.context.get('request', None)
if request and request.method == 'GET' and 'lang' in request.GET:
return request.GET['lang']
if request and request.method == 'GET' and (lang := request.GET.get('lang')):
if not self.flat and not re.fullmatch(LANGUAGE_CODE_REGEX, lang):
self.fail('unknown_locale', lang_code=lang)
return lang
else:
return None

Просмотреть файл

@ -341,6 +341,16 @@ class TestTranslationSerializerField(TestCase):
result = field.to_representation(field.get_attribute(self.addon))
assert result is None
def test_invalid_lang_value_raises_valiation_error(self):
bad_lang = 'en-US<foo>;'
request = Request(self.factory.get('/', {'lang': bad_lang}))
mock_serializer = serializers.Serializer(context={'request': request})
field = self.field_class()
field.bind('name', mock_serializer)
with self.assertRaises(serializers.ValidationError) as exc:
field.to_representation(field.get_attribute(self.addon))
assert exc.exception.detail == [f'The language code "{bad_lang}" is invalid.']
@override_settings(DRF_API_GATES={None: ('l10n_flat_input_output',)})
class TestTranslationSerializerFieldFlat(TestTranslationSerializerField):
@ -366,6 +376,17 @@ class TestTranslationSerializerFieldFlat(TestTranslationSerializerField):
result = field.run_validation(data['fr'])
assert result == data['fr']
def test_invalid_lang_value_raises_valiation_error(self):
# The flat API response doesn't return the lang value at all, so doesn't raise
request = Request(
self.factory.get('/', {'lang': 'en-USf<script>alert(1)</script>'})
)
mock_serializer = serializers.Serializer(context={'request': request})
field = self.field_class()
field.bind('name', mock_serializer)
result = field.to_representation(field.get_attribute(self.addon))
assert 'script' not in result
class TestESTranslationSerializerField(TestTranslationSerializerField):
field_class = ESTranslationSerializerField