From 0c6815910b460f29784c6d8c3ef15d5c3e7eeaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Poulain?= Date: Wed, 5 Aug 2020 16:52:53 +0200 Subject: [PATCH] Stronger check on blocks names (#6295) Ref: https://github.com/wagtail/wagtail-react-streamfield/issues/54 --- CHANGELOG.txt | 1 + docs/releases/2.11.rst | 1 + wagtail/core/blocks/base.py | 11 +++++++++++ wagtail/core/tests/test_blocks.py | 12 ++++++++++++ 4 files changed, 25 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index af98a7f2bc..e0243f1634 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -19,6 +19,7 @@ Changelog * Serve PDFs inline in the browser (Matt Westcott) * Make document `content-type` and `content-disposition` configurable via `WAGTAILDOCS_CONTENT_TYPES` and `WAGTAILDOCS_INLINE_CONTENT_TYPES` (Matt Westcott) * Slug generation no longer removes stopwords (Andy Chosak, Scott Cranfill) + * Add check to disallow StreamField block names that do not match Python variable syntax (François Poulain) * Fix: Make page-level actions accessible to keyboard users in page listing tables (Jesse Menn) * Fix: `WAGTAILFRONTENDCACHE_LANGUAGES` was being interpreted incorrectly. It now accepts a list of strings, as documented (Karl Hobley) * Fix: Update oEmbed endpoints to use https where available (Matt Westcott) diff --git a/docs/releases/2.11.rst b/docs/releases/2.11.rst index fb94cffde3..6dc0647952 100644 --- a/docs/releases/2.11.rst +++ b/docs/releases/2.11.rst @@ -28,6 +28,7 @@ Other features * Serve PDFs inline in the browser (Matt Westcott) * Make document ``content-type`` and ``content-disposition`` configurable via ``WAGTAILDOCS_CONTENT_TYPES`` and ``WAGTAILDOCS_INLINE_CONTENT_TYPES`` (Matt Westcott) * Slug generation no longer removes stopwords (Andy Chosak, Scott Cranfill) + * Add check to disallow StreamField block names that do not match Python variable syntax (François Poulain) Bug fixes diff --git a/wagtail/core/blocks/base.py b/wagtail/core/blocks/base.py index ba56b686ca..cdcc8c1a43 100644 --- a/wagtail/core/blocks/base.py +++ b/wagtail/core/blocks/base.py @@ -1,4 +1,5 @@ import collections +import re from importlib import import_module from django import forms @@ -318,6 +319,16 @@ class Block(metaclass=BaseBlock): id='wagtailcore.E001', )) + if not errors and not re.match(r'^[_a-zA-Z][_a-zA-Z0-9]*$', self.name): + errors.append(checks.Error( + "Block name %r is invalid" % self.name, + "Block names should follow standard Python conventions for " + "variable names: alpha-numeric and underscores, and cannot " + "begin with a digit", + obj=kwargs.get('field', self), + id='wagtailcore.E001', + )) + return errors def id_for_label(self, prefix): diff --git a/wagtail/core/tests/test_blocks.py b/wagtail/core/tests/test_blocks.py index 3d2cab35b0..3e392d21ac 100644 --- a/wagtail/core/tests/test_blocks.py +++ b/wagtail/core/tests/test_blocks.py @@ -3552,6 +3552,18 @@ class TestDateTimeBlock(TestCase): class TestSystemCheck(TestCase): + def test_name_cannot_contain_non_alphanumeric(self): + block = blocks.StreamBlock([ + ('heading', blocks.CharBlock()), + ('rich+text', blocks.RichTextBlock()), + ]) + + errors = block.check() + self.assertEqual(len(errors), 1) + self.assertEqual(errors[0].id, 'wagtailcore.E001') + self.assertEqual(errors[0].hint, "Block names should follow standard Python conventions for variable names: alpha-numeric and underscores, and cannot begin with a digit") + self.assertEqual(errors[0].obj, block.child_blocks['rich+text']) + def test_name_must_be_nonempty(self): block = blocks.StreamBlock([ ('heading', blocks.CharBlock()),