Compare commits
8 commits
develop
...
madlittlem
Author | SHA1 | Date | |
---|---|---|---|
|
2370dcadf6 | ||
|
d10625eb18 | ||
|
f421a2df2d | ||
|
4bb5fd33a3 | ||
|
e093481966 | ||
|
9f45d09fe7 | ||
|
66f085911c | ||
|
39efad1b8f |
1
changelog.d/11243.feature
Normal file
1
changelog.d/11243.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Add experimental room version `org.matrix.msc2716v4` to allow events to be created without `prev_events` (only `auth_events`).
|
|
@ -81,6 +81,8 @@ class RoomVersion:
|
||||||
msc2716_historical = attr.ib(type=bool)
|
msc2716_historical = attr.ib(type=bool)
|
||||||
# MSC2716: Adds support for redacting "insertion", "chunk", and "marker" events
|
# MSC2716: Adds support for redacting "insertion", "chunk", and "marker" events
|
||||||
msc2716_redactions = attr.ib(type=bool)
|
msc2716_redactions = attr.ib(type=bool)
|
||||||
|
# MSC2716: Adds support for events with no `prev_events` but with some `auth_events`
|
||||||
|
msc2716_empty_prev_events = attr.ib(type=bool)
|
||||||
|
|
||||||
|
|
||||||
class RoomVersions:
|
class RoomVersions:
|
||||||
|
@ -99,6 +101,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=False,
|
msc2403_knocking=False,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V2 = RoomVersion(
|
V2 = RoomVersion(
|
||||||
"2",
|
"2",
|
||||||
|
@ -115,6 +118,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=False,
|
msc2403_knocking=False,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V3 = RoomVersion(
|
V3 = RoomVersion(
|
||||||
"3",
|
"3",
|
||||||
|
@ -131,6 +135,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=False,
|
msc2403_knocking=False,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V4 = RoomVersion(
|
V4 = RoomVersion(
|
||||||
"4",
|
"4",
|
||||||
|
@ -147,6 +152,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=False,
|
msc2403_knocking=False,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V5 = RoomVersion(
|
V5 = RoomVersion(
|
||||||
"5",
|
"5",
|
||||||
|
@ -163,6 +169,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=False,
|
msc2403_knocking=False,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V6 = RoomVersion(
|
V6 = RoomVersion(
|
||||||
"6",
|
"6",
|
||||||
|
@ -179,6 +186,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=False,
|
msc2403_knocking=False,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
MSC2176 = RoomVersion(
|
MSC2176 = RoomVersion(
|
||||||
"org.matrix.msc2176",
|
"org.matrix.msc2176",
|
||||||
|
@ -195,6 +203,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=False,
|
msc2403_knocking=False,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V7 = RoomVersion(
|
V7 = RoomVersion(
|
||||||
"7",
|
"7",
|
||||||
|
@ -211,6 +220,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=True,
|
msc2403_knocking=True,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V8 = RoomVersion(
|
V8 = RoomVersion(
|
||||||
"8",
|
"8",
|
||||||
|
@ -227,6 +237,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=True,
|
msc2403_knocking=True,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
V9 = RoomVersion(
|
V9 = RoomVersion(
|
||||||
"9",
|
"9",
|
||||||
|
@ -243,6 +254,7 @@ class RoomVersions:
|
||||||
msc2403_knocking=True,
|
msc2403_knocking=True,
|
||||||
msc2716_historical=False,
|
msc2716_historical=False,
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
)
|
)
|
||||||
MSC2716v3 = RoomVersion(
|
MSC2716v3 = RoomVersion(
|
||||||
"org.matrix.msc2716v3",
|
"org.matrix.msc2716v3",
|
||||||
|
@ -259,6 +271,24 @@ class RoomVersions:
|
||||||
msc2403_knocking=True,
|
msc2403_knocking=True,
|
||||||
msc2716_historical=True,
|
msc2716_historical=True,
|
||||||
msc2716_redactions=True,
|
msc2716_redactions=True,
|
||||||
|
msc2716_empty_prev_events=False,
|
||||||
|
)
|
||||||
|
MSC2716v4 = RoomVersion(
|
||||||
|
"org.matrix.msc2716v4",
|
||||||
|
RoomDisposition.UNSTABLE,
|
||||||
|
EventFormatVersions.V3,
|
||||||
|
StateResolutionVersions.V2,
|
||||||
|
enforce_key_validity=True,
|
||||||
|
special_case_aliases_auth=False,
|
||||||
|
strict_canonicaljson=True,
|
||||||
|
limit_notifications_power_levels=True,
|
||||||
|
msc2176_redaction_rules=False,
|
||||||
|
msc3083_join_rules=False,
|
||||||
|
msc3375_redaction_rules=False,
|
||||||
|
msc2403_knocking=True,
|
||||||
|
msc2716_historical=True,
|
||||||
|
msc2716_redactions=True,
|
||||||
|
msc2716_empty_prev_events=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,6 +306,7 @@ KNOWN_ROOM_VERSIONS: Dict[str, RoomVersion] = {
|
||||||
RoomVersions.V8,
|
RoomVersions.V8,
|
||||||
RoomVersions.V9,
|
RoomVersions.V9,
|
||||||
RoomVersions.MSC2716v3,
|
RoomVersions.MSC2716v3,
|
||||||
|
RoomVersions.MSC2716v4,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -918,6 +918,7 @@ class EventCreationHandler:
|
||||||
full_state_ids_at_event = None
|
full_state_ids_at_event = None
|
||||||
if auth_event_ids is not None:
|
if auth_event_ids is not None:
|
||||||
# If auth events are provided, prev events must be also.
|
# If auth events are provided, prev events must be also.
|
||||||
|
# prev_event_ids could be an empty array though.
|
||||||
assert prev_event_ids is not None
|
assert prev_event_ids is not None
|
||||||
|
|
||||||
# Copy the full auth state before it stripped down
|
# Copy the full auth state before it stripped down
|
||||||
|
@ -949,14 +950,24 @@ class EventCreationHandler:
|
||||||
else:
|
else:
|
||||||
prev_event_ids = await self.store.get_prev_events_for_room(builder.room_id)
|
prev_event_ids = await self.store.get_prev_events_for_room(builder.room_id)
|
||||||
|
|
||||||
# we now ought to have some prev_events (unless it's a create event).
|
# Do a quick sanity check here, rather than waiting until we've created the
|
||||||
#
|
|
||||||
# do a quick sanity check here, rather than waiting until we've created the
|
|
||||||
# event and then try to auth it (which fails with a somewhat confusing "No
|
# event and then try to auth it (which fails with a somewhat confusing "No
|
||||||
# create event in auth events")
|
# create event in auth events")
|
||||||
assert (
|
room_version_obj = await self.store.get_room_version(builder.room_id)
|
||||||
builder.type == EventTypes.Create or len(prev_event_ids) > 0
|
if room_version_obj.msc2716_empty_prev_events:
|
||||||
), "Attempting to create an event with no prev_events"
|
# We allow events with no `prev_events` but it better have some `auth_events`
|
||||||
|
assert (
|
||||||
|
builder.type == EventTypes.Create
|
||||||
|
or len(prev_event_ids) > 0
|
||||||
|
# Allow an event to have empty list of prev_event_ids
|
||||||
|
# only if it has auth_event_ids.
|
||||||
|
or auth_event_ids
|
||||||
|
), "Attempting to create a non-m.room.create event with no prev_events or auth_event_ids"
|
||||||
|
else:
|
||||||
|
# we now ought to have some prev_events (unless it's a create event).
|
||||||
|
assert (
|
||||||
|
builder.type == EventTypes.Create or len(prev_event_ids) > 0
|
||||||
|
), "Attempting to create a non-m.room.create event with no prev_events"
|
||||||
|
|
||||||
event = await builder.build(
|
event = await builder.build(
|
||||||
prev_event_ids=prev_event_ids,
|
prev_event_ids=prev_event_ids,
|
||||||
|
|
|
@ -644,7 +644,8 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
||||||
if block_invite:
|
if block_invite:
|
||||||
raise SynapseError(403, "Invites have been disabled on this server")
|
raise SynapseError(403, "Invites have been disabled on this server")
|
||||||
|
|
||||||
if prev_event_ids:
|
# An empty prev_events list is allowed by room version "org.matrix.msc2716v4"
|
||||||
|
if prev_event_ids is not None:
|
||||||
return await self._local_membership_update(
|
return await self._local_membership_update(
|
||||||
requester=requester,
|
requester=requester,
|
||||||
target=target,
|
target=target,
|
||||||
|
|
|
@ -15,6 +15,7 @@ import logging
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
from synapse.api.constants import EventTypes
|
from synapse.api.constants import EventTypes
|
||||||
|
from synapse.api.room_versions import RoomVersions
|
||||||
from synapse.events import EventBase
|
from synapse.events import EventBase
|
||||||
from synapse.events.snapshot import EventContext
|
from synapse.events.snapshot import EventContext
|
||||||
from synapse.rest import admin
|
from synapse.rest import admin
|
||||||
|
@ -23,6 +24,7 @@ from synapse.types import create_requester
|
||||||
from synapse.util.stringutils import random_string
|
from synapse.util.stringutils import random_string
|
||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
from tests.test_utils.event_injection import create_event
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -156,6 +158,80 @@ class EventCreationTestCase(unittest.HomeserverTestCase):
|
||||||
self.assertEqual(len(events), 2)
|
self.assertEqual(len(events), 2)
|
||||||
self.assertEqual(events[0].event_id, events[1].event_id)
|
self.assertEqual(events[0].event_id, events[1].event_id)
|
||||||
|
|
||||||
|
def test_create_empty_prev_events_in_msc2716_room_version(self):
|
||||||
|
"""Try to create an event without any prev_events (only auth_events).
|
||||||
|
|
||||||
|
This is currently only supported in the experimental MSC2716v4+ room versions.
|
||||||
|
"""
|
||||||
|
room_id = self.helper.create_room_as(
|
||||||
|
self.user_id,
|
||||||
|
tok=self.access_token,
|
||||||
|
room_version=RoomVersions.MSC2716v4.identifier,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a member event we can use as an auth_event
|
||||||
|
memberEvent, memberEventContext = self.get_success(
|
||||||
|
create_event(
|
||||||
|
self.hs,
|
||||||
|
room_id=room_id,
|
||||||
|
type="m.room.member",
|
||||||
|
sender=self.requester.user.to_string(),
|
||||||
|
state_key=self.requester.user.to_string(),
|
||||||
|
content={"membership": "join"},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.get_success(
|
||||||
|
self.persist_event_storage.persist_event(memberEvent, memberEventContext)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Try to create the event with empty prev_events (only auth_events)
|
||||||
|
event, _ = self.get_success(
|
||||||
|
self.handler.create_event(
|
||||||
|
self.requester,
|
||||||
|
{
|
||||||
|
"type": EventTypes.Message,
|
||||||
|
"room_id": room_id,
|
||||||
|
"sender": self.requester.user.to_string(),
|
||||||
|
"content": {"msgtype": "m.text", "body": random_string(5)},
|
||||||
|
},
|
||||||
|
# Empty prev_events is the key thing we're testing here
|
||||||
|
prev_event_ids=[],
|
||||||
|
auth_event_ids=[memberEvent.event_id],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(event)
|
||||||
|
|
||||||
|
def test_reject_empty_prev_events_and_auth_events_in_msc2716_room_version(
|
||||||
|
self,
|
||||||
|
):
|
||||||
|
"""Try to create an event without any prev_events or auth_events.
|
||||||
|
Expect an exception to be raised.
|
||||||
|
|
||||||
|
This is currently only supported in the experimental MSC2716v4 room versions.
|
||||||
|
"""
|
||||||
|
room_id = self.helper.create_room_as(
|
||||||
|
self.user_id,
|
||||||
|
tok=self.access_token,
|
||||||
|
room_version=RoomVersions.MSC2716v4.identifier,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Try to create the event with empty prev_events and empty auth_events
|
||||||
|
self.get_failure(
|
||||||
|
self.handler.create_event(
|
||||||
|
self.requester,
|
||||||
|
{
|
||||||
|
"type": EventTypes.Message,
|
||||||
|
"room_id": room_id,
|
||||||
|
"sender": self.requester.user.to_string(),
|
||||||
|
"content": {"msgtype": "m.text", "body": random_string(5)},
|
||||||
|
},
|
||||||
|
prev_event_ids=[],
|
||||||
|
# The event should be rejected when there are no auth_events
|
||||||
|
auth_event_ids=[],
|
||||||
|
),
|
||||||
|
AssertionError,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ServerAclValidationTestCase(unittest.HomeserverTestCase):
|
class ServerAclValidationTestCase(unittest.HomeserverTestCase):
|
||||||
servlets = [
|
servlets = [
|
||||||
|
|
Loading…
Reference in a new issue