Commit 565b0a95 authored by Jérome Perrin's avatar Jérome Perrin

Formulator: validate TALES expressions in ZMI

Refuse setting an invalid TALES expression while saving in the ZMI.
parent e83e7960
Pipeline #22028 passed with stage
in 0 seconds
...@@ -43,7 +43,7 @@ DateTimeField, TextAreaField, CheckBoxField, ListField, LinesField, \ ...@@ -43,7 +43,7 @@ DateTimeField, TextAreaField, CheckBoxField, ListField, LinesField, \
MultiListField, IntegerField MultiListField, IntegerField
from Products.ERP5Form.CaptchaField import CaptchaField from Products.ERP5Form.CaptchaField import CaptchaField
from Products.Formulator.MethodField import Method from Products.Formulator.MethodField import Method
from Products.Formulator.TALESField import TALESMethod from Products.Formulator.TALESField import TALESField, TALESMethod
from Products.ERP5Type.Core.Folder import Folder from Products.ERP5Type.Core.Folder import Folder
from Products.ERP5Form.Form import field_value_cache from Products.ERP5Form.Form import field_value_cache
...@@ -1260,6 +1260,38 @@ class TestCaptchaField(ERP5TypeTestCase): ...@@ -1260,6 +1260,38 @@ class TestCaptchaField(ERP5TypeTestCase):
}) })
class TestTALESField(ERP5TypeTestCase):
def afterSetUp(self):
self.field = TALESField('test_field')
self.widget = self.field.widget
self.validator = self.field.validator
def test_validator_ok(self):
self.portal.REQUEST.set('field_test_field', 'python: 1 + 1')
validated = self.validator.validate(self.field, 'field_test_field', self.portal.REQUEST)
self.assertIsInstance(validated, TALESMethod)
self.assertEqual(validated._text, 'python: 1 + 1')
def test_validator_python_syntax_error(self):
self.portal.REQUEST.set('field_test_field', 'python: 1 - ')
with self.assertRaisesRegexp(ValidationError, 'invalid') as ctx:
self.validator.validate(self.field, 'field_test_field', self.portal.REQUEST)
self.assertEqual(ctx.exception.error_text, 'Python expression error:\ninvalid syntax (PythonExpr, line 1)')
def test_validator_string_syntax_error(self):
self.portal.REQUEST.set('field_test_field', 'string: ${non terminated')
with self.assertRaisesRegexp(ValidationError, 'invalid') as ctx:
self.validator.validate(self.field, 'field_test_field', self.portal.REQUEST)
self.assertEqual(ctx.exception.error_text, '$ must be doubled or followed by a simple path')
def test_validator_unknown_engine(self):
self.portal.REQUEST.set('field_test_field', 'notexists: ???')
with self.assertRaisesRegexp(ValidationError, 'invalid') as ctx:
self.validator.validate(self.field, 'field_test_field', self.portal.REQUEST)
self.assertEqual(ctx.exception.error_text, 'Unrecognized expression type "notexists".')
def makeDummyOid(): def makeDummyOid():
import time, random import time, random
return '%s%s' % (time.time(), random.random()) return '%s%s' % (time.time(), random.random())
...@@ -1280,4 +1312,5 @@ def test_suite(): ...@@ -1280,4 +1312,5 @@ def test_suite():
suite.addTest(unittest.makeSuite(TestProxyField)) suite.addTest(unittest.makeSuite(TestProxyField))
suite.addTest(unittest.makeSuite(TestFieldValueCache)) suite.addTest(unittest.makeSuite(TestFieldValueCache))
suite.addTest(unittest.makeSuite(TestCaptchaField)) suite.addTest(unittest.makeSuite(TestCaptchaField))
suite.addTest(unittest.makeSuite(TestTALESField))
return suite return suite
from __future__ import absolute_import from __future__ import absolute_import
import string import string
from .DummyField import fields from .DummyField import fields
from .Errors import ValidationError
from . import Widget, Validator from . import Widget, Validator
from Persistence import Persistent from Persistence import Persistent
import Acquisition import Acquisition
...@@ -77,6 +78,10 @@ except ImportError: ...@@ -77,6 +78,10 @@ except ImportError:
class TALESValidator(Validator.StringBaseValidator): class TALESValidator(Validator.StringBaseValidator):
message_names = Validator.StringBaseValidator.message_names +\
['invalid']
invalid = 'The TALES expression is invalid.'
def validate(self, field, key, REQUEST): def validate(self, field, key, REQUEST):
value = Validator.StringBaseValidator.validate(self, field, key, value = Validator.StringBaseValidator.validate(self, field, key,
REQUEST) REQUEST)
...@@ -84,6 +89,11 @@ class TALESValidator(Validator.StringBaseValidator): ...@@ -84,6 +89,11 @@ class TALESValidator(Validator.StringBaseValidator):
if value == "" and not field.get_value('required'): if value == "" and not field.get_value('required'):
return value return value
try:
getEngine().compile(value)
except (SyntaxError, getEngine().getCompilerError()) as e:
raise ValidationError('invalid', field, error_text=str(e))
return TALESMethod(value) return TALESMethod(value)
TALESValidatorInstance = TALESValidator() TALESValidatorInstance = TALESValidator()
......
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