Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Clean-up the template loading code. (#9200)
Browse files Browse the repository at this point in the history
* Enables autoescape by default for HTML files.
* Adds a new read_template method for reading a single template.
* Some logic clean-up.
  • Loading branch information
clokep authored Jan 27, 2021
1 parent 93b6158 commit e54746b
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 38 deletions.
37 changes: 37 additions & 0 deletions UPGRADE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,43 @@ for example:
wget https://packages.matrix.org/debian/pool/main/m/matrix-synapse-py3/matrix-synapse-py3_1.3.0+stretch1_amd64.deb
dpkg -i matrix-synapse-py3_1.3.0+stretch1_amd64.deb
Upgrading to v1.27.0
====================

Changes to HTML templates
-------------------------

The HTML templates for SSO and email notifications now have `Jinja2's autoescape <https://jinja.palletsprojects.com/en/2.11.x/api/#autoescaping>`_
enabled for files ending in ``.html``, ``.htm``, and ``.xml``. If you hae customised
these templates and see issues when viewing them you might need to update them.
It is expected that most configurations will need no changes.

If you have customised the templates *names* for these templates it is recommended
to verify they end in ``.html`` to ensure autoescape is enabled.

The above applies to the following templates:

* ``add_threepid.html``
* ``add_threepid_failure.html``
* ``add_threepid_success.html``
* ``notice_expiry.html``
* ``notice_expiry.html``
* ``notif_mail.html`` (which, by default, includes ``room.html`` and ``notif.html``)
* ``password_reset.html``
* ``password_reset_confirmation.html``
* ``password_reset_failure.html``
* ``password_reset_success.html``
* ``registration.html``
* ``registration_failure.html``
* ``registration_success.html``
* ``sso_account_deactivated.html``
* ``sso_auth_bad_user.html``
* ``sso_auth_confirm.html``
* ``sso_auth_success.html``
* ``sso_error.html``
* ``sso_login_idp_picker.html``
* ``sso_redirect_confirm.html``

Upgrading to v1.26.0
====================

Expand Down
1 change: 1 addition & 0 deletions changelog.d/9200.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Clean-up template loading code.
42 changes: 26 additions & 16 deletions synapse/config/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,36 +203,50 @@ def read_file(cls, file_path, config_name):
with open(file_path) as file_stream:
return file_stream.read()

def read_template(self, filename: str) -> jinja2.Template:
"""Load a template file from disk.
This function will attempt to load the given template from the default Synapse
template directory.
Files read are treated as Jinja templates. The templates is not rendered yet
and has autoescape enabled.
Args:
filename: A template filename to read.
Raises:
ConfigError: if the file's path is incorrect or otherwise cannot be read.
Returns:
A jinja2 template.
"""
return self.read_templates([filename])[0]

def read_templates(
self,
filenames: List[str],
custom_template_directory: Optional[str] = None,
autoescape: bool = False,
self, filenames: List[str], custom_template_directory: Optional[str] = None,
) -> List[jinja2.Template]:
"""Load a list of template files from disk using the given variables.
This function will attempt to load the given templates from the default Synapse
template directory. If `custom_template_directory` is supplied, that directory
is tried first.
Files read are treated as Jinja templates. These templates are not rendered yet.
Files read are treated as Jinja templates. The templates are not rendered yet
and have autoescape enabled.
Args:
filenames: A list of template filenames to read.
custom_template_directory: A directory to try to look for the templates
before using the default Synapse template directory instead.
autoescape: Whether to autoescape variables before inserting them into the
template.
Raises:
ConfigError: if the file's path is incorrect or otherwise cannot be read.
Returns:
A list of jinja2 templates.
"""
templates = []
search_directories = [self.default_template_dir]

# The loader will first look in the custom template directory (if specified) for the
Expand All @@ -249,7 +263,7 @@ def read_templates(
search_directories.insert(0, custom_template_directory)

loader = jinja2.FileSystemLoader(search_directories)
env = jinja2.Environment(loader=loader, autoescape=autoescape)
env = jinja2.Environment(loader=loader, autoescape=jinja2.select_autoescape(),)

# Update the environment with our custom filters
env.filters.update(
Expand All @@ -259,12 +273,8 @@ def read_templates(
}
)

for filename in filenames:
# Load the template
template = env.get_template(filename)
templates.append(template)

return templates
# Load the templates
return [env.get_template(filename) for filename in filenames]


def _format_ts_filter(value: int, format: str):
Expand Down
4 changes: 1 addition & 3 deletions synapse/config/captcha.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ def read_config(self, config, **kwargs):
"recaptcha_siteverify_api",
"https://www.recaptcha.net/recaptcha/api/siteverify",
)
self.recaptcha_template = self.read_templates(
["recaptcha.html"], autoescape=True
)[0]
self.recaptcha_template = self.read_template("recaptcha.html")

def generate_config_section(self, **kwargs):
return """\
Expand Down
2 changes: 1 addition & 1 deletion synapse/config/consent_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def __init__(self, *args):

def read_config(self, config, **kwargs):
consent_config = config.get("user_consent")
self.terms_template = self.read_templates(["terms.html"], autoescape=True)[0]
self.terms_template = self.read_template("terms.html")

if consent_config is None:
return
Expand Down
4 changes: 1 addition & 3 deletions synapse/config/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,7 @@ def read_config(self, config, **kwargs):
self.session_lifetime = session_lifetime

# The success template used during fallback auth.
self.fallback_success_template = self.read_templates(
["auth_success.html"], autoescape=True
)[0]
self.fallback_success_template = self.read_template("auth_success.html")

def generate_config_section(self, generate_secrets=False, **kwargs):
if generate_secrets:
Expand Down
18 changes: 16 additions & 2 deletions synapse/push/mailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,15 @@ def make_unsubscribe_link(


def safe_markup(raw_html: str) -> jinja2.Markup:
"""
Sanitise a raw HTML string to a set of allowed tags and attributes, and linkify any bare URLs.
Args
raw_html: Unsafe HTML.
Returns:
A Markup object ready to safely use in a Jinja template.
"""
return jinja2.Markup(
bleach.linkify(
bleach.clean(
Expand All @@ -684,8 +693,13 @@ def safe_markup(raw_html: str) -> jinja2.Markup:

def safe_text(raw_text: str) -> jinja2.Markup:
"""
Process text: treat it as HTML but escape any tags (ie. just escape the
HTML) then linkify it.
Sanitise text (escape any HTML tags), and then linkify any bare URLs.
Args
raw_text: Unsafe text which might include HTML markup.
Returns:
A Markup object ready to safely use in a Jinja template.
"""
return jinja2.Markup(
bleach.linkify(bleach.clean(raw_text, tags=[], attributes={}, strip=False))
Expand Down
2 changes: 1 addition & 1 deletion synapse/res/templates/sso_auth_bad_user.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<body>
<div>
<p>
We were unable to validate your <tt>{{server_name | e}}</tt> account via
We were unable to validate your <tt>{{ server_name }}</tt> account via
single-sign-on (SSO), because the SSO Identity Provider returned
different details than when you logged in.
</p>
Expand Down
4 changes: 2 additions & 2 deletions synapse/res/templates/sso_auth_confirm.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<body>
<div>
<p>
A client is trying to {{ description | e }}. To confirm this action,
<a href="{{ redirect_url | e }}">re-authenticate with single sign-on</a>.
A client is trying to {{ description }}. To confirm this action,
<a href="{{ redirect_url }}">re-authenticate with single sign-on</a>.
If you did not expect this, your account may be compromised!
</p>
</div>
Expand Down
2 changes: 1 addition & 1 deletion synapse/res/templates/sso_error.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<p>
There was an error during authentication:
</p>
<div id="errormsg" style="margin:20px 80px">{{ error_description | e }}</div>
<div id="errormsg" style="margin:20px 80px">{{ error_description }}</div>
<p>
If you are seeing this page after clicking a link sent to you via email, make
sure you only click the confirmation link once, and that you open the
Expand Down
12 changes: 6 additions & 6 deletions synapse/res/templates/sso_login_idp_picker.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/_matrix/static/client/login/style.css">
<title>{{server_name | e}} Login</title>
<title>{{ server_name }} Login</title>
</head>
<body>
<div id="container">
<h1 id="title">{{server_name | e}} Login</h1>
<h1 id="title">{{ server_name }} Login</h1>
<div class="login_flow">
<p>Choose one of the following identity providers:</p>
<form>
<input type="hidden" name="redirectUrl" value="{{redirect_url | e}}">
<input type="hidden" name="redirectUrl" value="{{ redirect_url }}">
<ul class="radiobuttons">
{% for p in providers %}
<li>
<input type="radio" name="idp" id="prov{{loop.index}}" value="{{p.idp_id}}">
<label for="prov{{loop.index}}">{{p.idp_name | e}}</label>
<input type="radio" name="idp" id="prov{{ loop.index }}" value="{{ p.idp_id }}">
<label for="prov{{ loop.index }}">{{ p.idp_name }}</label>
{% if p.idp_icon %}
<img src="{{p.idp_icon | mxc_to_http(32, 32)}}"/>
<img src="{{ p.idp_icon | mxc_to_http(32, 32) }}"/>
{% endif %}
</li>
{% endfor %}
Expand Down
6 changes: 3 additions & 3 deletions synapse/res/templates/sso_redirect_confirm.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
<title>SSO redirect confirmation</title>
</head>
<body>
<p>The application at <span style="font-weight:bold">{{ display_url | e }}</span> is requesting full access to your <span style="font-weight:bold">{{ server_name }}</span> Matrix account.</p>
<p>The application at <span style="font-weight:bold">{{ display_url }}</span> is requesting full access to your <span style="font-weight:bold">{{ server_name }}</span> Matrix account.</p>
<p>If you don't recognise this address, you should ignore this and close this tab.</p>
<p>
<a href="{{ redirect_url | e }}">I trust this address</a>
<a href="{{ redirect_url }}">I trust this address</a>
</p>
</body>
</html>
</html>

0 comments on commit e54746b

Please sign in to comment.