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

Implement GET /_matrix/client/r0/rooms/{roomId}/aliases #6939

Merged
merged 5 commits into from
Feb 18, 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
1 change: 1 addition & 0 deletions changelog.d/6939.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implement `GET /_matrix/client/r0/rooms/{roomId}/aliases` endpoint as per [MSC2432](https://github.com/matrix-org/matrix-doc/pull/2432).
17 changes: 16 additions & 1 deletion synapse/handlers/directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import logging
import string
from typing import List

from twisted.internet import defer

Expand All @@ -28,7 +29,7 @@
StoreError,
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

Expand Down Expand Up @@ -447,3 +448,17 @@ def edit_published_appservice_room_list(
yield self.store.set_room_is_public_appservice(
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
23 changes: 23 additions & 0 deletions synapse/rest/client/v1/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
from synapse.streams.config import PaginationConfig
from synapse.types import RoomAlias, RoomID, StreamToken, ThirdPartyInstanceID, UserID

MYPY = False
if MYPY:
import synapse.server

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -843,6 +847,24 @@ async def on_PUT(self, request, room_id, user_id):
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):
PATTERNS = client_patterns("/search$", v1=True)

Expand Down Expand Up @@ -931,6 +953,7 @@ def register_servlets(hs, http_server):
JoinedRoomsRestServlet(hs).register(http_server)
RoomEventServlet(hs).register(http_server)
RoomEventContextServlet(hs).register(http_server)
RoomAliasListServlet(hs).register(http_server)


def register_deprecated_servlets(hs, http_server):
Expand Down
70 changes: 69 additions & 1 deletion tests/rest/client/v1/test_rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
import synapse.rest.admin
from synapse.api.constants import EventContentFields, EventTypes, Membership
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.types import JsonDict, RoomAlias
from synapse.util.stringutils import random_string

from tests import unittest
Expand Down Expand Up @@ -1726,3 +1727,70 @@ def test_erased_sender(self):
self.assertEqual(len(events_after), 2, events_after)
self.assertDictEqual(events_after[0].get("content"), {}, events_after[0])
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)
28 changes: 19 additions & 9 deletions tests/unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import inspect
import logging
import time
from typing import Optional, Tuple, Type, TypeVar, Union

from mock import Mock

Expand All @@ -42,7 +43,13 @@
from synapse.types import Requester, UserID, create_requester
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.utils import default_config, setupdb

Expand Down Expand Up @@ -71,6 +78,9 @@ def new(*args, **kwargs):
return _around


T = TypeVar("T")


class TestCase(unittest.TestCase):
"""A subclass of twisted.trial's TestCase which looks for 'loglevel'
attributes on both itself and its individual test methods, to override the
Expand Down Expand Up @@ -334,14 +344,14 @@ def prepare(self, reactor, clock, homeserver):

def make_request(
self,
method,
path,
content=b"",
access_token=None,
request=SynapseRequest,
shorthand=True,
federation_auth_origin=None,
):
method: Union[bytes, str],
path: Union[bytes, str],
content: Union[bytes, dict] = b"",
access_token: Optional[str] = None,
request: Type[T] = SynapseRequest,
shorthand: bool = True,
federation_auth_origin: str = None,
) -> Tuple[T, FakeChannel]:
"""
Create a SynapseRequest at the path using the method and containing the
given content.
Expand Down