Skip to content
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:create cleanify into utils modules #75

Merged
merged 5 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Changelog

Release date: -

0.5.2
-----

Release date: N/A

- Add ``cleanify`` function to ``flask_ckeditor.utils`` for HTML sanitization.


0.5.1
-----
Expand Down
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ Utils

.. autofunction:: get_url
.. autofunction:: random_filename
.. autofunction:: cleanify
29 changes: 27 additions & 2 deletions docs/basic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ to True to use built-in resources. You can use ``custom_url`` to load your custo
CKEditor provides five types of preset (see `comparison table <https://ckeditor.com/cke4/presets-all>`_ for the differences):

- ``basic``
- ``standard`` default value
- ``standard`` (default value)
- ``full``
- ``standard-all`` (only available from CDN)
- ``full-all`` (only available from CDN)
Expand Down Expand Up @@ -100,7 +100,7 @@ It's quite simple, just call ``ckeditor.create()`` in the template:
<input type="submit">
</form>
You can use ``value`` parameter to pass preset value (i.e. ``ckeditor.create(value='blah...blah...')``.
You can use ``value`` parameter to pass preset value (i.e. ``ckeditor.create(value='blah...blah...')``).

Get the Data
------------
Expand All @@ -119,6 +119,31 @@ from ``request.form`` by passing ``ckeditor`` as key:
return render_template('index.html')
Clean the Data
--------------

It's recommended to sanitize the HTML input from user before saving it to the database.

The Flask-CKEditor provides a helper function `cleanify`. To use it, install the extra dependencies:

.. code-block:: bash
$ pip install flask-ckeditor[all]
Then call it for your form data (you could use ``allowed_tags`` to pass a list of custom allowed HTML tags):

.. code-block:: python
from flask import request, render_template
from flask_ckeditor.utils import cleanify
@app.route('/write')
def new_post():
if request.method == 'POST':
data = cleanify(request.form.get('ckeditor')) # <--
return render_template('index.html')
Working with Flask-WTF/WTForms
-------------------------------

Expand Down
20 changes: 19 additions & 1 deletion flask_ckeditor/utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import os
import uuid

import warnings
from flask import url_for

try:
import bleach
except ImportError:
warnings.warn('The "bleach" library is not installed, `cleanify` function will not be available.')


def get_url(endpoint_or_url):
if endpoint_or_url.startswith(('https://', 'http://', '/')):
Expand All @@ -15,3 +20,16 @@ def random_filename(old_filename):
ext = os.path.splitext(old_filename)[1]
new_filename = uuid.uuid4().hex + ext
return new_filename


def cleanify(text, *, allow_tags=None):
"""Clean the input from client, this function rely on bleach.

:parm text: input str
:parm allow_tags: if you don't want to use default `allow_tags`,
you can provide a Iterable which include html tag string like ['a', 'li',...].
"""
default_allowed_tags = {'a', 'abbr', 'b', 'blockquote', 'code',
'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'}
return bleach.clean(text, tags=allow_tags or default_allowed_tags)
1 change: 1 addition & 0 deletions requirements/example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ wtforms==3.1.1
# via
# flask-admin
# flask-wtf

1 change: 1 addition & 0 deletions requirements/tests.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ flask-wtf
flask-admin
flask-sqlalchemy
tablib
bleach
18 changes: 15 additions & 3 deletions requirements/tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
#
--index-url https://pypi.tuna.tsinghua.edu.cn/simple

bleach==6.1.0
# via -r requirements/tests.in
blinker==1.7.0
# via flask
click==8.1.7
# via flask
coverage[toml]==7.3.2
# via
# coverage
# pytest-cov
# via pytest-cov
exceptiongroup==1.2.0
# via pytest
flask==3.0.0
# via
# -r requirements/tests.in
Expand All @@ -26,6 +28,8 @@ flask-sqlalchemy==3.1.1
# via -r requirements/tests.in
flask-wtf==1.2.1
# via -r requirements/tests.in
greenlet==3.0.2
# via sqlalchemy
iniconfig==2.0.0
# via pytest
itsdangerous==2.1.2
Expand All @@ -49,12 +53,20 @@ pytest==7.4.3
# pytest-cov
pytest-cov==4.1.0
# via -r requirements/tests.in
six==1.16.0
# via bleach
sqlalchemy==2.0.23
# via flask-sqlalchemy
tablib==3.5.0
# via -r requirements/tests.in
tomli==2.0.1
# via
# coverage
# pytest
typing-extensions==4.8.0
# via sqlalchemy
webencodings==0.5.1
# via bleach
werkzeug==3.0.1
# via flask
wtforms==3.1.1
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
install_requires=[
'Flask'
],
extras_require={
'all': ['flask-wtf', 'bleach']
},
classifiers=[
'Environment :: Web Environment',
'Intended Audience :: Developers',
Expand Down
63 changes: 63 additions & 0 deletions test_flask_ckeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
"""
import json
import unittest
import sys
import builtins

from flask import Flask, render_template_string, current_app
from flask_wtf import FlaskForm, CSRFProtect

from flask_ckeditor import CKEditorField, _CKEditor, CKEditor, upload_success, upload_fail
from flask_ckeditor.utils import cleanify


class CKEditorTestCase(unittest.TestCase):
Expand Down Expand Up @@ -287,6 +290,66 @@ def test_upload_fail(self):
{'uploaded': 0, 'error': {'message': 'new error message'}}
)

def test_cleanify_input_js(self):
input = 'an <script>evil()</script> example'
clean_ouput = cleanify(input)
self.assertEqual(clean_ouput,
u'an &lt;script&gt;evil()&lt;/script&gt; example')

def test_cleanify_by_allow_tags(self):
input = '<b> hello <a> this is a url </a> !</b> <h1> this is h1 </h1>'
clean_out = cleanify(input, allow_tags=['b'])
self.assertEqual(clean_out,
'<b> hello &lt;a&gt; this is a url &lt;/a&gt; !</b> &lt;h1&gt; this is h1 &lt;/h1&gt;')

def test_cleanify_by_default_allow_tags(self):
self.maxDiff = None
input = """<a>xxxxx</a>
<abbr>xxxxx</abbr>
<b>xxxxxxx</b>
<blockquote>xxxxxxx</blockquote>
<code>print(hello)</code>
<em>xxxxx</em>
<i>xxxxxx</i>
<li>xxxxxx</li>
<ol>xxxxxx</ol>
<pre>xxxxxx</pre>
<strong>xxxxxx</strong>
<ul>xxxxxx</ul>
<h1>xxxxxxx</h1>
<h2>xxxxxxx</h2>
<h3>xxxxxxx</h3>
<h4>xxxxxxx</h4>
<h5>xxxxxxx</h5>
<p>xxxxxxxx</p>
"""
clean_out = cleanify(input)
self.assertEqual(clean_out, input)

def test_import_cleanify_without_install_bleach(self):
origin_import = builtins.__import__
origin_modules = sys.modules.copy()

def import_hook(name, *args, **kwargs):
if name == 'bleach':
raise ImportError('test case module')
else:
return origin_import(name, *args, **kwargs)

if 'flask_ckeditor.utils' in sys.modules:
del sys.modules['flask_ckeditor.utils']
builtins.__import__ = import_hook

with self.assertWarns(UserWarning) as w:
from flask_ckeditor.utils import cleanify # noqa: F401

self.assertEqual(str(w.warning),
'The "bleach" library is not installed, `cleanify` function will not be available.')

# recover default
builtins.__import__ = origin_import
sys.modules = origin_modules


if __name__ == '__main__':
unittest.main()
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ deps =
pytest
coverage
flask_wtf
bleach

[testenv:coverage]
commands =
Expand Down
Loading