Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

122 portrait image file not supported by pil #123

Merged
merged 4 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions news/122.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix #122 validating if image is supported by PIL showing a validation error if not.
Include Pillow dependency in setup.py.
Fix ValueError: User could not be found in BaseTest setUp adding a transaction.commit().
[rber474]
29 changes: 29 additions & 0 deletions plone/app/users/browser/account.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from AccessControl import Unauthorized
from Acquisition import aq_inner
from PIL import Image
from PIL import UnidentifiedImageError
from plone.app.layout.navigation.interfaces import INavigationRoot
from plone.app.users.browser.interfaces import IAccountPanelForm
from plone.app.users.browser.schemaeditor import getFromBaseSchema
Expand Down Expand Up @@ -44,6 +46,11 @@
),
)

MESSAGE_IMAGE_NOT_SUPPORTED = _(
"message_image_not_supported",
"The file you selected is not supported by Pillow. " "Please choose another.",
)


def getSchema(schema_interface, schema_adapter, form_name=None):
request = getRequest()
Expand Down Expand Up @@ -259,6 +266,23 @@ def validate_email(self, action, data):
if err_str:
notifyWidgetActionExecutionError(action, "email", err_str)

def validate_portrait(self, action, data):
"""Portrait validation.
Checks if image is supported by Pillow.
SVG files are not yet supported.
"""
error_keys = [error.field.getName() for error in action.form.widgets.errors]
if "portrait" not in error_keys and data["portrait"] is not None:
portrait = data["portrait"].open()
try:
Image.open(portrait)
except UnidentifiedImageError:
notifyWidgetActionExecutionError(
action, "portrait", MESSAGE_IMAGE_NOT_SUPPORTED
)
except Exception as exc:
raise exc

@button.buttonAndHandler(_("Save"))
def handleSave(self, action):
CheckAuthenticator(self.request)
Expand All @@ -269,6 +293,11 @@ def handleSave(self, action):
if "email" in data:
self.validate_email(action, data)

# Validate portrait, upload image could be not supported
# by PIL what raises an exception when scaling image.
if "portrait" in data:
self.validate_portrait(action, data)

if action.form.widgets.errors:
self.status = self.formErrorsMessage
return
Expand Down
2 changes: 2 additions & 0 deletions plone/app/users/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from zope.component import getSiteManager
from zope.component import getUtility

import transaction
import unittest


Expand All @@ -42,6 +43,7 @@ def setUp(self):

self.browser = Browser(self.layer["app"])
self.request = self.layer["request"]
transaction.commit()

def tearDown(self):
login(self.portal, "admin")
Expand Down
45 changes: 45 additions & 0 deletions plone/app/users/tests/test_portrait.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from pkg_resources import resource_stream
from plone.app.testing import SITE_OWNER_NAME
from plone.app.testing import SITE_OWNER_PASSWORD
from plone.app.users.tests.base import BaseTestCase


class TestPortrait(BaseTestCase):
def test_regression_supported_image_type_122(self):
# https://github.com/plone/plone.app.users/issues/122

self.browser.open("http://nohost/plone/")
self.browser.getLink("Log in").click()
self.browser.getControl("Login Name").value = SITE_OWNER_NAME
self.browser.getControl("Password").value = SITE_OWNER_PASSWORD
self.browser.getControl("Log in").click()
self.browser.open("http://nohost/plone/@@personal-information")
self.browser.getControl(name="form.widgets.email").value = "[email protected]"
portrait_file = resource_stream("plone.app.users.tests", "onepixel.jpg")
self.browser.getControl(name="form.widgets.portrait").add_file(
portrait_file, "image/jpg", "onepixel.# jpg"
)
self.browser.getControl("Save").click()
self.assertIn("Changes saved.", self.browser.contents)

def test_not_supported_image_type_122(self):
# https://github.com/plone/plone.app.users/issues/122

self.browser.open("http://nohost/plone/")
self.browser.getLink("Log in").click()
self.browser.getControl("Login Name").value = SITE_OWNER_NAME
self.browser.getControl("Password").value = SITE_OWNER_PASSWORD
self.browser.getControl("Log in").click()
self.browser.open("http://nohost/plone/@@personal-information")
self.browser.getControl(name="form.widgets.email").value = "[email protected]"
portrait_file = resource_stream(
"plone.app.users.tests", "transparent_square.svg"
)
self.browser.getControl(name="form.widgets.portrait").add_file(
portrait_file, "image/svg+xml", "onepixel.# jpg"
)
self.browser.getControl("Save").click()
self.assertIn(
"The file you selected is not supported by Pillow. Please choose another.",
self.browser.contents,
)
3 changes: 3 additions & 0 deletions plone/app/users/tests/transparent_square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ Zope = [
]
python-dateutil = ['dateutil']
ignore-packages = ['Products.CMFPlone']
Pillow = ['PIL']

##
# Add extra configuration options in .meta.toml:
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
extras_require=extras_require,
install_requires=[
"Acquisition",
"Pillow",
"Products.GenericSetup",
"Products.PlonePAS >= 5.0.1",
"Products.statusmessages",
Expand Down