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

Check jinja version for consent resource #4327

Merged
merged 3 commits into from
Jan 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/4327.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Check jinja version for consent resource
9 changes: 1 addition & 8 deletions synapse/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,8 @@

sys.dont_write_bytecode = True


try:
python_dependencies.check_requirements()
except python_dependencies.DependencyException as e:
message = "\n".join([
"Missing Requirements: %s" % (", ".join(e.dependencies),),
"To install run:",
" pip install --upgrade --force %s" % (" ".join(e.dependencies),),
"",
])
sys.stderr.writelines(message)
sys.stderr.writelines(e.message)
sys.exit(1)
38 changes: 37 additions & 1 deletion synapse/config/server.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# 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");
# you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@
import os.path

from synapse.http.endpoint import parse_and_validate_server_name
from synapse.python_dependencies import DependencyException, check_requirements

from ._base import Config, ConfigError

Expand Down Expand Up @@ -204,6 +205,8 @@ def read_config(self, config):
]
})

_check_resource_config(self.listeners)

def default_config(self, server_name, data_dir_path, **kwargs):
_, bind_port = parse_and_validate_server_name(server_name)
if bind_port is not None:
Expand Down Expand Up @@ -465,3 +468,36 @@ def _warn_if_webclient_configured(listeners):
if name == 'webclient':
logger.warning(NO_MORE_WEB_CLIENT_WARNING)
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)
55 changes: 36 additions & 19 deletions synapse/python_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@
]

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"],
"postgres": ["psycopg2>=2.6"],

# ConsentResource uses select_autoescape, which arrived in jinja 2.9
"resources.consent": ["Jinja2>=2.9"],

"saml2": ["pysaml2>=4.5.0"],
"url_preview": ["lxml>=3.5.0"],
"test": ["mock>=2.0"],
Expand All @@ -83,19 +87,31 @@ def list_requirements():


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),),
"",
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to pull this up as a top level template string and then use the multiline quotes, but that's a matter of taste

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that would have been a good idea. I just c&ped it tbh.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair


@property
def dependencies(self):
for i in self.args[0]:
yield '"' + i + '"'


def check_requirements(_get_distribution=get_distribution):

def check_requirements(for_feature=None, _get_distribution=get_distribution):
deps_needed = []
errors = []

# Check the base dependencies exist -- they all must be installed.
for dependency in REQUIREMENTS:
if for_feature:
reqs = CONDITIONAL_REQUIREMENTS[for_feature]
else:
reqs = REQUIREMENTS

for dependency in reqs:
try:
_get_distribution(dependency)
except VersionConflict as e:
Expand All @@ -108,23 +124,24 @@ def check_requirements(_get_distribution=get_distribution):
deps_needed.append(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
# installed.
OPTS = sum(CONDITIONAL_REQUIREMENTS.values(), [])

for dependency in OPTS:
try:
_get_distribution(dependency)
except VersionConflict:
deps_needed.append(dependency)
errors.append("Needed %s but it was not installed" % (dependency,))
except DistributionNotFound:
# If it's not found, we don't care
pass
if not for_feature:
# Check the optional dependencies are up to date. We allow them to not be
# installed.
OPTS = sum(CONDITIONAL_REQUIREMENTS.values(), [])

for dependency in OPTS:
try:
_get_distribution(dependency)
except VersionConflict:
deps_needed.append(dependency)
errors.append("Needed %s but it was not installed" % (dependency,))
except DistributionNotFound:
# If it's not found, we don't care
pass

if deps_needed:
for e in errors:
logging.exception(e)
logging.error(e)

raise DependencyException(deps_needed)

Expand Down