Commit 70552845 by Adam Palay

fix translations for profile images (TNL-3901)

parent e9c8b4b0
...@@ -6,7 +6,7 @@ from collections import namedtuple ...@@ -6,7 +6,7 @@ from collections import namedtuple
from django.conf import settings from django.conf import settings
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.utils.translation import ugettext as _, ugettext_noop as _noop from django.utils.translation import ugettext as _
from PIL import Image from PIL import Image
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage
...@@ -58,13 +58,6 @@ def get_valid_file_types(): ...@@ -58,13 +58,6 @@ def get_valid_file_types():
return ', '.join([', '.join(IMAGE_TYPES[ft].extensions) for ft in IMAGE_TYPES.keys()]) return ', '.join([', '.join(IMAGE_TYPES[ft].extensions) for ft in IMAGE_TYPES.keys()])
FILE_UPLOAD_TOO_LARGE = _noop(u'The file must be smaller than {image_max_size} in size.'.format(image_max_size=user_friendly_size(settings.PROFILE_IMAGE_MAX_BYTES))) # pylint: disable=line-too-long
FILE_UPLOAD_TOO_SMALL = _noop(u'The file must be at least {image_min_size} in size.'.format(image_min_size=user_friendly_size(settings.PROFILE_IMAGE_MIN_BYTES))) # pylint: disable=line-too-long
FILE_UPLOAD_BAD_TYPE = _noop(u'The file must be one of the following types: {valid_file_types}.'.format(valid_file_types=get_valid_file_types())) # pylint: disable=line-too-long
FILE_UPLOAD_BAD_EXT = _noop(u'The file name extension for this file does not match the file data. The file may be corrupted.') # pylint: disable=line-too-long
FILE_UPLOAD_BAD_MIMETYPE = _noop(u'The Content-Type header for this file does not match the file data. The file may be corrupted.') # pylint: disable=line-too-long
class ImageValidationError(Exception): class ImageValidationError(Exception):
""" """
Exception to use when the system rejects a user-supplied source image. Exception to use when the system rejects a user-supplied source image.
...@@ -90,25 +83,46 @@ def validate_uploaded_image(uploaded_file): ...@@ -90,25 +83,46 @@ def validate_uploaded_image(uploaded_file):
# see also: http://en.wikipedia.org/wiki/Magic_number_%28programming%29 # see also: http://en.wikipedia.org/wiki/Magic_number_%28programming%29
if uploaded_file.size > settings.PROFILE_IMAGE_MAX_BYTES: if uploaded_file.size > settings.PROFILE_IMAGE_MAX_BYTES:
raise ImageValidationError(FILE_UPLOAD_TOO_LARGE) file_upload_too_large = _(
u'The file must be smaller than {image_max_size} in size.'
).format(
image_max_size=user_friendly_size(settings.PROFILE_IMAGE_MAX_BYTES)
)
raise ImageValidationError(file_upload_too_large)
elif uploaded_file.size < settings.PROFILE_IMAGE_MIN_BYTES: elif uploaded_file.size < settings.PROFILE_IMAGE_MIN_BYTES:
raise ImageValidationError(FILE_UPLOAD_TOO_SMALL) file_upload_too_small = _(
u'The file must be at least {image_min_size} in size.'
).format(
image_min_size=user_friendly_size(settings.PROFILE_IMAGE_MIN_BYTES)
)
raise ImageValidationError(file_upload_too_small)
# check the file extension looks acceptable # check the file extension looks acceptable
filename = unicode(uploaded_file.name).lower() filename = unicode(uploaded_file.name).lower()
filetype = [ft for ft in IMAGE_TYPES if any(filename.endswith(ext) for ext in IMAGE_TYPES[ft].extensions)] filetype = [ft for ft in IMAGE_TYPES if any(filename.endswith(ext) for ext in IMAGE_TYPES[ft].extensions)]
if not filetype: if not filetype:
raise ImageValidationError(FILE_UPLOAD_BAD_TYPE) file_upload_bad_type = _(
u'The file must be one of the following types: {valid_file_types}.'
).format(valid_file_types=get_valid_file_types())
raise ImageValidationError(file_upload_bad_type)
filetype = filetype[0] filetype = filetype[0]
# check mimetype matches expected file type # check mimetype matches expected file type
if uploaded_file.content_type not in IMAGE_TYPES[filetype].mimetypes: if uploaded_file.content_type not in IMAGE_TYPES[filetype].mimetypes:
raise ImageValidationError(FILE_UPLOAD_BAD_MIMETYPE) file_upload_bad_mimetype = _(
u'The Content-Type header for this file does not match '
u'the file data. The file may be corrupted.'
)
raise ImageValidationError(file_upload_bad_mimetype)
# check magic number matches expected file type # check magic number matches expected file type
headers = IMAGE_TYPES[filetype].magic headers = IMAGE_TYPES[filetype].magic
if uploaded_file.read(len(headers[0]) / 2).encode('hex') not in headers: if uploaded_file.read(len(headers[0]) / 2).encode('hex') not in headers:
raise ImageValidationError(FILE_UPLOAD_BAD_EXT) file_upload_bad_ext = _(
u'The file name extension for this file does not match '
u'the file data. The file may be corrupted.'
)
raise ImageValidationError(file_upload_bad_ext)
# avoid unexpected errors from subsequent modules expecting the fp to be at 0 # avoid unexpected errors from subsequent modules expecting the fp to be at 0
uploaded_file.seek(0) uploaded_file.seek(0)
......
...@@ -16,15 +16,11 @@ import mock ...@@ -16,15 +16,11 @@ import mock
from PIL import Image from PIL import Image
from ..images import ( from ..images import (
FILE_UPLOAD_TOO_LARGE,
FILE_UPLOAD_TOO_SMALL,
FILE_UPLOAD_BAD_TYPE,
FILE_UPLOAD_BAD_EXT,
FILE_UPLOAD_BAD_MIMETYPE,
create_profile_images, create_profile_images,
ImageValidationError, ImageValidationError,
remove_profile_images, remove_profile_images,
validate_uploaded_image, validate_uploaded_image,
get_valid_file_types,
) )
from .helpers import make_image_file, make_uploaded_file from .helpers import make_image_file, make_uploaded_file
...@@ -35,6 +31,12 @@ class TestValidateUploadedImage(TestCase): ...@@ -35,6 +31,12 @@ class TestValidateUploadedImage(TestCase):
""" """
Test validate_uploaded_image Test validate_uploaded_image
""" """
FILE_UPLOAD_BAD_TYPE = (
u'The file must be one of the following types: {valid_file_types}.'.format(
valid_file_types=get_valid_file_types()
)
)
def check_validation_result(self, uploaded_file, expected_failure_message): def check_validation_result(self, uploaded_file, expected_failure_message):
""" """
Internal DRY helper. Internal DRY helper.
...@@ -48,10 +50,10 @@ class TestValidateUploadedImage(TestCase): ...@@ -48,10 +50,10 @@ class TestValidateUploadedImage(TestCase):
self.assertEqual(uploaded_file.tell(), 0) self.assertEqual(uploaded_file.tell(), 0)
@ddt.data( @ddt.data(
(99, FILE_UPLOAD_TOO_SMALL), (99, u"The file must be at least 100 bytes in size."),
(100, ), (100, ),
(1024, ), (1024, ),
(1025, FILE_UPLOAD_TOO_LARGE), (1025, u"The file must be smaller than 1 KB in size."),
) )
@ddt.unpack @ddt.unpack
@override_settings(PROFILE_IMAGE_MIN_BYTES=100, PROFILE_IMAGE_MAX_BYTES=1024) @override_settings(PROFILE_IMAGE_MIN_BYTES=100, PROFILE_IMAGE_MAX_BYTES=1024)
...@@ -85,6 +87,10 @@ class TestValidateUploadedImage(TestCase): ...@@ -85,6 +87,10 @@ class TestValidateUploadedImage(TestCase):
Ensure that validation fails when the file extension does not match the Ensure that validation fails when the file extension does not match the
file data. file data.
""" """
file_upload_bad_ext = (
u'The file name extension for this file does not match '
u'the file data. The file may be corrupted.'
)
# make a bmp, try to fool the function into thinking it's a jpeg # make a bmp, try to fool the function into thinking it's a jpeg
with make_image_file(extension=".bmp") as bmp_file: with make_image_file(extension=".bmp") as bmp_file:
with closing(NamedTemporaryFile(suffix=".jpeg")) as fake_jpeg_file: with closing(NamedTemporaryFile(suffix=".jpeg")) as fake_jpeg_file:
...@@ -97,17 +103,21 @@ class TestValidateUploadedImage(TestCase): ...@@ -97,17 +103,21 @@ class TestValidateUploadedImage(TestCase):
) )
with self.assertRaises(ImageValidationError) as ctx: with self.assertRaises(ImageValidationError) as ctx:
validate_uploaded_image(uploaded_file) validate_uploaded_image(uploaded_file)
self.assertEqual(ctx.exception.message, FILE_UPLOAD_BAD_EXT) self.assertEqual(ctx.exception.message, file_upload_bad_ext)
def test_content_type(self): def test_content_type(self):
""" """
Ensure that validation fails when the content_type header and file Ensure that validation fails when the content_type header and file
extension do not match extension do not match
""" """
file_upload_bad_mimetype = (
u'The Content-Type header for this file does not match '
u'the file data. The file may be corrupted.'
)
with make_uploaded_file(extension=".jpeg", content_type="image/gif") as uploaded_file: with make_uploaded_file(extension=".jpeg", content_type="image/gif") as uploaded_file:
with self.assertRaises(ImageValidationError) as ctx: with self.assertRaises(ImageValidationError) as ctx:
validate_uploaded_image(uploaded_file) validate_uploaded_image(uploaded_file)
self.assertEqual(ctx.exception.message, FILE_UPLOAD_BAD_MIMETYPE) self.assertEqual(ctx.exception.message, file_upload_bad_mimetype)
@ddt.ddt @ddt.ddt
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment