Validation Messages: Add <strong> for missing_wheel and forbidden_filepaths #200
@ -118,12 +118,14 @@ EXPECTED_VALIDATION_ERRORS = {
|
|||||||
'source': ['The manifest file is missing.'],
|
'source': ['The manifest file is missing.'],
|
||||||
},
|
},
|
||||||
'invalid-manifest-toml.zip': {'source': ['Manifest file contains invalid code.']},
|
'invalid-manifest-toml.zip': {'source': ['Manifest file contains invalid code.']},
|
||||||
'invalid-theme-multiple-xmls.zip': {'source': ['Themes can only contain <strong>one XML file</strong>.']},
|
'invalid-theme-multiple-xmls.zip': {
|
||||||
'invalid-theme-multiple-xmls-macosx.zip': {'source': ['Archive contains forbidden files or directories: __MACOSX/']},
|
'source': ['Themes can only contain <strong>one XML file</strong>.']
|
||||||
|
},
|
||||||
|
'invalid-theme-multiple-xmls-macosx.zip': {
|
||||||
|
'source': ['Archive contains forbidden files or directories: <strong>__MACOSX/</strong>']
|
||||||
|
},
|
||||||
'invalid-missing-wheels.zip': {
|
'invalid-missing-wheels.zip': {
|
||||||
'source': [
|
'source': ['Python wheel missing: <strong>addon/wheels/test-wheel-whatever.whl</strong>']
|
||||||
'Python wheel missing: addon/wheels/test-wheel-whatever.whl'
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
POST_DATA = {
|
POST_DATA = {
|
||||||
@ -224,6 +226,16 @@ class SubmitFileTest(TestCase):
|
|||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertDictEqual(response.context['form'].errors, expected_errors)
|
self.assertDictEqual(response.context['form'].errors, expected_errors)
|
||||||
|
|
||||||
|
def test_validation_errors_with_html(self):
|
||||||
|
self.assertEqual(Extension.objects.count(), 0)
|
||||||
|
user = UserFactory()
|
||||||
|
self.client.force_login(user)
|
||||||
|
|
||||||
|
with open(TEST_FILES_DIR / 'invalid-theme-multiple-xmls-macosx.zip', 'rb') as fp:
|
||||||
|
response = self.client.post(self.url, {'source': fp, 'agreed_with_terms': True})
|
||||||
|
|
||||||
|
self.assertNotContains(response, "<", html=False)
|
||||||
|
|
||||||
def test_addon_without_top_level_directory(self):
|
def test_addon_without_top_level_directory(self):
|
||||||
self.assertEqual(Extension.objects.count(), 0)
|
self.assertEqual(Extension.objects.count(), 0)
|
||||||
user = UserFactory()
|
user = UserFactory()
|
||||||
|
@ -4,6 +4,7 @@ import zipfile
|
|||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.utils.html import escape
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
@ -36,11 +37,15 @@ class FileForm(forms.ModelForm):
|
|||||||
# TODO: surface TOML parsing errors?
|
# TODO: surface TOML parsing errors?
|
||||||
'invalid_manifest_toml': _('Manifest file contains invalid code.'),
|
'invalid_manifest_toml': _('Manifest file contains invalid code.'),
|
||||||
'invalid_missing_init': mark_safe(_('Add-on file missing: <strong>__init__.py</strong>.')),
|
'invalid_missing_init': mark_safe(_('Add-on file missing: <strong>__init__.py</strong>.')),
|
||||||
'missing_or_multiple_theme_xml': mark_safe(_('Themes can only contain <strong>one XML file</strong>.')),
|
'missing_or_multiple_theme_xml': mark_safe(
|
||||||
|
_('Themes can only contain <strong>one XML file</strong>.')
|
||||||
|
),
|
||||||
'invalid_zip_archive': msg_only_zip_files,
|
'invalid_zip_archive': msg_only_zip_files,
|
||||||
'missing_manifest_toml': _('The manifest file is missing.'),
|
'missing_manifest_toml': _('The manifest file is missing.'),
|
||||||
'missing_wheel': _('Python wheel missing: %(path)s'), # TODO <strong>%(path)s</strong>
|
'missing_wheel': _('Python wheel missing: <strong>%(path)s</strong>'),
|
||||||
'forbidden_filepaths': _('Archive contains forbidden files or directories: %(paths)s'), #TODO <strong>%(paths)s</strong>
|
'forbidden_filepaths': mark_safe(
|
||||||
|
|||||||
|
_('Archive contains forbidden files or directories: <strong>%(paths)s</strong>')
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -145,12 +150,10 @@ class FileForm(forms.ModelForm):
|
|||||||
manifest, error_codes = utils.read_manifest_from_zip(file_path)
|
manifest, error_codes = utils.read_manifest_from_zip(file_path)
|
||||||
for code in error_codes:
|
for code in error_codes:
|
||||||
if isinstance(code, dict):
|
if isinstance(code, dict):
|
||||||
errors.append(
|
error_message = str(self.error_messages[code['code']])
|
||||||
Oleg-Komarov
commented
why is why is `str` cast needed here?
|
|||||||
forms.ValidationError(
|
sanitized_params = {k: escape(v) for k, v in code['params'].items()}
|
||||||
self.error_messages[code['code']],
|
error_message = mark_safe(error_message % sanitized_params)
|
||||||
params=code['params'],
|
errors.append(forms.ValidationError(error_message))
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
errors.append(forms.ValidationError(self.error_messages[code]))
|
errors.append(forms.ValidationError(self.error_messages[code]))
|
||||||
if errors:
|
if errors:
|
||||||
|
Loading…
Reference in New Issue
Block a user
this line and the line above look inconsistent: both of them have parameters, but only one is wrapped into
mark_safe
inside theerror_messages
declarationthis is confusing and doesn't establish a consistent pattern for further use: if it's possible it's better to make them the same
it seems that the code below (in
clean
) already takes care ofmark_safe
for cases when params are passed, so I would expect thatmark_safe
in this line is not needed. if this is not true, then the code structure is surprising - we should think how to make it more transparent.