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

Update module API "update room membership" method to allow for remote joins #13441

1 change: 1 addition & 0 deletions changelog.d/13441.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add remote join capability to the module API "update_room_membership" method (in a backwards compatible manner).
babolivier marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions synapse/module_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,7 @@ async def update_room_membership(
room_id: str,
new_membership: str,
content: Optional[JsonDict] = None,
remote_room_hosts: Optional[List[str]] = None,
) -> EventBase:
"""Updates the membership of a user to the given value.

Expand All @@ -946,6 +947,7 @@ async def update_room_membership(
https://spec.matrix.org/unstable/client-server-api/#mroommember for the
list of allowed values.
content: Additional values to include in the resulting event's content.
remote_room_hosts: Remote servers to send the update to.
babolivier marked this conversation as resolved.
Show resolved Hide resolved

Returns:
The newly created membership event.
Expand Down Expand Up @@ -1005,6 +1007,7 @@ async def update_room_membership(
room_id=room_id,
action=new_membership,
content=content,
remote_room_hosts=remote_room_hosts,
)

# Try to retrieve the resulting event.
Expand Down
40 changes: 37 additions & 3 deletions tests/module_api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from unittest.mock import Mock
from unittest.mock import MagicMock, Mock, patch

from twisted.internet import defer

from synapse.api.constants import EduTypes, EventTypes
from synapse.api.errors import NotFoundError
from synapse.events import EventBase
from synapse.federation.units import Transaction
from synapse.handlers.presence import UserPresenceState
Expand All @@ -26,7 +27,7 @@

from tests.events.test_presence_router import send_presence_update, sync_presence
from tests.replication._base import BaseMultiWorkerStreamTestCase
from tests.test_utils import simple_async_mock
from tests.test_utils import make_awaitable, simple_async_mock
from tests.test_utils.event_injection import inject_member_event
from tests.unittest import HomeserverTestCase, override_config
from tests.utils import USE_POSTGRES_FOR_TESTS
Expand Down Expand Up @@ -409,7 +410,8 @@ def test_send_local_online_presence_to_federation(self):

self.assertTrue(found_update)

def test_update_membership(self):
@patch("synapse.handlers.room_member.RoomMemberMasterHandler._remote_join")
def test_update_membership(self, mocked_remote_join):
"""Tests that the module API can update the membership of a user in a room."""
peter = self.register_user("peter", "hackme")
lesley = self.register_user("lesley", "hackme")
Expand Down Expand Up @@ -532,6 +534,38 @@ def test_update_membership(self):
self.assertEqual(res["displayname"], "simone")
self.assertIsNone(res["avatar_url"])

# Check that no remote join attempts have occurred thus far.
babolivier marked this conversation as resolved.
Show resolved Hide resolved
self.assertFalse(mocked_remote_join.called)

# Necessary to fake a remote join.
fake_stream_id = 1
if isinstance(mocked_remote_join, MagicMock):
# AyncMock is not supported in this Python version.
mocked_remote_join.return_value = make_awaitable(
("fake-event-id", fake_stream_id)
)
else:
mocked_remote_join.return_value = "fake-event-id", fake_stream_id
babolivier marked this conversation as resolved.
Show resolved Hide resolved
fake_remote_host = f"{self.module_api.server_name}-remote"

# Given that the join is to be faked, we expect the relevant join event not to
# be persisted and the module API method to raise that.
self.get_failure(
defer.ensureDeferred(
self.module_api.update_room_membership(
sender=peter,
target=peter,
room_id=f"!nonexistent:{fake_remote_host}",
new_membership="join",
remote_room_hosts=[fake_remote_host],
)
),
NotFoundError,
)

# Check that a remote join was attempted.
self.assertEqual(mocked_remote_join.call_count, 1)

def test_get_room_state(self):
"""Tests that a module can retrieve the state of a room through the module API."""
user_id = self.register_user("peter", "hackme")
Expand Down