Check jinja version for consent resource (#4327)

* Raise a ConfigError if an invalid resource is specified

* Require Jinja 2.9 for the consent resource

* changelog
This commit is contained in:
Richard van der Hoff 2019-01-07 10:14:31 +00:00 committed by GitHub
parent a27e501b09
commit b7c0218812
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 27 deletions

1
changelog.d/4327.bugfix Normal file
View file

@ -0,0 +1 @@
Check jinja version for consent resource

View file

@ -19,15 +19,8 @@ from synapse import python_dependencies # noqa: E402
sys.dont_write_bytecode = True sys.dont_write_bytecode = True
try: try:
python_dependencies.check_requirements() python_dependencies.check_requirements()
except python_dependencies.DependencyException as e: except python_dependencies.DependencyException as e:
message = "\n".join([ sys.stderr.writelines(e.message)
"Missing Requirements: %s" % (", ".join(e.dependencies),),
"To install run:",
" pip install --upgrade --force %s" % (" ".join(e.dependencies),),
"",
])
sys.stderr.writelines(message)
sys.exit(1) sys.exit(1)

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2014-2016 OpenMarket Ltd # Copyright 2014-2016 OpenMarket Ltd
# Copyright 2017 New Vector Ltd # Copyright 2017-2018 New Vector Ltd
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ import logging
import os.path import os.path
from synapse.http.endpoint import parse_and_validate_server_name from synapse.http.endpoint import parse_and_validate_server_name
from synapse.python_dependencies import DependencyException, check_requirements
from ._base import Config, ConfigError from ._base import Config, ConfigError
@ -204,6 +205,8 @@ class ServerConfig(Config):
] ]
}) })
_check_resource_config(self.listeners)
def default_config(self, server_name, data_dir_path, **kwargs): def default_config(self, server_name, data_dir_path, **kwargs):
_, bind_port = parse_and_validate_server_name(server_name) _, bind_port = parse_and_validate_server_name(server_name)
if bind_port is not None: if bind_port is not None:
@ -465,3 +468,36 @@ def _warn_if_webclient_configured(listeners):
if name == 'webclient': if name == 'webclient':
logger.warning(NO_MORE_WEB_CLIENT_WARNING) logger.warning(NO_MORE_WEB_CLIENT_WARNING)
return return
KNOWN_RESOURCES = (
'client',
'consent',
'federation',
'keys',
'media',
'metrics',
'replication',
'static',
'webclient',
)
def _check_resource_config(listeners):
resource_names = set(
res_name
for listener in listeners
for res in listener.get("resources", [])
for res_name in res.get("names", [])
)
for resource in resource_names:
if resource not in KNOWN_RESOURCES:
raise ConfigError(
"Unknown listener resource '%s'" % (resource, )
)
if resource == "consent":
try:
check_requirements('resources.consent')
except DependencyException as e:
raise ConfigError(e.message)

View file

@ -65,9 +65,13 @@ REQUIREMENTS = [
] ]
CONDITIONAL_REQUIREMENTS = { CONDITIONAL_REQUIREMENTS = {
"email.enable_notifs": ["Jinja2>=2.8", "bleach>=1.4.2"], "email.enable_notifs": ["Jinja2>=2.9", "bleach>=1.4.2"],
"matrix-synapse-ldap3": ["matrix-synapse-ldap3>=0.1"], "matrix-synapse-ldap3": ["matrix-synapse-ldap3>=0.1"],
"postgres": ["psycopg2>=2.6"], "postgres": ["psycopg2>=2.6"],
# ConsentResource uses select_autoescape, which arrived in jinja 2.9
"resources.consent": ["Jinja2>=2.9"],
"saml2": ["pysaml2>=4.5.0"], "saml2": ["pysaml2>=4.5.0"],
"url_preview": ["lxml>=3.5.0"], "url_preview": ["lxml>=3.5.0"],
"test": ["mock>=2.0"], "test": ["mock>=2.0"],
@ -83,19 +87,31 @@ def list_requirements():
class DependencyException(Exception): class DependencyException(Exception):
@property
def message(self):
return "\n".join([
"Missing Requirements: %s" % (", ".join(self.dependencies),),
"To install run:",
" pip install --upgrade --force %s" % (" ".join(self.dependencies),),
"",
])
@property @property
def dependencies(self): def dependencies(self):
for i in self.args[0]: for i in self.args[0]:
yield '"' + i + '"' yield '"' + i + '"'
def check_requirements(_get_distribution=get_distribution): def check_requirements(for_feature=None, _get_distribution=get_distribution):
deps_needed = [] deps_needed = []
errors = [] errors = []
# Check the base dependencies exist -- they all must be installed. if for_feature:
for dependency in REQUIREMENTS: reqs = CONDITIONAL_REQUIREMENTS[for_feature]
else:
reqs = REQUIREMENTS
for dependency in reqs:
try: try:
_get_distribution(dependency) _get_distribution(dependency)
except VersionConflict as e: except VersionConflict as e:
@ -108,23 +124,24 @@ def check_requirements(_get_distribution=get_distribution):
deps_needed.append(dependency) deps_needed.append(dependency)
errors.append("Needed %s but it was not installed" % (dependency,)) errors.append("Needed %s but it was not installed" % (dependency,))
# Check the optional dependencies are up to date. We allow them to not be if not for_feature:
# installed. # Check the optional dependencies are up to date. We allow them to not be
OPTS = sum(CONDITIONAL_REQUIREMENTS.values(), []) # installed.
OPTS = sum(CONDITIONAL_REQUIREMENTS.values(), [])
for dependency in OPTS: for dependency in OPTS:
try: try:
_get_distribution(dependency) _get_distribution(dependency)
except VersionConflict: except VersionConflict:
deps_needed.append(dependency) deps_needed.append(dependency)
errors.append("Needed %s but it was not installed" % (dependency,)) errors.append("Needed %s but it was not installed" % (dependency,))
except DistributionNotFound: except DistributionNotFound:
# If it's not found, we don't care # If it's not found, we don't care
pass pass
if deps_needed: if deps_needed:
for e in errors: for e in errors:
logging.exception(e) logging.error(e)
raise DependencyException(deps_needed) raise DependencyException(deps_needed)