Projet

Général

Profil

0001-fields-add-validation-on-comment-field-30618.patch

Nicolas Roche, 15 mai 2020 16:05

Télécharger (8,29 ko)

Voir les différences:

Subject: [PATCH] fields: add validation on comment field (#30618)

 tests/test_admin_pages.py | 74 +++++++++++++++++++++++++++++++++++++++
 wcs/fields.py             |  2 ++
 wcs/qommon/form.py        | 11 ++++--
 3 files changed, 84 insertions(+), 3 deletions(-)
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
-