Compare commits

...

8 commits

Author SHA1 Message Date
Eric Eastwood 2370dcadf6 Remove redundant length check
> if `len(auth_event_ids) == 0` then `auth_event_ids` will be falsey, so the extra check is redundant.
>
> -- https://github.com/matrix-org/synapse/pull/11243#discussion_r745408186
2021-11-09 14:14:37 -06:00
Eric Eastwood d10625eb18
Update test description to be accurate
Previously just a copy paste

Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
2021-11-08 12:35:29 -06:00
Eric Eastwood f421a2df2d Fix lints 2021-11-04 20:25:30 -05:00
Eric Eastwood 4bb5fd33a3 Add tests for creating events with empty prev_events 2021-11-04 20:18:46 -05:00
Eric Eastwood e093481966
More clarification and specificity in errors/comments
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
2021-11-04 15:27:40 -05:00
Eric Eastwood 9f45d09fe7 Allow member state events without prev_events 2021-11-03 18:51:29 -05:00
Eric Eastwood 66f085911c Add changelog 2021-11-03 18:45:17 -05:00
Eric Eastwood 39efad1b8f Allow events to be created with no prev_events
The event still needs to have auth_events defined to be valid.

Split out from https://github.com/matrix-org/synapse/pull/11114
2021-11-03 18:38:26 -05:00
5 changed files with 127 additions and 7 deletions

View file

@ -0,0 +1 @@
Add experimental room version `org.matrix.msc2716v4` to allow events to be created without `prev_events` (only `auth_events`).

View file

@ -81,6 +81,8 @@ class RoomVersion:
msc2716_historical = attr.ib(type=bool)
# MSC2716: Adds support for redacting "insertion", "chunk", and "marker" events
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:
@ -99,6 +101,7 @@ class RoomVersions:
msc2403_knocking=False,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V2 = RoomVersion(
"2",
@ -115,6 +118,7 @@ class RoomVersions:
msc2403_knocking=False,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V3 = RoomVersion(
"3",
@ -131,6 +135,7 @@ class RoomVersions:
msc2403_knocking=False,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V4 = RoomVersion(
"4",
@ -147,6 +152,7 @@ class RoomVersions:
msc2403_knocking=False,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V5 = RoomVersion(
"5",
@ -163,6 +169,7 @@ class RoomVersions:
msc2403_knocking=False,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V6 = RoomVersion(
"6",
@ -179,6 +186,7 @@ class RoomVersions:
msc2403_knocking=False,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
MSC2176 = RoomVersion(
"org.matrix.msc2176",
@ -195,6 +203,7 @@ class RoomVersions:
msc2403_knocking=False,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V7 = RoomVersion(
"7",
@ -211,6 +220,7 @@ class RoomVersions:
msc2403_knocking=True,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V8 = RoomVersion(
"8",
@ -227,6 +237,7 @@ class RoomVersions:
msc2403_knocking=True,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
V9 = RoomVersion(
"9",
@ -243,6 +254,7 @@ class RoomVersions:
msc2403_knocking=True,
msc2716_historical=False,
msc2716_redactions=False,
msc2716_empty_prev_events=False,
)
MSC2716v3 = RoomVersion(
"org.matrix.msc2716v3",
@ -259,6 +271,24 @@ class RoomVersions:
msc2403_knocking=True,
msc2716_historical=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.V9,
RoomVersions.MSC2716v3,
RoomVersions.MSC2716v4,
)
}

View file

@ -918,6 +918,7 @@ class EventCreationHandler:
full_state_ids_at_event = None
if auth_event_ids is not None:
# 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
# Copy the full auth state before it stripped down
@ -949,14 +950,24 @@ class EventCreationHandler:
else:
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
# create event in auth events")
assert (
builder.type == EventTypes.Create or len(prev_event_ids) > 0
), "Attempting to create an event with no prev_events"
room_version_obj = await self.store.get_room_version(builder.room_id)
if room_version_obj.msc2716_empty_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(
prev_event_ids=prev_event_ids,

View file

@ -644,7 +644,8 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
if block_invite:
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(
requester=requester,
target=target,

View file

@ -15,6 +15,7 @@ import logging
from typing import Tuple
from synapse.api.constants import EventTypes
from synapse.api.room_versions import RoomVersions
from synapse.events import EventBase
from synapse.events.snapshot import EventContext
from synapse.rest import admin
@ -23,6 +24,7 @@ from synapse.types import create_requester
from synapse.util.stringutils import random_string
from tests import unittest
from tests.test_utils.event_injection import create_event
logger = logging.getLogger(__name__)
@ -156,6 +158,80 @@ class EventCreationTestCase(unittest.HomeserverTestCase):
self.assertEqual(len(events), 2)
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):
servlets = [