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

Remove deprecated delete room admin API POST /_synapse/admin/v1/rooms/<room_id>/delete #11213

Merged
merged 6 commits into from
Nov 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions changelog.d/11213.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove deprecated admin API to delete rooms (`POST /_synapse/admin/v1/rooms/<room_id>/delete`).
10 changes: 0 additions & 10 deletions docs/admin_api/rooms.md
Original file line number Diff line number Diff line change
Expand Up @@ -520,16 +520,6 @@ With all that being said, if you still want to try and recover the room:
4. If `new_room_user_id` was given, a 'Content Violation' will have been
created. Consider whether you want to delete that roomm.

## Deprecated endpoint

The previous deprecated API will be removed in a future release, it was:

```
POST /_synapse/admin/v1/rooms/<room_id>/delete
```

It behaves the same way than the current endpoint except the path and the method.

# Make Room Admin API

Grants another user the highest power available to a local user who is in the room.
Expand Down
10 changes: 10 additions & 0 deletions docs/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ process, for example:

# Upgrading to v1.47.0

## Removal of old Room Admin API

The following admin APIs were deprecated in [Synapse 1.34](https://github.com/matrix-org/synapse/blob/v1.34.0/CHANGES.md#deprecations-and-removals)
(released on 2021-05-17) and have now been removed:

- `POST /_synapse/admin/v1/<room_id>/delete`

Any scripts still using the above APIs should be converted to use the
[Delete Room API](https://matrix-org.github.io/synapse/latest/admin_api/rooms.html#delete-room-api).

## Deprecation of the `user_may_create_room_with_invites` module callback

The `user_may_create_room_with_invites` is deprecated and will be removed in a future
Expand Down
2 changes: 0 additions & 2 deletions synapse/rest/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
RegistrationTokenRestServlet,
)
from synapse.rest.admin.rooms import (
DeleteRoomRestServlet,
ForwardExtremitiesRestServlet,
JoinRoomAliasServlet,
ListRoomRestServlet,
Expand Down Expand Up @@ -221,7 +220,6 @@ def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
RoomStateRestServlet(hs).register(http_server)
RoomRestServlet(hs).register(http_server)
RoomMembersRestServlet(hs).register(http_server)
DeleteRoomRestServlet(hs).register(http_server)
JoinRoomAliasServlet(hs).register(http_server)
VersionServlet(hs).register(http_server)
UserAdminServlet(hs).register(http_server)
Expand Down
141 changes: 53 additions & 88 deletions synapse/rest/admin/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,41 +46,6 @@
logger = logging.getLogger(__name__)


class DeleteRoomRestServlet(RestServlet):
"""Delete a room from server.

It is a combination and improvement of shutdown and purge room.

Shuts down a room by removing all local users from the room.
Blocking all future invites and joins to the room is optional.

If desired any local aliases will be repointed to a new room
created by `new_room_user_id` and kicked users will be auto-
joined to the new room.

If 'purge' is true, it will remove all traces of a room from the database.
"""

PATTERNS = admin_patterns("/rooms/(?P<room_id>[^/]+)/delete$")

def __init__(self, hs: "HomeServer"):
self.hs = hs
self.auth = hs.get_auth()
self.room_shutdown_handler = hs.get_room_shutdown_handler()
self.pagination_handler = hs.get_pagination_handler()

async def on_POST(
self, request: SynapseRequest, room_id: str
) -> Tuple[int, JsonDict]:
return await _delete_room(
request,
room_id,
self.auth,
self.room_shutdown_handler,
self.pagination_handler,
)


class ListRoomRestServlet(RestServlet):
"""
List all rooms that are known to the homeserver. Results are returned
Expand Down Expand Up @@ -218,14 +183,66 @@ async def on_GET(
async def on_DELETE(
self, request: SynapseRequest, room_id: str
) -> Tuple[int, JsonDict]:
return await _delete_room(
return await self._delete_room(
request,
room_id,
self.auth,
self.room_shutdown_handler,
self.pagination_handler,
)

async def _delete_room(
self,
request: SynapseRequest,
room_id: str,
auth: "Auth",
room_shutdown_handler: "RoomShutdownHandler",
pagination_handler: "PaginationHandler",
) -> Tuple[int, JsonDict]:
requester = await auth.get_user_by_req(request)
await assert_user_is_admin(auth, requester.user)

content = parse_json_object_from_request(request)

block = content.get("block", False)
if not isinstance(block, bool):
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"Param 'block' must be a boolean, if given",
Codes.BAD_JSON,
)

purge = content.get("purge", True)
if not isinstance(purge, bool):
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"Param 'purge' must be a boolean, if given",
Codes.BAD_JSON,
)

force_purge = content.get("force_purge", False)
if not isinstance(force_purge, bool):
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"Param 'force_purge' must be a boolean, if given",
Codes.BAD_JSON,
)

ret = await room_shutdown_handler.shutdown_room(
room_id=room_id,
new_room_user_id=content.get("new_room_user_id"),
new_room_name=content.get("room_name"),
message=content.get("message"),
requester_user_id=requester.user.to_string(),
block=block,
)

# Purge room
if purge:
await pagination_handler.purge_room(room_id, force=force_purge)

return 200, ret


class RoomMembersRestServlet(RestServlet):
"""
Expand Down Expand Up @@ -617,55 +634,3 @@ async def on_GET(
)

return 200, results


async def _delete_room(
request: SynapseRequest,
room_id: str,
auth: "Auth",
room_shutdown_handler: "RoomShutdownHandler",
pagination_handler: "PaginationHandler",
) -> Tuple[int, JsonDict]:
requester = await auth.get_user_by_req(request)
await assert_user_is_admin(auth, requester.user)

content = parse_json_object_from_request(request)

block = content.get("block", False)
if not isinstance(block, bool):
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"Param 'block' must be a boolean, if given",
Codes.BAD_JSON,
)

purge = content.get("purge", True)
if not isinstance(purge, bool):
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"Param 'purge' must be a boolean, if given",
Codes.BAD_JSON,
)

force_purge = content.get("force_purge", False)
if not isinstance(force_purge, bool):
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"Param 'force_purge' must be a boolean, if given",
Codes.BAD_JSON,
)

ret = await room_shutdown_handler.shutdown_room(
room_id=room_id,
new_room_user_id=content.get("new_room_user_id"),
new_room_name=content.get("room_name"),
message=content.get("message"),
requester_user_id=requester.user.to_string(),
block=block,
)

# Purge room
if purge:
await pagination_handler.purge_room(room_id, force=force_purge)

return 200, ret
39 changes: 15 additions & 24 deletions tests/rest/admin/test_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
from typing import List, Optional
from unittest.mock import Mock

from parameterized import parameterized_class

import synapse.rest.admin
from synapse.api.constants import EventTypes, Membership
from synapse.api.errors import Codes
Expand All @@ -29,13 +27,6 @@
"""Tests admin REST events for /rooms paths."""


@parameterized_class(
("method", "url_template"),
[
("POST", "/_synapse/admin/v1/rooms/%s/delete"),
("DELETE", "/_synapse/admin/v1/rooms/%s"),
],
)
class DeleteRoomTestCase(unittest.HomeserverTestCase):
servlets = [
synapse.rest.admin.register_servlets,
Expand Down Expand Up @@ -67,15 +58,15 @@ def prepare(self, reactor, clock, hs):
self.room_id = self.helper.create_room_as(
self.other_user, tok=self.other_user_tok
)
self.url = self.url_template % self.room_id
self.url = "/_synapse/admin/v1/rooms/%s" % self.room_id

def test_requester_is_no_admin(self):
"""
If the user is not a server admin, an error 403 is returned.
"""

channel = self.make_request(
self.method,
"DELETE",
self.url,
json.dumps({}),
access_token=self.other_user_tok,
Expand All @@ -88,10 +79,10 @@ def test_room_does_not_exist(self):
"""
Check that unknown rooms/server return error 404.
"""
url = self.url_template % "!unknown:test"
url = "/_synapse/admin/v1/rooms/%s" % "!unknown:test"

channel = self.make_request(
self.method,
"DELETE",
url,
json.dumps({}),
access_token=self.admin_user_tok,
Expand All @@ -104,10 +95,10 @@ def test_room_is_not_valid(self):
"""
Check that invalid room names, return an error 400.
"""
url = self.url_template % "invalidroom"
url = "/_synapse/admin/v1/rooms/%s" % "invalidroom"

channel = self.make_request(
self.method,
"DELETE",
url,
json.dumps({}),
access_token=self.admin_user_tok,
Expand All @@ -126,7 +117,7 @@ def test_new_room_user_does_not_exist(self):
body = json.dumps({"new_room_user_id": "@unknown:test"})

channel = self.make_request(
self.method,
"DELETE",
self.url,
content=body.encode(encoding="utf_8"),
access_token=self.admin_user_tok,
Expand All @@ -145,7 +136,7 @@ def test_new_room_user_is_not_local(self):
body = json.dumps({"new_room_user_id": "@not:exist.bla"})

channel = self.make_request(
self.method,
"DELETE",
self.url,
content=body.encode(encoding="utf_8"),
access_token=self.admin_user_tok,
Expand All @@ -164,7 +155,7 @@ def test_block_is_not_bool(self):
body = json.dumps({"block": "NotBool"})

channel = self.make_request(
self.method,
"DELETE",
self.url,
content=body.encode(encoding="utf_8"),
access_token=self.admin_user_tok,
Expand All @@ -180,7 +171,7 @@ def test_purge_is_not_bool(self):
body = json.dumps({"purge": "NotBool"})

channel = self.make_request(
self.method,
"DELETE",
self.url,
content=body.encode(encoding="utf_8"),
access_token=self.admin_user_tok,
Expand All @@ -206,7 +197,7 @@ def test_purge_room_and_block(self):
body = json.dumps({"block": True, "purge": True})

channel = self.make_request(
self.method,
"DELETE",
self.url.encode("ascii"),
content=body.encode(encoding="utf_8"),
access_token=self.admin_user_tok,
Expand Down Expand Up @@ -239,7 +230,7 @@ def test_purge_room_and_not_block(self):
body = json.dumps({"block": False, "purge": True})

channel = self.make_request(
self.method,
"DELETE",
self.url.encode("ascii"),
content=body.encode(encoding="utf_8"),
access_token=self.admin_user_tok,
Expand Down Expand Up @@ -273,7 +264,7 @@ def test_block_room_and_not_purge(self):
body = json.dumps({"block": False, "purge": False})

channel = self.make_request(
self.method,
"DELETE",
self.url.encode("ascii"),
content=body.encode(encoding="utf_8"),
access_token=self.admin_user_tok,
Expand Down Expand Up @@ -319,7 +310,7 @@ def test_shutdown_room_consent(self):

# Test that the admin can still send shutdown
channel = self.make_request(
self.method,
"DELETE",
self.url,
json.dumps({"new_room_user_id": self.admin_user}),
access_token=self.admin_user_tok,
Expand Down Expand Up @@ -365,7 +356,7 @@ def test_shutdown_room_block_peek(self):

# Test that the admin can still send shutdown
channel = self.make_request(
self.method,
"DELETE",
self.url,
json.dumps({"new_room_user_id": self.admin_user}),
access_token=self.admin_user_tok,
Expand Down