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

Add third_party module callbacks to check if a user can delete a room and deactivate a user #12028

Merged
merged 15 commits into from
Mar 9, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add tests for test_check_can_shutdown_room and test_check_can_deactiv…
…ate_user
  • Loading branch information
Half-Shot committed Mar 9, 2022

Verified

This commit was signed with the committer’s verified signature.
ararslan Alex Arslan
commit e66329f4776ecc07159c5490cf4ee6c334ff8e05
8 changes: 6 additions & 2 deletions synapse/events/third_party_rules.py
Original file line number Diff line number Diff line change
@@ -159,8 +159,12 @@ def __init__(self, hs: "HomeServer"):
CHECK_VISIBILITY_CAN_BE_MODIFIED_CALLBACK
] = []
self._on_new_event_callbacks: List[ON_NEW_EVENT_CALLBACK] = []
self._check_can_shutdown_room_callbacks: List[CHECK_CAN_SHUTDOWN_ROOM_CALLBACK] = []
self._check_can_deactivate_user_callbacks: List[CHECK_CAN_DEACTIVATE_USER_CALLBACK] = []
self._check_can_shutdown_room_callbacks: List[
CHECK_CAN_SHUTDOWN_ROOM_CALLBACK
] = []
self._check_can_deactivate_user_callbacks: List[
CHECK_CAN_DEACTIVATE_USER_CALLBACK
] = []
self._on_profile_update_callbacks: List[ON_PROFILE_UPDATE_CALLBACK] = []
self._on_user_deactivation_status_changed_callbacks: List[
ON_USER_DEACTIVATION_STATUS_CHANGED_CALLBACK
6 changes: 0 additions & 6 deletions synapse/module_api/__init__.py
Original file line number Diff line number Diff line change
@@ -285,15 +285,12 @@ def register_third_party_rules_callbacks(
CHECK_VISIBILITY_CAN_BE_MODIFIED_CALLBACK
] = None,
on_new_event: Optional[ON_NEW_EVENT_CALLBACK] = None,
<<<<<<< HEAD
check_can_shutdown_room: Optional[CHECK_CAN_SHUTDOWN_ROOM_CALLBACK] = None,
check_can_deactivate_user: Optional[CHECK_CAN_DEACTIVATE_USER_CALLBACK] = None,
=======
on_profile_update: Optional[ON_PROFILE_UPDATE_CALLBACK] = None,
on_user_deactivation_status_changed: Optional[
ON_USER_DEACTIVATION_STATUS_CHANGED_CALLBACK
] = None,
>>>>>>> origin/develop
) -> None:
"""Registers callbacks for third party event rules capabilities.

@@ -305,13 +302,10 @@ def register_third_party_rules_callbacks(
check_threepid_can_be_invited=check_threepid_can_be_invited,
check_visibility_can_be_modified=check_visibility_can_be_modified,
on_new_event=on_new_event,
<<<<<<< HEAD
check_can_shutdown_room=check_can_shutdown_room,
check_can_deactivate_user=check_can_deactivate_user,
=======
on_profile_update=on_profile_update,
on_user_deactivation_status_changed=on_user_deactivation_status_changed,
>>>>>>> origin/develop
)

def register_presence_router_callbacks(
9 changes: 9 additions & 0 deletions synapse/rest/admin/rooms.py
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@ def __init__(self, hs: "HomeServer"):
self._auth = hs.get_auth()
self._store = hs.get_datastores().main
self._pagination_handler = hs.get_pagination_handler()
self._third_party_rules = hs.get_third_party_event_rules()

async def on_DELETE(
self, request: SynapseRequest, room_id: str
@@ -106,6 +107,14 @@ async def on_DELETE(
HTTPStatus.BAD_REQUEST, "%s is not a legal room ID" % (room_id,)
)

# Check this here, as otherwise we'll only fail after the background job has been started.
if not await self._third_party_rules.check_can_shutdown_room(
requester.user.to_string(), room_id
):
raise SynapseError(
403, "Shutdown of this room is forbidden", Codes.FORBIDDEN
)

delete_id = self._pagination_handler.start_shutdown_and_purge_room(
room_id=room_id,
new_room_user_id=content.get("new_room_user_id"),
121 changes: 121 additions & 0 deletions tests/rest/client/test_third_party_rules.py
Original file line number Diff line number Diff line change
@@ -775,3 +775,124 @@ def test_on_user_deactivation_status_changed_admin(self) -> None:
self.assertEqual(args[0], user_id)
self.assertFalse(args[1])
self.assertTrue(args[2])

def test_check_can_deactivate_user(self) -> None:
"""Tests that the on_user_deactivation_status_changed module callback is called
correctly when processing a user's deactivation.
"""
# Register a mocked callback.
deactivation_mock = Mock(return_value=make_awaitable(False))
third_party_rules = self.hs.get_third_party_event_rules()
third_party_rules._check_can_deactivate_user_callbacks.append(
deactivation_mock,
)

# Register a user that we'll deactivate.
user_id = self.register_user("altan", "password")
tok = self.login("altan", "password")

# Deactivate that user.
channel = self.make_request(
"POST",
"/_matrix/client/v3/account/deactivate",
{
"auth": {
"type": LoginType.PASSWORD,
"password": "password",
"identifier": {
"type": "m.id.user",
"user": user_id,
},
},
"erase": True,
},
access_token=tok,
)

# Check that the deactivation was blocked
self.assertEqual(channel.code, 403, channel.json_body)

# Check that the mock was called once.
deactivation_mock.assert_called_once()
args = deactivation_mock.call_args[0]

# Check that the mock was called with the right requester
self.assertEqual(args[0].user.to_string(), user_id)

# Check that the mock was called with the right user ID
self.assertEqual(args[1], user_id)

def test_check_can_deactivate_user_admin(self) -> None:
"""Tests that the on_user_deactivation_status_changed module callback is called
correctly when processing a user's deactivation triggered by a server admin.
"""
# Register a mocked callback.
deactivation_mock = Mock(return_value=make_awaitable(False))
third_party_rules = self.hs.get_third_party_event_rules()
third_party_rules._check_can_deactivate_user_callbacks.append(
deactivation_mock,
)

# Register an admin user.
admin_user_id = self.register_user("admin", "password", admin=True)
admin_tok = self.login("admin", "password")

# Register a user that we'll deactivate.
user_id = self.register_user("altan", "password")

# Deactivate the user.
channel = self.make_request(
"PUT",
"/_synapse/admin/v2/users/%s" % user_id,
{"deactivated": True},
access_token=admin_tok,
)

# Check that the deactivation was blocked
self.assertEqual(channel.code, 403, channel.json_body)

# Check that the mock was called once.
deactivation_mock.assert_called_once()
args = deactivation_mock.call_args[0]

# Check that the mock was called with the right requester
self.assertEqual(args[0].user.to_string(), admin_user_id)

# Check that the mock was called with the right user ID
self.assertEqual(args[1], user_id)

def test_check_can_shutdown_room(self) -> None:
"""Tests that the check_can_shutdown_room module callback is called
correctly when processing an admin's shutdown room request.
"""
# Register a mocked callback.
shutdown_mock = Mock(return_value=make_awaitable(False))
third_party_rules = self.hs.get_third_party_event_rules()
third_party_rules._check_can_shutdown_room_callbacks.append(
shutdown_mock,
)

# Register an admin user.
admin_user_id = self.register_user("admin", "password", admin=True)
admin_tok = self.login("admin", "password")

# Shutdown the room.
channel = self.make_request(
"DELETE",
"/_synapse/admin/v2/rooms/%s" % self.room_id,
{},
access_token=admin_tok,
)

# Check that the shutdown was blocked
self.assertEqual(channel.code, 403, channel.json_body)

# Check that the mock was called once.
shutdown_mock.assert_called_once()
args = shutdown_mock.call_args[0]

# Check that the mock was called with the right user ID
self.assertEqual(args[0], admin_user_id)

# Check that the mock was called with the right room ID
self.assertEqual(args[1], self.room_id)