Browse Source

Clean-up the template loading code. (#9200)

* Enables autoescape by default for HTML files.
* Adds a new read_template method for reading a single template.
* Some logic clean-up.
tags/v1.27.0rc1
Patrick Cloke 3 years ago
committed by GitHub
parent
commit
e54746bdf7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 96 additions and 38 deletions
  1. +37
    -0
      UPGRADE.rst
  2. +1
    -0
      changelog.d/9200.misc
  3. +26
    -16
      synapse/config/_base.py
  4. +1
    -3
      synapse/config/captcha.py
  5. +1
    -1
      synapse/config/consent_config.py
  6. +1
    -3
      synapse/config/registration.py
  7. +16
    -2
      synapse/push/mailer.py
  8. +1
    -1
      synapse/res/templates/sso_auth_bad_user.html
  9. +2
    -2
      synapse/res/templates/sso_auth_confirm.html
  10. +1
    -1
      synapse/res/templates/sso_error.html
  11. +6
    -6
      synapse/res/templates/sso_login_idp_picker.html
  12. +3
    -3
      synapse/res/templates/sso_redirect_confirm.html

+ 37
- 0
UPGRADE.rst View File

@@ -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
====================



+ 1
- 0
changelog.d/9200.misc View File

@@ -0,0 +1 @@
Clean-up template loading code.

+ 26
- 16
synapse/config/_base.py View File

@@ -203,11 +203,28 @@ class Config:
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.

@@ -215,7 +232,8 @@ class Config:
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.
@@ -223,16 +241,12 @@ class Config:
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
@@ -249,7 +263,7 @@ class Config:
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(
@@ -259,12 +273,8 @@ class Config:
}
)

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):


+ 1
- 3
synapse/config/captcha.py View File

@@ -28,9 +28,7 @@ class CaptchaConfig(Config):
"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 """\


+ 1
- 1
synapse/config/consent_config.py View File

@@ -89,7 +89,7 @@ class ConsentConfig(Config):

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


+ 1
- 3
synapse/config/registration.py View File

@@ -176,9 +176,7 @@ class RegistrationConfig(Config):
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:


+ 16
- 2
synapse/push/mailer.py View File

@@ -668,6 +668,15 @@ class Mailer:


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(
@@ -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))


+ 1
- 1
synapse/res/templates/sso_auth_bad_user.html View File

@@ -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>


+ 2
- 2
synapse/res/templates/sso_auth_confirm.html View File

@@ -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>


+ 1
- 1
synapse/res/templates/sso_error.html View File

@@ -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


+ 6
- 6
synapse/res/templates/sso_login_idp_picker.html View File

@@ -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 %}


+ 3
- 3
synapse/res/templates/sso_redirect_confirm.html View File

@@ -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>

Loading…
Cancel
Save