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

Remove old /_matrix/client/*/admin endpoints #8785

Merged
merged 6 commits into from
Nov 25, 2020
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
22 changes: 22 additions & 0 deletions UPGRADE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,28 @@ shown below:

return {"localpart": localpart}

Removal historical Synapse Admin API
------------------------------------

Historically, the Synapse Admin API has been accessible under:

* ``/_matrix/client/api/v1/admin``
* ``/_matrix/client/unstable/admin``
* ``/_matrix/client/r0/admin``
* ``/_synapse/admin/v1``

The endpoints with ``/_matrix/client/*`` prefixes have been removed as of v1.24.0.
The Admin API is now only accessible under:

* ``/_synapse/admin/v1``

The only exception is the `/admin/whois` endpoint, which is
`also available via the client-server API <https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-admin-whois-userid>`_.

The deprecation of the old endpoints was announced with Synapse 1.20.0 (released
on 2020-09-22) and makes it easier for homeserver admins to lock down external
access to the Admin API endpoints.

Upgrading to v1.23.0
====================

Expand Down
1 change: 1 addition & 0 deletions changelog.d/8785.removal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove old `/_matrix/client/*/admin` endpoints which was deprecated since Synapse 1.20.0.
7 changes: 7 additions & 0 deletions docs/admin_api/user_admin_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ The api is::

GET /_synapse/admin/v1/whois/<user_id>

and::

GET /_matrix/client/r0/admin/whois/<userId>

See also: `Client Server API Whois
<https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-admin-whois-userid>`_

To use it, you will need to authenticate by providing an ``access_token`` for a
server admin: see `README.rst <README.rst>`_.

Expand Down
2 changes: 1 addition & 1 deletion synapse/_scripts/register_new_matrix_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def request_registration(
exit=sys.exit,
):

url = "%s/_matrix/client/r0/admin/register" % (server_location,)
url = "%s/_synapse/admin/v1/register" % (server_location,)

# Get the nonce
r = requests.get(url, verify=False)
Expand Down
12 changes: 3 additions & 9 deletions synapse/rest/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@
from synapse.api.errors import Codes, NotFoundError, SynapseError
from synapse.http.server import JsonResource
from synapse.http.servlet import RestServlet, parse_json_object_from_request
from synapse.rest.admin._base import (
admin_patterns,
assert_requester_is_admin,
historical_admin_path_patterns,
)
from synapse.rest.admin._base import admin_patterns, assert_requester_is_admin
from synapse.rest.admin.devices import (
DeleteDevicesRestServlet,
DeviceRestServlet,
Expand Down Expand Up @@ -84,7 +80,7 @@ def on_GET(self, request):


class PurgeHistoryRestServlet(RestServlet):
PATTERNS = historical_admin_path_patterns(
PATTERNS = admin_patterns(
"/purge_history/(?P<room_id>[^/]*)(/(?P<event_id>[^/]+))?"
)

Expand Down Expand Up @@ -169,9 +165,7 @@ async def on_POST(self, request, room_id, event_id):


class PurgeHistoryStatusRestServlet(RestServlet):
PATTERNS = historical_admin_path_patterns(
"/purge_history_status/(?P<purge_id>[^/]+)"
)
PATTERNS = admin_patterns("/purge_history_status/(?P<purge_id>[^/]+)")

def __init__(self, hs):
"""
Expand Down
22 changes: 0 additions & 22 deletions synapse/rest/admin/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,6 @@
from synapse.types import UserID


def historical_admin_path_patterns(path_regex):
"""Returns the list of patterns for an admin endpoint, including historical ones

This is a backwards-compatibility hack. Previously, the Admin API was exposed at
various paths under /_matrix/client. This function returns a list of patterns
matching those paths (as well as the new one), so that existing scripts which rely
on the endpoints being available there are not broken.

Note that this should only be used for existing endpoints: new ones should just
register for the /_synapse/admin path.
"""
return [
re.compile(prefix + path_regex)
for prefix in (
"^/_synapse/admin/v1",
"^/_matrix/client/api/v1/admin",
"^/_matrix/client/unstable/admin",
"^/_matrix/client/r0/admin",
)
]


def admin_patterns(path_regex: str, version: str = "v1"):
"""Returns the list of patterns for an admin endpoint

Expand Down
7 changes: 2 additions & 5 deletions synapse/rest/admin/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@

from synapse.api.errors import SynapseError
from synapse.http.servlet import RestServlet
from synapse.rest.admin._base import (
assert_user_is_admin,
historical_admin_path_patterns,
)
from synapse.rest.admin._base import admin_patterns, assert_user_is_admin

logger = logging.getLogger(__name__)

Expand All @@ -28,7 +25,7 @@ class DeleteGroupAdminRestServlet(RestServlet):
"""Allows deleting of local groups
"""

PATTERNS = historical_admin_path_patterns("/delete_group/(?P<group_id>[^/]*)")
PATTERNS = admin_patterns("/delete_group/(?P<group_id>[^/]*)")

def __init__(self, hs):
self.group_server = hs.get_groups_server_handler()
Expand Down
15 changes: 6 additions & 9 deletions synapse/rest/admin/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
admin_patterns,
assert_requester_is_admin,
assert_user_is_admin,
historical_admin_path_patterns,
)

logger = logging.getLogger(__name__)
Expand All @@ -34,10 +33,10 @@ class QuarantineMediaInRoom(RestServlet):
"""

PATTERNS = (
historical_admin_path_patterns("/room/(?P<room_id>[^/]+)/media/quarantine")
admin_patterns("/room/(?P<room_id>[^/]+)/media/quarantine")
+
# This path kept around for legacy reasons
historical_admin_path_patterns("/quarantine_media/(?P<room_id>[^/]+)")
admin_patterns("/quarantine_media/(?P<room_id>[^/]+)")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably something else to deprecate at some point, but no real rush on that (and out of scope for this pull request).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It is a task for an other PR.

)

def __init__(self, hs):
Expand All @@ -63,9 +62,7 @@ class QuarantineMediaByUser(RestServlet):
this server.
"""

PATTERNS = historical_admin_path_patterns(
"/user/(?P<user_id>[^/]+)/media/quarantine"
)
PATTERNS = admin_patterns("/user/(?P<user_id>[^/]+)/media/quarantine")

def __init__(self, hs):
self.store = hs.get_datastore()
Expand All @@ -90,7 +87,7 @@ class QuarantineMediaByID(RestServlet):
it via this server.
"""

PATTERNS = historical_admin_path_patterns(
PATTERNS = admin_patterns(
"/media/quarantine/(?P<server_name>[^/]+)/(?P<media_id>[^/]+)"
)

Expand All @@ -116,7 +113,7 @@ class ListMediaInRoom(RestServlet):
"""Lists all of the media in a given room.
"""

PATTERNS = historical_admin_path_patterns("/room/(?P<room_id>[^/]+)/media")
PATTERNS = admin_patterns("/room/(?P<room_id>[^/]+)/media")

def __init__(self, hs):
self.store = hs.get_datastore()
Expand All @@ -134,7 +131,7 @@ async def on_GET(self, request, room_id):


class PurgeMediaCacheRestServlet(RestServlet):
PATTERNS = historical_admin_path_patterns("/purge_media_cache")
PATTERNS = admin_patterns("/purge_media_cache")

def __init__(self, hs):
self.media_repository = hs.get_media_repository()
Expand Down
3 changes: 1 addition & 2 deletions synapse/rest/admin/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
admin_patterns,
assert_requester_is_admin,
assert_user_is_admin,
historical_admin_path_patterns,
)
from synapse.storage.databases.main.room import RoomSortOrder
from synapse.types import RoomAlias, RoomID, UserID, create_requester
Expand All @@ -44,7 +43,7 @@ class ShutdownRoomRestServlet(RestServlet):
joined to the new room.
"""

PATTERNS = historical_admin_path_patterns("/shutdown_room/(?P<room_id>[^/]+)")
PATTERNS = admin_patterns("/shutdown_room/(?P<room_id>[^/]+)")

def __init__(self, hs):
self.hs = hs
Expand Down
25 changes: 15 additions & 10 deletions synapse/rest/admin/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
admin_patterns,
assert_requester_is_admin,
assert_user_is_admin,
historical_admin_path_patterns,
)
from synapse.rest.client.v2_alpha._base import client_patterns
from synapse.types import JsonDict, UserID

if TYPE_CHECKING:
Expand All @@ -55,7 +55,7 @@


class UsersRestServlet(RestServlet):
PATTERNS = historical_admin_path_patterns("/users/(?P<user_id>[^/]*)$")
PATTERNS = admin_patterns("/users/(?P<user_id>[^/]*)$")

def __init__(self, hs):
self.hs = hs
Expand Down Expand Up @@ -338,7 +338,7 @@ class UserRegisterServlet(RestServlet):
nonce to the time it was generated, in int seconds.
"""

PATTERNS = historical_admin_path_patterns("/register")
PATTERNS = admin_patterns("/register")
NONCE_TIMEOUT = 60

def __init__(self, hs):
Expand Down Expand Up @@ -461,7 +461,14 @@ async def on_POST(self, request):


class WhoisRestServlet(RestServlet):
PATTERNS = historical_admin_path_patterns("/whois/(?P<user_id>[^/]*)")
path_regex = "/whois/(?P<user_id>[^/]*)$"
PATTERNS = (
admin_patterns(path_regex)
+
# URL for spec reason
# https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-admin-whois-userid
client_patterns("/admin" + path_regex, v1=True)
)

def __init__(self, hs):
self.hs = hs
Expand All @@ -485,7 +492,7 @@ async def on_GET(self, request, user_id):


class DeactivateAccountRestServlet(RestServlet):
PATTERNS = historical_admin_path_patterns("/deactivate/(?P<target_user_id>[^/]*)")
PATTERNS = admin_patterns("/deactivate/(?P<target_user_id>[^/]*)")

def __init__(self, hs):
self._deactivate_account_handler = hs.get_deactivate_account_handler()
Expand Down Expand Up @@ -516,7 +523,7 @@ async def on_POST(self, request, target_user_id):


class AccountValidityRenewServlet(RestServlet):
PATTERNS = historical_admin_path_patterns("/account_validity/validity$")
PATTERNS = admin_patterns("/account_validity/validity$")

def __init__(self, hs):
"""
Expand Down Expand Up @@ -559,9 +566,7 @@ class ResetPasswordRestServlet(RestServlet):
200 OK with empty object if success otherwise an error.
"""

PATTERNS = historical_admin_path_patterns(
"/reset_password/(?P<target_user_id>[^/]*)"
)
PATTERNS = admin_patterns("/reset_password/(?P<target_user_id>[^/]*)")

def __init__(self, hs):
self.store = hs.get_datastore()
Expand Down Expand Up @@ -603,7 +608,7 @@ class SearchUsersRestServlet(RestServlet):
200 OK with json object {list[dict[str, Any]], count} or empty object.
"""

PATTERNS = historical_admin_path_patterns("/search_users/(?P<target_user_id>[^/]*)")
PATTERNS = admin_patterns("/search_users/(?P<target_user_id>[^/]*)")

def __init__(self, hs):
self.hs = hs
Expand Down
2 changes: 1 addition & 1 deletion tests/rest/admin/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def test_delete_group(self):
self.assertIn(group_id, self._get_groups_user_is_in(self.other_user_token))

# Now delete the group
url = "/admin/delete_group/" + group_id
url = "/_synapse/admin/v1/delete_group/" + group_id
request, channel = self.make_request(
"POST",
url.encode("ascii"),
Expand Down
4 changes: 2 additions & 2 deletions tests/rest/admin/test_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_shutdown_room_consent(self):
)

# Test that the admin can still send shutdown
url = "admin/shutdown_room/" + room_id
url = "/_synapse/admin/v1/shutdown_room/" + room_id
request, channel = self.make_request(
"POST",
url.encode("ascii"),
Expand Down Expand Up @@ -112,7 +112,7 @@ def test_shutdown_room_block_peek(self):
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])

# Test that the admin can still send shutdown
url = "admin/shutdown_room/" + room_id
url = "/_synapse/admin/v1/shutdown_room/" + room_id
request, channel = self.make_request(
"POST",
url.encode("ascii"),
Expand Down
Loading