mirror of
https://mau.dev/maunium/synapse.git
synced 2024-09-27 20:19:03 +02:00
Implement GET /_matrix/client/r0/rooms/{roomId}/aliases (#6939)
per matrix-org/matrix-doc#2432
This commit is contained in:
parent
3f1cd14791
commit
adfaea8c69
5 changed files with 128 additions and 11 deletions
1
changelog.d/6939.feature
Normal file
1
changelog.d/6939.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Implement `GET /_matrix/client/r0/rooms/{roomId}/aliases` endpoint as per [MSC2432](https://github.com/matrix-org/matrix-doc/pull/2432).
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import string
|
import string
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ from synapse.api.errors import (
|
||||||
StoreError,
|
StoreError,
|
||||||
SynapseError,
|
SynapseError,
|
||||||
)
|
)
|
||||||
from synapse.types import RoomAlias, UserID, get_domain_from_id
|
from synapse.types import Requester, RoomAlias, UserID, get_domain_from_id
|
||||||
|
|
||||||
from ._base import BaseHandler
|
from ._base import BaseHandler
|
||||||
|
|
||||||
|
@ -452,3 +453,17 @@ class DirectoryHandler(BaseHandler):
|
||||||
yield self.store.set_room_is_public_appservice(
|
yield self.store.set_room_is_public_appservice(
|
||||||
room_id, appservice_id, network_id, visibility == "public"
|
room_id, appservice_id, network_id, visibility == "public"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def get_aliases_for_room(
|
||||||
|
self, requester: Requester, room_id: str
|
||||||
|
) -> List[str]:
|
||||||
|
"""
|
||||||
|
Get a list of the aliases that currently point to this room on this server
|
||||||
|
"""
|
||||||
|
# allow access to server admins and current members of the room
|
||||||
|
is_admin = await self.auth.is_server_admin(requester.user)
|
||||||
|
if not is_admin:
|
||||||
|
await self.auth.check_joined_room(room_id, requester.user.to_string())
|
||||||
|
|
||||||
|
aliases = await self.store.get_aliases_for_room(room_id)
|
||||||
|
return aliases
|
||||||
|
|
|
@ -45,6 +45,10 @@ from synapse.storage.state import StateFilter
|
||||||
from synapse.streams.config import PaginationConfig
|
from synapse.streams.config import PaginationConfig
|
||||||
from synapse.types import RoomAlias, RoomID, StreamToken, ThirdPartyInstanceID, UserID
|
from synapse.types import RoomAlias, RoomID, StreamToken, ThirdPartyInstanceID, UserID
|
||||||
|
|
||||||
|
MYPY = False
|
||||||
|
if MYPY:
|
||||||
|
import synapse.server
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -843,6 +847,24 @@ class RoomTypingRestServlet(RestServlet):
|
||||||
return 200, {}
|
return 200, {}
|
||||||
|
|
||||||
|
|
||||||
|
class RoomAliasListServlet(RestServlet):
|
||||||
|
PATTERNS = client_patterns("/rooms/(?P<room_id>[^/]*)/aliases", unstable=False)
|
||||||
|
|
||||||
|
def __init__(self, hs: "synapse.server.HomeServer"):
|
||||||
|
super().__init__()
|
||||||
|
self.auth = hs.get_auth()
|
||||||
|
self.directory_handler = hs.get_handlers().directory_handler
|
||||||
|
|
||||||
|
async def on_GET(self, request, room_id):
|
||||||
|
requester = await self.auth.get_user_by_req(request)
|
||||||
|
|
||||||
|
alias_list = await self.directory_handler.get_aliases_for_room(
|
||||||
|
requester, room_id
|
||||||
|
)
|
||||||
|
|
||||||
|
return 200, {"aliases": alias_list}
|
||||||
|
|
||||||
|
|
||||||
class SearchRestServlet(RestServlet):
|
class SearchRestServlet(RestServlet):
|
||||||
PATTERNS = client_patterns("/search$", v1=True)
|
PATTERNS = client_patterns("/search$", v1=True)
|
||||||
|
|
||||||
|
@ -931,6 +953,7 @@ def register_servlets(hs, http_server):
|
||||||
JoinedRoomsRestServlet(hs).register(http_server)
|
JoinedRoomsRestServlet(hs).register(http_server)
|
||||||
RoomEventServlet(hs).register(http_server)
|
RoomEventServlet(hs).register(http_server)
|
||||||
RoomEventContextServlet(hs).register(http_server)
|
RoomEventContextServlet(hs).register(http_server)
|
||||||
|
RoomAliasListServlet(hs).register(http_server)
|
||||||
|
|
||||||
|
|
||||||
def register_deprecated_servlets(hs, http_server):
|
def register_deprecated_servlets(hs, http_server):
|
||||||
|
|
|
@ -28,8 +28,9 @@ from twisted.internet import defer
|
||||||
import synapse.rest.admin
|
import synapse.rest.admin
|
||||||
from synapse.api.constants import EventContentFields, EventTypes, Membership
|
from synapse.api.constants import EventContentFields, EventTypes, Membership
|
||||||
from synapse.handlers.pagination import PurgeStatus
|
from synapse.handlers.pagination import PurgeStatus
|
||||||
from synapse.rest.client.v1 import login, profile, room
|
from synapse.rest.client.v1 import directory, login, profile, room
|
||||||
from synapse.rest.client.v2_alpha import account
|
from synapse.rest.client.v2_alpha import account
|
||||||
|
from synapse.types import JsonDict, RoomAlias
|
||||||
from synapse.util.stringutils import random_string
|
from synapse.util.stringutils import random_string
|
||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
@ -1726,3 +1727,70 @@ class ContextTestCase(unittest.HomeserverTestCase):
|
||||||
self.assertEqual(len(events_after), 2, events_after)
|
self.assertEqual(len(events_after), 2, events_after)
|
||||||
self.assertDictEqual(events_after[0].get("content"), {}, events_after[0])
|
self.assertDictEqual(events_after[0].get("content"), {}, events_after[0])
|
||||||
self.assertEqual(events_after[1].get("content"), {}, events_after[1])
|
self.assertEqual(events_after[1].get("content"), {}, events_after[1])
|
||||||
|
|
||||||
|
|
||||||
|
class DirectoryTestCase(unittest.HomeserverTestCase):
|
||||||
|
|
||||||
|
servlets = [
|
||||||
|
synapse.rest.admin.register_servlets_for_client_rest_resource,
|
||||||
|
directory.register_servlets,
|
||||||
|
login.register_servlets,
|
||||||
|
room.register_servlets,
|
||||||
|
]
|
||||||
|
|
||||||
|
def prepare(self, reactor, clock, homeserver):
|
||||||
|
self.room_owner = self.register_user("room_owner", "test")
|
||||||
|
self.room_owner_tok = self.login("room_owner", "test")
|
||||||
|
|
||||||
|
self.room_id = self.helper.create_room_as(
|
||||||
|
self.room_owner, tok=self.room_owner_tok
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_no_aliases(self):
|
||||||
|
res = self._get_aliases(self.room_owner_tok)
|
||||||
|
self.assertEqual(res["aliases"], [])
|
||||||
|
|
||||||
|
def test_not_in_room(self):
|
||||||
|
self.register_user("user", "test")
|
||||||
|
user_tok = self.login("user", "test")
|
||||||
|
res = self._get_aliases(user_tok, expected_code=403)
|
||||||
|
self.assertEqual(res["errcode"], "M_FORBIDDEN")
|
||||||
|
|
||||||
|
def test_with_aliases(self):
|
||||||
|
alias1 = self._random_alias()
|
||||||
|
alias2 = self._random_alias()
|
||||||
|
|
||||||
|
self._set_alias_via_directory(alias1)
|
||||||
|
self._set_alias_via_directory(alias2)
|
||||||
|
|
||||||
|
res = self._get_aliases(self.room_owner_tok)
|
||||||
|
self.assertEqual(set(res["aliases"]), {alias1, alias2})
|
||||||
|
|
||||||
|
def _get_aliases(self, access_token: str, expected_code: int = 200) -> JsonDict:
|
||||||
|
"""Calls the endpoint under test. returns the json response object."""
|
||||||
|
request, channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
"/_matrix/client/r0/rooms/%s/aliases" % (self.room_id,),
|
||||||
|
access_token=access_token,
|
||||||
|
)
|
||||||
|
self.render(request)
|
||||||
|
self.assertEqual(channel.code, expected_code, channel.result)
|
||||||
|
res = channel.json_body
|
||||||
|
self.assertIsInstance(res, dict)
|
||||||
|
if expected_code == 200:
|
||||||
|
self.assertIsInstance(res["aliases"], list)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _random_alias(self) -> str:
|
||||||
|
return RoomAlias(random_string(5), self.hs.hostname).to_string()
|
||||||
|
|
||||||
|
def _set_alias_via_directory(self, alias: str, expected_code: int = 200):
|
||||||
|
url = "/_matrix/client/r0/directory/room/" + alias
|
||||||
|
data = {"room_id": self.room_id}
|
||||||
|
request_data = json.dumps(data)
|
||||||
|
|
||||||
|
request, channel = self.make_request(
|
||||||
|
"PUT", url, request_data, access_token=self.room_owner_tok
|
||||||
|
)
|
||||||
|
self.render(request)
|
||||||
|
self.assertEqual(channel.code, expected_code, channel.result)
|
||||||
|
|
|
@ -21,6 +21,7 @@ import hmac
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
from typing import Optional, Tuple, Type, TypeVar, Union
|
||||||
|
|
||||||
from mock import Mock
|
from mock import Mock
|
||||||
|
|
||||||
|
@ -42,7 +43,13 @@ from synapse.server import HomeServer
|
||||||
from synapse.types import Requester, UserID, create_requester
|
from synapse.types import Requester, UserID, create_requester
|
||||||
from synapse.util.ratelimitutils import FederationRateLimiter
|
from synapse.util.ratelimitutils import FederationRateLimiter
|
||||||
|
|
||||||
from tests.server import get_clock, make_request, render, setup_test_homeserver
|
from tests.server import (
|
||||||
|
FakeChannel,
|
||||||
|
get_clock,
|
||||||
|
make_request,
|
||||||
|
render,
|
||||||
|
setup_test_homeserver,
|
||||||
|
)
|
||||||
from tests.test_utils.logging_setup import setup_logging
|
from tests.test_utils.logging_setup import setup_logging
|
||||||
from tests.utils import default_config, setupdb
|
from tests.utils import default_config, setupdb
|
||||||
|
|
||||||
|
@ -71,6 +78,9 @@ def around(target):
|
||||||
return _around
|
return _around
|
||||||
|
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class TestCase(unittest.TestCase):
|
class TestCase(unittest.TestCase):
|
||||||
"""A subclass of twisted.trial's TestCase which looks for 'loglevel'
|
"""A subclass of twisted.trial's TestCase which looks for 'loglevel'
|
||||||
attributes on both itself and its individual test methods, to override the
|
attributes on both itself and its individual test methods, to override the
|
||||||
|
@ -334,14 +344,14 @@ class HomeserverTestCase(TestCase):
|
||||||
|
|
||||||
def make_request(
|
def make_request(
|
||||||
self,
|
self,
|
||||||
method,
|
method: Union[bytes, str],
|
||||||
path,
|
path: Union[bytes, str],
|
||||||
content=b"",
|
content: Union[bytes, dict] = b"",
|
||||||
access_token=None,
|
access_token: Optional[str] = None,
|
||||||
request=SynapseRequest,
|
request: Type[T] = SynapseRequest,
|
||||||
shorthand=True,
|
shorthand: bool = True,
|
||||||
federation_auth_origin=None,
|
federation_auth_origin: str = None,
|
||||||
):
|
) -> Tuple[T, FakeChannel]:
|
||||||
"""
|
"""
|
||||||
Create a SynapseRequest at the path using the method and containing the
|
Create a SynapseRequest at the path using the method and containing the
|
||||||
given content.
|
given content.
|
||||||
|
|
Loading…
Reference in a new issue