-
Notifications
You must be signed in to change notification settings - Fork 381
Fix join being denied after being invited over federation #18075
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
MadLittleMods
merged 48 commits into
develop
from
madlittlemods/debug-synapse-consistency-invite-join
Jan 27, 2025
Merged
Changes from all commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
e4c3e7b
Add membership to event representation when logging
MadLittleMods d31ff53
Debug logging
MadLittleMods 1d64beb
A couple more debug logs
MadLittleMods a32c1ba
Pipe store access to `check_state_dependent_auth_rules`
MadLittleMods 9a35155
Revert "Pipe store access to `check_state_dependent_auth_rules`"
MadLittleMods 825b249
Add out-of-band membership to auth events when creating new events
MadLittleMods 0698dcf
Add changelog
MadLittleMods 8c6b294
Clean up fix
MadLittleMods e4dad14
Merge branch 'develop' into madlittlemods/debug-synapse-consistency-i…
MadLittleMods 7e60ec0
It's fine to notify about out-of-band membership
MadLittleMods ad8ed0c
Remove duplicated code
MadLittleMods d0639e4
Restore `notifier.notify_replication()`
MadLittleMods 7855892
Log all handled events
MadLittleMods b3bda0e
Clean up some pre-existing tests
MadLittleMods 0d01cda
Try adding out of band federation trial tests
MadLittleMods 83237f7
User1 can join remote room
MadLittleMods 1779d76
Move `DeviceListResyncTestCase` to their own file
MadLittleMods 4f0cf80
Move `StripUnsignedFromEventsTestCase` to a more specific file
MadLittleMods 741f256
Fix extremities typo
MadLittleMods a736ead
More robust test timeout
MadLittleMods 70cbff8
Clean up test
MadLittleMods 9716478
More cleanup
MadLittleMods 05c875c
Better explanations
MadLittleMods 0a757b6
Reset the mocks when we don't need them anymore
MadLittleMods d9bf5a9
Add test that reproduces the problem
MadLittleMods f885575
Add tests for accepting and rejecting the invite
MadLittleMods 87cfe87
Try to explain regression test
MadLittleMods 33ac6c9
Harden up the tests
MadLittleMods 0d871b6
More hardening
MadLittleMods 2fbc2fa
Allow events to auth correctly (computed state matches our auth events)
MadLittleMods bbeb68a
Debug logs to figure out why rejected
MadLittleMods 11d9970
Revert "Debug logs to figure out why rejected"
MadLittleMods 872f717
Remove debug logs
MadLittleMods d85d84c
Clean up whitespace
MadLittleMods 14dc54b
Unable to reproduce to with knocks
MadLittleMods 139db20
Bump db calls
MadLittleMods 78bee3d
Fix presence tests
MadLittleMods 074483d
Fix sync join/ban race test failing
MadLittleMods 545f22d
Fix lints
MadLittleMods 0b31100
Fix federation sender shard tests
MadLittleMods 27b7c68
Merge branch 'develop' into madlittlemods/debug-synapse-consistency-i…
MadLittleMods d80984e
Better `user_id` parameter for `is_mine_id`
MadLittleMods ab098d9
Fix some typos
MadLittleMods 2d5d246
Assert instead of nest
MadLittleMods dc547d6
Restore log
MadLittleMods e9ee86a
Explain why not using `spec=MatrixFederationHttpClient`
MadLittleMods 6cea84c
Merge branch 'develop' into madlittlemods/debug-synapse-consistency-i…
MadLittleMods 42df9e6
Expand comment but still no concrete answer
MadLittleMods File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Fix join being denied after being invited over federation. Also fixes other out-of-band membership transitions. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
# | ||
# This file is licensed under the Affero General Public License (AGPL) version 3. | ||
# | ||
# Copyright (C) 2024 New Vector, Ltd | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU Affero General Public License as | ||
# published by the Free Software Foundation, either version 3 of the | ||
# License, or (at your option) any later version. | ||
# | ||
# See the GNU Affero General Public License for more details: | ||
# <https://www.gnu.org/licenses/agpl-3.0.html>. | ||
# | ||
# Originally licensed under the Apache License, Version 2.0: | ||
# <http://www.apache.org/licenses/LICENSE-2.0>. | ||
# | ||
# [This file includes modifications made by New Vector Limited] | ||
# | ||
# | ||
|
||
import logging | ||
from unittest.mock import AsyncMock, Mock | ||
|
||
from twisted.test.proto_helpers import MemoryReactor | ||
|
||
from synapse.handlers.device import DeviceListUpdater | ||
from synapse.server import HomeServer | ||
from synapse.types import JsonDict | ||
from synapse.util import Clock | ||
from synapse.util.retryutils import NotRetryingDestination | ||
|
||
from tests import unittest | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class DeviceListResyncTestCase(unittest.HomeserverTestCase): | ||
anoadragon453 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None: | ||
self.store = self.hs.get_datastores().main | ||
|
||
def test_retry_device_list_resync(self) -> None: | ||
"""Tests that device lists are marked as stale if they couldn't be synced, and | ||
that stale device lists are retried periodically. | ||
""" | ||
remote_user_id = "@john:test_remote" | ||
remote_origin = "test_remote" | ||
|
||
# Track the number of attempts to resync the user's device list. | ||
self.resync_attempts = 0 | ||
|
||
# When this function is called, increment the number of resync attempts (only if | ||
# we're querying devices for the right user ID), then raise a | ||
# NotRetryingDestination error to fail the resync gracefully. | ||
def query_user_devices( | ||
destination: str, user_id: str, timeout: int = 30000 | ||
) -> JsonDict: | ||
if user_id == remote_user_id: | ||
self.resync_attempts += 1 | ||
|
||
raise NotRetryingDestination(0, 0, destination) | ||
|
||
# Register the mock on the federation client. | ||
federation_client = self.hs.get_federation_client() | ||
federation_client.query_user_devices = Mock(side_effect=query_user_devices) # type: ignore[method-assign] | ||
|
||
# Register a mock on the store so that the incoming update doesn't fail because | ||
# we don't share a room with the user. | ||
self.store.get_rooms_for_user = AsyncMock(return_value=["!someroom:test"]) | ||
|
||
# Manually inject a fake device list update. We need this update to include at | ||
# least one prev_id so that the user's device list will need to be retried. | ||
device_list_updater = self.hs.get_device_handler().device_list_updater | ||
assert isinstance(device_list_updater, DeviceListUpdater) | ||
self.get_success( | ||
device_list_updater.incoming_device_list_update( | ||
origin=remote_origin, | ||
edu_content={ | ||
"deleted": False, | ||
"device_display_name": "Mobile", | ||
"device_id": "QBUAZIFURK", | ||
"prev_id": [5], | ||
"stream_id": 6, | ||
"user_id": remote_user_id, | ||
}, | ||
) | ||
) | ||
|
||
# Check that there was one resync attempt. | ||
self.assertEqual(self.resync_attempts, 1) | ||
|
||
# Check that the resync attempt failed and caused the user's device list to be | ||
# marked as stale. | ||
need_resync = self.get_success( | ||
self.store.get_user_ids_requiring_device_list_resync() | ||
) | ||
self.assertIn(remote_user_id, need_resync) | ||
|
||
# Check that waiting for 30 seconds caused Synapse to retry resyncing the device | ||
# list. | ||
self.reactor.advance(30) | ||
self.assertEqual(self.resync_attempts, 2) | ||
|
||
def test_cross_signing_keys_retry(self) -> None: | ||
"""Tests that resyncing a device list correctly processes cross-signing keys from | ||
the remote server. | ||
""" | ||
remote_user_id = "@john:test_remote" | ||
remote_master_key = "85T7JXPFBAySB/jwby4S3lBPTqY3+Zg53nYuGmu1ggY" | ||
remote_self_signing_key = "QeIiFEjluPBtI7WQdG365QKZcFs9kqmHir6RBD0//nQ" | ||
|
||
# Register mock device list retrieval on the federation client. | ||
federation_client = self.hs.get_federation_client() | ||
federation_client.query_user_devices = AsyncMock( # type: ignore[method-assign] | ||
return_value={ | ||
"user_id": remote_user_id, | ||
"stream_id": 1, | ||
"devices": [], | ||
"master_key": { | ||
"user_id": remote_user_id, | ||
"usage": ["master"], | ||
"keys": {"ed25519:" + remote_master_key: remote_master_key}, | ||
}, | ||
"self_signing_key": { | ||
"user_id": remote_user_id, | ||
"usage": ["self_signing"], | ||
"keys": { | ||
"ed25519:" + remote_self_signing_key: remote_self_signing_key | ||
}, | ||
}, | ||
} | ||
) | ||
|
||
# Resync the device list. | ||
device_handler = self.hs.get_device_handler() | ||
self.get_success( | ||
device_handler.device_list_updater.multi_user_device_resync( | ||
[remote_user_id] | ||
), | ||
) | ||
|
||
# Retrieve the cross-signing keys for this user. | ||
keys = self.get_success( | ||
self.store.get_e2e_cross_signing_keys_bulk(user_ids=[remote_user_id]), | ||
) | ||
self.assertIn(remote_user_id, keys) | ||
key = keys[remote_user_id] | ||
assert key is not None | ||
|
||
# Check that the master key is the one returned by the mock. | ||
master_key = key["master"] | ||
self.assertEqual(len(master_key["keys"]), 1) | ||
self.assertTrue("ed25519:" + remote_master_key in master_key["keys"].keys()) | ||
self.assertTrue(remote_master_key in master_key["keys"].values()) | ||
|
||
# Check that the self-signing key is the one returned by the mock. | ||
self_signing_key = key["self_signing"] | ||
self.assertEqual(len(self_signing_key["keys"]), 1) | ||
self.assertTrue( | ||
"ed25519:" + remote_self_signing_key in self_signing_key["keys"].keys(), | ||
) | ||
self.assertTrue(remote_self_signing_key in self_signing_key["keys"].values()) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.