This is an automated email from the ASF dual-hosted git repository. kaxilnaik pushed a commit to branch v1-10-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 60f631f75dff1c0e4340cf43e520a88c5f2ab07e Author: Ash Berlin-Taylor <[email protected]> AuthorDate: Mon Jun 8 22:27:02 2020 +0100 Don't use the `|safe` filter in code, it's risky (#9180) Most things already use the `Markup` class to correctly escape problem areas, this commit just fixes the last instances so that we can assert that `|safe` is never used. (cherry-picked from 7fd3695766095a358803b79454bde26e5e28c1f0) --- .pre-commit-config.yaml | 7 ++++ airflow/contrib/plugins/metastore_browser/main.py | 4 +-- .../templates/metastore_browser/dbs.html | 2 +- airflow/www/static/main.css | 4 +++ airflow/www/templates/airflow/chart.html | 2 +- airflow/www/templates/airflow/code.html | 2 +- airflow/www/templates/airflow/config.html | 2 +- airflow/www/templates/airflow/dag.html | 6 ++-- airflow/www/templates/airflow/dag_code.html | 2 +- airflow/www/templates/airflow/duration_chart.html | 4 +-- airflow/www/templates/airflow/gantt.html | 4 +-- airflow/www/templates/airflow/graph.html | 14 ++++---- airflow/www/templates/airflow/list_dags.html | 4 +-- airflow/www/templates/airflow/query.html | 2 +- airflow/www/templates/airflow/task.html | 8 +---- airflow/www/templates/airflow/task_instance.html | 2 +- airflow/www/templates/airflow/ti_code.html | 2 +- airflow/www/templates/airflow/tree.html | 2 +- airflow/www/templates/airflow/xcom.html | 1 - airflow/www/views.py | 38 ++++++++++++---------- airflow/www_rbac/static/css/main.css | 4 +++ airflow/www_rbac/templates/airflow/chart.html | 2 +- airflow/www_rbac/templates/airflow/code.html | 2 +- airflow/www_rbac/templates/airflow/config.html | 2 +- airflow/www_rbac/templates/airflow/dag.html | 6 ++-- airflow/www_rbac/templates/airflow/dag_code.html | 2 +- .../www_rbac/templates/airflow/duration_chart.html | 4 +-- airflow/www_rbac/templates/airflow/gantt.html | 6 ++-- airflow/www_rbac/templates/airflow/graph.html | 14 ++++---- airflow/www_rbac/templates/airflow/model_list.html | 2 +- airflow/www_rbac/templates/airflow/task.html | 8 +---- .../www_rbac/templates/airflow/task_instance.html | 2 +- airflow/www_rbac/templates/airflow/ti_code.html | 2 +- airflow/www_rbac/templates/airflow/xcom.html | 1 - airflow/www_rbac/utils.py | 19 +++++++---- airflow/www_rbac/views.py | 22 +++++-------- 36 files changed, 108 insertions(+), 102 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7e49b77..88ab3cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -228,6 +228,13 @@ repos: files: ^setup.py$|^INSTALL$|^CONTRIBUTING.rst$ pass_filenames: false require_serial: true + - id: dont-use-safe-filter + language: pygrep + name: Don't use safe in templates + description: the Safe filter is error-prone, use Markup() in code instead + entry: "\\|\\s*safe" + files: \.html$ + pass_filenames: true - id: python2-fastcheck language: pygrep name: Find common Python 3 vs. 2.7 compatibility problems diff --git a/airflow/contrib/plugins/metastore_browser/main.py b/airflow/contrib/plugins/metastore_browser/main.py index b0643ac..6826030 100644 --- a/airflow/contrib/plugins/metastore_browser/main.py +++ b/airflow/contrib/plugins/metastore_browser/main.py @@ -20,7 +20,7 @@ from datetime import datetime import json -from flask import Blueprint, request +from flask import Blueprint, Markup, request from flask_admin import BaseView, expose import pandas as pd @@ -67,7 +67,7 @@ class MetastoreBrowserView(BaseView, wwwutils.DataProfilingMixin): escape=False, na_rep='',) return self.render( - "metastore_browser/dbs.html", table=table) + "metastore_browser/dbs.html", table=Markup(table)) @expose('/table/') def table(self): diff --git a/airflow/contrib/plugins/metastore_browser/templates/metastore_browser/dbs.html b/airflow/contrib/plugins/metastore_browser/templates/metastore_browser/dbs.html index 9555a02..6a6e187 100644 --- a/airflow/contrib/plugins/metastore_browser/templates/metastore_browser/dbs.html +++ b/airflow/contrib/plugins/metastore_browser/templates/metastore_browser/dbs.html @@ -23,5 +23,5 @@ <h4> <span>Hive Databases</span> </h4> - {{ table|safe }} + {{ table }} {% endblock %} diff --git a/airflow/www/static/main.css b/airflow/www/static/main.css index 2740a0d..c5008b8 100644 --- a/airflow/www/static/main.css +++ b/airflow/www/static/main.css @@ -224,6 +224,10 @@ div.square { box-shadow: inset 0 6px 6px rgba(0, 0, 0, 0.4); } +.dag-doc { + margin-bottom: 15px; +} + .hll { background-color: #ffffcc } .c { color: #408080; font-style: italic } /* Comment */ .err { border: 1px solid #FF0000 } /* Error */ diff --git a/airflow/www/templates/airflow/chart.html b/airflow/www/templates/airflow/chart.html index 1fc3779..128364c 100644 --- a/airflow/www/templates/airflow/chart.html +++ b/airflow/www/templates/airflow/chart.html @@ -46,7 +46,7 @@ <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> </form> </div> -<div style="clear: both;">{{ chart |safe }}</div> +<div style="clear: both;">{{ chart }}</div> <hr/> {% endblock %} diff --git a/airflow/www/templates/airflow/code.html b/airflow/www/templates/airflow/code.html index 522c8f4..a91975f 100644 --- a/airflow/www/templates/airflow/code.html +++ b/airflow/www/templates/airflow/code.html @@ -40,6 +40,6 @@ {% endif %} {% if code_html %} - {{ code_html|safe }} + {{ code_html }} {% endif %} {% endblock %} diff --git a/airflow/www/templates/airflow/config.html b/airflow/www/templates/airflow/config.html index 0aedb17..f7786be 100644 --- a/airflow/www/templates/airflow/config.html +++ b/airflow/www/templates/airflow/config.html @@ -36,7 +36,7 @@ {% endif %} {% if code_html %} - {{ code_html|safe }} + {{ code_html }} {% endif %} <hr> diff --git a/airflow/www/templates/airflow/dag.html b/airflow/www/templates/airflow/dag.html index 89d3ce0..67e32a3 100644 --- a/airflow/www/templates/airflow/dag.html +++ b/airflow/www/templates/airflow/dag.html @@ -369,8 +369,8 @@ function updateQueryStringParameter(uri, key, value) { }); subdag_id = sd; execution_date = d; - $('#task_id').html(t); - $('#execution_date').html(d); + $('#task_id').text(t); + $('#execution_date').text(d); $('#myModal').modal({}); $("#myModal").css("margin-top","0px") if (subdag_id === undefined) @@ -428,7 +428,7 @@ function updateQueryStringParameter(uri, key, value) { function call_modal_dag(dag) { id = dag && dag.id; execution_date = dag && dag.execution_date; - $('#dag_id').html(dag_id); + $('#dag_id').text(dag_id); $('#dagModal').modal({}); $("#dagModal").css("margin-top","0px"); } diff --git a/airflow/www/templates/airflow/dag_code.html b/airflow/www/templates/airflow/dag_code.html index 05a5553..2649f72 100644 --- a/airflow/www/templates/airflow/dag_code.html +++ b/airflow/www/templates/airflow/dag_code.html @@ -26,7 +26,7 @@ <div class="active"> <a onclick="toggleWrap()">Toggle wrap</a> </div> - {{ html_code|safe }} + {{ html_code }} {% endblock %} {% block tail %} diff --git a/airflow/www/templates/airflow/duration_chart.html b/airflow/www/templates/airflow/duration_chart.html index 392dc17..ff5d8ab 100644 --- a/airflow/www/templates/airflow/duration_chart.html +++ b/airflow/www/templates/airflow/duration_chart.html @@ -50,8 +50,8 @@ <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> </form> </div> -<div id="dur_chart" style="clear: both;">{{ chart |safe }}</div> -<div id="cum_dur_chart" style="clear: both;">{{ cum_chart | safe}}</div> +<div id="dur_chart" style="clear: both;">{{ chart }}</div> +<div id="cum_dur_chart" style="clear: both;">{{ cum_chart }}</div> <hr/> {% endblock %} diff --git a/airflow/www/templates/airflow/gantt.html b/airflow/www/templates/airflow/gantt.html index a76b3851..f2bea89 100644 --- a/airflow/www/templates/airflow/gantt.html +++ b/airflow/www/templates/airflow/gantt.html @@ -33,7 +33,7 @@ Base date: {{ form.base_date(class_="form-control") }} Number of runs: {{ form.num_runs(class_="form-control") }} Run:<input type="hidden" value="{{ dag.dag_id }}" name="dag_id"> - {{ form.execution_date(class_="form-control") | safe }} + {{ form.execution_date(class_="form-control") }} <input type="submit" value="Go" class="btn btn-default" action="" method="get"> <input type="hidden" name="root" value="{{ root if root else '' }}"> <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> @@ -57,7 +57,7 @@ var dag_id = '{{ dag.dag_id }}'; var task_id = ''; var execution_date = ''; - data = {{ data |tojson|safe }}; + data = {{ data |tojson }}; var gantt = d3.gantt() .taskTypes(data.taskNames) .taskStatus(data.taskStatus) diff --git a/airflow/www/templates/airflow/graph.html b/airflow/www/templates/airflow/graph.html index 0535bf8..dcbe4f9 100644 --- a/airflow/www/templates/airflow/graph.html +++ b/airflow/www/templates/airflow/graph.html @@ -32,7 +32,7 @@ {% block body %} {{ super() }} {% if doc_md %} -<div class="rich_doc" style="margin-bottom: 15px;">{{ doc_md|safe }}</div> +{{ doc_md }} {% endif %} <div class="form-inline"> <form method="get" style="float:left;"> @@ -40,9 +40,9 @@ Base date: {{ form.base_date(class_="form-control") }} Number of runs: {{ form.num_runs(class_="form-control") }} Run: - {{ form.execution_date(class_="form-control") | safe }} + {{ form.execution_date(class_="form-control") }} Layout: - {{ form.arrange(class_="form-control") | safe }} + {{ form.arrange(class_="form-control") }} <input type="hidden" name="root" value="{{ root }}"> <input type="hidden" value="{{ dag.dag_id }}" name="dag_id"> <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> @@ -107,10 +107,10 @@ var upstream_color = "#2020A0"; var downstream_color = "#0000FF"; - var nodes = {{ nodes|tojson|safe }}; - var edges = {{ edges|tojson|safe }}; - var tasks = {{ tasks|tojson|safe }}; - var task_instances = {{ task_instances|tojson|safe }}; + var nodes = {{ nodes|tojson }}; + var edges = {{ edges|tojson }}; + var tasks = {{ tasks|tojson }}; + var task_instances = {{ task_instances|tojson }}; var execution_date = "{{ execution_date }}"; var arrange = "{{ arrange }}"; var g = dagreD3.json.decode(nodes, edges); diff --git a/airflow/www/templates/airflow/list_dags.html b/airflow/www/templates/airflow/list_dags.html index 3e9fe29..e9398eb 100644 --- a/airflow/www/templates/airflow/list_dags.html +++ b/airflow/www/templates/airflow/list_dags.html @@ -216,8 +216,8 @@ {% if filter_groups %} var filter = new AdminFilters( '#filter_form', '.field-filters', - {{ filter_groups|tojson|safe }}, - {{ active_filters|tojson|safe }} + {{ filter_groups|tojson }}, + {{ active_filters|tojson }} ); {% endif %} })(jQuery); diff --git a/airflow/www/templates/airflow/query.html b/airflow/www/templates/airflow/query.html index 6a41e7b..b5c4546 100644 --- a/airflow/www/templates/airflow/query.html +++ b/airflow/www/templates/airflow/query.html @@ -43,7 +43,7 @@ </div> </div> </form> - {{ results|safe }} + {{ results }} {% endblock %} {% block tail %} {{ super() }} diff --git a/airflow/www/templates/airflow/task.html b/airflow/www/templates/airflow/task.html index 2fe0b0e..fb53ca7 100644 --- a/airflow/www/templates/airflow/task.html +++ b/airflow/www/templates/airflow/task.html @@ -39,14 +39,11 @@ </tr> {% endfor %} </table> - {% if html_code is defined %} - {{ html_code|safe }} - {% endif %} </div> <div> {% for attr, value in special_attrs_rendered.items() %} <h5>Attribute: {{ attr }}</h5> - {{ value|safe }} + {{ value }} {% endfor %} <h5>Task Instance Attributes</h5> <table class="table table-striped table-bordered"> @@ -74,8 +71,5 @@ </tr> {% endfor %} </table> - {% if html_code is defined %} - {{ html_code|safe }} - {% endif %} </div> {% endblock %} diff --git a/airflow/www/templates/airflow/task_instance.html b/airflow/www/templates/airflow/task_instance.html index 2380a4b..e1e4819 100644 --- a/airflow/www/templates/airflow/task_instance.html +++ b/airflow/www/templates/airflow/task_instance.html @@ -35,7 +35,7 @@ {{ task_id }} <input type="hidden" value="{{ dag.dag_id }}" name="dag_id"> </span> - {{ form.execution_date(class_="form-control") | safe }} + {{ form.execution_date(class_="form-control") }} </div> </form> diff --git a/airflow/www/templates/airflow/ti_code.html b/airflow/www/templates/airflow/ti_code.html index 7531a01..5ca5f59 100644 --- a/airflow/www/templates/airflow/ti_code.html +++ b/airflow/www/templates/airflow/ti_code.html @@ -25,6 +25,6 @@ <h4>{{ title }}</h4> {% for k, v in html_dict.items() %} <h5>{{ k }}</h5> - {{ v|safe }} + {{ v }} {% endfor %} {% endblock %} diff --git a/airflow/www/templates/airflow/tree.html b/airflow/www/templates/airflow/tree.html index 6bfb465..5804efc 100644 --- a/airflow/www/templates/airflow/tree.html +++ b/airflow/www/templates/airflow/tree.html @@ -84,7 +84,7 @@ $('span.status_square').tooltip({html: true}); var devicePixelRatio = window.devicePixelRatio || 1; -var data = {{ data|tojson|safe }}; +var data = {{ data|tojson }}; var barHeight = 20; var axisHeight = 40; var square_x = parseInt(500 * devicePixelRatio); diff --git a/airflow/www/templates/airflow/xcom.html b/airflow/www/templates/airflow/xcom.html index b043e95..a79467b 100644 --- a/airflow/www/templates/airflow/xcom.html +++ b/airflow/www/templates/airflow/xcom.html @@ -36,6 +36,5 @@ </tr> {% endfor %} </table> - {{ html_code|safe }} </div> {% endblock %} diff --git a/airflow/www/views.py b/airflow/www/views.py index a069f17..e98096d 100644 --- a/airflow/www/views.py +++ b/airflow/www/views.py @@ -236,20 +236,25 @@ def pygment_html_render(s, lexer=lexers.TextLexer): def render(obj, lexer): out = "" if isinstance(obj, basestring): - out += pygment_html_render(obj, lexer) + out += Markup(pygment_html_render(obj, lexer)) elif isinstance(obj, (tuple, list)): for i, s in enumerate(obj): - out += "<div>List item #{}</div>".format(i) - out += "<div>" + pygment_html_render(s, lexer) + "</div>" + out += Markup("<div>List item #{}</div>".format(i)) + out += Markup("<div>" + pygment_html_render(s, lexer) + "</div>") elif isinstance(obj, dict): for k, v in obj.items(): - out += '<div>Dict item "{}"</div>'.format(k) - out += "<div>" + pygment_html_render(v, lexer) + "</div>" + out += Markup('<div>Dict item "{}"</div>'.format(k)) + out += Markup("<div>" + pygment_html_render(v, lexer) + "</div>") return out -def wrapped_markdown(s): - return '<div class="rich_doc">' + markdown.markdown(s) + "</div>" +def wrapped_markdown(s, css_class=None): + if s is None: + return None + + return Markup( + '<div class="rich_doc {css_class}" >' + markdown.markdown(s) + "</div>" + ).format(css_class=css_class) attr_renderer = { @@ -694,15 +699,15 @@ class Airflow(AirflowViewMixin, BaseView): dag_id = request.args.get('dag_id') dag_orm = models.DagModel.get_dagmodel(dag_id, session=session) code = DagCode.get_code_by_fileloc(dag_orm.fileloc) - html_code = highlight( - code, lexers.PythonLexer(), HtmlFormatter(linenos=True)) + html_code = Markup(highlight( + code, lexers.PythonLexer(), HtmlFormatter(linenos=True))) except Exception as e: all_errors += ( "Exception encountered during " + "dag_id retrieval/dag retrieval fallback/code highlighting:\n\n{}\n".format(e) ) - html_code = '<p>Failed to load file.</p><p>Details: {}</p>'.format( + html_code = Markup('<p>Failed to load file.</p><p>Details: {}</p>').format( escape(all_errors)) return self.render( @@ -819,8 +824,7 @@ class Airflow(AirflowViewMixin, BaseView): if template_field in attr_renderer: html_dict[template_field] = attr_renderer[template_field](content) else: - html_dict[template_field] = ( - "<pre><code>" + str(content) + "</pre></code>") + html_dict[template_field] = Markup("<pre><code>{}</pre></code>").format(str(content)) return self.render( 'airflow/ti_code.html', @@ -1741,7 +1745,7 @@ class Airflow(AirflowViewMixin, BaseView): if not tasks: flash("No tasks found", "error") session.commit() - doc_md = markdown.markdown(dag.doc_md) if hasattr(dag, 'doc_md') and dag.doc_md else '' + doc_md = wrapped_markdown(getattr(dag, 'doc_md', None), css_class='dag-doc') external_logs = conf.get('elasticsearch', 'frontend') return self.render( @@ -1873,8 +1877,8 @@ class Airflow(AirflowViewMixin, BaseView): demo_mode=conf.getboolean('webserver', 'demo_mode'), root=root, form=form, - chart=chart.htmlcontent, - cum_chart=cum_chart.htmlcontent + chart=Markup(chart.htmlcontent), + cum_chart=Markup(cum_chart.htmlcontent) ) @expose('/tries') @@ -1940,7 +1944,7 @@ class Airflow(AirflowViewMixin, BaseView): demo_mode=conf.getboolean('webserver', 'demo_mode'), root=root, form=form, - chart=chart.htmlcontent + chart=Markup(chart.htmlcontent) ) @expose('/landing_times') @@ -2396,7 +2400,7 @@ class QueryView(wwwutils.DataProfilingMixin, AirflowViewMixin, BaseView): return self.render( 'airflow/query.html', form=form, title="Ad Hoc Query", - results=results or '', + results=Markup(results or ''), has_data=has_data) diff --git a/airflow/www_rbac/static/css/main.css b/airflow/www_rbac/static/css/main.css index f5636d9..8b2324b 100644 --- a/airflow/www_rbac/static/css/main.css +++ b/airflow/www_rbac/static/css/main.css @@ -291,6 +291,10 @@ label[for="timezone-other"], display: block; } +.dag-doc { + margin-bottom: 15px; +} + .hll { background-color: #ffc; } .c { color: #408080; font-style: italic; } /* Comment */ .err { border: 1px solid #f00; } /* Error */ diff --git a/airflow/www_rbac/templates/airflow/chart.html b/airflow/www_rbac/templates/airflow/chart.html index 07865c8..5e2a29f 100644 --- a/airflow/www_rbac/templates/airflow/chart.html +++ b/airflow/www_rbac/templates/airflow/chart.html @@ -42,7 +42,7 @@ <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> </form> </div> -<div style="clear: both;">{{ chart |safe }}</div> +<div style="clear: both;">{{ chart }}</div> <hr/> {% endblock %} diff --git a/airflow/www_rbac/templates/airflow/code.html b/airflow/www_rbac/templates/airflow/code.html index adbcfbf..725f642 100644 --- a/airflow/www_rbac/templates/airflow/code.html +++ b/airflow/www_rbac/templates/airflow/code.html @@ -39,6 +39,6 @@ {% endif %} {% if code_html %} - {{ code_html|safe }} + {{ code_html }} {% endif %} {% endblock %} diff --git a/airflow/www_rbac/templates/airflow/config.html b/airflow/www_rbac/templates/airflow/config.html index f617b68..3ea81c4 100644 --- a/airflow/www_rbac/templates/airflow/config.html +++ b/airflow/www_rbac/templates/airflow/config.html @@ -35,7 +35,7 @@ {% endif %} {% if code_html %} - {{ code_html|safe }} + {{ code_html }} {% endif %} <hr> diff --git a/airflow/www_rbac/templates/airflow/dag.html b/airflow/www_rbac/templates/airflow/dag.html index dda7cf9..b5f4d00 100644 --- a/airflow/www_rbac/templates/airflow/dag.html +++ b/airflow/www_rbac/templates/airflow/dag.html @@ -376,8 +376,8 @@ function updateQueryStringParameter(uri, key, value) { }); subdag_id = sd; execution_date = d; - $('#task_id').html(t); - $('#execution_date').html(d); + $('#task_id').text(t); + $('#execution_date').text(d); $('#myModal').modal({}); $("#myModal").css("margin-top","0px"); $('#extra_links').prev('hr').hide(); @@ -474,7 +474,7 @@ function updateQueryStringParameter(uri, key, value) { function call_modal_dag(dag) { id = dag && dag.id; execution_date = dag && dag.execution_date; - $('#dag_id').html(dag_id); + $('#dag_id').text(dag_id); $('#dagModal').modal({}); $("#dagModal").css("margin-top","0px"); } diff --git a/airflow/www_rbac/templates/airflow/dag_code.html b/airflow/www_rbac/templates/airflow/dag_code.html index 2650efc..92a74aa 100644 --- a/airflow/www_rbac/templates/airflow/dag_code.html +++ b/airflow/www_rbac/templates/airflow/dag_code.html @@ -24,7 +24,7 @@ <div class="active"> <a onclick="toggleWrap()">Toggle wrap</a> </div> - {{ html_code|safe }} + {{ html_code }} {% endblock %} {% block tail %} diff --git a/airflow/www_rbac/templates/airflow/duration_chart.html b/airflow/www_rbac/templates/airflow/duration_chart.html index 4955f11..b1b9fa0 100644 --- a/airflow/www_rbac/templates/airflow/duration_chart.html +++ b/airflow/www_rbac/templates/airflow/duration_chart.html @@ -46,8 +46,8 @@ <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> </form> </div> -<div id="dur_chart" style="clear: both;">{{ chart |safe }}</div> -<div id="cum_dur_chart" style="clear: both;">{{ cum_chart | safe}}</div> +<div id="dur_chart" style="clear: both;">{{ chart }}</div> +<div id="cum_dur_chart" style="clear: both;">{{ cum_chart }}</div> <hr/> {% endblock %} diff --git a/airflow/www_rbac/templates/airflow/gantt.html b/airflow/www_rbac/templates/airflow/gantt.html index 6e7fa9f..7a5e954 100644 --- a/airflow/www_rbac/templates/airflow/gantt.html +++ b/airflow/www_rbac/templates/airflow/gantt.html @@ -30,7 +30,7 @@ Base date: {{ form.base_date(class_="form-control") }} Number of runs: {{ form.num_runs(class_="form-control") }} Run:<input type="hidden" value="{{ dag.dag_id }}" name="dag_id"> - {{ form.execution_date(class_="form-control") | safe }} + {{ form.execution_date(class_="form-control") }} <input type="submit" value="Go" class="btn btn-default" action="" method="get"> <input type="hidden" name="root" value="{{ root if root else '' }}"> <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> @@ -52,8 +52,8 @@ $( document ).ready(function() { var dag_id = '{{ dag.dag_id }}'; var task_id = ''; - var exection_date = ''; - data = {{ data |tojson|safe }}; + var execution_date = ''; + data = {{ data |tojson }}; var gantt = d3.gantt() .taskTypes(data.taskNames) .height(data.height) diff --git a/airflow/www_rbac/templates/airflow/graph.html b/airflow/www_rbac/templates/airflow/graph.html index 9585b67..e2ab0f1 100644 --- a/airflow/www_rbac/templates/airflow/graph.html +++ b/airflow/www_rbac/templates/airflow/graph.html @@ -27,7 +27,7 @@ {% block content %} {{ super() }} {% if doc_md %} -<div class="rich_doc" style="margin-bottom: 15px;">{{ doc_md|safe }}</div> +{{ doc_md }} {% endif %} <div class="form-inline"> <form method="get" style="float:left;"> @@ -35,9 +35,9 @@ Base date: {{ form.base_date(class_="form-control") }} Number of runs: {{ form.num_runs(class_="form-control") }} Run: - {{ form.execution_date(class_="form-control") | safe }} + {{ form.execution_date(class_="form-control") }} Layout: - {{ form.arrange(class_="form-control") | safe }} + {{ form.arrange(class_="form-control") }} <input type="hidden" name="root" value="{{ root }}"> <input type="hidden" value="{{ dag.dag_id }}" name="dag_id"> <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}"> @@ -104,14 +104,14 @@ var initialStrokeWidth = '3px'; var highlightStrokeWidth = '5px'; - var nodes = {{ nodes|tojson|safe }}; - var edges = {{ edges|tojson|safe }}; + var nodes = {{ nodes|tojson }}; + var edges = {{ edges|tojson }}; var execution_date = "{{ execution_date }}"; var arrange = "{{ arrange }}"; // Below variables are being used in dag.js - var tasks = {{ tasks|tojson|safe }}; - var task_instances = {{ task_instances|tojson|safe }}; + var tasks = {{ tasks|tojson }}; + var task_instances = {{ task_instances|tojson }}; var getTaskInstanceURL = "{{ url_for('Airflow.task_instances') }}" + "?dag_id=" + encodeURIComponent(dag_id) + "&execution_date=" + encodeURIComponent(execution_date); diff --git a/airflow/www_rbac/templates/airflow/model_list.html b/airflow/www_rbac/templates/airflow/model_list.html index aba6e52..dc5bec0 100644 --- a/airflow/www_rbac/templates/airflow/model_list.html +++ b/airflow/www_rbac/templates/airflow/model_list.html @@ -78,7 +78,7 @@ {% if formatter and formatter(item) %} <td>{{ formatter(item) }}</td> {% elif item[value] != None %} - <td>{{ item[value]|safe }}</td> + <td>{{ item[value] }}</td> {% else %} <td></td> {% endif %} diff --git a/airflow/www_rbac/templates/airflow/task.html b/airflow/www_rbac/templates/airflow/task.html index 02ad445..5278a74 100644 --- a/airflow/www_rbac/templates/airflow/task.html +++ b/airflow/www_rbac/templates/airflow/task.html @@ -37,14 +37,11 @@ </tr> {% endfor %} </table> - {% if html_code is defined %} - {{ html_code|safe }} - {% endif %} </div> <div> {% for attr, value in special_attrs_rendered.items() %} <h5>Attribute: {{ attr }}</h5> - {{ value|safe }} + {{ value }} {% endfor %} <h5>Task Instance Attributes</h5> <table class="table table-striped table-bordered"> @@ -72,8 +69,5 @@ </tr> {% endfor %} </table> - {% if html_code is defined %} - {{ html_code|safe }} - {% endif %} </div> {% endblock %} diff --git a/airflow/www_rbac/templates/airflow/task_instance.html b/airflow/www_rbac/templates/airflow/task_instance.html index b424c65..ec43800 100644 --- a/airflow/www_rbac/templates/airflow/task_instance.html +++ b/airflow/www_rbac/templates/airflow/task_instance.html @@ -32,7 +32,7 @@ {{ task_id }} <input type="hidden" value="{{ task_id }}" name="task_id"> </span> - {{ form.execution_date(class_="form-control") | safe }} + {{ form.execution_date(class_="form-control") }} </div> </form> diff --git a/airflow/www_rbac/templates/airflow/ti_code.html b/airflow/www_rbac/templates/airflow/ti_code.html index 32a0739..05f5472 100644 --- a/airflow/www_rbac/templates/airflow/ti_code.html +++ b/airflow/www_rbac/templates/airflow/ti_code.html @@ -23,6 +23,6 @@ <h4>{{ title }}</h4> {% for k, v in html_dict.items() %} <h5>{{ k }}</h5> - {{ v|safe }} + {{ v }} {% endfor %} {% endblock %} diff --git a/airflow/www_rbac/templates/airflow/xcom.html b/airflow/www_rbac/templates/airflow/xcom.html index 16174b1..ac99c25 100644 --- a/airflow/www_rbac/templates/airflow/xcom.html +++ b/airflow/www_rbac/templates/airflow/xcom.html @@ -37,6 +37,5 @@ </tr> {% endfor %} </table> - {{ html_code|safe }} </div> {% endblock %} diff --git a/airflow/www_rbac/utils.py b/airflow/www_rbac/utils.py index c2c551b..ffd79b1 100644 --- a/airflow/www_rbac/utils.py +++ b/airflow/www_rbac/utils.py @@ -300,20 +300,25 @@ def pygment_html_render(s, lexer=lexers.TextLexer): def render(obj, lexer): out = "" if isinstance(obj, basestring): - out += pygment_html_render(obj, lexer) + out += Markup(pygment_html_render(obj, lexer)) elif isinstance(obj, (tuple, list)): for i, s in enumerate(obj): - out += "<div>List item #{}</div>".format(i) - out += "<div>" + pygment_html_render(s, lexer) + "</div>" + out += Markup("<div>List item #{}</div>").format(i) + out += Markup("<div>" + pygment_html_render(s, lexer) + "</div>") elif isinstance(obj, dict): for k, v in obj.items(): - out += '<div>Dict item "{}"</div>'.format(k) - out += "<div>" + pygment_html_render(v, lexer) + "</div>" + out += Markup('<div>Dict item "{}"</div>').format(k) + out += Markup("<div>" + pygment_html_render(v, lexer) + "</div>") return out -def wrapped_markdown(s): - return '<div class="rich_doc">' + markdown.markdown(s) + "</div>" +def wrapped_markdown(s, css_class=None): + if s is None: + return None + + return Markup( + '<div class="rich_doc {css_class}" >' + markdown.markdown(s) + "</div>" + ).format(css_class=css_class) def get_attr_renderer(): diff --git a/airflow/www_rbac/views.py b/airflow/www_rbac/views.py index ef2b751..f9f7604 100644 --- a/airflow/www_rbac/views.py +++ b/airflow/www_rbac/views.py @@ -33,7 +33,6 @@ from urllib.parse import unquote import six from six.moves.urllib.parse import quote -import markdown import pendulum import sqlalchemy as sqla from flask import ( @@ -540,15 +539,15 @@ class Airflow(AirflowBaseView): dag_id = request.args.get('dag_id') dag_orm = DagModel.get_dagmodel(dag_id, session=session) code = DagCode.get_code_by_fileloc(dag_orm.fileloc) - html_code = highlight( - code, lexers.PythonLexer(), HtmlFormatter(linenos=True)) + html_code = Markup(highlight( + code, lexers.PythonLexer(), HtmlFormatter(linenos=True))) except Exception as e: all_errors += ( "Exception encountered during " + "dag_id retrieval/dag retrieval fallback/code highlighting:\n\n{}\n".format(e) ) - html_code = '<p>Failed to load file.</p><p>Details: {}</p>'.format( + html_code = Markup('<p>Failed to load file.</p><p>Details: {}</p>').format( escape(all_errors)) return self.render_template( @@ -635,11 +634,9 @@ class Airflow(AirflowBaseView): for template_field in task.template_fields: content = getattr(task, template_field) if template_field in wwwutils.get_attr_renderer(): - html_dict[template_field] = \ - wwwutils.get_attr_renderer()[template_field](content) + html_dict[template_field] = wwwutils.get_attr_renderer()[template_field](content) else: - html_dict[template_field] = ( - "<pre><code>" + str(content) + "</pre></code>") + html_dict[template_field] = Markup("<pre><code>{}</pre></code>").format(str(content)) return self.render_template( 'airflow/ti_code.html', @@ -1618,8 +1615,7 @@ class Airflow(AirflowBaseView): if not tasks: flash("No tasks found", "error") session.commit() - doc_md = markdown.markdown(dag.doc_md) \ - if hasattr(dag, 'doc_md') and dag.doc_md else '' + doc_md = wwwutils.wrapped_markdown(getattr(dag, 'doc_md', None), css_class='dag-doc') external_logs = conf.get('elasticsearch', 'frontend') return self.render_template( @@ -1751,8 +1747,8 @@ class Airflow(AirflowBaseView): demo_mode=conf.getboolean('webserver', 'demo_mode'), root=root, form=form, - chart=chart.htmlcontent, - cum_chart=cum_chart.htmlcontent + chart=Markup(chart.htmlcontent), + cum_chart=Markup(cum_chart.htmlcontent), ) @expose('/tries') @@ -1819,7 +1815,7 @@ class Airflow(AirflowBaseView): demo_mode=conf.getboolean('webserver', 'demo_mode'), root=root, form=form, - chart=chart.htmlcontent + chart=Markup(chart.htmlcontent), ) @expose('/landing_times')
