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

Remove the experimental flag for knocking and use stable prefixes / endpoints. #10167

Merged
merged 5 commits into from
Jun 15, 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/10167.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implement "room knocking" as per [MSC2403](https://github.com/matrix-org/matrix-doc/pull/2403). Contributed by Sorunome and anoa.
4 changes: 2 additions & 2 deletions synapse/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Membership:

INVITE = "invite"
JOIN = "join"
KNOCK = "xyz.amorgan.knock"
KNOCK = "knock"
LEAVE = "leave"
BAN = "ban"
LIST = (INVITE, JOIN, KNOCK, LEAVE, BAN)
Expand All @@ -58,7 +58,7 @@ class PresenceState:

class JoinRules:
PUBLIC = "public"
KNOCK = "xyz.amorgan.knock"
KNOCK = "knock"
INVITE = "invite"
PRIVATE = "private"
# As defined for MSC3083.
Expand Down
7 changes: 4 additions & 3 deletions synapse/api/room_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ class RoomVersions:
msc3083_join_rules=True,
msc2403_knocking=False,
)
MSC2403 = RoomVersion(
"xyz.amorgan.knock",
RoomDisposition.UNSTABLE,
V7 = RoomVersion(
"7",
RoomDisposition.STABLE,
EventFormatVersions.V3,
StateResolutionVersions.V2,
enforce_key_validity=True,
Expand All @@ -206,6 +206,7 @@ class RoomVersions:
RoomVersions.V6,
RoomVersions.MSC2176,
RoomVersions.MSC3083,
RoomVersions.V7,
)
# Note that we do not include MSC2043 here unless it is enabled in the config.
} # type: Dict[str, RoomVersion]
7 changes: 0 additions & 7 deletions synapse/config/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersions
from synapse.config._base import Config
from synapse.types import JsonDict

Expand All @@ -30,9 +29,3 @@ def read_config(self, config: JsonDict, **kwargs):

# MSC3026 (busy presence state)
self.msc3026_enabled = experimental.get("msc3026_enabled", False) # type: bool

# MSC2403 (room knocking)
self.msc2403_enabled = experimental.get("msc2403_enabled", False) # type: bool
if self.msc2403_enabled:
# Enable the MSC2403 unstable room version
KNOWN_ROOM_VERSIONS[RoomVersions.MSC2403.identifier] = RoomVersions.MSC2403
9 changes: 2 additions & 7 deletions synapse/federation/federation_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ def __init__(self, hs: "HomeServer"):
self._clock.looping_call(self._clear_tried_cache, 60 * 1000)
self.state = hs.get_state_handler()
self.transport_layer = hs.get_federation_transport_client()
self._msc2403_enabled = hs.config.experimental.msc2403_enabled

self.hostname = hs.hostname
self.signing_key = hs.signing_key
Expand Down Expand Up @@ -621,11 +620,7 @@ async def make_membership_event(
SynapseError: if the chosen remote server returns a 300/400 code, or
no servers successfully handle the request.
"""
valid_memberships = {Membership.JOIN, Membership.LEAVE}

# Allow knocking if the feature is enabled
if self._msc2403_enabled:
valid_memberships.add(Membership.KNOCK)
valid_memberships = {Membership.JOIN, Membership.LEAVE, Membership.KNOCK}

if membership not in valid_memberships:
raise RuntimeError(
Expand Down Expand Up @@ -989,7 +984,7 @@ async def send_request(destination: str) -> JsonDict:
return await self._do_send_knock(destination, pdu)

return await self._try_destination_list(
"xyz.amorgan.knock/send_knock", destinations, send_request
"send_knock", destinations, send_request
)

async def _do_send_knock(self, destination: str, pdu: EventBase) -> JsonDict:
Expand Down
27 changes: 3 additions & 24 deletions synapse/federation/transport/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class TransportLayerClient:
def __init__(self, hs):
self.server_name = hs.hostname
self.client = hs.get_federation_http_client()
self._msc2403_enabled = hs.config.experimental.msc2403_enabled

@log_function
def get_room_state_ids(self, destination, room_id, event_id):
Expand Down Expand Up @@ -221,29 +220,14 @@ async def make_membership_event(
Fails with ``FederationDeniedError`` if the remote destination
is not in our federation whitelist
"""
valid_memberships = {Membership.JOIN, Membership.LEAVE}

# Allow knocking if the feature is enabled
if self._msc2403_enabled:
valid_memberships.add(Membership.KNOCK)
valid_memberships = {Membership.JOIN, Membership.LEAVE, Membership.KNOCK}

if membership not in valid_memberships:
raise RuntimeError(
"make_membership_event called with membership='%s', must be one of %s"
% (membership, ",".join(valid_memberships))
)

# Knock currently uses an unstable prefix
if membership == Membership.KNOCK:
# Create a path in the form of /unstable/xyz.amorgan.knock/make_knock/...
path = _create_path(
FEDERATION_UNSTABLE_PREFIX + "/xyz.amorgan.knock",
"/make_knock/%s/%s",
room_id,
user_id,
)
else:
path = _create_v1_path("/make_%s/%s/%s", membership, room_id, user_id)
path = _create_v1_path("/make_%s/%s/%s", membership, room_id, user_id)

ignore_backoff = False
retry_on_dns_fail = False
Expand Down Expand Up @@ -366,12 +350,7 @@ async def send_knock_v1(

The list of state events may be empty.
"""
path = _create_path(
FEDERATION_UNSTABLE_PREFIX + "/xyz.amorgan.knock",
"/send_knock/%s/%s",
room_id,
event_id,
)
path = _create_v1_path("/send_knock/%s/%s", room_id, event_id)

return await self.client.put_json(
destination=destination, path=path, data=content
Expand Down
22 changes: 2 additions & 20 deletions synapse/federation/transport/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,6 @@ async def on_PUT(self, origin, content, query, room_id, event_id):
class FederationMakeKnockServlet(BaseFederationServerServlet):
PATH = "/make_knock/(?P<room_id>[^/]*)/(?P<user_id>[^/]*)"

PREFIX = FEDERATION_UNSTABLE_PREFIX + "/xyz.amorgan.knock"

async def on_GET(self, origin, content, query, room_id, user_id):
try:
# Retrieve the room versions the remote homeserver claims to support
Expand All @@ -585,8 +583,6 @@ async def on_GET(self, origin, content, query, room_id, user_id):
class FederationV1SendKnockServlet(BaseFederationServerServlet):
PATH = "/send_knock/(?P<room_id>[^/]*)/(?P<event_id>[^/]*)"

PREFIX = FEDERATION_UNSTABLE_PREFIX + "/xyz.amorgan.knock"

async def on_PUT(self, origin, content, query, room_id, event_id):
content = await self.handler.on_send_knock_request(origin, content, room_id)
return 200, content
Expand Down Expand Up @@ -1610,6 +1606,8 @@ async def on_GET(self, origin, content, query, room_id):
FederationVersionServlet,
RoomComplexityServlet,
FederationSpaceSummaryServlet,
FederationV1SendKnockServlet,
FederationMakeKnockServlet,
) # type: Tuple[Type[BaseFederationServlet], ...]

OPENID_SERVLET_CLASSES = (
Expand Down Expand Up @@ -1652,12 +1650,6 @@ async def on_GET(self, origin, content, query, room_id):
) # type: Tuple[Type[BaseFederationServlet], ...]


MSC2403_SERVLET_CLASSES = (
FederationV1SendKnockServlet,
FederationMakeKnockServlet,
)


DEFAULT_SERVLET_GROUPS = (
"federation",
"room_list",
Expand Down Expand Up @@ -1700,16 +1692,6 @@ def register_servlets(
server_name=hs.hostname,
).register(resource)

# Register msc2403 (knocking) servlets if the feature is enabled
if hs.config.experimental.msc2403_enabled:
for servletclass in MSC2403_SERVLET_CLASSES:
servletclass(
hs=hs,
authenticator=authenticator,
ratelimiter=ratelimiter,
server_name=hs.hostname,
).register(resource)

if "openid" in servlet_groups:
for servletclass in OPENID_SERVLET_CLASSES:
servletclass(
Expand Down
6 changes: 2 additions & 4 deletions synapse/handlers/federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2009,8 +2009,7 @@ async def on_make_knock_request(
"""
if get_domain_from_id(user_id) != origin:
logger.info(
"Get /xyz.amorgan.knock/make_knock request for user %r"
"from different origin %s, ignoring",
"Get /make_knock request for user %r from different origin %s, ignoring",
user_id,
origin,
)
Expand Down Expand Up @@ -2077,8 +2076,7 @@ async def on_send_knock_request(

if get_domain_from_id(event.sender) != origin:
logger.info(
"Got /xyz.amorgan.knock/send_knock request for user %r "
"from different origin %s",
"Got /send_knock request for user %r from different origin %s",
event.sender,
origin,
)
Expand Down
5 changes: 1 addition & 4 deletions synapse/handlers/room_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -707,10 +707,7 @@ async def update_membership_locked(
knock.event_id, txn_id, requester, content
)

elif (
self.config.experimental.msc2403_enabled
and effective_membership_state == Membership.KNOCK
):
elif effective_membership_state == Membership.KNOCK:
if not is_host_in_room:
# The knock needs to be sent over federation instead
remote_room_hosts.append(get_domain_from_id(room_id))
Expand Down
5 changes: 1 addition & 4 deletions synapse/rest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,7 @@ def register_servlets(client_resource, hs):
account_validity.register_servlets(hs, client_resource)
relations.register_servlets(hs, client_resource)
password_policy.register_servlets(hs, client_resource)

# Register msc2403 (knocking) servlets if the feature is enabled
if hs.config.experimental.msc2403_enabled:
knock.register_servlets(hs, client_resource)
knock.register_servlets(hs, client_resource)

# moving to /_synapse/admin
admin.register_servlets_for_client_rest_resource(hs, client_resource)
Expand Down
6 changes: 2 additions & 4 deletions synapse/rest/client/v2_alpha/knock.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,10 @@

class KnockRoomAliasServlet(RestServlet):
"""
POST /xyz.amorgan.knock/{roomIdOrAlias}
POST /knock/{roomIdOrAlias}
"""

PATTERNS = client_patterns(
"/xyz.amorgan.knock/(?P<room_identifier>[^/]*)", releases=()
)
PATTERNS = client_patterns("/knock/(?P<room_identifier>[^/]*)")

def __init__(self, hs: "HomeServer"):
super().__init__()
Expand Down
22 changes: 9 additions & 13 deletions tests/federation/transport/test_knocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
from tests.test_utils import event_injection
from tests.unittest import FederatingHomeserverTestCase, TestCase, override_config

# An identifier to use while MSC2304 is not in a stable release of the spec
KNOCK_UNSTABLE_IDENTIFIER = "xyz.amorgan.knock"


class KnockingStrippedStateEventHelperMixin(TestCase):
def send_example_state_events_to_room(
Expand Down Expand Up @@ -61,7 +58,7 @@ def send_example_state_events_to_room(
self.get_success(
event_injection.inject_event(
hs,
room_version=RoomVersions.MSC2403.identifier,
room_version=RoomVersions.V7.identifier,
room_id=room_id,
sender=sender,
type="com.example.secret",
Expand Down Expand Up @@ -121,7 +118,7 @@ def send_example_state_events_to_room(
self.get_success(
event_injection.inject_event(
hs,
room_version=RoomVersions.MSC2403.identifier,
room_version=RoomVersions.V7.identifier,
room_id=room_id,
sender=sender,
type=event_type,
Expand All @@ -135,7 +132,7 @@ def send_example_state_events_to_room(
room_state[EventTypes.Create] = {
"content": {
"creator": sender,
"room_version": RoomVersions.MSC2403.identifier,
"room_version": RoomVersions.V7.identifier,
},
"state_key": "",
}
Expand Down Expand Up @@ -232,7 +229,7 @@ def test_room_state_returned_when_knocking(self):
room_id = self.helper.create_room_as(
"u1",
is_public=False,
room_version=RoomVersions.MSC2403.identifier,
room_version=RoomVersions.V7.identifier,
tok=user_token,
)

Expand All @@ -243,14 +240,13 @@ def test_room_state_returned_when_knocking(self):

channel = self.make_request(
"GET",
"/_matrix/federation/unstable/%s/make_knock/%s/%s?ver=%s"
"/_matrix/federation/v1/make_knock/%s/%s?ver=%s"
% (
KNOCK_UNSTABLE_IDENTIFIER,
room_id,
fake_knocking_user_id,
# Inform the remote that we support the room version of the room we're
# knocking on
RoomVersions.MSC2403.identifier,
RoomVersions.V7.identifier,
),
)
self.assertEquals(200, channel.code, channel.result)
Expand All @@ -275,7 +271,7 @@ def test_room_state_returned_when_knocking(self):
self.clock,
self.hs.hostname,
self.hs.signing_key,
room_version=RoomVersions.MSC2403,
room_version=RoomVersions.V7,
event_dict=knock_event,
)

Expand All @@ -287,8 +283,8 @@ def test_room_state_returned_when_knocking(self):
# Send the signed knock event into the room
channel = self.make_request(
"PUT",
"/_matrix/federation/unstable/%s/send_knock/%s/%s"
% (KNOCK_UNSTABLE_IDENTIFIER, room_id, signed_knock_event.event_id),
"/_matrix/federation/v1/send_knock/%s/%s"
% (room_id, signed_knock_event.event_id),
signed_knock_event_json,
)
self.assertEquals(200, channel.code, channel.result)
Expand Down
8 changes: 4 additions & 4 deletions tests/rest/client/v2_alpha/test_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ def prepare(self, reactor, clock, hs):
self.room_id = self.helper.create_room_as(
self.user_id,
is_public=False,
room_version="xyz.amorgan.knock",
room_version="7",
tok=self.tok,
)

Expand Down Expand Up @@ -363,15 +363,15 @@ def test_knock_room_state(self):
# Knock on a room
channel = self.make_request(
"POST",
"/_matrix/client/unstable/xyz.amorgan.knock/%s" % (self.room_id,),
"/_matrix/client/r0/knock/%s" % (self.room_id,),
b"{}",
self.knocker_tok,
)
self.assertEquals(200, channel.code, channel.result)

# We expect to see the knock event in the stripped room state later
self.expected_room_state[EventTypes.Member] = {
"content": {"membership": "xyz.amorgan.knock", "displayname": "knocker"},
"content": {"membership": "knock", "displayname": "knocker"},
"state_key": "@knocker:test",
}

Expand All @@ -384,7 +384,7 @@ def test_knock_room_state(self):
self.assertEqual(channel.code, 200, channel.json_body)

# Extract the stripped room state events from /sync
knock_entry = channel.json_body["rooms"]["xyz.amorgan.knock"]
knock_entry = channel.json_body["rooms"]["knock"]
room_state_events = knock_entry[self.room_id]["knock_state"]["events"]

# Validate that the knock membership event came last
Expand Down