mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
parent
868b0e34c9
commit
0eeaebcc90
@ -89,11 +89,21 @@ class RestApi(Api):
|
||||
arg = err.args[0]
|
||||
if isinstance(arg, dict):
|
||||
errors = []
|
||||
for field, messages in arg.items():
|
||||
if isinstance(messages, list):
|
||||
for message in messages:
|
||||
error = {"field": field, "message": message}
|
||||
errors.append(error)
|
||||
for field, item in arg.items():
|
||||
messages = list()
|
||||
|
||||
if isinstance(item, list):
|
||||
messages = item
|
||||
elif isinstance(item, dict):
|
||||
for item_value in item.values():
|
||||
if isinstance(item_value, list) or isinstance(
|
||||
item_value, tuple
|
||||
):
|
||||
messages.extend(item_value)
|
||||
|
||||
for message in messages:
|
||||
error = {"field": field, "message": message}
|
||||
errors.append(error)
|
||||
|
||||
if len(errors) > 0:
|
||||
data["errors"] = errors
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from marshmallow import ValidationError, fields, post_load, validates_schema
|
||||
from marshmallow import ValidationError, fields, post_load, validate, validates_schema
|
||||
|
||||
from project.api import marshmallow
|
||||
from project.api.schemas import SQLAlchemyBaseSchema
|
||||
@ -43,6 +43,7 @@ class ImageWriteSchemaMixin(object):
|
||||
required=False,
|
||||
load_only=True,
|
||||
allow_none=True,
|
||||
validate=[validate.URL()],
|
||||
metadata={
|
||||
"description": "URL to image. Either image_url or image_base64 has to be defined."
|
||||
},
|
||||
@ -76,20 +77,24 @@ class ImageWriteSchemaMixin(object):
|
||||
return item
|
||||
|
||||
def load_image_data(self, image_base64, image_url):
|
||||
image = None
|
||||
try:
|
||||
image = None
|
||||
|
||||
if image_base64:
|
||||
image = get_image_from_base64_str(image_base64)
|
||||
elif image_url:
|
||||
image = get_image_from_url(image_url)
|
||||
if image_base64:
|
||||
image = get_image_from_base64_str(image_base64)
|
||||
elif image_url:
|
||||
image = get_image_from_url(image_url)
|
||||
|
||||
if not image:
|
||||
return None, None
|
||||
if not image:
|
||||
return None, None
|
||||
|
||||
validate_image(image)
|
||||
resize_image_to_max(image)
|
||||
encoding_format = get_mime_type_from_image(image)
|
||||
data = get_bytes_from_image(image)
|
||||
except Exception as e:
|
||||
raise ValidationError(e.args)
|
||||
|
||||
validate_image(image)
|
||||
resize_image_to_max(image)
|
||||
encoding_format = get_mime_type_from_image(image)
|
||||
data = get_bytes_from_image(image)
|
||||
return encoding_format, data
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import requests
|
||||
|
||||
min_image_size = 320
|
||||
max_image_size = 1024
|
||||
supported_formats = ["jpeg", "png", "gif"]
|
||||
supported_formats = ["png", "jpeg", "gif"]
|
||||
|
||||
|
||||
def get_data_uri_from_bytes(data: bytes, encoding_format: str) -> str:
|
||||
@ -34,8 +34,14 @@ def get_mime_type_from_image(image: PIL.Image) -> str:
|
||||
|
||||
|
||||
def get_bytes_from_image(image: PIL.Image) -> bytes:
|
||||
format = (
|
||||
image.format
|
||||
if image.format.lower() in supported_formats
|
||||
else supported_formats[0]
|
||||
)
|
||||
|
||||
imgByteArr = BytesIO()
|
||||
image.save(imgByteArr, format=image.format)
|
||||
image.save(imgByteArr, format=format)
|
||||
return imgByteArr.getvalue()
|
||||
|
||||
|
||||
@ -49,8 +55,3 @@ def validate_image(image: PIL.Image):
|
||||
raise ValueError(
|
||||
f"Image is too small ({image.width}x{image.height}px). At least {min_image_size}x{min_image_size}px."
|
||||
)
|
||||
|
||||
if image.format.lower() not in supported_formats:
|
||||
raise ValueError(
|
||||
f"Image format {image.format} is not supported. Supported formats: {', '.join(supported_formats)}."
|
||||
)
|
||||
|
||||
2
project/static/angular-elements.js
vendored
2
project/static/angular-elements.js
vendored
File diff suppressed because one or more lines are too long
@ -67,22 +67,27 @@ def test_events(client, seeder, utils):
|
||||
utils.get_ok(url)
|
||||
|
||||
|
||||
def test_events_post(client, seeder, utils, app):
|
||||
def prepare_events_post_data(seeder, utils):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
place_id = seeder.upsert_default_event_place(admin_unit_id)
|
||||
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
|
||||
|
||||
url = utils.get_url("api_v1_organization_event_list", id=admin_unit_id)
|
||||
response = utils.post_json(
|
||||
url,
|
||||
{
|
||||
"name": "Fest",
|
||||
"start": "2021-02-07T11:00:00.000Z",
|
||||
"place": {"id": place_id},
|
||||
"organizer": {"id": organizer_id},
|
||||
"photo": {"image_base64": seeder.get_default_image_upload_base64()},
|
||||
},
|
||||
data = {
|
||||
"name": "Fest",
|
||||
"start": "2021-02-07T11:00:00.000Z",
|
||||
"place": {"id": place_id},
|
||||
"organizer": {"id": organizer_id},
|
||||
"photo": {"image_base64": seeder.get_default_image_base64()},
|
||||
}
|
||||
return url, data, admin_unit_id, place_id, organizer_id
|
||||
|
||||
|
||||
def test_events_post(client, seeder, utils, app):
|
||||
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
|
||||
seeder, utils
|
||||
)
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_created(response)
|
||||
assert "id" in response.json
|
||||
|
||||
@ -101,6 +106,34 @@ def test_events_post(client, seeder, utils, app):
|
||||
assert event.photo.encoding_format == "image/png"
|
||||
|
||||
|
||||
def test_events_post_photo_no_data(client, seeder, utils, app):
|
||||
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
|
||||
seeder, utils
|
||||
)
|
||||
data["photo"] = dict()
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_unprocessable_entity(response)
|
||||
|
||||
error = response.json["errors"][0]
|
||||
assert error["field"] == "photo"
|
||||
assert error["message"] == "Either image_url or image_base64 has to be defined."
|
||||
|
||||
|
||||
def test_events_post_photo_too_small(client, seeder, utils, app):
|
||||
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
|
||||
seeder, utils
|
||||
)
|
||||
data["photo"][
|
||||
"image_base64"
|
||||
] = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAgMAAABieywaAAAACVBMVEUAAAD///9fX1/S0ecCAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAACklEQVQImWNoAAAAggCByxOyYQAAAABJRU5ErkJggg=="
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_unprocessable_entity(response)
|
||||
|
||||
error = response.json["errors"][0]
|
||||
assert error["field"] == "photo"
|
||||
assert error["message"] == "Image is too small (1x1px). At least 320x320px."
|
||||
|
||||
|
||||
def test_places(client, seeder, utils):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
seeder.upsert_default_event_place(admin_unit_id)
|
||||
|
||||
@ -26,12 +26,16 @@ def test_validate_image_too_small():
|
||||
assert "too small" in str(e.value)
|
||||
|
||||
|
||||
def test_validate_image_unsupported_format():
|
||||
def test_get_bytes_from_image():
|
||||
from io import BytesIO
|
||||
|
||||
import PIL
|
||||
|
||||
from project.imageutils import get_image_from_bytes, min_image_size, validate_image
|
||||
from project.imageutils import (
|
||||
get_bytes_from_image,
|
||||
get_image_from_bytes,
|
||||
min_image_size,
|
||||
)
|
||||
|
||||
image = PIL.Image.new("RGB", (min_image_size, min_image_size))
|
||||
imgByteArr = BytesIO()
|
||||
@ -39,7 +43,7 @@ def test_validate_image_unsupported_format():
|
||||
|
||||
tif_image = get_image_from_bytes(imgByteArr.getvalue())
|
||||
|
||||
with pytest.raises(ValueError) as e:
|
||||
validate_image(tif_image)
|
||||
new_bytes = get_bytes_from_image(tif_image)
|
||||
new_image = get_image_from_bytes(new_bytes)
|
||||
|
||||
assert "not supported" in str(e.value)
|
||||
assert new_image.format.lower() == "png"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user