Skip to content

Commit

Permalink
feat: Update bleach to version >5.0.0 (#55)
Browse files Browse the repository at this point in the history
* feat: Update bleach to version >5.0.0

* Feat: update testsuite to match tests for bleach>5.0.0

* Dep: update versions of dependency bleach

* Docs: update docs for bleach>5.0.0

Co-authored-by: Laityned <diederik@digitalpatrol.nl>
  • Loading branch information
Laityned and Laityned committed May 16, 2022
1 parent 58fa42b commit 1c80b32
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 39 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install django==${{ matrix.django-version }} "bleach<5" coverage mock
pip install django==${{ matrix.django-version }} "bleach>=5,<6" coverage mock
python setup.py install
- name: Run coverage
run: |
Expand Down Expand Up @@ -59,7 +59,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install --pre django "bleach<5" coverage mock
pip install --pre django "bleach>=5,<6" coverage mock
python setup.py install
- name: Run tests
run: |
Expand Down
15 changes: 13 additions & 2 deletions django_bleach/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from django.utils.safestring import mark_safe

import bleach
import warnings
from bleach.css_sanitizer import CSSSanitizer
from importlib import import_module

from django_bleach.utils import get_bleach_default_options
Expand Down Expand Up @@ -43,7 +45,7 @@ class BleachField(forms.CharField):

def __init__(self, allowed_tags=None, allowed_attributes=None,
allowed_styles=None, allowed_protocols=None,
strip_comments=None, strip_tags=None, *args, **kwargs):
strip_comments=None, strip_tags=None, css_sanitizer=None, *args, **kwargs):

self.widget = get_default_widget()

Expand All @@ -56,7 +58,16 @@ def __init__(self, allowed_tags=None, allowed_attributes=None,
if allowed_attributes is not None:
self.bleach_options["attributes"] = allowed_attributes
if allowed_styles is not None:
self.bleach_options["styles"] = allowed_styles
warnings.warn(
"allowed_styles will be deprecated, use css_sanitizer instead",
DeprecationWarning
)

if css_sanitizer:
warnings.warn("allowed_styles argument is ignored since css_sanitizer is favoured over allowed_styles")
self.bleach_options["css_sanitizer"] = CSSSanitizer(allowed_css_properties=allowed_styles)
if css_sanitizer is not None:
self.bleach_options["css_sanitizer"] = css_sanitizer
if allowed_protocols is not None:
self.bleach_options["protocols"] = allowed_protocols
if strip_tags is not None:
Expand Down
16 changes: 13 additions & 3 deletions django_bleach/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.db import models
from django.utils.safestring import mark_safe

import warnings
from bleach import clean
from bleach.css_sanitizer import CSSSanitizer

from . import forms
from .utils import get_bleach_default_options
Expand All @@ -10,7 +12,7 @@
class BleachField(models.TextField):
def __init__(self, allowed_tags=None, allowed_attributes=None,
allowed_styles=None, allowed_protocols=None,
strip_tags=None, strip_comments=None, *args, **kwargs):
strip_tags=None, strip_comments=None, css_sanitizer=None, *args, **kwargs):

super().__init__(*args, **kwargs)

Expand All @@ -21,7 +23,15 @@ def __init__(self, allowed_tags=None, allowed_attributes=None,
if allowed_attributes:
self.bleach_kwargs["attributes"] = allowed_attributes
if allowed_styles:
self.bleach_kwargs["styles"] = allowed_styles
warnings.warn(
"allowed_styles will be deprecated, use css_sanitizer instead",
DeprecationWarning
)
if css_sanitizer:
warnings.warn("allowed_styles argument is ignored since css_sanitizer is favoured over allowed_styles")
self.bleach_kwargs["css_sanitizer"] = CSSSanitizer(allowed_css_properties=allowed_styles)
if css_sanitizer:
self.bleach_kwargs["css_sanitizer"] = css_sanitizer
if allowed_protocols:
self.bleach_kwargs["protocols"] = allowed_protocols
if strip_tags:
Expand All @@ -39,7 +49,7 @@ def formfield(self, form_class=forms.BleachField, **kwargs):
"max_length": self.max_length,
"allowed_tags": self.bleach_kwargs.get("tags"),
"allowed_attributes": self.bleach_kwargs.get("attributes"),
"allowed_styles": self.bleach_kwargs.get("styles"),
"css_sanitizer": self.bleach_kwargs.get("css_sanitizer"),
"allowed_protocols": self.bleach_kwargs.get("protocols"),
"strip_tags": self.bleach_kwargs.get("strip"),
"strip_comments": self.bleach_kwargs.get("strip_comments"),
Expand Down
58 changes: 47 additions & 11 deletions django_bleach/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
from django.test import TestCase, override_settings
from django.utils.safestring import SafeString

from bleach.css_sanitizer import CSSSanitizer

from django_bleach.forms import BleachField
from testproject.constants import ALLOWED_ATTRIBUTES, ALLOWED_PROTOCOLS, ALLOWED_STYLES, ALLOWED_TAGS
from testproject.constants import (
ALLOWED_ATTRIBUTES,
ALLOWED_CSS_PROPERTIES,
ALLOWED_PROTOCOLS,
ALLOWED_STYLES,
ALLOWED_TAGS,
)
from testproject.forms import BleachForm, CustomBleachWidget


Expand All @@ -21,6 +29,22 @@ def test_return_type(self):
field = BleachField()
self.assertIsInstance(field.to_python("some text"), SafeString)

def test_deprecation_allowed_styles(self):
with self.assertWarns(DeprecationWarning):
BleachField(allowed_styles=ALLOWED_STYLES)

def test_prefer_css_sanitizer_over_allowed_styles(self):
with self.assertWarnsMessage(
UserWarning,
"allowed_styles argument is ignored since css_sanitizer is favoured over allowed_styles"
):
field = BleachField(
allowed_styles=['color', 'text-align'],
css_sanitizer=CSSSanitizer(allowed_css_properties=ALLOWED_CSS_PROPERTIES)
)
self.assertIsInstance(field.bleach_options["css_sanitizer"], CSSSanitizer)
self.assertEqual(field.bleach_options["css_sanitizer"].allowed_css_properties, ALLOWED_CSS_PROPERTIES)

def test_bleaching(self):
""" Test values are bleached """
test_data = {
Expand All @@ -30,7 +54,7 @@ def test_bleaching(self):
"<script>alert(\"Hello World\")</script>",
'bleach_attrs': "<a href=\"https://www.google.com\" "
"target=\"_blank\">google.com</a>",
'bleach_styles': "<li style=\"color: white\">item</li>"
'bleach_css_sanitizer': "<li style=\"color: white\">item</li>",
}
form = BleachForm(data=test_data)
form.is_valid()
Expand All @@ -50,8 +74,8 @@ def test_bleaching(self):
'<a href="https://www.google.com">google.com</a>'
)
self.assertNotEqual(
form.cleaned_data['bleach_styles'],
test_data['bleach_styles']
form.cleaned_data['bleach_css_sanitizer'],
test_data['bleach_css_sanitizer']
)

def test_tags(self):
Expand All @@ -62,7 +86,7 @@ def test_tags(self):
'bleach_strip': "<ul><li>one</li><li>two</li></ul>",
'bleach_attrs': "<a href=\"https://www.google.com\" "
"title=\"Google\">google.com</a>",
'bleach_styles': "<li style=\"color: white;\">item</li>"
'bleach_css_sanitizer': "<li style=\"color: white;\">item</li>"
}
form = BleachForm(data=test_data)
form.is_valid()
Expand All @@ -78,8 +102,8 @@ def test_tags(self):
test_data['bleach_attrs']
)
self.assertEqual(
form.cleaned_data['bleach_styles'],
test_data['bleach_styles']
form.cleaned_data['bleach_css_sanitizer'],
test_data['bleach_css_sanitizer']
)

def test_attrs(self):
Expand All @@ -93,11 +117,11 @@ def test_attrs(self):
'no_tags': list_html,
'bleach_strip': list_html,
'bleach_attrs': list_html,
'bleach_styles': list_html
'bleach_css_sanitizer': list_html
}
form = BleachForm(data=test_data)
form.is_valid()
self.assertEqual(form.cleaned_data['no_tags'], 'onetwo')
self.assertEqual(form.cleaned_data['no_tags'], '\none\ntwo')

self.assertEqual(
form.cleaned_data['bleach_strip'],
Expand All @@ -108,7 +132,7 @@ def test_attrs(self):
test_data['bleach_strip']
)
self.assertEqual(
form.cleaned_data['bleach_styles'],
form.cleaned_data['bleach_css_sanitizer'],
'<ul><li>one</li><li>two</li></ul>'
)

Expand Down Expand Up @@ -150,6 +174,13 @@ class CustomForm(forms.Form):
allowed_tags=ALLOWED_TAGS,
allowed_styles=ALLOWED_STYLES
)
bleach_css_sanitizer = BleachField(
max_length=100,
strip_tags=False,
allowed_attributes=['style'],
allowed_tags=ALLOWED_TAGS,
css_sanitizer=CSSSanitizer(allowed_css_properties=ALLOWED_CSS_PROPERTIES)
)
self.CustomForm = CustomForm

def test_custom_widget_type(self):
Expand All @@ -172,7 +203,8 @@ def test_custom_widget_bleaches_content(self):
'target="_blank">google.com</a>'
'<a href="https://www.google.com">google.com</a>'
),
'bleach_styles': '<li style="color: white">item</li>'
'bleach_styles': '<li style="color: white">item</li>',
'bleach_css_sanitizer': '<li style="color: white">item</li>'
}
form = self.CustomForm(data=test_data)
form.is_valid()
Expand All @@ -195,3 +227,7 @@ def test_custom_widget_bleaches_content(self):
form.cleaned_data['bleach_styles'],
test_data['bleach_styles']
)
self.assertNotEqual(
form.cleaned_data['bleach_css_sanitizer'],
test_data['bleach_css_sanitizer']
)
32 changes: 27 additions & 5 deletions django_bleach/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
from django.test import TestCase
from django.utils.safestring import SafeString

from bleach.css_sanitizer import CSSSanitizer

from django_bleach.models import BleachField
from testproject.constants import ALLOWED_ATTRIBUTES, ALLOWED_PROTOCOLS, ALLOWED_STYLES, ALLOWED_TAGS
from testproject.constants import (
ALLOWED_ATTRIBUTES,
ALLOWED_CSS_PROPERTIES,
ALLOWED_PROTOCOLS,
ALLOWED_STYLES,
ALLOWED_TAGS,
)


class BleachContent(models.Model):
Expand All @@ -15,7 +23,7 @@ class BleachContent(models.Model):
content = BleachField(
allowed_attributes=ALLOWED_ATTRIBUTES,
allowed_protocols=ALLOWED_PROTOCOLS,
allowed_styles=ALLOWED_STYLES,
css_sanitizer=CSSSanitizer(allowed_css_properties=ALLOWED_CSS_PROPERTIES),
allowed_tags=ALLOWED_TAGS,
strip_comments=True,
strip_tags=True
Expand All @@ -36,7 +44,7 @@ def test_bleaching(self):
'bleach_strip': """<script>alert("Hello World")</script>""",
'bleach_attrs': "<a href=\"http://www.google.com\" "
"target=\"_blank\">google.com</a>",
'bleach_styles': "<li style=\"color: white\">item</li>",
'bleach_css_sanitizer': "<li style=\"color: white\">item</li>",
'bleach_comment': "<!-- this is a comment -->",
}
expected_values = {
Expand All @@ -45,14 +53,28 @@ def test_bleaching(self):
'bleach_strip': """alert("Hello World")""",
'bleach_attrs':
"<a>google.com</a>",
'bleach_styles': "<li style=\"color: white;\">item</li>",
'bleach_css_sanitizer': "<li style=\"color: white;\">item</li>",
'bleach_comment': ""
}

for key, value in test_data.items():
obj = BleachContent.objects.create(content=value)
self.assertEqual(obj.content, expected_values[key])

def test_deprecation_allowed_styles(self):
with self.assertWarns(DeprecationWarning):
BleachField(allowed_styles=ALLOWED_STYLES)

def test_prefer_css_sanitizer_over_allowed_styles(self):
with self.assertWarnsMessage(
UserWarning,
"allowed_styles argument is ignored since css_sanitizer is favoured over allowed_styles"
):
field = BleachField(allowed_styles=['color', 'text-align'],
css_sanitizer=CSSSanitizer(allowed_css_properties=ALLOWED_CSS_PROPERTIES))
self.assertIsInstance(field.bleach_kwargs["css_sanitizer"], CSSSanitizer)
self.assertEqual(field.bleach_kwargs["css_sanitizer"].allowed_css_properties, ALLOWED_CSS_PROPERTIES)

def test_retrieved_values_are_template_safe(self):
obj = BleachContent.objects.create(content="some content")
obj.refresh_from_db()
Expand Down Expand Up @@ -80,7 +102,7 @@ class BleachNullableContent(models.Model):
content = BleachField(
allowed_attributes=ALLOWED_ATTRIBUTES,
allowed_protocols=ALLOWED_PROTOCOLS,
allowed_styles=ALLOWED_STYLES,
css_sanitizer=CSSSanitizer(allowed_css_properties=ALLOWED_CSS_PROPERTIES),
allowed_tags=ALLOWED_TAGS,
strip_comments=True,
strip_tags=True,
Expand Down
8 changes: 5 additions & 3 deletions django_bleach/tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
from django.forms import Textarea
from django.test import TestCase, override_settings

from bleach.css_sanitizer import CSSSanitizer
from unittest.mock import patch

from django_bleach.forms import get_default_widget
from django_bleach.utils import get_bleach_default_options
from testproject.constants import ALLOWED_ATTRIBUTES, ALLOWED_PROTOCOLS, ALLOWED_STYLES, ALLOWED_TAGS
from testproject.constants import ALLOWED_ATTRIBUTES, ALLOWED_CSS_PROPERTIES, ALLOWED_PROTOCOLS, ALLOWED_TAGS
from testproject.forms import CustomBleachWidget


Expand All @@ -25,10 +26,11 @@ def test_custom_proto(self, settings):
self.assertEqual(bleach_args['protocols'], ALLOWED_PROTOCOLS)

@patch('django_bleach.utils.settings',
BLEACH_ALLOWED_STYLES=ALLOWED_STYLES)
BLEACH_ALLOWED_STYLES=ALLOWED_CSS_PROPERTIES)
def test_custom_styles(self, settings):
bleach_args = get_bleach_default_options()
self.assertEqual(bleach_args['styles'], ALLOWED_STYLES)
self.assertIsInstance(bleach_args['css_sanitizer'], CSSSanitizer)
self.assertEqual(bleach_args['css_sanitizer'].allowed_css_properties, ALLOWED_CSS_PROPERTIES)

@patch('django_bleach.utils.settings', BLEACH_ALLOWED_TAGS=ALLOWED_TAGS)
def test_custom_tags(self, settings):
Expand Down
9 changes: 7 additions & 2 deletions django_bleach/utils.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
from django.conf import settings

from bleach.css_sanitizer import CSSSanitizer


def get_bleach_default_options():
bleach_args = {}
bleach_settings = {
"BLEACH_ALLOWED_TAGS": "tags",
"BLEACH_ALLOWED_ATTRIBUTES": "attributes",
"BLEACH_ALLOWED_STYLES": "styles",
"BLEACH_ALLOWED_STYLES": "css_sanitizer",
"BLEACH_STRIP_TAGS": "strip",
"BLEACH_STRIP_COMMENTS": "strip_comments",
"BLEACH_ALLOWED_PROTOCOLS": "protocols"
}

for setting, kwarg in bleach_settings.items():
if hasattr(settings, setting):
bleach_args[kwarg] = getattr(settings, setting)
attr = getattr(settings, setting)
if setting == "BLEACH_ALLOWED_STYLES":
attr = CSSSanitizer(allowed_css_properties=attr)
bleach_args[kwarg] = attr

return bleach_args
8 changes: 6 additions & 2 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,18 @@ completely optional::

You can override each of these for individual ``BleachField`` form and model
fields if you need to. Simply pass in one of the following settings you want to
override as a named parameter to the ``BleachField``::
override as a named parameter to the ``BleachField``:

* ``allowed_tags``
* ``allowed_attributes``
* ``allowed_styles``
* ``allowed_protocols``
* ``strip_tags``
* ``strip_comments``
* ``css_sanitizer``

The following argument will be deprecated in the near future:

* ``allowed_styles``

An example, where blog posts should be allowed to contain images and headings::

Expand Down

0 comments on commit 1c80b32

Please sign in to comment.