Skip to content

Commit

Permalink
Revert "Add config option to restrict auto accepting only from local …
Browse files Browse the repository at this point in the history
…users"

This reverts commit ca17c65.
  • Loading branch information
devonh committed Apr 29, 2024
1 parent ca17c65 commit d75438b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 148 deletions.
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,10 @@ modules:
- module: synapse_auto_accept_invite.InviteAutoAccepter
config:
# Optional: if set to true, then only invites for direct messages (1:1 rooms)
# will be auto accepted.
# will be auto accepted. Otherwise, all room invites are accepted.
# Defaults to false.
accept_invites_only_for_direct_messages: false

# Optional: if set to true, then only invites from local users will be auto
# accepted.
# Defaults to false.
accept_invites_only_from_local_users: false

# (For workerised Synapse deployments)
#
# This module should only be active on a single worker process at once,
Expand Down
66 changes: 24 additions & 42 deletions synapse_auto_accept_invite/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
@attr.s(auto_attribs=True, frozen=True)
class InviteAutoAccepterConfig:
accept_invites_only_for_direct_messages: bool = False
accept_invites_only_from_local_users: bool = False
worker_to_run_on: Optional[str] = None


Expand Down Expand Up @@ -67,15 +66,11 @@ def parse_config(config: Dict[str, Any]) -> InviteAutoAccepterConfig:
accept_invites_only_for_direct_messages = config.get(
"accept_invites_only_for_direct_messages", False
)
accept_invites_only_from_local_users = config.get(
"accept_invites_only_from_local_users", False
)

worker_to_run_on = config.get("worker_to_run_on", None)

return InviteAutoAccepterConfig(
accept_invites_only_for_direct_messages=accept_invites_only_for_direct_messages,
accept_invites_only_from_local_users=accept_invites_only_from_local_users,
worker_to_run_on=worker_to_run_on,
)

Expand All @@ -87,50 +82,37 @@ async def on_new_event(self, event: EventBase, *args: Any) -> None:
event: The incoming event.
"""
# Check if the event is an invite for a local user.
is_invite_for_local_user = (
if (
event.type == "m.room.member"
and event.is_state()
and event.membership == "invite"
and self._api.is_mine(event.state_key)
)

# Only accept invites for direct messages if the configuration mandates it.
is_direct_message = event.content.get("is_direct", False)
is_allowed_by_direct_message_rules = (
not self._config.accept_invites_only_for_direct_messages
or is_direct_message is True
)

# Only accept invites from remote users if the configuration mandates it.
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 (
is_invite_for_local_user
and is_allowed_by_direct_message_rules
and is_allowed_by_local_user_rules
):
# 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)
run_as_background_process(
"retry_make_join",
self._retry_make_join,
event.state_key,
event.state_key,
event.room_id,
"join",
bg_start_span=False,
)

if is_direct_message:
# Mark this room as a direct message!
await self._mark_room_as_direct_message(
event.state_key, event.sender, event.room_id
is_direct_message = event.content.get("is_direct", False)

# Only accept invites for direct messages if the configuration mandates it, otherwise accept all invites.
if (
not self._config.accept_invites_only_for_direct_messages
or is_direct_message is True
):
# 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)
run_as_background_process(
"retry_make_join",
self._retry_make_join,
event.state_key,
event.state_key,
event.room_id,
"join",
bg_start_span=False,
)

if is_direct_message:
# Mark this room as a direct message!
await self._mark_room_as_direct_message(
event.state_key, event.sender, event.room_id
)

async def _mark_room_as_direct_message(
self, user_id: str, dm_user_id: str, room_id: str
) -> None:
Expand Down
101 changes: 1 addition & 100 deletions tests/test_accept_invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ async def test_accept_invite_direct_message(self) -> None:
},
)

async def test_invite_remote_user(self) -> None:
async def test_remote_user(self) -> None:
"""Tests that receiving an invite for a remote user does nothing."""
invite = MockEvent(
sender=self.user_id,
Expand All @@ -210,36 +210,6 @@ async def test_invite_remote_user(self) -> None:

self.mocked_update_membership.assert_not_called()

async def test_invite_from_remote_user(self) -> None:
"""Tests that receiving an invite for a local user, from a remote user, makes the
module attempt to make the invitee join the room."""
invite = MockEvent(
sender=self.remote_invitee,
state_key=self.invitee,
type="m.room.member",
content={"membership": "invite"},
)
join_event = MockEvent(
sender="someone",
state_key="someone",
type="m.room.member",
content={"membership": "join"},
)
self.mocked_update_membership.return_value = make_awaitable(join_event)

# Stop mypy from complaining that we give on_new_event a MockEvent rather than an
# EventBase.
await self.module.on_new_event(event=invite) # type: ignore[arg-type]

await self.retry_assertions(
self.mocked_update_membership,
1,
sender=invite.state_key,
target=invite.state_key,
room_id=invite.room_id,
new_membership="join",
)

async def test_not_state(self) -> None:
"""Tests that receiving an invite that's not a state event does nothing."""
invite = MockEvent(
Expand Down Expand Up @@ -350,83 +320,14 @@ async def test_ignore_invite_if_only_enabled_for_direct_messages(self) -> None:
mocked_update_membership: Mock = module._api.update_room_membership # type: ignore[assignment]
mocked_update_membership.assert_not_called()

async def test_accept_invite_local_user_if_only_enabled_from_local_users(
self,
) -> None:
"""Tests that, if the module is configured to only accept invites from local users, invites
from local users are still automatically accepted.
"""
module = create_module(
config_override={"accept_invites_only_from_local_users": True},
)

# Patch out the account data get and put methods with dummy awaitables.
account_data_put: Mock = cast(Mock, module._api.account_data_manager.put_global)
account_data_put.return_value = make_awaitable(None)

account_data_get: Mock = cast(Mock, module._api.account_data_manager.get_global)
account_data_get.return_value = make_awaitable({})

mocked_update_membership: Mock = module._api.update_room_membership # type: ignore[assignment]
join_event = MockEvent(
sender="someone",
state_key="someone",
type="m.room.member",
content={"membership": "join"},
)
mocked_update_membership.return_value = make_awaitable(join_event)

invite = MockEvent(
sender=self.user_id,
state_key=self.invitee,
type="m.room.member",
content={"membership": "invite", "is_direct": True},
)

# Stop mypy from complaining that we give on_new_event a MockEvent rather than an
# EventBase.
await module.on_new_event(event=invite) # type: ignore[arg-type]

await self.retry_assertions(
mocked_update_membership,
1,
sender=invite.state_key,
target=invite.state_key,
room_id=invite.room_id,
new_membership="join",
)

async def test_ignore_invite_if_only_enabled_from_local_users(self) -> None:
"""Tests that, if the module is configured to only accept invites from local users,
invites from non-local users are ignored."""
module = create_module(
config_override={"accept_invites_only_from_local_users": True},
)

invite = MockEvent(
sender=self.remote_invitee,
state_key=self.invitee,
type="m.room.member",
content={"membership": "invite"},
)

# Stop mypy from complaining that we give on_new_event a MockEvent rather than an
# EventBase.
await module.on_new_event(event=invite) # type: ignore[arg-type]

mocked_update_membership: Mock = module._api.update_room_membership # type: ignore[assignment]
mocked_update_membership.assert_not_called()

def test_config_parse(self) -> None:
"""Tests that a correct configuration passes parse_config."""
config = {
"accept_invites_only_for_direct_messages": True,
"accept_invites_only_from_local_users": True,
}
parsed_config = InviteAutoAccepter.parse_config(config)

self.assertTrue(parsed_config.accept_invites_only_for_direct_messages)
self.assertTrue(parsed_config.accept_invites_only_from_local_users)

def test_runs_on_only_one_worker(self) -> None:
"""
Expand Down

0 comments on commit d75438b

Please sign in to comment.