0001-fields-add-validation-on-comment-field-30618.patch
tests/test_admin_pages.py | ||
---|---|---|
1729 | 1729 |
resp = app.get('/backoffice/forms/1/fields/') |
1730 | 1730 |
resp.forms[0]['label'] = '<div>blah</div>' |
1731 | 1731 |
resp.forms[0]['type'] = 'Comment' |
1732 | 1732 |
resp = resp.forms[0].submit() |
1733 | 1733 |
assert resp.location == 'http://example.net/backoffice/forms/1/fields/' |
1734 | 1734 |
assert FormDef.get(formdef.id).fields[-1].label == '<div>blah</div>' |
1735 | 1735 | |
1736 | 1736 | |
1737 |
def test_form_comment_field_textwidget_validation(pub): |
|
1738 |
create_superuser(pub) |
|
1739 |
FormDef.wipe() |
|
1740 |
formdef = FormDef() |
|
1741 |
formdef.name = 'form title' |
|
1742 |
# legacy, ezt syntax in a non-html field will be presented as a textarea |
|
1743 |
formdef.fields = [fields.CommentField(id='1', type='comment', |
|
1744 |
label='[if-any toto]hello world[end]')] |
|
1745 |
formdef.store() |
|
1746 |
app = login(get_app(pub)) |
|
1747 |
resp = app.get('/backoffice/forms/1/fields/1/') |
|
1748 | ||
1749 |
# bad {% %} Django template syntax |
|
1750 |
assert 'WysiwygTextWidget' not in resp.text |
|
1751 |
resp.form.fields['label'][0].value = '{% if cond %}no endif provided' |
|
1752 |
resp = resp.form.submit('submit') |
|
1753 |
assert 'syntax error in Django template: Unclosed tag on line 1' in resp.text |
|
1754 | ||
1755 |
# bad {{ }} Django template syntax |
|
1756 |
assert 'WysiwygTextWidget' not in resp.text |
|
1757 |
resp.form.fields['label'][0].value = '{{0+0}}' |
|
1758 |
resp = resp.form.submit('submit') |
|
1759 |
assert 'syntax error in Django template: Could not parse' in resp.text |
|
1760 | ||
1761 |
# bad EZT syntax |
|
1762 |
assert 'WysiwygTextWidget' not in resp.text |
|
1763 |
resp.form.fields['label'][0].value = '[end]' |
|
1764 |
resp = resp.form.submit('submit') |
|
1765 |
assert 'syntax error in ezt template: unmatched [end]' in resp.text |
|
1766 | ||
1767 |
# good syntax |
|
1768 |
assert 'WysiwygTextWidget' not in resp.text |
|
1769 |
resp.form.fields['label'][0].value = '{{variable}}' |
|
1770 |
resp = resp.form.submit('submit') |
|
1771 |
assert FormDef.get(formdef.id).fields[0].label == '{{variable}}' |
|
1772 | ||
1773 |
def test_form_comment_field_wysiwygtextwidget_validation(pub): |
|
1774 |
create_superuser(pub) |
|
1775 |
create_role() |
|
1776 | ||
1777 |
FormDef.wipe() |
|
1778 |
formdef = FormDef() |
|
1779 |
formdef.name = 'form title' |
|
1780 |
formdef.fields = [fields.CommentField(id='1', label='a comment field', type='comment')] |
|
1781 |
formdef.store() |
|
1782 | ||
1783 |
app = login(get_app(pub)) |
|
1784 |
resp = app.get('/backoffice/forms/1/fields/1/') |
|
1785 |
assert 'a comment field' in resp.text |
|
1786 | ||
1787 |
# bad {% %} Django template syntax |
|
1788 |
assert 'WysiwygTextWidget' in resp.text |
|
1789 |
resp.form.fields['label'][0].value = '{% if cond %}no endif provided' |
|
1790 |
resp = resp.form.submit('submit') |
|
1791 |
assert 'syntax error in Django template: Unclosed tag on line 1' in resp.text |
|
1792 | ||
1793 |
# bad {{ }} Django template syntax |
|
1794 |
assert 'WysiwygTextWidget' in resp.text |
|
1795 |
resp.form.fields['label'][0].value = '{{0+0}}' |
|
1796 |
resp = resp.form.submit('submit') |
|
1797 |
assert 'syntax error in Django template: Could not parse' in resp.text |
|
1798 | ||
1799 |
# bad EZT syntax |
|
1800 |
assert 'WysiwygTextWidget' in resp.text |
|
1801 |
resp.form.fields['label'][0].value = '[end]' |
|
1802 |
resp = resp.form.submit('submit') |
|
1803 |
assert 'syntax error in ezt template: unmatched [end]' in resp.text |
|
1804 | ||
1805 |
# good syntax |
|
1806 |
assert 'WysiwygTextWidget' in resp.text |
|
1807 |
resp.form.fields['label'][0].value = '{{variable}}' |
|
1808 |
resp = resp.form.submit('submit') |
|
1809 |
assert FormDef.get(formdef.id).fields[0].label == '{{variable}}' |
|
1810 | ||
1737 | 1811 |
def test_form_edit_map_field(pub): |
1738 | 1812 |
create_superuser(pub) |
1739 | 1813 |
create_role() |
1740 | 1814 | |
1741 | 1815 |
FormDef.wipe() |
1742 | 1816 |
formdef = FormDef() |
1743 | 1817 |
formdef.name = 'form title' |
1744 | 1818 |
formdef.fields = [fields.MapField(id='1', label='a field', type='map')] |
wcs/fields.py | ||
---|---|---|
714 | 714 | |
715 | 715 |
def get_display_locations_options(self): |
716 | 716 |
return [('validation', _('Validation Page')), |
717 | 717 |
('summary', _('Summary Page'))] |
718 | 718 | |
719 | 719 |
def fill_admin_form(self, form): |
720 | 720 |
if self.label and (self.label[0] != '<' and '[end]' in self.label): |
721 | 721 |
form.add(TextWidget, 'label', title=_('Label'), value=self.label, |
722 |
validation_function=ComputedExpressionWidget.validate_template, |
|
722 | 723 |
required=True, cols=70, rows=3, render_br=False) |
723 | 724 |
else: |
724 | 725 |
form.add(WysiwygTextWidget, 'label', title=_('Label'), |
726 |
validation_function=ComputedExpressionWidget.validate_template, |
|
725 | 727 |
value=self.get_html_content(), required=True) |
726 | 728 |
form.add(StringWidget, 'extra_css_class', title = _('Extra classes for CSS styling'), |
727 | 729 |
value=self.extra_css_class, size=30, advanced=(not self.extra_css_class)) |
728 | 730 |
form.add(ConditionWidget, 'condition', title=_('Display Condition'), value=self.condition, |
729 | 731 |
required=False, size=50, django_only=True, |
730 | 732 |
advanced=not(bool(self.condition))) |
731 | 733 |
form.add(CheckboxesWidget, 'display_locations', title=_('Display Locations'), |
732 | 734 |
options=self.get_display_locations_options(), |
wcs/qommon/form.py | ||
---|---|---|
571 | 571 |
return str(humanduration2seconds(self.value)) if value else None |
572 | 572 | |
573 | 573 | |
574 | 574 |
class TextWidget(quixote.form.TextWidget): |
575 | 575 |
def __init__(self, name, *args, **kwargs): |
576 | 576 |
self.validation_function = kwargs.pop('validation_function', None) |
577 | 577 |
super(TextWidget, self).__init__(name, *args, **kwargs) |
578 | 578 | |
579 |
def _parse(self, request): |
|
579 |
def _parse(self, request, use_validation_function=True):
|
|
580 | 580 |
quixote.form.TextWidget._parse(self, request) |
581 | 581 |
if self.value is not None: |
582 | 582 |
try: |
583 | 583 |
maxlength = int(self.attrs.get('maxlength', 0)) |
584 | 584 |
except (TypeError, ValueError): |
585 | 585 |
maxlength = 0 |
586 | 586 |
if maxlength: |
587 | 587 |
if len(self.value) > maxlength: |
588 | 588 |
self.error = _('too many characters (limit is %d)') % maxlength |
589 |
if self.validation_function: |
|
589 |
if use_validation_function and self.validation_function:
|
|
590 | 590 |
try: |
591 | 591 |
self.validation_function(self.value) |
592 | 592 |
except ValueError as e: |
593 | 593 |
self.error = str(e) |
594 | 594 | |
595 | 595 | |
596 | 596 |
class CheckboxWidget(quixote.form.CheckboxWidget): |
597 | 597 |
''' |
... | ... | |
1549 | 1549 |
%s |
1550 | 1550 |
],{mode:'multiple', multipleSeparator:', '}); |
1551 | 1551 |
</script>''' % (id, known_tags)) |
1552 | 1552 |
return r.getvalue() |
1553 | 1553 | |
1554 | 1554 | |
1555 | 1555 |
class WysiwygTextWidget(TextWidget): |
1556 | 1556 |
def _parse(self, request): |
1557 |
TextWidget._parse(self, request) |
|
1557 |
TextWidget._parse(self, request, use_validation_function=False)
|
|
1558 | 1558 |
if self.value: |
1559 | 1559 |
if _sanitizeHTML: |
1560 | 1560 |
self.value = _sanitizeHTML(self.value, get_request().charset, 'text/html') |
1561 | 1561 |
if self.value.startswith('<br />'): |
1562 | 1562 |
self.value = self.value[6:] |
1563 | 1563 |
if self.value.endswith('<br />'): |
1564 | 1564 |
self.value = self.value[:-6] |
1565 | 1565 |
# unescape Django template tags |
1566 | 1566 |
parser = HTMLParser() |
1567 | 1567 |
charset = get_publisher().site_charset |
1568 | 1568 |
def unquote_django(matchobj): |
1569 | 1569 |
return force_str(parser.unescape(force_text(matchobj.group(0), charset))) |
1570 | 1570 |
self.value = re.sub('{[{%](.*?)[%}]}', unquote_django, self.value) |
1571 |
if self.validation_function: |
|
1572 |
try: |
|
1573 |
self.validation_function(self.value) |
|
1574 |
except ValueError as e: |
|
1575 |
self.error = str(e) |
|
1571 | 1576 | |
1572 | 1577 |
def add_media(self): |
1573 | 1578 |
get_response().add_javascript(['qommon.wysiwyg.js']) |
1574 | 1579 | |
1575 | 1580 |
def render_content(self): |
1576 | 1581 |
from ckeditor.widgets import DEFAULT_CONFIG as CKEDITOR_DEFAULT_CONFIG |
1577 | 1582 |
attrs = self.attrs.copy() |
1578 | 1583 |
config = copy.deepcopy(CKEDITOR_DEFAULT_CONFIG) |
1579 |
- |