Merge pull request #5119 from matrix-org/rav/admin_api_urls

Move the admin API to `/_synapse/admin/v1`
This commit is contained in:
Richard van der Hoff 2019-05-02 10:11:59 +01:00 committed by GitHub
commit 1df2f80367
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 180 additions and 114 deletions

1
changelog.d/5119.feature Normal file
View File

@ -0,0 +1 @@
Move admin APIs to `/_synapse/admin/v1`. (The old paths are retained for backwards-compatibility, for now).

View File

@ -13,7 +13,7 @@ This API extends the validity of an account by as much time as configured in the
The API is:: The API is::
POST /_matrix/client/unstable/admin/account_validity/validity POST /_synapse/admin/v1/account_validity/validity
with the following body: with the following body:

View File

@ -8,7 +8,7 @@ being deleted.
The API is: The API is:
``` ```
POST /_matrix/client/r0/admin/delete_group/<group_id> POST /_synapse/admin/v1/delete_group/<group_id>
``` ```
including an `access_token` of a server admin. including an `access_token` of a server admin.

View File

@ -4,7 +4,7 @@ This API gets a list of known media in a room.
The API is: The API is:
``` ```
GET /_matrix/client/r0/admin/room/<room_id>/media GET /_synapse/admin/v1/room/<room_id>/media
``` ```
including an `access_token` of a server admin. including an `access_token` of a server admin.

View File

@ -10,7 +10,7 @@ paginate further back in the room from the point being purged from.
The API is: The API is:
``POST /_matrix/client/r0/admin/purge_history/<room_id>[/<event_id>]`` ``POST /_synapse/admin/v1/purge_history/<room_id>[/<event_id>]``
including an ``access_token`` of a server admin. including an ``access_token`` of a server admin.
@ -49,7 +49,7 @@ Purge status query
It is possible to poll for updates on recent purges with a second API; It is possible to poll for updates on recent purges with a second API;
``GET /_matrix/client/r0/admin/purge_history_status/<purge_id>`` ``GET /_synapse/admin/v1/purge_history_status/<purge_id>``
(again, with a suitable ``access_token``). This API returns a JSON body like (again, with a suitable ``access_token``). This API returns a JSON body like
the following: the following:

View File

@ -6,7 +6,7 @@ media.
The API is:: The API is::
POST /_matrix/client/r0/admin/purge_media_cache?before_ts=<unix_timestamp_in_ms>&access_token=<access_token> POST /_synapse/admin/v1/purge_media_cache?before_ts=<unix_timestamp_in_ms>&access_token=<access_token>
{} {}

View File

@ -12,7 +12,7 @@ is not enabled.
To fetch the nonce, you need to request one from the API:: To fetch the nonce, you need to request one from the API::
> GET /_matrix/client/r0/admin/register > GET /_synapse/admin/v1/register
< {"nonce": "thisisanonce"} < {"nonce": "thisisanonce"}
@ -22,7 +22,7 @@ body containing the nonce, username, password, whether they are an admin
As an example:: As an example::
> POST /_matrix/client/r0/admin/register > POST /_synapse/admin/v1/register
> { > {
"nonce": "thisisanonce", "nonce": "thisisanonce",
"username": "pepper_roni", "username": "pepper_roni",

View File

@ -5,7 +5,7 @@ This API returns information about a specific user account.
The api is:: The api is::
GET /_matrix/client/r0/admin/whois/<user_id> GET /_synapse/admin/v1/whois/<user_id>
including an ``access_token`` of a server admin. including an ``access_token`` of a server admin.
@ -50,7 +50,7 @@ references to it).
The api is:: The api is::
POST /_matrix/client/r0/admin/deactivate/<user_id> POST /_synapse/admin/v1/deactivate/<user_id>
with a body of: with a body of:
@ -73,7 +73,7 @@ Changes the password of another user.
The api is:: The api is::
POST /_matrix/client/r0/admin/reset_password/<user_id> POST /_synapse/admin/v1/reset_password/<user_id>
with a body of: with a body of:

View File

@ -8,7 +8,7 @@ contains Synapse version information).
The api is:: The api is::
GET /_matrix/client/r0/admin/server_version GET /_synapse/admin/v1/server_version
including an ``access_token`` of a server admin. including an ``access_token`` of a server admin.

View File

@ -136,8 +136,8 @@ pid_file: DATADIR/homeserver.pid
# #
# Valid resource names are: # Valid resource names are:
# #
# client: the client-server API (/_matrix/client). Also implies 'media' and # client: the client-server API (/_matrix/client), and the synapse admin
# 'static'. # API (/_synapse/admin). Also implies 'media' and 'static'.
# #
# consent: user consent forms (/_matrix/consent). See # consent: user consent forms (/_matrix/consent). See
# docs/consent_tracking.md. # docs/consent_tracking.md.

View File

@ -62,6 +62,7 @@ from synapse.python_dependencies import check_requirements
from synapse.replication.http import REPLICATION_PREFIX, ReplicationRestResource from synapse.replication.http import REPLICATION_PREFIX, ReplicationRestResource
from synapse.replication.tcp.resource import ReplicationStreamProtocolFactory from synapse.replication.tcp.resource import ReplicationStreamProtocolFactory
from synapse.rest import ClientRestResource from synapse.rest import ClientRestResource
from synapse.rest.admin import AdminRestResource
from synapse.rest.key.v2 import KeyApiV2Resource from synapse.rest.key.v2 import KeyApiV2Resource
from synapse.rest.media.v0.content_repository import ContentRepoResource from synapse.rest.media.v0.content_repository import ContentRepoResource
from synapse.rest.well_known import WellKnownResource from synapse.rest.well_known import WellKnownResource
@ -180,6 +181,7 @@ class SynapseHomeServer(HomeServer):
"/_matrix/client/v2_alpha": client_resource, "/_matrix/client/v2_alpha": client_resource,
"/_matrix/client/versions": client_resource, "/_matrix/client/versions": client_resource,
"/.well-known/matrix/client": WellKnownResource(self), "/.well-known/matrix/client": WellKnownResource(self),
"/_synapse/admin": AdminRestResource(self),
}) })
if self.get_config().saml2_enabled: if self.get_config().saml2_enabled:

View File

@ -388,8 +388,8 @@ class ServerConfig(Config):
# #
# Valid resource names are: # Valid resource names are:
# #
# client: the client-server API (/_matrix/client). Also implies 'media' and # client: the client-server API (/_matrix/client), and the synapse admin
# 'static'. # API (/_synapse/admin). Also implies 'media' and 'static'.
# #
# consent: user consent forms (/_matrix/consent). See # consent: user consent forms (/_matrix/consent). See
# docs/consent_tracking.md. # docs/consent_tracking.md.

View File

@ -13,11 +13,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import synapse.rest.admin
from synapse.http.server import JsonResource from synapse.http.server import JsonResource
from synapse.rest.client import versions from synapse.rest.client import versions
from synapse.rest.client.v1 import ( from synapse.rest.client.v1 import (
admin,
directory, directory,
events, events,
initial_sync, initial_sync,
@ -58,8 +57,14 @@ from synapse.rest.client.v2_alpha import (
class ClientRestResource(JsonResource): class ClientRestResource(JsonResource):
"""A resource for version 1 of the matrix client API.""" """Matrix Client API REST resource.
This gets mounted at various points under /_matrix/client, including:
* /_matrix/client/r0
* /_matrix/client/api/v1
* /_matrix/client/unstable
* etc
"""
def __init__(self, hs): def __init__(self, hs):
JsonResource.__init__(self, hs, canonical_json=False) JsonResource.__init__(self, hs, canonical_json=False)
self.register_servlets(self, hs) self.register_servlets(self, hs)
@ -82,7 +87,6 @@ class ClientRestResource(JsonResource):
presence.register_servlets(hs, client_resource) presence.register_servlets(hs, client_resource)
directory.register_servlets(hs, client_resource) directory.register_servlets(hs, client_resource)
voip.register_servlets(hs, client_resource) voip.register_servlets(hs, client_resource)
admin.register_servlets(hs, client_resource)
pusher.register_servlets(hs, client_resource) pusher.register_servlets(hs, client_resource)
push_rule.register_servlets(hs, client_resource) push_rule.register_servlets(hs, client_resource)
logout.register_servlets(hs, client_resource) logout.register_servlets(hs, client_resource)
@ -111,3 +115,6 @@ class ClientRestResource(JsonResource):
room_upgrade_rest_servlet.register_servlets(hs, client_resource) room_upgrade_rest_servlet.register_servlets(hs, client_resource)
capabilities.register_servlets(hs, client_resource) capabilities.register_servlets(hs, client_resource)
account_validity.register_servlets(hs, client_resource) account_validity.register_servlets(hs, client_resource)
# moving to /_synapse/admin
synapse.rest.admin.register_servlets(hs, client_resource)

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2014-2016 OpenMarket Ltd # Copyright 2014-2016 OpenMarket Ltd
# Copyright 2018 New Vector Ltd # Copyright 2018-2019 New Vector Ltd
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ import hashlib
import hmac import hmac
import logging import logging
import platform import platform
import re
from six import text_type from six import text_type
from six.moves import http_client from six.moves import http_client
@ -27,7 +28,9 @@ from twisted.internet import defer
import synapse import synapse
from synapse.api.constants import Membership, UserTypes from synapse.api.constants import Membership, UserTypes
from synapse.api.errors import AuthError, Codes, NotFoundError, SynapseError from synapse.api.errors import AuthError, Codes, NotFoundError, SynapseError
from synapse.http.server import JsonResource
from synapse.http.servlet import ( from synapse.http.servlet import (
RestServlet,
assert_params_in_dict, assert_params_in_dict,
parse_integer, parse_integer,
parse_json_object_from_request, parse_json_object_from_request,
@ -36,16 +39,37 @@ from synapse.http.servlet import (
from synapse.types import UserID, create_requester from synapse.types import UserID, create_requester
from synapse.util.versionstring import get_version_string from synapse.util.versionstring import get_version_string
from .base import ClientV1RestServlet, client_path_patterns
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class UsersRestServlet(ClientV1RestServlet): def historical_admin_path_patterns(path_regex):
PATTERNS = client_path_patterns("/admin/users/(?P<user_id>[^/]*)") """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 list(
re.compile(prefix + path_regex)
for prefix in (
"^/_synapse/admin/v1",
"^/_matrix/client/api/v1/admin",
"^/_matrix/client/unstable/admin",
"^/_matrix/client/r0/admin"
)
)
class UsersRestServlet(RestServlet):
PATTERNS = historical_admin_path_patterns("/users/(?P<user_id>[^/]*)")
def __init__(self, hs): def __init__(self, hs):
super(UsersRestServlet, self).__init__(hs) self.hs = hs
self.auth = hs.get_auth()
self.handlers = hs.get_handlers() self.handlers = hs.get_handlers()
@defer.inlineCallbacks @defer.inlineCallbacks
@ -69,8 +93,11 @@ class UsersRestServlet(ClientV1RestServlet):
defer.returnValue((200, ret)) defer.returnValue((200, ret))
class VersionServlet(ClientV1RestServlet): class VersionServlet(RestServlet):
PATTERNS = client_path_patterns("/admin/server_version") PATTERNS = historical_admin_path_patterns("/server_version")
def __init__(self, hs):
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_GET(self, request): def on_GET(self, request):
@ -88,18 +115,17 @@ class VersionServlet(ClientV1RestServlet):
defer.returnValue((200, ret)) defer.returnValue((200, ret))
class UserRegisterServlet(ClientV1RestServlet): class UserRegisterServlet(RestServlet):
""" """
Attributes: Attributes:
NONCE_TIMEOUT (int): Seconds until a generated nonce won't be accepted NONCE_TIMEOUT (int): Seconds until a generated nonce won't be accepted
nonces (dict[str, int]): The nonces that we will accept. A dict of nonces (dict[str, int]): The nonces that we will accept. A dict of
nonce to the time it was generated, in int seconds. nonce to the time it was generated, in int seconds.
""" """
PATTERNS = client_path_patterns("/admin/register") PATTERNS = historical_admin_path_patterns("/register")
NONCE_TIMEOUT = 60 NONCE_TIMEOUT = 60
def __init__(self, hs): def __init__(self, hs):
super(UserRegisterServlet, self).__init__(hs)
self.handlers = hs.get_handlers() self.handlers = hs.get_handlers()
self.reactor = hs.get_reactor() self.reactor = hs.get_reactor()
self.nonces = {} self.nonces = {}
@ -226,11 +252,12 @@ class UserRegisterServlet(ClientV1RestServlet):
defer.returnValue((200, result)) defer.returnValue((200, result))
class WhoisRestServlet(ClientV1RestServlet): class WhoisRestServlet(RestServlet):
PATTERNS = client_path_patterns("/admin/whois/(?P<user_id>[^/]*)") PATTERNS = historical_admin_path_patterns("/whois/(?P<user_id>[^/]*)")
def __init__(self, hs): def __init__(self, hs):
super(WhoisRestServlet, self).__init__(hs) self.hs = hs
self.auth = hs.get_auth()
self.handlers = hs.get_handlers() self.handlers = hs.get_handlers()
@defer.inlineCallbacks @defer.inlineCallbacks
@ -251,12 +278,12 @@ class WhoisRestServlet(ClientV1RestServlet):
defer.returnValue((200, ret)) defer.returnValue((200, ret))
class PurgeMediaCacheRestServlet(ClientV1RestServlet): class PurgeMediaCacheRestServlet(RestServlet):
PATTERNS = client_path_patterns("/admin/purge_media_cache") PATTERNS = historical_admin_path_patterns("/purge_media_cache")
def __init__(self, hs): def __init__(self, hs):
self.media_repository = hs.get_media_repository() self.media_repository = hs.get_media_repository()
super(PurgeMediaCacheRestServlet, self).__init__(hs) self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_POST(self, request): def on_POST(self, request):
@ -274,9 +301,9 @@ class PurgeMediaCacheRestServlet(ClientV1RestServlet):
defer.returnValue((200, ret)) defer.returnValue((200, ret))
class PurgeHistoryRestServlet(ClientV1RestServlet): class PurgeHistoryRestServlet(RestServlet):
PATTERNS = client_path_patterns( PATTERNS = historical_admin_path_patterns(
"/admin/purge_history/(?P<room_id>[^/]*)(/(?P<event_id>[^/]+))?" "/purge_history/(?P<room_id>[^/]*)(/(?P<event_id>[^/]+))?"
) )
def __init__(self, hs): def __init__(self, hs):
@ -285,9 +312,9 @@ class PurgeHistoryRestServlet(ClientV1RestServlet):
Args: Args:
hs (synapse.server.HomeServer) hs (synapse.server.HomeServer)
""" """
super(PurgeHistoryRestServlet, self).__init__(hs)
self.pagination_handler = hs.get_pagination_handler() self.pagination_handler = hs.get_pagination_handler()
self.store = hs.get_datastore() self.store = hs.get_datastore()
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_POST(self, request, room_id, event_id): def on_POST(self, request, room_id, event_id):
@ -371,9 +398,9 @@ class PurgeHistoryRestServlet(ClientV1RestServlet):
})) }))
class PurgeHistoryStatusRestServlet(ClientV1RestServlet): class PurgeHistoryStatusRestServlet(RestServlet):
PATTERNS = client_path_patterns( PATTERNS = historical_admin_path_patterns(
"/admin/purge_history_status/(?P<purge_id>[^/]+)" "/purge_history_status/(?P<purge_id>[^/]+)"
) )
def __init__(self, hs): def __init__(self, hs):
@ -382,8 +409,8 @@ class PurgeHistoryStatusRestServlet(ClientV1RestServlet):
Args: Args:
hs (synapse.server.HomeServer) hs (synapse.server.HomeServer)
""" """
super(PurgeHistoryStatusRestServlet, self).__init__(hs)
self.pagination_handler = hs.get_pagination_handler() self.pagination_handler = hs.get_pagination_handler()
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_GET(self, request, purge_id): def on_GET(self, request, purge_id):
@ -400,12 +427,12 @@ class PurgeHistoryStatusRestServlet(ClientV1RestServlet):
defer.returnValue((200, purge_status.asdict())) defer.returnValue((200, purge_status.asdict()))
class DeactivateAccountRestServlet(ClientV1RestServlet): class DeactivateAccountRestServlet(RestServlet):
PATTERNS = client_path_patterns("/admin/deactivate/(?P<target_user_id>[^/]*)") PATTERNS = historical_admin_path_patterns("/deactivate/(?P<target_user_id>[^/]*)")
def __init__(self, hs): def __init__(self, hs):
super(DeactivateAccountRestServlet, self).__init__(hs)
self._deactivate_account_handler = hs.get_deactivate_account_handler() self._deactivate_account_handler = hs.get_deactivate_account_handler()
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_POST(self, request, target_user_id): def on_POST(self, request, target_user_id):
@ -438,13 +465,13 @@ class DeactivateAccountRestServlet(ClientV1RestServlet):
})) }))
class ShutdownRoomRestServlet(ClientV1RestServlet): class ShutdownRoomRestServlet(RestServlet):
"""Shuts down a room by removing all local users from the room and blocking """Shuts down a room by removing all local users from the room and blocking
all future invites and joins to the room. Any local aliases will be repointed all future invites and joins to the room. Any local aliases will be repointed
to a new room created by `new_room_user_id` and kicked users will be auto to a new room created by `new_room_user_id` and kicked users will be auto
joined to the new room. joined to the new room.
""" """
PATTERNS = client_path_patterns("/admin/shutdown_room/(?P<room_id>[^/]+)") PATTERNS = historical_admin_path_patterns("/shutdown_room/(?P<room_id>[^/]+)")
DEFAULT_MESSAGE = ( DEFAULT_MESSAGE = (
"Sharing illegal content on this server is not permitted and rooms in" "Sharing illegal content on this server is not permitted and rooms in"
@ -452,12 +479,13 @@ class ShutdownRoomRestServlet(ClientV1RestServlet):
) )
def __init__(self, hs): def __init__(self, hs):
super(ShutdownRoomRestServlet, self).__init__(hs) self.hs = hs
self.store = hs.get_datastore() self.store = hs.get_datastore()
self.state = hs.get_state_handler() self.state = hs.get_state_handler()
self._room_creation_handler = hs.get_room_creation_handler() self._room_creation_handler = hs.get_room_creation_handler()
self.event_creation_handler = hs.get_event_creation_handler() self.event_creation_handler = hs.get_event_creation_handler()
self.room_member_handler = hs.get_room_member_handler() self.room_member_handler = hs.get_room_member_handler()
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_POST(self, request, room_id): def on_POST(self, request, room_id):
@ -564,15 +592,15 @@ class ShutdownRoomRestServlet(ClientV1RestServlet):
})) }))
class QuarantineMediaInRoom(ClientV1RestServlet): class QuarantineMediaInRoom(RestServlet):
"""Quarantines all media in a room so that no one can download it via """Quarantines all media in a room so that no one can download it via
this server. this server.
""" """
PATTERNS = client_path_patterns("/admin/quarantine_media/(?P<room_id>[^/]+)") PATTERNS = historical_admin_path_patterns("/quarantine_media/(?P<room_id>[^/]+)")
def __init__(self, hs): def __init__(self, hs):
super(QuarantineMediaInRoom, self).__init__(hs)
self.store = hs.get_datastore() self.store = hs.get_datastore()
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_POST(self, request, room_id): def on_POST(self, request, room_id):
@ -588,13 +616,12 @@ class QuarantineMediaInRoom(ClientV1RestServlet):
defer.returnValue((200, {"num_quarantined": num_quarantined})) defer.returnValue((200, {"num_quarantined": num_quarantined}))
class ListMediaInRoom(ClientV1RestServlet): class ListMediaInRoom(RestServlet):
"""Lists all of the media in a given room. """Lists all of the media in a given room.
""" """
PATTERNS = client_path_patterns("/admin/room/(?P<room_id>[^/]+)/media") PATTERNS = historical_admin_path_patterns("/room/(?P<room_id>[^/]+)/media")
def __init__(self, hs): def __init__(self, hs):
super(ListMediaInRoom, self).__init__(hs)
self.store = hs.get_datastore() self.store = hs.get_datastore()
@defer.inlineCallbacks @defer.inlineCallbacks
@ -609,11 +636,11 @@ class ListMediaInRoom(ClientV1RestServlet):
defer.returnValue((200, {"local": local_mxcs, "remote": remote_mxcs})) defer.returnValue((200, {"local": local_mxcs, "remote": remote_mxcs}))
class ResetPasswordRestServlet(ClientV1RestServlet): class ResetPasswordRestServlet(RestServlet):
"""Post request to allow an administrator reset password for a user. """Post request to allow an administrator reset password for a user.
This needs user to have administrator access in Synapse. This needs user to have administrator access in Synapse.
Example: Example:
http://localhost:8008/_matrix/client/api/v1/admin/reset_password/ http://localhost:8008/_synapse/admin/v1/reset_password/
@user:to_reset_password?access_token=admin_access_token @user:to_reset_password?access_token=admin_access_token
JsonBodyToSend: JsonBodyToSend:
{ {
@ -622,11 +649,10 @@ class ResetPasswordRestServlet(ClientV1RestServlet):
Returns: Returns:
200 OK with empty object if success otherwise an error. 200 OK with empty object if success otherwise an error.
""" """
PATTERNS = client_path_patterns("/admin/reset_password/(?P<target_user_id>[^/]*)") PATTERNS = historical_admin_path_patterns("/reset_password/(?P<target_user_id>[^/]*)")
def __init__(self, hs): def __init__(self, hs):
self.store = hs.get_datastore() self.store = hs.get_datastore()
super(ResetPasswordRestServlet, self).__init__(hs)
self.hs = hs self.hs = hs
self.auth = hs.get_auth() self.auth = hs.get_auth()
self._set_password_handler = hs.get_set_password_handler() self._set_password_handler = hs.get_set_password_handler()
@ -653,20 +679,19 @@ class ResetPasswordRestServlet(ClientV1RestServlet):
defer.returnValue((200, {})) defer.returnValue((200, {}))
class GetUsersPaginatedRestServlet(ClientV1RestServlet): class GetUsersPaginatedRestServlet(RestServlet):
"""Get request to get specific number of users from Synapse. """Get request to get specific number of users from Synapse.
This needs user to have administrator access in Synapse. This needs user to have administrator access in Synapse.
Example: Example:
http://localhost:8008/_matrix/client/api/v1/admin/users_paginate/ http://localhost:8008/_synapse/admin/v1/users_paginate/
@admin:user?access_token=admin_access_token&start=0&limit=10 @admin:user?access_token=admin_access_token&start=0&limit=10
Returns: Returns:
200 OK with json object {list[dict[str, Any]], count} or empty object. 200 OK with json object {list[dict[str, Any]], count} or empty object.
""" """
PATTERNS = client_path_patterns("/admin/users_paginate/(?P<target_user_id>[^/]*)") PATTERNS = historical_admin_path_patterns("/users_paginate/(?P<target_user_id>[^/]*)")
def __init__(self, hs): def __init__(self, hs):
self.store = hs.get_datastore() self.store = hs.get_datastore()
super(GetUsersPaginatedRestServlet, self).__init__(hs)
self.hs = hs self.hs = hs
self.auth = hs.get_auth() self.auth = hs.get_auth()
self.handlers = hs.get_handlers() self.handlers = hs.get_handlers()
@ -706,7 +731,7 @@ class GetUsersPaginatedRestServlet(ClientV1RestServlet):
"""Post request to get specific number of users from Synapse.. """Post request to get specific number of users from Synapse..
This needs user to have administrator access in Synapse. This needs user to have administrator access in Synapse.
Example: Example:
http://localhost:8008/_matrix/client/api/v1/admin/users_paginate/ http://localhost:8008/_synapse/admin/v1/users_paginate/
@admin:user?access_token=admin_access_token @admin:user?access_token=admin_access_token
JsonBodyToSend: JsonBodyToSend:
{ {
@ -736,21 +761,20 @@ class GetUsersPaginatedRestServlet(ClientV1RestServlet):
defer.returnValue((200, ret)) defer.returnValue((200, ret))
class SearchUsersRestServlet(ClientV1RestServlet): class SearchUsersRestServlet(RestServlet):
"""Get request to search user table for specific users according to """Get request to search user table for specific users according to
search term. search term.
This needs user to have administrator access in Synapse. This needs user to have administrator access in Synapse.
Example: Example:
http://localhost:8008/_matrix/client/api/v1/admin/search_users/ http://localhost:8008/_synapse/admin/v1/search_users/
@admin:user?access_token=admin_access_token&term=alice @admin:user?access_token=admin_access_token&term=alice
Returns: Returns:
200 OK with json object {list[dict[str, Any]], count} or empty object. 200 OK with json object {list[dict[str, Any]], count} or empty object.
""" """
PATTERNS = client_path_patterns("/admin/search_users/(?P<target_user_id>[^/]*)") PATTERNS = historical_admin_path_patterns("/search_users/(?P<target_user_id>[^/]*)")
def __init__(self, hs): def __init__(self, hs):
self.store = hs.get_datastore() self.store = hs.get_datastore()
super(SearchUsersRestServlet, self).__init__(hs)
self.hs = hs self.hs = hs
self.auth = hs.get_auth() self.auth = hs.get_auth()
self.handlers = hs.get_handlers() self.handlers = hs.get_handlers()
@ -784,15 +808,15 @@ class SearchUsersRestServlet(ClientV1RestServlet):
defer.returnValue((200, ret)) defer.returnValue((200, ret))
class DeleteGroupAdminRestServlet(ClientV1RestServlet): class DeleteGroupAdminRestServlet(RestServlet):
"""Allows deleting of local groups """Allows deleting of local groups
""" """
PATTERNS = client_path_patterns("/admin/delete_group/(?P<group_id>[^/]*)") PATTERNS = historical_admin_path_patterns("/delete_group/(?P<group_id>[^/]*)")
def __init__(self, hs): def __init__(self, hs):
super(DeleteGroupAdminRestServlet, self).__init__(hs)
self.group_server = hs.get_groups_server_handler() self.group_server = hs.get_groups_server_handler()
self.is_mine_id = hs.is_mine_id self.is_mine_id = hs.is_mine_id
self.auth = hs.get_auth()
@defer.inlineCallbacks @defer.inlineCallbacks
def on_POST(self, request, group_id): def on_POST(self, request, group_id):
@ -809,16 +833,14 @@ class DeleteGroupAdminRestServlet(ClientV1RestServlet):
defer.returnValue((200, {})) defer.returnValue((200, {}))
class AccountValidityRenewServlet(ClientV1RestServlet): class AccountValidityRenewServlet(RestServlet):
PATTERNS = client_path_patterns("/admin/account_validity/validity$") PATTERNS = historical_admin_path_patterns("/account_validity/validity$")
def __init__(self, hs): def __init__(self, hs):
""" """
Args: Args:
hs (synapse.server.HomeServer): server hs (synapse.server.HomeServer): server
""" """
super(AccountValidityRenewServlet, self).__init__(hs)
self.hs = hs self.hs = hs
self.account_activity_handler = hs.get_account_validity_handler() self.account_activity_handler = hs.get_account_validity_handler()
self.auth = hs.get_auth() self.auth = hs.get_auth()
@ -847,6 +869,14 @@ class AccountValidityRenewServlet(ClientV1RestServlet):
defer.returnValue((200, res)) defer.returnValue((200, res))
class AdminRestResource(JsonResource):
"""The REST resource which gets mounted at /_synapse/admin"""
def __init__(self, hs):
JsonResource.__init__(self, hs, canonical_json=False)
register_servlets(hs, self)
def register_servlets(hs, http_server): def register_servlets(hs, http_server):
WhoisRestServlet(hs).register(http_server) WhoisRestServlet(hs).register(http_server)
PurgeMediaCacheRestServlet(hs).register(http_server) PurgeMediaCacheRestServlet(hs).register(http_server)

View File

@ -14,8 +14,9 @@
# limitations under the License. # limitations under the License.
from mock import Mock from mock import Mock
import synapse.rest.admin
from synapse.api.constants import UserTypes from synapse.api.constants import UserTypes
from synapse.rest.client.v1 import admin, login, room from synapse.rest.client.v1 import login, room
from synapse.rest.client.v2_alpha import user_directory from synapse.rest.client.v2_alpha import user_directory
from synapse.storage.roommember import ProfileInfo from synapse.storage.roommember import ProfileInfo
@ -29,7 +30,7 @@ class UserDirectoryTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
login.register_servlets, login.register_servlets,
admin.register_servlets, synapse.rest.admin.register_servlets,
room.register_servlets, room.register_servlets,
] ]
@ -327,7 +328,7 @@ class TestUserDirSearchDisabled(unittest.HomeserverTestCase):
user_directory.register_servlets, user_directory.register_servlets,
room.register_servlets, room.register_servlets,
login.register_servlets, login.register_servlets,
admin.register_servlets, synapse.rest.admin.register_servlets,
] ]
def make_homeserver(self, reactor, clock): def make_homeserver(self, reactor, clock):

View File

@ -19,7 +19,8 @@ import pkg_resources
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
from synapse.rest.client.v1 import admin, login, room import synapse.rest.admin
from synapse.rest.client.v1 import login, room
from tests.unittest import HomeserverTestCase from tests.unittest import HomeserverTestCase
@ -33,7 +34,7 @@ class EmailPusherTests(HomeserverTestCase):
skip = "No Jinja installed" if not load_jinja2_templates else None skip = "No Jinja installed" if not load_jinja2_templates else None
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
room.register_servlets, room.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -17,7 +17,8 @@ from mock import Mock
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
from synapse.rest.client.v1 import admin, login, room import synapse.rest.admin
from synapse.rest.client.v1 import login, room
from synapse.util.logcontext import make_deferred_yieldable from synapse.util.logcontext import make_deferred_yieldable
from tests.unittest import HomeserverTestCase from tests.unittest import HomeserverTestCase
@ -32,7 +33,7 @@ class HTTPPusherTests(HomeserverTestCase):
skip = "No Jinja installed" if not load_jinja2_templates else None skip = "No Jinja installed" if not load_jinja2_templates else None
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
room.register_servlets, room.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Copyright 2019 New Vector Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

View File

@ -19,8 +19,9 @@ import json
from mock import Mock from mock import Mock
import synapse.rest.admin
from synapse.api.constants import UserTypes from synapse.api.constants import UserTypes
from synapse.rest.client.v1 import admin, events, login, room from synapse.rest.client.v1 import events, login, room
from synapse.rest.client.v2_alpha import groups from synapse.rest.client.v2_alpha import groups
from tests import unittest from tests import unittest
@ -29,7 +30,7 @@ from tests import unittest
class VersionTestCase(unittest.HomeserverTestCase): class VersionTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
] ]
@ -62,7 +63,7 @@ class VersionTestCase(unittest.HomeserverTestCase):
class UserRegisterTestCase(unittest.HomeserverTestCase): class UserRegisterTestCase(unittest.HomeserverTestCase):
servlets = [admin.register_servlets] servlets = [synapse.rest.admin.register_servlets]
def make_homeserver(self, reactor, clock): def make_homeserver(self, reactor, clock):
@ -358,7 +359,7 @@ class UserRegisterTestCase(unittest.HomeserverTestCase):
class ShutdownRoomTestCase(unittest.HomeserverTestCase): class ShutdownRoomTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
events.register_servlets, events.register_servlets,
room.register_servlets, room.register_servlets,
@ -495,7 +496,7 @@ class ShutdownRoomTestCase(unittest.HomeserverTestCase):
class DeleteGroupTestCase(unittest.HomeserverTestCase): class DeleteGroupTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
groups.register_servlets, groups.register_servlets,
] ]

View File

@ -15,8 +15,9 @@
import os import os
import synapse.rest.admin
from synapse.api.urls import ConsentURIBuilder from synapse.api.urls import ConsentURIBuilder
from synapse.rest.client.v1 import admin, login, room from synapse.rest.client.v1 import login, room
from synapse.rest.consent import consent_resource from synapse.rest.consent import consent_resource
from tests import unittest from tests import unittest
@ -31,7 +32,7 @@ except Exception:
class ConsentResourceTestCase(unittest.HomeserverTestCase): class ConsentResourceTestCase(unittest.HomeserverTestCase):
skip = "No Jinja installed" if not load_jinja2_templates else None skip = "No Jinja installed" if not load_jinja2_templates else None
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
room.register_servlets, room.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -15,7 +15,8 @@
import json import json
from synapse.rest.client.v1 import admin, login, room import synapse.rest.admin
from synapse.rest.client.v1 import login, room
from tests import unittest from tests import unittest
@ -23,7 +24,7 @@ from tests import unittest
class IdentityTestCase(unittest.HomeserverTestCase): class IdentityTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
room.register_servlets, room.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -17,7 +17,8 @@
from mock import Mock, NonCallableMock from mock import Mock, NonCallableMock
from synapse.rest.client.v1 import admin, events, login, room import synapse.rest.admin
from synapse.rest.client.v1 import events, login, room
from tests import unittest from tests import unittest
@ -28,7 +29,7 @@ class EventStreamPermissionsTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
events.register_servlets, events.register_servlets,
room.register_servlets, room.register_servlets,
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -1,6 +1,7 @@
import json import json
from synapse.rest.client.v1 import admin, login import synapse.rest.admin
from synapse.rest.client.v1 import login
from tests import unittest from tests import unittest
@ -10,7 +11,7 @@ LOGIN_URL = b"/_matrix/client/r0/login"
class LoginRestServletTestCase(unittest.HomeserverTestCase): class LoginRestServletTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -22,8 +22,9 @@ from six.moves.urllib import parse as urlparse
from twisted.internet import defer from twisted.internet import defer
import synapse.rest.admin
from synapse.api.constants import Membership from synapse.api.constants import Membership
from synapse.rest.client.v1 import admin, login, room from synapse.rest.client.v1 import login, room
from tests import unittest from tests import unittest
@ -803,7 +804,7 @@ class RoomMessageListTestCase(RoomBase):
class RoomSearchTestCase(unittest.HomeserverTestCase): class RoomSearchTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
room.register_servlets, room.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -16,8 +16,8 @@
from twisted.internet.defer import succeed from twisted.internet.defer import succeed
import synapse.rest.admin
from synapse.api.constants import LoginType from synapse.api.constants import LoginType
from synapse.rest.client.v1 import admin
from synapse.rest.client.v2_alpha import auth, register from synapse.rest.client.v2_alpha import auth, register
from tests import unittest from tests import unittest
@ -27,7 +27,7 @@ class FallbackAuthTests(unittest.HomeserverTestCase):
servlets = [ servlets = [
auth.register_servlets, auth.register_servlets,
admin.register_servlets, synapse.rest.admin.register_servlets,
register.register_servlets, register.register_servlets,
] ]
hijack_auth = False hijack_auth = False

View File

@ -12,9 +12,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import synapse.rest.admin
from synapse.api.room_versions import DEFAULT_ROOM_VERSION, KNOWN_ROOM_VERSIONS from synapse.api.room_versions import DEFAULT_ROOM_VERSION, KNOWN_ROOM_VERSIONS
from synapse.rest.client.v1 import admin, login from synapse.rest.client.v1 import login
from synapse.rest.client.v2_alpha import capabilities from synapse.rest.client.v2_alpha import capabilities
from tests import unittest from tests import unittest
@ -23,7 +23,7 @@ from tests import unittest
class CapabilitiesTestCase(unittest.HomeserverTestCase): class CapabilitiesTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
capabilities.register_servlets, capabilities.register_servlets,
login.register_servlets, login.register_servlets,
] ]

View File

@ -4,10 +4,11 @@ import os
import pkg_resources import pkg_resources
import synapse.rest.admin
from synapse.api.constants import LoginType from synapse.api.constants import LoginType
from synapse.api.errors import Codes from synapse.api.errors import Codes
from synapse.appservice import ApplicationService from synapse.appservice import ApplicationService
from synapse.rest.client.v1 import admin, login from synapse.rest.client.v1 import login
from synapse.rest.client.v2_alpha import account_validity, register, sync from synapse.rest.client.v2_alpha import account_validity, register, sync
from tests import unittest from tests import unittest
@ -198,7 +199,7 @@ class AccountValidityTestCase(unittest.HomeserverTestCase):
servlets = [ servlets = [
register.register_servlets, register.register_servlets,
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
sync.register_servlets, sync.register_servlets,
account_validity.register_servlets, account_validity.register_servlets,
@ -307,7 +308,7 @@ class AccountValidityRenewalByEmailTestCase(unittest.HomeserverTestCase):
skip = "No Jinja installed" if not load_jinja2_templates else None skip = "No Jinja installed" if not load_jinja2_templates else None
servlets = [ servlets = [
register.register_servlets, register.register_servlets,
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
sync.register_servlets, sync.register_servlets,
account_validity.register_servlets, account_validity.register_servlets,

View File

@ -15,7 +15,8 @@
from mock import Mock from mock import Mock
from synapse.rest.client.v1 import admin, login, room import synapse.rest.admin
from synapse.rest.client.v1 import login, room
from synapse.rest.client.v2_alpha import sync from synapse.rest.client.v2_alpha import sync
from tests import unittest from tests import unittest
@ -72,7 +73,7 @@ class FilterTestCase(unittest.HomeserverTestCase):
class SyncTypingTests(unittest.HomeserverTestCase): class SyncTypingTests(unittest.HomeserverTestCase):
servlets = [ servlets = [
admin.register_servlets, synapse.rest.admin.register_servlets,
room.register_servlets, room.register_servlets,
login.register_servlets, login.register_servlets,
sync.register_servlets, sync.register_servlets,

View File

@ -12,8 +12,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import synapse.rest.admin
from synapse.rest.client.v1 import admin, login, room from synapse.rest.client.v1 import login, room
from synapse.rest.client.v2_alpha import sync from synapse.rest.client.v2_alpha import sync
from tests import unittest from tests import unittest
@ -23,7 +23,7 @@ class ConsentNoticesTests(unittest.HomeserverTestCase):
servlets = [ servlets = [
sync.register_servlets, sync.register_servlets,
admin.register_servlets, synapse.rest.admin.register_servlets,
login.register_servlets, login.register_servlets,
room.register_servlets, room.register_servlets,
] ]

View File

@ -18,8 +18,9 @@ from mock import Mock
from twisted.internet import defer from twisted.internet import defer
import synapse.rest.admin
from synapse.http.site import XForwardedForRequest from synapse.http.site import XForwardedForRequest
from synapse.rest.client.v1 import admin, login from synapse.rest.client.v1 import login
from tests import unittest from tests import unittest
@ -205,7 +206,7 @@ class ClientIpStoreTestCase(unittest.HomeserverTestCase):
class ClientIpAuthTestCase(unittest.HomeserverTestCase): class ClientIpAuthTestCase(unittest.HomeserverTestCase):
servlets = [admin.register_servlets, login.register_servlets] servlets = [synapse.rest.admin.register_servlets, login.register_servlets]
def make_homeserver(self, reactor, clock): def make_homeserver(self, reactor, clock):
hs = self.setup_test_homeserver() hs = self.setup_test_homeserver()