mirror of
https://github.com/element-hq/synapse.git
synced 2024-12-14 11:57:44 +00:00
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.
This commit is contained in:
parent
93b61589b0
commit
e54746bdf7
12 changed files with 96 additions and 38 deletions
37
UPGRADE.rst
37
UPGRADE.rst
|
@ -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
changelog.d/9200.misc
Normal file
1
changelog.d/9200.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Clean-up template loading code.
|
|
@ -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):
|
||||
|
|
|
@ -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 """\
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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…
Reference in a new issue