1
0

Merge branch 'develop' into shay/more_batching

This commit is contained in:
Shay
2022-10-06 11:33:43 -07:00
committed by GitHub
15 changed files with 281 additions and 11 deletions

View File

@@ -1,12 +1,28 @@
Synapse 1.69.0rc1 (2022-10-04)
Synapse 1.69.0rc2 (2022-10-06)
==============================
Please note that legacy Prometheus metric names are now deprecated and will be removed in Synapse 1.73.0.
Server administrators should update their dashboards and alerting rules to avoid using the deprecated metric names.
See the [upgrade notes](https://matrix-org.github.io/synapse/v1.69/upgrade.html#upgrading-to-v1690) for more details.
Deprecations and Removals
-------------------------
- Deprecate the `generate_short_term_login_token` method in favor of an async `create_login_token` method in the Module API. ([\#13842](https://github.com/matrix-org/synapse/issues/13842))
Internal Changes
----------------
- Ensure Synapse v1.69 works with upcoming database changes in v1.70. ([\#14045](https://github.com/matrix-org/synapse/issues/14045))
- Fix a bug introduced in Synapse v1.68.0 where messages could not be sent in rooms with non-integer `notifications` power level. ([\#14073](https://github.com/matrix-org/synapse/issues/14073))
- Temporarily pin build-system requirements to workaround an incompatibility with poetry-core 1.3.0. This will be reverted before the v1.69.0 release proper, see [\#14079](https://github.com/matrix-org/synapse/issues/14079). ([\#14080](https://github.com/matrix-org/synapse/issues/14080))
Synapse 1.69.0rc1 (2022-10-04)
==============================
Features
--------

1
changelog.d/14065.misc Normal file
View File

@@ -0,0 +1 @@
Fix a bug introduced in Synapse 1.35.0 where errors parsing a `/send_join` or `/state` response would produce excessive, low-quality Sentry events.

1
changelog.d/14087.doc Normal file
View File

@@ -0,0 +1 @@
The changelog entry ending in a full stop or exclamation mark is not optional.

6
debian/changelog vendored
View File

@@ -1,3 +1,9 @@
matrix-synapse-py3 (1.69.0~rc2) stable; urgency=medium
* New Synapse release 1.69.0rc2.
-- Synapse Packaging team <packages@matrix.org> Thu, 06 Oct 2022 14:45:00 +0100
matrix-synapse-py3 (1.69.0~rc1) stable; urgency=medium
* The man page for the hash_password script has been updated to reflect

View File

@@ -390,7 +390,7 @@ This file will become part of our [changelog](
https://github.com/matrix-org/synapse/blob/master/CHANGES.md) at the next
release, so the content of the file should be a short description of your
change in the same style as the rest of the changelog. The file can contain Markdown
formatting, and should end with a full stop (.) or an exclamation mark (!) for
formatting, and must end with a full stop (.) or an exclamation mark (!) for
consistency.
Adding credits to the changelog is encouraged, we value your

View File

@@ -423,7 +423,7 @@ Synapse config:
user_mapping_provider:
config:
display_name_template: "{{ user.name }}"
email_template: "{{ '{{ user.email }}' }}"
email_template: "{{ user.email }}"
```
Relevant documents:

View File

@@ -128,6 +128,39 @@ you may specify `enable_legacy_metrics: false` in your homeserver configuration.
A list of affected metrics is available on the [Metrics How-to page](https://matrix-org.github.io/synapse/v1.69/metrics-howto.html?highlight=metrics%20deprecated#renaming-of-metrics--deprecation-of-old-names-in-12).
## Deprecation of the `generate_short_term_login_token` module API method
The following method of the module API has been deprecated, and is scheduled to
be remove in v1.71.0:
```python
def generate_short_term_login_token(
self,
user_id: str,
duration_in_ms: int = (2 * 60 * 1000),
auth_provider_id: str = "",
auth_provider_session_id: Optional[str] = None,
) -> str:
...
```
It has been replaced by an asynchronous equivalent:
```python
async def create_login_token(
self,
user_id: str,
duration_in_ms: int = (2 * 60 * 1000),
auth_provider_id: Optional[str] = None,
auth_provider_session_id: Optional[str] = None,
) -> str:
...
```
Synapse will log a warning when a module uses the deprecated method, to help
administrators find modules using it.
# Upgrading to v1.68.0
Two changes announced in the upgrade notes for v1.67.0 have now landed in v1.68.0.

View File

@@ -106,6 +106,9 @@ disallow_untyped_defs = False
[mypy-tests.handlers.test_user_directory]
disallow_untyped_defs = True
[mypy-tests.push.test_bulk_push_rule_evaluator]
disallow_untyped_defs = True
[mypy-tests.test_server]
disallow_untyped_defs = True

View File

@@ -57,7 +57,7 @@ manifest-path = "rust/Cargo.toml"
[tool.poetry]
name = "matrix-synapse"
version = "1.69.0rc1"
version = "1.69.0rc2"
description = "Homeserver for the Matrix decentralised comms protocol"
authors = ["Matrix.org Team and Contributors <packages@matrix.org>"]
license = "Apache-2.0"
@@ -307,7 +307,7 @@ twine = "*"
towncrier = ">=18.6.0rc1"
[build-system]
requires = ["poetry-core>=1.0.0", "setuptools_rust>=1.3"]
requires = ["poetry-core==1.2.0", "setuptools_rust==1.5.2"]
build-backend = "poetry.core.masonry.api"

View File

@@ -45,6 +45,7 @@ from synapse.federation.units import Transaction
from synapse.http.matrixfederationclient import ByteParser
from synapse.http.types import QueryParams
from synapse.types import JsonDict
from synapse.util import ExceptionBundle
logger = logging.getLogger(__name__)
@@ -926,8 +927,7 @@ class SendJoinParser(ByteParser[SendJoinResponse]):
return len(data)
def finish(self) -> SendJoinResponse:
for c in self._coros:
c.close()
_close_coros(self._coros)
if self._response.event_dict:
self._response.event = make_event_from_dict(
@@ -970,6 +970,27 @@ class _StateParser(ByteParser[StateRequestResponse]):
return len(data)
def finish(self) -> StateRequestResponse:
for c in self._coros:
c.close()
_close_coros(self._coros)
return self._response
def _close_coros(coros: Iterable[Generator[None, bytes, None]]) -> None:
"""Close each of the given coroutines.
Always calls .close() on each coroutine, even if doing so raises an exception.
Any exceptions raised are aggregated into an ExceptionBundle.
:raises ExceptionBundle: if at least one coroutine fails to close.
"""
exceptions = []
for c in coros:
try:
c.close()
except Exception as e:
exceptions.append(e)
if exceptions:
# raise from the first exception so that the traceback has slightly more context
raise ExceptionBundle(
f"There were {len(exceptions)} errors closing coroutines", exceptions
) from exceptions[0]

View File

@@ -748,6 +748,40 @@ class ModuleApi:
)
)
async def create_login_token(
self,
user_id: str,
duration_in_ms: int = (2 * 60 * 1000),
auth_provider_id: Optional[str] = None,
auth_provider_session_id: Optional[str] = None,
) -> str:
"""Create a login token suitable for m.login.token authentication
Added in Synapse v1.69.0.
Args:
user_id: gives the ID of the user that the token is for
duration_in_ms: the time that the token will be valid for
auth_provider_id: the ID of the SSO IdP that the user used to authenticate
to get this token, if any. This is encoded in the token so that
/login can report stats on number of successful logins by IdP.
auth_provider_session_id: The session ID got during login from the SSO IdP,
if any.
"""
# The deprecated `generate_short_term_login_token` method defaulted to an empty
# string for the `auth_provider_id` because of how the underlying macaroon was
# generated. This will change to a proper NULL-able field when the tokens get
# moved to the database.
return self._hs.get_macaroon_generator().generate_short_term_login_token(
user_id,
auth_provider_id or "",
auth_provider_session_id,
duration_in_ms,
)
def generate_short_term_login_token(
self,
user_id: str,
@@ -759,6 +793,9 @@ class ModuleApi:
Added in Synapse v1.9.0.
This was deprecated in Synapse v1.69.0 in favor of create_login_token, and will
be removed in Synapse 1.71.0.
Args:
user_id: gives the ID of the user that the token is for
@@ -768,6 +805,11 @@ class ModuleApi:
to get this token, if any. This is encoded in the token so that
/login can report stats on number of successful logins by IdP.
"""
logger.warn(
"A module configured on this server uses ModuleApi.generate_short_term_login_token(), "
"which is deprecated in favor of ModuleApi.create_login_token(), and will be removed in "
"Synapse 1.71.0",
)
return self._hs.get_macaroon_generator().generate_short_term_login_token(
user_id,
auth_provider_id,

View File

@@ -304,6 +304,30 @@ class BulkPushRuleEvaluator:
event, context, event_id_to_event
)
# Recursively attempt to find the thread this event relates to.
if relation.rel_type == RelationTypes.THREAD:
thread_id = relation.parent_id
else:
# Since the event has not yet been persisted we check whether
# the parent is part of a thread.
thread_id = await self.store.get_thread_id(relation.parent_id) or "main"
# It's possible that old room versions have non-integer power levels (floats or
# strings). Workaround this by explicitly converting to int.
notification_levels = power_levels.get("notifications", {})
if not event.room_version.msc3667_int_only_power_levels:
for user_id, level in notification_levels.items():
notification_levels[user_id] = int(level)
evaluator = PushRuleEvaluator(
_flatten_dict(event),
room_member_count,
sender_power_level,
notification_levels,
relations,
self._relations_match_enabled,
)
relation = relation_from_event(event)
# If the event does not have a relation, then cannot have any mutual
# relations or thread ID.

View File

@@ -15,7 +15,7 @@
import json
import logging
import typing
from typing import Any, Callable, Dict, Generator, Optional
from typing import Any, Callable, Dict, Generator, Optional, Sequence
import attr
from frozendict import frozendict
@@ -193,3 +193,15 @@ def log_failure(
# Version string with git info. Computed here once so that we don't invoke git multiple
# times.
SYNAPSE_VERSION = get_distribution_version_string("matrix-synapse", __file__)
class ExceptionBundle(Exception):
# A poor stand-in for something like Python 3.11's ExceptionGroup.
# (A backport called `exceptiongroup` exists but seems overkill: we just want a
# container type here.)
def __init__(self, message: str, exceptions: Sequence[Exception]):
parts = [message]
for e in exceptions:
parts.append(str(e))
super().__init__("\n - ".join(parts))
self.exceptions = exceptions

View File

@@ -13,6 +13,7 @@
# limitations under the License.
import json
from unittest.mock import Mock
from synapse.api.room_versions import RoomVersions
from synapse.federation.transport.client import SendJoinParser
@@ -94,3 +95,39 @@ class SendJoinParserTestCase(TestCase):
# Retrieve and check the parsed SendJoinResponse
parsed_response = parser.finish()
self.assertEqual(parsed_response.servers_in_room, ["hs1", "hs2"])
def test_errors_closing_coroutines(self) -> None:
"""Check we close all coroutines, even if closing the first raises an Exception.
We also check that an Exception of some kind is raised, but we don't make any
assertions about its attributes or type.
"""
parser = SendJoinParser(RoomVersions.V1, False)
response = {"org.matrix.msc3706.servers_in_room": ["hs1", "hs2"]}
serialisation = json.dumps(response).encode()
# Mock the coroutines managed by this parser.
# The first one will error when we try to close it.
coro_1 = Mock()
coro_1.close = Mock(side_effect=RuntimeError("Couldn't close coro 1"))
coro_2 = Mock()
coro_3 = Mock()
coro_3.close = Mock(side_effect=RuntimeError("Couldn't close coro 3"))
parser._coros = [coro_1, coro_2, coro_3]
# Send half of the data to the parser
parser.write(serialisation[: len(serialisation) // 2])
# Close the parser. There should be _some_ kind of exception, but it need not
# be that RuntimeError directly. E.g. we might want to raise a wrapper
# encompassing multiple errors from multiple coroutines.
with self.assertRaises(Exception):
parser.finish()
# In any case, we should have tried to close both coros.
coro_1.close.assert_called()
coro_2.close.assert_called()
coro_3.close.assert_called()

View File

@@ -0,0 +1,74 @@
from unittest.mock import patch
from synapse.api.room_versions import RoomVersions
from synapse.push.bulk_push_rule_evaluator import BulkPushRuleEvaluator
from synapse.rest import admin
from synapse.rest.client import login, register, room
from synapse.types import create_requester
from tests import unittest
class TestBulkPushRuleEvaluator(unittest.HomeserverTestCase):
servlets = [
admin.register_servlets_for_client_rest_resource,
room.register_servlets,
login.register_servlets,
register.register_servlets,
]
def test_action_for_event_by_user_handles_noninteger_power_levels(self) -> None:
"""We should convert floats and strings to integers before passing to Rust.
Reproduces #14060.
A lack of validation: the gift that keeps on giving.
"""
# Create a new user and room.
alice = self.register_user("alice", "pass")
token = self.login(alice, "pass")
room_id = self.helper.create_room_as(
alice, room_version=RoomVersions.V9.identifier, tok=token
)
# Alter the power levels in that room to include stringy and floaty levels.
# We need to suppress the validation logic or else it will reject these dodgy
# values. (Presumably this validation was not always present.)
event_creation_handler = self.hs.get_event_creation_handler()
requester = create_requester(alice)
with patch("synapse.events.validator.validate_canonicaljson"), patch(
"synapse.events.validator.jsonschema.validate"
):
self.helper.send_state(
room_id,
"m.room.power_levels",
{
"users": {alice: "100"}, # stringy
"notifications": {"room": 100.0}, # float
},
token,
state_key="",
)
# Create a new message event, and try to evaluate it under the dodgy
# power level event.
event, context = self.get_success(
event_creation_handler.create_event(
requester,
{
"type": "m.room.message",
"room_id": room_id,
"content": {
"msgtype": "m.text",
"body": "helo",
},
"sender": alice,
},
)
)
bulk_evaluator = BulkPushRuleEvaluator(self.hs)
# should not raise
self.get_success(bulk_evaluator.action_for_event_by_user(event, context))