fields: don't allow an invalid value in map fields (#55629)

This commit is contained in:
Frédéric Péters 2021-07-16 09:55:37 +02:00
parent f6c363e959
commit 228a25bf8e
4 changed files with 101 additions and 1 deletions

View File

@ -6250,6 +6250,96 @@ def test_create_carddata(two_pubs):
assert carddef.data_class().count() == 0
def test_create_carddata_with_map_field(two_pubs):
CardDef.wipe()
FormDef.wipe()
if two_pubs.is_using_postgresql():
two_pubs.loggederror_class.wipe()
carddef = CardDef()
carddef.name = 'My card'
carddef.fields = [
MapField(id='1', label='map', varname='map'),
]
carddef.store()
wf = Workflow(name='create-carddata')
wf.possible_status = Workflow.get_default_workflow().possible_status[:]
create = CreateCarddataWorkflowStatusItem()
create.label = 'Create CardDef'
create.varname = 'mycard'
create.id = '_create'
create.formdef_slug = carddef.url_name
create.mappings = [
Mapping(field_id='1', expression=''),
]
create.parent = wf.possible_status[1]
wf.possible_status[1].items.insert(0, create)
wf.store()
formdef = FormDef()
formdef.name = 'source form'
formdef.fields = [
MapField(id='1', label='map', varname='map'),
]
formdef.workflow_id = wf.id
formdef.store()
formdata = formdef.data_class()()
formdata.data = {}
formdata.just_created()
assert carddef.data_class().count() == 0
# empty value
formdata = formdef.data_class()()
formdata.data = {}
formdata.just_created()
formdata.perform_workflow()
assert carddef.data_class().count() == 1
assert not carddef.data_class().select()[0].data.get('1')
# valid coordinates
create.mappings[0].expression = '1;2'
wf.store()
formdef.refresh_from_storage()
carddef.data_class().wipe()
formdata = formdef.data_class()()
formdata.data = {}
formdata.just_created()
formdata.perform_workflow()
assert carddef.data_class().count() == 1
assert carddef.data_class().select()[0].data.get('1') == '1;2'
# invalid value
create.mappings[0].expression = 'plop'
wf.store()
formdef.refresh_from_storage()
carddef.data_class().wipe()
formdata = formdef.data_class()()
formdata.data = {}
formdata.just_created()
formdata.perform_workflow()
assert carddef.data_class().count() == 1
assert not carddef.data_class().select()[0].data.get('1')
if two_pubs.is_using_postgresql():
errors = two_pubs.loggederror_class.select()
assert len(errors) == 1
assert any('invalid coordinates' in (error.exception_message or '') for error in errors)
# value from formdata
create.mappings[0].expression = '{{ form_var_map }}'
wf.store()
formdef.refresh_from_storage()
carddef.data_class().wipe()
formdata = formdef.data_class()()
formdata.data = {'1': '2;3'}
formdata.just_created()
formdata.perform_workflow()
assert carddef.data_class().count() == 1
assert carddef.data_class().select()[0].data.get('1') == '2;3'
def test_create_carddata_user_association(two_pubs):
CardDef.wipe()
FormDef.wipe()
@ -6265,6 +6355,7 @@ def test_create_carddata_user_association(two_pubs):
carddef.fields = []
carddef.user_support = 'optional'
carddef.store()
carddef.data_class().wipe()
wf = Workflow(name='create-carddata')
wf.possible_status = Workflow.get_default_workflow().possible_status[:]

View File

@ -3063,6 +3063,11 @@ class MapField(WidgetField, MapOptionsMixin):
def get_structured_value(self, data):
return self.get_json_value(data.get(self.id))
def set_value(self, data, value):
if value and ';' not in value:
raise Exception('invalid coordinates %r (missing ;)' % value)
super().set_value(data, value)
register_field_class(MapField)

View File

@ -2643,7 +2643,7 @@ class MapWidget(CompositeWidget):
self.map_attributes['data-def-lng'] = kwargs['default_position'].split(';')[1]
def initial_position(self):
if self.value:
if self.value and ';' in self.value:
return {'lat': self.value.split(';')[0], 'lng': self.value.split(';')[1]}
return None

View File

@ -473,6 +473,10 @@ class StorableObject:
filename, ignore_errors=ignore_errors, ignore_migration=ignore_migration, **kwargs
)
def refresh_from_storage(self):
obj = self.get(self.id)
self.__dict__ = obj.__dict__
@classmethod
def get_ids(cls, ids, ignore_errors=False, order_by=None, **kwargs):
objects = []