mirror of
https://github.com/element-hq/synapse.git
synced 2025-05-12 00:00:40 -04:00
Never autojoin deactivated & suspended users. (#18073)
This PR changes the logic so that deactivated users are always ignored. Suspended users were already effectively ignored as Synapse forbids a join while suspended. --------- Co-authored-by: Devon Hudson <devon.dmytro@gmail.com>
This commit is contained in:
parent
8f27b3af07
commit
628351b98d
1
changelog.d/18073.bugfix
Normal file
1
changelog.d/18073.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Deactivated users will no longer automatically accept an invite when `auto_accept_invites` is enabled.
|
@ -66,32 +66,49 @@ class InviteAutoAccepter:
|
|||||||
event: The incoming event.
|
event: The incoming event.
|
||||||
"""
|
"""
|
||||||
# Check if the event is an invite for a local user.
|
# Check if the event is an invite for a local user.
|
||||||
is_invite_for_local_user = (
|
if (
|
||||||
event.type == EventTypes.Member
|
event.type != EventTypes.Member
|
||||||
and event.is_state()
|
or event.is_state() is False
|
||||||
and event.membership == Membership.INVITE
|
or event.membership != Membership.INVITE
|
||||||
and self._api.is_mine(event.state_key)
|
or self._api.is_mine(event.state_key) is False
|
||||||
)
|
):
|
||||||
|
return
|
||||||
|
|
||||||
# Only accept invites for direct messages if the configuration mandates it.
|
# Only accept invites for direct messages if the configuration mandates it.
|
||||||
is_direct_message = event.content.get("is_direct", False)
|
is_direct_message = event.content.get("is_direct", False)
|
||||||
is_allowed_by_direct_message_rules = (
|
if (
|
||||||
not self._config.accept_invites_only_for_direct_messages
|
self._config.accept_invites_only_for_direct_messages
|
||||||
or is_direct_message is True
|
and is_direct_message is False
|
||||||
)
|
):
|
||||||
|
return
|
||||||
|
|
||||||
# Only accept invites from remote users if the configuration mandates it.
|
# Only accept invites from remote users if the configuration mandates it.
|
||||||
is_from_local_user = self._api.is_mine(event.sender)
|
is_from_local_user = self._api.is_mine(event.sender)
|
||||||
is_allowed_by_local_user_rules = (
|
|
||||||
not self._config.accept_invites_only_from_local_users
|
|
||||||
or is_from_local_user is True
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
is_invite_for_local_user
|
self._config.accept_invites_only_from_local_users
|
||||||
and is_allowed_by_direct_message_rules
|
and is_from_local_user is False
|
||||||
and is_allowed_by_local_user_rules
|
|
||||||
):
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check the user is activated.
|
||||||
|
recipient = await self._api.get_userinfo_by_id(event.state_key)
|
||||||
|
|
||||||
|
# Ignore if the user doesn't exist.
|
||||||
|
if recipient is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Never accept invites for deactivated users.
|
||||||
|
if recipient.is_deactivated:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Never accept invites for suspended users.
|
||||||
|
if recipient.suspended:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Never accept invites for locked users.
|
||||||
|
if recipient.locked:
|
||||||
|
return
|
||||||
|
|
||||||
# Make the user join the room. We run this as a background process to circumvent a race condition
|
# Make the user join the room. We run this as a background process to circumvent a race condition
|
||||||
# that occurs when responding to invites over federation (see https://github.com/matrix-org/synapse-auto-accept-invite/issues/12)
|
# that occurs when responding to invites over federation (see https://github.com/matrix-org/synapse-auto-accept-invite/issues/12)
|
||||||
run_as_background_process(
|
run_as_background_process(
|
||||||
|
@ -39,7 +39,7 @@ from synapse.module_api import ModuleApi
|
|||||||
from synapse.rest import admin
|
from synapse.rest import admin
|
||||||
from synapse.rest.client import login, room
|
from synapse.rest.client import login, room
|
||||||
from synapse.server import HomeServer
|
from synapse.server import HomeServer
|
||||||
from synapse.types import StreamToken, create_requester
|
from synapse.types import StreamToken, UserID, UserInfo, create_requester
|
||||||
from synapse.util import Clock
|
from synapse.util import Clock
|
||||||
|
|
||||||
from tests.handlers.test_sync import generate_sync_config
|
from tests.handlers.test_sync import generate_sync_config
|
||||||
@ -349,6 +349,169 @@ class AutoAcceptInvitesTestCase(FederatingHomeserverTestCase):
|
|||||||
join_updates, _ = sync_join(self, invited_user_id)
|
join_updates, _ = sync_join(self, invited_user_id)
|
||||||
self.assertEqual(len(join_updates), 0)
|
self.assertEqual(len(join_updates), 0)
|
||||||
|
|
||||||
|
@override_config(
|
||||||
|
{
|
||||||
|
"auto_accept_invites": {
|
||||||
|
"enabled": True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
async def test_ignore_invite_for_missing_user(self) -> None:
|
||||||
|
"""Tests that receiving an invite for a missing user is ignored."""
|
||||||
|
inviting_user_id = self.register_user("inviter", "pass")
|
||||||
|
inviting_user_tok = self.login("inviter", "pass")
|
||||||
|
|
||||||
|
# A local user who receives an invite
|
||||||
|
invited_user_id = "@fake:" + self.hs.config.server.server_name
|
||||||
|
|
||||||
|
# Create a room and send an invite to the other user
|
||||||
|
room_id = self.helper.create_room_as(
|
||||||
|
inviting_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.helper.invite(
|
||||||
|
room_id,
|
||||||
|
inviting_user_id,
|
||||||
|
invited_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
join_updates, _ = sync_join(self, inviting_user_id)
|
||||||
|
# Assert that the last event in the room was not a member event for the target user.
|
||||||
|
self.assertEqual(
|
||||||
|
join_updates[0].timeline.events[-1].content["membership"], "invite"
|
||||||
|
)
|
||||||
|
|
||||||
|
@override_config(
|
||||||
|
{
|
||||||
|
"auto_accept_invites": {
|
||||||
|
"enabled": True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
async def test_ignore_invite_for_deactivated_user(self) -> None:
|
||||||
|
"""Tests that receiving an invite for a deactivated user is ignored."""
|
||||||
|
inviting_user_id = self.register_user("inviter", "pass", admin=True)
|
||||||
|
inviting_user_tok = self.login("inviter", "pass")
|
||||||
|
|
||||||
|
# A local user who receives an invite
|
||||||
|
invited_user_id = self.register_user("invitee", "pass")
|
||||||
|
|
||||||
|
# Create a room and send an invite to the other user
|
||||||
|
room_id = self.helper.create_room_as(
|
||||||
|
inviting_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"PUT",
|
||||||
|
"/_synapse/admin/v2/users/%s" % invited_user_id,
|
||||||
|
{"deactivated": True},
|
||||||
|
access_token=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert channel.code == 200
|
||||||
|
|
||||||
|
self.helper.invite(
|
||||||
|
room_id,
|
||||||
|
inviting_user_id,
|
||||||
|
invited_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
join_updates, b = sync_join(self, inviting_user_id)
|
||||||
|
# Assert that the last event in the room was not a member event for the target user.
|
||||||
|
self.assertEqual(
|
||||||
|
join_updates[0].timeline.events[-1].content["membership"], "invite"
|
||||||
|
)
|
||||||
|
|
||||||
|
@override_config(
|
||||||
|
{
|
||||||
|
"auto_accept_invites": {
|
||||||
|
"enabled": True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
async def test_ignore_invite_for_suspended_user(self) -> None:
|
||||||
|
"""Tests that receiving an invite for a suspended user is ignored."""
|
||||||
|
inviting_user_id = self.register_user("inviter", "pass", admin=True)
|
||||||
|
inviting_user_tok = self.login("inviter", "pass")
|
||||||
|
|
||||||
|
# A local user who receives an invite
|
||||||
|
invited_user_id = self.register_user("invitee", "pass")
|
||||||
|
|
||||||
|
# Create a room and send an invite to the other user
|
||||||
|
room_id = self.helper.create_room_as(
|
||||||
|
inviting_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_synapse/admin/v1/suspend/{invited_user_id}",
|
||||||
|
{"suspend": True},
|
||||||
|
access_token=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert channel.code == 200
|
||||||
|
|
||||||
|
self.helper.invite(
|
||||||
|
room_id,
|
||||||
|
inviting_user_id,
|
||||||
|
invited_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
join_updates, b = sync_join(self, inviting_user_id)
|
||||||
|
# Assert that the last event in the room was not a member event for the target user.
|
||||||
|
self.assertEqual(
|
||||||
|
join_updates[0].timeline.events[-1].content["membership"], "invite"
|
||||||
|
)
|
||||||
|
|
||||||
|
@override_config(
|
||||||
|
{
|
||||||
|
"auto_accept_invites": {
|
||||||
|
"enabled": True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
async def test_ignore_invite_for_locked_user(self) -> None:
|
||||||
|
"""Tests that receiving an invite for a suspended user is ignored."""
|
||||||
|
inviting_user_id = self.register_user("inviter", "pass", admin=True)
|
||||||
|
inviting_user_tok = self.login("inviter", "pass")
|
||||||
|
|
||||||
|
# A local user who receives an invite
|
||||||
|
invited_user_id = self.register_user("invitee", "pass")
|
||||||
|
|
||||||
|
# Create a room and send an invite to the other user
|
||||||
|
room_id = self.helper.create_room_as(
|
||||||
|
inviting_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_synapse/admin/v2/users/{invited_user_id}",
|
||||||
|
{"locked": True},
|
||||||
|
access_token=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert channel.code == 200
|
||||||
|
|
||||||
|
self.helper.invite(
|
||||||
|
room_id,
|
||||||
|
inviting_user_id,
|
||||||
|
invited_user_id,
|
||||||
|
tok=inviting_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
join_updates, b = sync_join(self, inviting_user_id)
|
||||||
|
# Assert that the last event in the room was not a member event for the target user.
|
||||||
|
self.assertEqual(
|
||||||
|
join_updates[0].timeline.events[-1].content["membership"], "invite"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_request_key = 0
|
_request_key = 0
|
||||||
|
|
||||||
@ -647,6 +810,22 @@ def create_module(
|
|||||||
module_api.is_mine.side_effect = lambda a: a.split(":")[1] == "test"
|
module_api.is_mine.side_effect = lambda a: a.split(":")[1] == "test"
|
||||||
module_api.worker_name = worker_name
|
module_api.worker_name = worker_name
|
||||||
module_api.sleep.return_value = make_multiple_awaitable(None)
|
module_api.sleep.return_value = make_multiple_awaitable(None)
|
||||||
|
module_api.get_userinfo_by_id.return_value = UserInfo(
|
||||||
|
user_id=UserID.from_string("@user:test"),
|
||||||
|
is_admin=False,
|
||||||
|
is_guest=False,
|
||||||
|
consent_server_notice_sent=None,
|
||||||
|
consent_ts=None,
|
||||||
|
consent_version=None,
|
||||||
|
appservice_id=None,
|
||||||
|
creation_ts=0,
|
||||||
|
user_type=None,
|
||||||
|
is_deactivated=False,
|
||||||
|
locked=False,
|
||||||
|
is_shadow_banned=False,
|
||||||
|
approved=True,
|
||||||
|
suspended=False,
|
||||||
|
)
|
||||||
|
|
||||||
if config_override is None:
|
if config_override is None:
|
||||||
config_override = {}
|
config_override = {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user