Skip to content

Commit

Permalink
fix validators
Browse files Browse the repository at this point in the history
  • Loading branch information
cekk committed Sep 17, 2024
1 parent dc12bd6 commit 94183e3
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 92 deletions.
217 changes: 138 additions & 79 deletions src/iosanita/contenttypes/restapi/deserializers/dxcontent.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from copy import deepcopy
from iosanita.contenttypes.interfaces import IIosanitaContenttypesLayer
from iosanita.contenttypes.interfaces import IoSanitaMigrationMarker
from plone import api
from plone.dexterity.interfaces import IDexterityContent
from plone.formwidget.geolocation.geolocation import Geolocation
from plone.restapi import _
from plone.restapi.deserializer import json_body
from plone.restapi.deserializer.dxcontent import DeserializeFromJson as BaseDeserializer
Expand Down Expand Up @@ -31,6 +33,15 @@ def __call__(
mask_validation_errors=mask_validation_errors,
)

@property
def mutual_required_msg(self):
return api.portal.translate(
_(
"mutual_required_field_msg",
default="Compila almeno uno di questi campi.",
)
)

def validate_data_iosanita(self, data, create):
if IoSanitaMigrationMarker.providedBy(self.request):
return
Expand Down Expand Up @@ -61,97 +72,145 @@ def validate_a_chi_si_rivolge(self, portal_type, data, create):
# skip check
return

a_chi_si_rivolge = data.get("a_chi_si_rivolge", {})
a_chi_si_rivolge_tassonomia = data.get("a_chi_si_rivolge_tassonomia", [])
has_a_chi_si_rivolge = self.has_field_value(
data=data, create=create, field_id="a_chi_si_rivolge", is_block_field=True
)
has_a_chi_si_rivolge_tassonomia = self.has_field_value(
data=data, create=create, field_id="a_chi_si_rivolge_tassonomia"
)

if not create:
if not a_chi_si_rivolge:
a_chi_si_rivolge = getattr(self.context, "a_chi_si_rivolge", {})
if not a_chi_si_rivolge_tassonomia:
a_chi_si_rivolge_tassonomia = getattr(
self.context, "a_chi_si_rivolge_tassonomia", []
)
if self.is_empty_blocks(a_chi_si_rivolge) and not a_chi_si_rivolge_tassonomia:
msg = api.portal.translate(
_(
"a_chi_si_rivolge_validation_error",
default='Devi compilare almeno uno dei due campi del tab "A chi si rivolge".',
if not has_a_chi_si_rivolge and not has_a_chi_si_rivolge_tassonomia:
raise BadRequest(
json.dumps(
[
{
"field": "a_chi_si_rivolge",
"message": self.mutual_required_msg,
},
{
"field": "a_chi_si_rivolge_tassonomia",
"message": self.mutual_required_msg,
},
{
"message": api.portal.translate(
_(
"a_chi_si_rivolge_validation_error",
default='Devi compilare almeno uno dei due campi del tab "A chi si rivolge".',
)
)
},
]
)
)
# temporaneamente commentato perché Volto non lo gestisce bene
# raise BadRequest(
# json.dumps(
# [
# {"field": "a_chi_si_rivolge", "message": msg},
# {"field": "a_chi_si_rivolge_tassonomia", "message": msg},
# ]
# )
# )
raise BadRequest(json.dumps({"error": {"message": msg}}))

def validate_event(self, data, create):
# validate organizzato da
if not create:
if (
"organizzato_da_esterno" not in data
and "organizzato_da_interno" not in data # noqa
):
return

if (
"webinar" not in data
and "struttura_correlata" not in data # noqa
and "geolocation" not in data # noqa
):
return

organizzato_da_esterno = data.get("organizzato_da_esterno", {})
organizzato_da_interno = data.get("organizzato_da_interno", [])

if self.is_empty_blocks(organizzato_da_esterno) and not organizzato_da_interno:
msg = api.portal.translate(
_(
"organizzato_validation_error",
default='Devi compilare almeno uno dei due campi per "Organizzato da" nel tab "Contatti".',

has_organizzato_da_esterno = self.has_field_value(
data=data,
create=create,
field_id="organizzato_da_esterno",
is_block_field=True,
)
has_organizzato_da_interno = self.has_field_value(
data=data, create=create, field_id="organizzato_da_interno"
)

if not has_organizzato_da_esterno and not has_organizzato_da_interno:
raise BadRequest(
json.dumps(
[
{
"field": "organizzato_da_esterno",
"message": self.mutual_required_msg,
},
{
"field": "organizzato_da_interno",
"message": self.mutual_required_msg,
},
{
"message": api.portal.translate(
_(
"organizzato_validation_error",
default='Devi compilare almeno uno dei due campi per "Organizzato da" nel tab "Contatti".',
)
)
},
]
)
)
# temporaneamente commentato perché Volto non lo gestisce bene
# raise BadRequest(
# [
# {"field": "organizzato_da_esterno", "message": msg},
# {"field": "organizzato_da_interno", "message": msg},
# ]
# )
raise BadRequest(json.dumps({"error": {"message": msg}}))

# validate dove
has_webinar = not self.is_empty_blocks(data.get("webinar", {}))
has_struttura_correlata = data.get("struttura_correlata", [])
has_location_infos = self.has_location_infos(data)
has_webinar = self.has_field_value(
data=data, create=create, field_id="webinar", is_block_field=True
)
has_struttura_correlata = self.has_field_value(
data=data, create=create, field_id="struttura_correlata"
)

has_location_infos = self.has_location_infos(data=data, create=create)
if not has_webinar and not has_struttura_correlata and not has_location_infos:
msg = api.portal.translate(
_(
"dove_event_validation_error",
default='Devi compilare almeno uno tra i campi "Webinar", "Struttura di riferimento" o "Geolocation" del tab "Dove".',
raise BadRequest(
json.dumps(
[
{
"field": "webinar",
"message": self.mutual_required_msg,
},
{
"field": "struttura_correlata",
"message": self.mutual_required_msg,
},
{
"field": "geolocation",
"message": self.mutual_required_msg,
},
{
"message": api.portal.translate(
_(
"dove_validation_error",
default='Devi compilare almeno uno dei campi obbligatori nel tab "Dove".',
)
)
},
]
)
)
raise BadRequest(json.dumps({"error": {"message": msg}}))

def has_location_infos(self, data):
has_data = True
for fieldname in ["geolocation"]:
value = data.get(fieldname, None)
if not value or value in [{"latitude": 0, "longitude": 0}]:
has_data = False
return has_data

def is_empty_blocks(self, blocks_field):
blocks = blocks_field.get("blocks", {})
if not blocks:
return True
blocks_data = list(blocks.values())
for block in blocks_data:
if block.get("plaintext", ""):
# there is some text

def has_location_infos(self, data, create):
value = self.get_field_value(data, create, "geolocation")
if not value:
return False
if isinstance(value, Geolocation):
geolocation = {
"latitude": getattr(value, "latitude", 0),
"longitude": getattr(value, "longitude", 0),
}
else:
geolocation = deepcopy(value)
if geolocation in [{"latitude": 0, "longitude": 0}]:
return False
return True

def has_field_value(self, data, create, field_id, is_block_field=False):
value = self.get_field_value(data, create, field_id)
if not value:
return False
if is_block_field:
blocks = value.get("blocks", {})
if not blocks:
return False
blocks_data = list(blocks.values())
for block in blocks_data:
if block.get("plaintext", ""):
# there is some text
return True
return False
return True

def get_field_value(self, data, create, field_id):
if field_id in data:
return data[field_id]
if not create:
return getattr(self.context, field_id, None)
return None
49 changes: 36 additions & 13 deletions src/iosanita/contenttypes/tests/test_custom_validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,19 @@ def test_event_raise_badrequest_if_missing_organizzato_da(self):
self.assertEqual(resp.status_code, 400)
self.assertEqual(
json.loads(resp.json()["message"]),
{
"error": {
[
{
"field": "organizzato_da_esterno",
"message": "Compila almeno uno di questi campi.",
},
{
"field": "organizzato_da_interno",
"message": "Compila almeno uno di questi campi.",
},
{
"message": 'Devi compilare almeno uno dei due campi per "Organizzato da" nel tab "Contatti".'
}
},
},
],
)

# organizzato_da_esterno is considered empty block
Expand All @@ -85,11 +93,19 @@ def test_event_raise_badrequest_if_missing_organizzato_da(self):
self.assertEqual(resp.status_code, 400)
self.assertEqual(
json.loads(resp.json()["message"]),
{
"error": {
[
{
"field": "organizzato_da_esterno",
"message": "Compila almeno uno di questi campi.",
},
{
"field": "organizzato_da_interno",
"message": "Compila almeno uno di questi campi.",
},
{
"message": 'Devi compilare almeno uno dei due campi per "Organizzato da" nel tab "Contatti".'
}
},
},
],
)

# now compile only organizzato_da_interno
Expand Down Expand Up @@ -124,14 +140,21 @@ def test_raise_bad_request_if_missing_a_chi_si_rivolge_fields(self):
resp = self.api_session.post(self.portal_url, json=data)

self.assertEqual(resp.status_code, 400)

self.assertEqual(
json.loads(resp.json()["message"]),
{
"error": {
[
{
"field": "a_chi_si_rivolge",
"message": "Compila almeno uno di questi campi.",
},
{
"field": "a_chi_si_rivolge_tassonomia",
"message": "Compila almeno uno di questi campi.",
},
{
"message": 'Devi compilare almeno uno dei due campi del tab "A chi si rivolge".'
}
},
},
],
)

# a_chi_si_rivolge is considered empty block
Expand Down

0 comments on commit 94183e3

Please sign in to comment.