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

Commit 91018d7

Browse files
committed
Merge remote-tracking branch 'origin/develop' into rav/cachedlist_error_handling
2 parents 82b4ea6 + 6c0b44a commit 91018d7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+959
-906
lines changed

changelog.d/11865.removal

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Deprecate using `synctl` with the config option `synctl_cache_factor` and print a warning if a user still uses this option.

changelog.d/12077.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a long-standing bug where Synapse would make additional failing requests over federation for missing data.

changelog.d/12092.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
User `assertEqual` instead of the deprecated `assertEquals` in test code.

changelog.d/12098.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug introduced in Synapse 1.51.0rc1 where incoming federation transactions containing at least one EDU would be dropped if debug logging was enabled for `synapse.8631_debug`.

changelog.d/12100.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a long-standing bug which could cause push notifications to malfunction if `use_frozen_dicts` was set in the configuration.

synapse/api/filtering.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
Dict,
2323
Iterable,
2424
List,
25+
Mapping,
2526
Optional,
2627
Set,
2728
TypeVar,
@@ -361,10 +362,10 @@ def _check(self, event: FilterEvent) -> bool:
361362
return self._check_fields(field_matchers)
362363
else:
363364
content = event.get("content")
364-
# Content is assumed to be a dict below, so ensure it is. This should
365+
# Content is assumed to be a mapping below, so ensure it is. This should
365366
# always be true for events, but account_data has been allowed to
366367
# have non-dict content.
367-
if not isinstance(content, dict):
368+
if not isinstance(content, Mapping):
368369
content = {}
369370

370371
sender = event.get("sender", None)

synapse/federation/federation_client.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -615,11 +615,15 @@ def _is_unknown_endpoint(
615615
synapse_error = e.to_synapse_error()
616616
# There is no good way to detect an "unknown" endpoint.
617617
#
618-
# Dendrite returns a 404 (with no body); synapse returns a 400
618+
# Dendrite returns a 404 (with a body of "404 page not found");
619+
# Conduit returns a 404 (with no body); and Synapse returns a 400
619620
# with M_UNRECOGNISED.
620-
return e.code == 404 or (
621-
e.code == 400 and synapse_error.errcode == Codes.UNRECOGNIZED
622-
)
621+
#
622+
# This needs to be rather specific as some endpoints truly do return 404
623+
# errors.
624+
return (
625+
e.code == 404 and (not e.response or e.response == b"404 page not found")
626+
) or (e.code == 400 and synapse_error.errcode == Codes.UNRECOGNIZED)
623627

624628
async def _try_destination_list(
625629
self,
@@ -1002,7 +1006,7 @@ async def _do_send_join(
10021006
)
10031007
except HttpResponseException as e:
10041008
# If an error is received that is due to an unrecognised endpoint,
1005-
# fallback to the v1 endpoint. Otherwise consider it a legitmate error
1009+
# fallback to the v1 endpoint. Otherwise, consider it a legitimate error
10061010
# and raise.
10071011
if not self._is_unknown_endpoint(e):
10081012
raise
@@ -1071,7 +1075,7 @@ async def _do_send_invite(
10711075
except HttpResponseException as e:
10721076
# If an error is received that is due to an unrecognised endpoint,
10731077
# fallback to the v1 endpoint if the room uses old-style event IDs.
1074-
# Otherwise consider it a legitmate error and raise.
1078+
# Otherwise, consider it a legitimate error and raise.
10751079
err = e.to_synapse_error()
10761080
if self._is_unknown_endpoint(e, err):
10771081
if room_version.event_format != EventFormatVersions.V1:
@@ -1132,7 +1136,7 @@ async def _do_send_leave(self, destination: str, pdu: EventBase) -> JsonDict:
11321136
)
11331137
except HttpResponseException as e:
11341138
# If an error is received that is due to an unrecognised endpoint,
1135-
# fallback to the v1 endpoint. Otherwise consider it a legitmate error
1139+
# fallback to the v1 endpoint. Otherwise, consider it a legitimate error
11361140
# and raise.
11371141
if not self._is_unknown_endpoint(e):
11381142
raise
@@ -1458,8 +1462,8 @@ async def send_request(
14581462
)
14591463
except HttpResponseException as e:
14601464
# If an error is received that is due to an unrecognised endpoint,
1461-
# fallback to the unstable endpoint. Otherwise consider it a
1462-
# legitmate error and raise.
1465+
# fallback to the unstable endpoint. Otherwise, consider it a
1466+
# legitimate error and raise.
14631467
if not self._is_unknown_endpoint(e):
14641468
raise
14651469

synapse/federation/transport/server/federation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async def on_PUT(
110110
if issue_8631_logger.isEnabledFor(logging.DEBUG):
111111
DEVICE_UPDATE_EDUS = ["m.device_list_update", "m.signing_key_update"]
112112
device_list_updates = [
113-
edu.content
113+
edu.get("content", {})
114114
for edu in transaction_data.get("edus", [])
115115
if edu.get("edu_type") in DEVICE_UPDATE_EDUS
116116
]

synapse/push/push_rule_evaluator.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515

1616
import logging
1717
import re
18-
from typing import Any, Dict, List, Optional, Pattern, Tuple, Union
18+
from typing import Any, Dict, List, Mapping, Optional, Pattern, Tuple, Union
1919

2020
from matrix_common.regex import glob_to_regex, to_word_pattern
2121

2222
from synapse.events import EventBase
23-
from synapse.types import JsonDict, UserID
23+
from synapse.types import UserID
2424
from synapse.util.caches.lrucache import LruCache
2525

2626
logger = logging.getLogger(__name__)
@@ -223,7 +223,7 @@ def _glob_matches(glob: str, value: str, word_boundary: bool = False) -> bool:
223223

224224

225225
def _flatten_dict(
226-
d: Union[EventBase, JsonDict],
226+
d: Union[EventBase, Mapping[str, Any]],
227227
prefix: Optional[List[str]] = None,
228228
result: Optional[Dict[str, str]] = None,
229229
) -> Dict[str, str]:
@@ -234,7 +234,7 @@ def _flatten_dict(
234234
for key, value in d.items():
235235
if isinstance(value, str):
236236
result[".".join(prefix + [key])] = value.lower()
237-
elif isinstance(value, dict):
237+
elif isinstance(value, Mapping):
238238
_flatten_dict(value, prefix=(prefix + [key]), result=result)
239239

240240
return result

synctl

+8
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ YELLOW = "\x1b[1;33m"
3737
RED = "\x1b[1;31m"
3838
NORMAL = "\x1b[m"
3939

40+
SYNCTL_CACHE_FACTOR_WARNING = """\
41+
Setting 'synctl_cache_factor' in the config is deprecated. Instead, please do
42+
one of the following:
43+
- Either set the environment variable 'SYNAPSE_CACHE_FACTOR'
44+
- or set 'caches.global_factor' in the homeserver config.
45+
--------------------------------------------------------------------------------"""
46+
4047

4148
def pid_running(pid):
4249
try:
@@ -228,6 +235,7 @@ def main():
228235
start_stop_synapse = True
229236

230237
if cache_factor:
238+
write(SYNCTL_CACHE_FACTOR_WARNING)
231239
os.environ["SYNAPSE_CACHE_FACTOR"] = str(cache_factor)
232240

233241
cache_factors = config.get("synctl_cache_factors", {})

tests/api/test_auth.py

+18-18
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def test_get_user_by_req_user_valid_token(self):
7171
request.args[b"access_token"] = [self.test_token]
7272
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
7373
requester = self.get_success(self.auth.get_user_by_req(request))
74-
self.assertEquals(requester.user.to_string(), self.test_user)
74+
self.assertEqual(requester.user.to_string(), self.test_user)
7575

7676
def test_get_user_by_req_user_bad_token(self):
7777
self.store.get_user_by_access_token = simple_async_mock(None)
@@ -109,7 +109,7 @@ def test_get_user_by_req_appservice_valid_token(self):
109109
request.args[b"access_token"] = [self.test_token]
110110
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
111111
requester = self.get_success(self.auth.get_user_by_req(request))
112-
self.assertEquals(requester.user.to_string(), self.test_user)
112+
self.assertEqual(requester.user.to_string(), self.test_user)
113113

114114
def test_get_user_by_req_appservice_valid_token_good_ip(self):
115115
from netaddr import IPSet
@@ -128,7 +128,7 @@ def test_get_user_by_req_appservice_valid_token_good_ip(self):
128128
request.args[b"access_token"] = [self.test_token]
129129
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
130130
requester = self.get_success(self.auth.get_user_by_req(request))
131-
self.assertEquals(requester.user.to_string(), self.test_user)
131+
self.assertEqual(requester.user.to_string(), self.test_user)
132132

133133
def test_get_user_by_req_appservice_valid_token_bad_ip(self):
134134
from netaddr import IPSet
@@ -195,7 +195,7 @@ def test_get_user_by_req_appservice_valid_token_valid_user_id(self):
195195
request.args[b"user_id"] = [masquerading_user_id]
196196
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
197197
requester = self.get_success(self.auth.get_user_by_req(request))
198-
self.assertEquals(
198+
self.assertEqual(
199199
requester.user.to_string(), masquerading_user_id.decode("utf8")
200200
)
201201

@@ -242,10 +242,10 @@ def test_get_user_by_req_appservice_valid_token_valid_device_id(self):
242242
request.args[b"org.matrix.msc3202.device_id"] = [masquerading_device_id]
243243
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
244244
requester = self.get_success(self.auth.get_user_by_req(request))
245-
self.assertEquals(
245+
self.assertEqual(
246246
requester.user.to_string(), masquerading_user_id.decode("utf8")
247247
)
248-
self.assertEquals(requester.device_id, masquerading_device_id.decode("utf8"))
248+
self.assertEqual(requester.device_id, masquerading_device_id.decode("utf8"))
249249

250250
@override_config({"experimental_features": {"msc3202_device_masquerading": True}})
251251
def test_get_user_by_req_appservice_valid_token_invalid_device_id(self):
@@ -275,8 +275,8 @@ def test_get_user_by_req_appservice_valid_token_invalid_device_id(self):
275275
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
276276

277277
failure = self.get_failure(self.auth.get_user_by_req(request), AuthError)
278-
self.assertEquals(failure.value.code, 400)
279-
self.assertEquals(failure.value.errcode, Codes.EXCLUSIVE)
278+
self.assertEqual(failure.value.code, 400)
279+
self.assertEqual(failure.value.errcode, Codes.EXCLUSIVE)
280280

281281
def test_get_user_by_req__puppeted_token__not_tracking_puppeted_mau(self):
282282
self.store.get_user_by_access_token = simple_async_mock(
@@ -309,7 +309,7 @@ def test_get_user_by_req__puppeted_token__tracking_puppeted_mau(self):
309309
request.args[b"access_token"] = [self.test_token]
310310
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
311311
self.get_success(self.auth.get_user_by_req(request))
312-
self.assertEquals(self.store.insert_client_ip.call_count, 2)
312+
self.assertEqual(self.store.insert_client_ip.call_count, 2)
313313

314314
def test_get_user_from_macaroon(self):
315315
self.store.get_user_by_access_token = simple_async_mock(
@@ -369,9 +369,9 @@ def test_blocking_mau(self):
369369
self.store.get_monthly_active_count = simple_async_mock(lots_of_users)
370370

371371
e = self.get_failure(self.auth.check_auth_blocking(), ResourceLimitError)
372-
self.assertEquals(e.value.admin_contact, self.hs.config.server.admin_contact)
373-
self.assertEquals(e.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
374-
self.assertEquals(e.value.code, 403)
372+
self.assertEqual(e.value.admin_contact, self.hs.config.server.admin_contact)
373+
self.assertEqual(e.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
374+
self.assertEqual(e.value.code, 403)
375375

376376
# Ensure does not throw an error
377377
self.store.get_monthly_active_count = simple_async_mock(small_number_of_users)
@@ -473,9 +473,9 @@ def test_hs_disabled(self):
473473
self.auth_blocking._hs_disabled = True
474474
self.auth_blocking._hs_disabled_message = "Reason for being disabled"
475475
e = self.get_failure(self.auth.check_auth_blocking(), ResourceLimitError)
476-
self.assertEquals(e.value.admin_contact, self.hs.config.server.admin_contact)
477-
self.assertEquals(e.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
478-
self.assertEquals(e.value.code, 403)
476+
self.assertEqual(e.value.admin_contact, self.hs.config.server.admin_contact)
477+
self.assertEqual(e.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
478+
self.assertEqual(e.value.code, 403)
479479

480480
def test_hs_disabled_no_server_notices_user(self):
481481
"""Check that 'hs_disabled_message' works correctly when there is no
@@ -488,9 +488,9 @@ def test_hs_disabled_no_server_notices_user(self):
488488
self.auth_blocking._hs_disabled = True
489489
self.auth_blocking._hs_disabled_message = "Reason for being disabled"
490490
e = self.get_failure(self.auth.check_auth_blocking(), ResourceLimitError)
491-
self.assertEquals(e.value.admin_contact, self.hs.config.server.admin_contact)
492-
self.assertEquals(e.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
493-
self.assertEquals(e.value.code, 403)
491+
self.assertEqual(e.value.admin_contact, self.hs.config.server.admin_contact)
492+
self.assertEqual(e.value.errcode, Codes.RESOURCE_LIMIT_EXCEEDED)
493+
self.assertEqual(e.value.code, 403)
494494

495495
def test_server_notices_mxid_special_cased(self):
496496
self.auth_blocking._hs_disabled = True

tests/api/test_filtering.py

+20-10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from unittest.mock import patch
1919

2020
import jsonschema
21+
from frozendict import frozendict
2122

2223
from synapse.api.constants import EventContentFields
2324
from synapse.api.errors import SynapseError
@@ -327,6 +328,15 @@ def test_filter_labels(self):
327328

328329
self.assertFalse(Filter(self.hs, definition)._check(event))
329330

331+
# check it works with frozendicts too
332+
event = MockEvent(
333+
sender="@foo:bar",
334+
type="m.room.message",
335+
room_id="!secretbase:unknown",
336+
content=frozendict({EventContentFields.LABELS: ["#fun"]}),
337+
)
338+
self.assertTrue(Filter(self.hs, definition)._check(event))
339+
330340
def test_filter_not_labels(self):
331341
definition = {"org.matrix.not_labels": ["#fun"]}
332342
event = MockEvent(
@@ -364,7 +374,7 @@ def test_filter_presence_match(self):
364374
)
365375

366376
results = self.get_success(user_filter.filter_presence(events=events))
367-
self.assertEquals(events, results)
377+
self.assertEqual(events, results)
368378

369379
def test_filter_presence_no_match(self):
370380
user_filter_json = {"presence": {"types": ["m.*"]}}
@@ -388,7 +398,7 @@ def test_filter_presence_no_match(self):
388398
)
389399

390400
results = self.get_success(user_filter.filter_presence(events=events))
391-
self.assertEquals([], results)
401+
self.assertEqual([], results)
392402

393403
def test_filter_room_state_match(self):
394404
user_filter_json = {"room": {"state": {"types": ["m.*"]}}}
@@ -407,7 +417,7 @@ def test_filter_room_state_match(self):
407417
)
408418

409419
results = self.get_success(user_filter.filter_room_state(events=events))
410-
self.assertEquals(events, results)
420+
self.assertEqual(events, results)
411421

412422
def test_filter_room_state_no_match(self):
413423
user_filter_json = {"room": {"state": {"types": ["m.*"]}}}
@@ -428,7 +438,7 @@ def test_filter_room_state_no_match(self):
428438
)
429439

430440
results = self.get_success(user_filter.filter_room_state(events))
431-
self.assertEquals([], results)
441+
self.assertEqual([], results)
432442

433443
def test_filter_rooms(self):
434444
definition = {
@@ -444,7 +454,7 @@ def test_filter_rooms(self):
444454

445455
filtered_room_ids = list(Filter(self.hs, definition).filter_rooms(room_ids))
446456

447-
self.assertEquals(filtered_room_ids, ["!allowed:example.com"])
457+
self.assertEqual(filtered_room_ids, ["!allowed:example.com"])
448458

449459
@unittest.override_config({"experimental_features": {"msc3440_enabled": True}})
450460
def test_filter_relations(self):
@@ -486,7 +496,7 @@ async def events_have_relations(*args, **kwargs):
486496
Filter(self.hs, definition)._check_event_relations(events)
487497
)
488498
)
489-
self.assertEquals(filtered_events, events[1:])
499+
self.assertEqual(filtered_events, events[1:])
490500

491501
def test_add_filter(self):
492502
user_filter_json = {"room": {"state": {"types": ["m.*"]}}}
@@ -497,8 +507,8 @@ def test_add_filter(self):
497507
)
498508
)
499509

500-
self.assertEquals(filter_id, 0)
501-
self.assertEquals(
510+
self.assertEqual(filter_id, 0)
511+
self.assertEqual(
502512
user_filter_json,
503513
(
504514
self.get_success(
@@ -524,6 +534,6 @@ def test_get_filter(self):
524534
)
525535
)
526536

527-
self.assertEquals(filter.get_filter_json(), user_filter_json)
537+
self.assertEqual(filter.get_filter_json(), user_filter_json)
528538

529-
self.assertRegexpMatches(repr(filter), r"<FilterCollection \{.*\}>")
539+
self.assertRegex(repr(filter), r"<FilterCollection \{.*\}>")

0 commit comments

Comments
 (0)