-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add templatetags to clean HTML within django templates #16
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
45c07e5
Added templatetags and get_settings functionality
wes-otf 5ab15cd
Added conversion of iterables to sets
wes-otf 3eaab9e
added frozenset to allow for hashing
wes-otf 929f253
Removed frozen set
wes-otf 5d66ab1
Typo fix
wes-otf 7db98eb
Added settings tests & fixed templatetags tests
wes-otf aaa3236
Updated to convert setting iterables to sets
wes-otf db505a4
Added docstring to nh3_value
wes-otf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import nh3 | ||
from django import template | ||
from django.utils.safestring import SafeText, mark_safe | ||
|
||
from django_nh3.utils import get_nh3_default_options | ||
|
||
register = template.Library() | ||
|
||
|
||
@register.filter(name="nh3") | ||
def nh3_value(value: str | None, tags: str | None = None) -> SafeText: | ||
""" | ||
Takes an input HTML value and sanitizes it utilizing nh3, | ||
returning a SafeText object that can be rendered by Django. | ||
|
||
Accepts an optional argument of allowed tags. Should be a comma delimited | ||
string (ie. "img,span" or "img") | ||
""" | ||
if value is None: | ||
return None | ||
|
||
args = {} | ||
|
||
nh3_args = get_nh3_default_options() | ||
if tags is not None: | ||
args = nh3_args.copy() | ||
args["tags"] = set(tags.split(",")) | ||
else: | ||
args = nh3_args | ||
|
||
nh3_value = nh3.clean(value, **args) | ||
return mark_safe(nh3_value) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import logging | ||
from typing import Any | ||
|
||
from django.conf import settings | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def get_nh3_default_options() -> dict[str, Any]: | ||
""" | ||
Pull the django-nh3 settings similarly to how django-bleach handled them. | ||
|
||
Some django-bleach settings can be mapped to django-nh3 settings without | ||
any changes: | ||
|
||
BLEACH_ALLOWED_TAGS -> NH3_ALLOWED_TAGS | ||
BLEACH_ALLOWED_ATTRIBUTES -> NH3_ALLOWED_ATTRIBUTES | ||
BLEACH_STRIP_COMMENTS -> NH3_STRIP_COMMENTS | ||
|
||
While other settings are have no current support in nh3: | ||
|
||
BLEACH_ALLOWED_STYLES -> There is no support for styling | ||
BLEACH_ALLOWED_PROTOCOLS -> There is no suport for protocols | ||
BLEACH_STRIP_TAGS -> This is the default behavior of nh3 | ||
|
||
""" | ||
nh3_args: dict[str, Any] = {} | ||
|
||
nh3_settings = { | ||
"NH3_ALLOWED_TAGS": "tags", | ||
"NH3_ALLOWED_ATTRIBUTES": "attributes", | ||
"NH3_STRIP_COMMENTS": "strip_comments", | ||
} | ||
|
||
for setting, kwarg in nh3_settings.items(): | ||
if hasattr(settings, setting): | ||
attr = getattr(settings, setting) | ||
|
||
# Convert from general iterables to sets | ||
if setting == "NH3_ALLOWED_TAGS": | ||
attr = set(attr) | ||
elif setting == "NH3_ALLOWED_ATTRIBUTES": | ||
copy_dict = attr.copy() | ||
for tag, attributes in attr.items(): | ||
copy_dict[tag] = set(attributes) | ||
attr = copy_dict | ||
|
||
nh3_args[kwarg] = attr | ||
|
||
return nh3_args |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
ALLOWED_ATTRIBUTES = {"*": {"class", "style"}, "a": {"href", "title"}} | ||
|
||
ALLOWED_TAGS = {"a", "li", "ul"} | ||
|
||
STRIP_COMMENTS = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from unittest.mock import patch | ||
|
||
from django.test import TestCase | ||
from django_nh3.utils import get_nh3_default_options | ||
|
||
from .constants import ALLOWED_ATTRIBUTES, ALLOWED_TAGS, STRIP_COMMENTS | ||
|
||
|
||
class TestBleachOptions(TestCase): | ||
@patch( | ||
"django_nh3.utils.settings", | ||
NH3_ALLOWED_ATTRIBUTES=ALLOWED_ATTRIBUTES, | ||
) | ||
def test_custom_attrs(self, settings): | ||
nh3_args = get_nh3_default_options() | ||
self.assertEqual(nh3_args["attributes"], ALLOWED_ATTRIBUTES) | ||
|
||
@patch( | ||
"django_nh3.utils.settings", | ||
NH3_ALLOWED_TAGS=ALLOWED_TAGS, | ||
) | ||
def test_custom_tags(self, settings): | ||
nh3_args = get_nh3_default_options() | ||
self.assertEqual(nh3_args["tags"], ALLOWED_TAGS) | ||
|
||
@patch( | ||
"django_nh3.utils.settings", | ||
NH3_STRIP_COMMENTS=STRIP_COMMENTS, | ||
) | ||
def test_strip_comments(self, settings): | ||
nh3_args = get_nh3_default_options() | ||
self.assertEqual(nh3_args["strip_comments"], STRIP_COMMENTS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from django.template import Context, Template | ||
from django.test import TestCase | ||
|
||
|
||
class TestBleachTemplates(TestCase): | ||
"""Test template tags""" | ||
|
||
def test_bleaching(self): | ||
"""Test that unsafe tags are sanitised""" | ||
context = Context( | ||
{"some_unsafe_content": '<script>alert("Hello World!")</script>'}, | ||
) | ||
template_to_render = Template( | ||
"{% load nh3_tags %}" "{{ some_unsafe_content|nh3 }}" | ||
) | ||
rendered_template = template_to_render.render(context) | ||
self.assertEqual("", rendered_template) | ||
|
||
def test_bleaching_none(self): | ||
"""Test that None is handled properly as an input""" | ||
context = Context({"none_value": None}) | ||
template_to_render = Template( | ||
"{% load nh3_tags %}" "{{ none_value|nh3 }}" | ||
) | ||
rendered_template = template_to_render.render(context) | ||
self.assertEqual("None", rendered_template) | ||
|
||
def test_bleaching_tags(self): | ||
"""Test provided tags are kept""" | ||
context = Context( | ||
{ | ||
"some_unsafe_content": ( | ||
"<b><img src='' " | ||
"onerror='alert(\\'hax\\')'>" | ||
"I'm not trying to XSS you</b>" | ||
) | ||
} | ||
) | ||
template_to_render = Template( | ||
"{% load nh3_tags %}" '{{ some_unsafe_content|nh3:"img" }}' | ||
) | ||
rendered_template = template_to_render.render(context) | ||
self.assertInHTML( | ||
'<img src="">I\'m not trying to XSS you', rendered_template | ||
) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a docstring on this please? Nothing complex, just something basic that descibes the fact it takes a value and will run clean on it & return a safe value to include in the template.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just added! Not sure if there's a specific format you prefer so I can add to it if you have a preference. Cheers!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect - thank you!