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

Allow room creator to send MSC2716 related events in existing room versions #10566

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6481502
Allow room creator to send MSC2716 related events in existing room ve…
MadLittleMods Aug 10, 2021
13d0929
Add changelog
MadLittleMods Aug 10, 2021
259303a
Stop people from trying to redact MSC2716 events in unsupported room …
MadLittleMods Aug 10, 2021
16a41dd
Populate rooms.creator column for easy lookup
MadLittleMods Aug 20, 2021
fffce99
Merge branch 'develop' into madlittlemods/room-creator-allowed-to-msc…
MadLittleMods Aug 20, 2021
aafa069
Remove and switch away from get_create_event_for_room_txn
MadLittleMods Aug 20, 2021
fedd250
Fix no create event being found because no state events persisted yet
MadLittleMods Aug 21, 2021
8a2db20
Fix and add tests for rooms creator bg update
MadLittleMods Aug 21, 2021
2b177b7
Populate rooms.creator field for easy lookup
MadLittleMods Aug 25, 2021
ee406df
Add changelog
MadLittleMods Aug 25, 2021
9f8e22b
Fix usage
MadLittleMods Aug 25, 2021
759e78c
Merge branch 'develop' into madlittlemods/room-creator-allowed-to-msc…
MadLittleMods Aug 25, 2021
71c20f7
Merge branch 'madlittlemods/populate-rooms-creator-field' into madlit…
MadLittleMods Aug 25, 2021
9b828ab
Remove extra delta already included in #10697
MadLittleMods Aug 25, 2021
3c9b5a6
Don't worry about setting creator for invite
MadLittleMods Aug 25, 2021
9a600ff
Only iterate over rows missing the creator
MadLittleMods Aug 31, 2021
79b4991
Use constant to fetch room creator field
MadLittleMods Aug 31, 2021
25db289
More protection from other random types
MadLittleMods Aug 31, 2021
41e72c2
Move new background update to end of list
MadLittleMods Aug 31, 2021
9a3c015
Fix query casing
MadLittleMods Aug 31, 2021
9a887a4
Fix ambiguity iterating over cursor instead of list
MadLittleMods Aug 31, 2021
6f9cb41
Move code not under the MSC2716 room version underneath an experiment…
MadLittleMods Aug 31, 2021
ad29e96
Add ordering to rooms creator background update
MadLittleMods Sep 1, 2021
462ab25
Add comment to better document constant
MadLittleMods Sep 1, 2021
a3581d3
Use constant field
MadLittleMods Sep 1, 2021
20196c8
Merge branch 'madlittlemods/populate-rooms-creator-field' into madlit…
MadLittleMods Sep 1, 2021
725cf22
Merge branch 'develop' into madlittlemods/room-creator-allowed-to-msc…
MadLittleMods Sep 1, 2021
e047e42
Merge branch 'develop' into madlittlemods/room-creator-allowed-to-msc…
MadLittleMods Sep 1, 2021
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/10566.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow room creators to send historical events specified by [MSC2716](https://github.com/matrix-org/matrix-doc/pull/2716) in existing room versions.
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 4 additions & 2 deletions synapse/handlers/federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -934,9 +934,11 @@ async def _handle_marker_event(self, origin: str, marker_event: EventBase):
return

# Skip processing a marker event if the room version doesn't
# support it.
# support it or the event is not from the room creator.
room_version = await self.store.get_room_version(marker_event.room_id)
if not room_version.msc2716_historical:
create_event = await self.store.get_create_event_for_room(marker_event.room_id)
room_creator = create_event.content.get("creator", None)
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
if not room_version.msc2716_historical or marker_event.sender != room_creator:
return

logger.debug("_handle_marker_event: received %s", marker_event)
Expand Down
14 changes: 9 additions & 5 deletions synapse/storage/databases/main/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1770,10 +1770,12 @@ def _handle_insertion_event(self, txn: LoggingTransaction, event: EventBase):
# Not a insertion event
return

# Skip processing a insertion event if the room version doesn't
# support it.
# Skip processing an insertion event if the room version doesn't
# support it or the event is not from the room creator.
room_version = self.store.get_room_version_txn(txn, event.room_id)
if not room_version.msc2716_historical:
create_event = self.store.get_create_event_for_room_txn(txn, event.room_id)
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
room_creator = create_event.content.get("creator", None)
if not room_version.msc2716_historical or event.sender != room_creator:
return

next_chunk_id = event.content.get(EventContentFields.MSC2716_NEXT_CHUNK_ID)
Expand Down Expand Up @@ -1822,9 +1824,11 @@ def _handle_chunk_event(self, txn: LoggingTransaction, event: EventBase):
return

# Skip processing a chunk event if the room version doesn't
# support it.
# support it or the event is not from the room creator.
room_version = self.store.get_room_version_txn(txn, event.room_id)
if not room_version.msc2716_historical:
create_event = self.store.get_create_event_for_room_txn(txn, event.room_id)
room_creator = create_event.content.get("creator", None)
if not room_version.msc2716_historical or event.sender != room_creator:
return

chunk_id = event.content.get(EventContentFields.MSC2716_CHUNK_ID)
Expand Down
70 changes: 69 additions & 1 deletion synapse/storage/databases/main/events_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
from synapse.replication.tcp.streams import BackfillStream
from synapse.replication.tcp.streams.events import EventsStream
from synapse.storage._base import SQLBaseStore, db_to_json, make_in_list_sql_clause
from synapse.storage.database import DatabasePool
from synapse.storage.database import DatabasePool, LoggingTransaction
from synapse.storage.engines import PostgresEngine
from synapse.storage.util.id_generators import MultiWriterIdGenerator, StreamIdGenerator
from synapse.storage.util.sequence import build_sequence_generator
Expand Down Expand Up @@ -223,6 +223,74 @@ async def get_received_ts(self, event_id: str) -> Optional[int]:
desc="get_received_ts",
)

# Inform mypy that if allow_none is False (the default) then get_event

# always returns an EventBase.
@overload
def get_event_txn(
self,
event_id: str,
allow_rejected: bool = False,
allow_none: Literal[False] = False,
) -> EventBase:
...

@overload
def get_event_txn(
self,
event_id: str,
allow_rejected: bool = False,
allow_none: Literal[True] = False,
) -> Optional[EventBase]:
...

def get_event_txn(
self,
txn: LoggingTransaction,
event_id: str,
allow_rejected: bool = False,
allow_none: bool = False,
) -> Optional[EventBase]:
"""Get an event from the database by event_id.
Args:
txn: Transaction object
event_id: The event_id of the event to fetch
get_prev_content: If True and event is a state event,
include the previous states content in the unsigned field.
allow_rejected: If True, return rejected events. Otherwise,
behave as per allow_none.
allow_none: If True, return None if no event found, if
False throw a NotFoundError
check_room_id: if not None, check the room of the found event.
If there is a mismatch, behave as per allow_none.
Returns:
The event, or None if the event was not found and allow_none=True
Raises:
NotFoundError: if the event_id was not found and allow_none=False
"""
event_map = self._fetch_event_rows(txn, [event_id])
event_info = event_map[event_id]
if event_info is None and not allow_none:
raise NotFoundError("Could not find event %s" % (event_id,))

rejected_reason = event_info["rejected_reason"]
if not allow_rejected and rejected_reason:
return

d = db_to_json(event_info["json"])
internal_metadata = db_to_json(event_info["internal_metadata"])
room_version_id = event_info["room_version_id"]
room_version = KNOWN_ROOM_VERSIONS.get(room_version_id)

event = make_event_from_dict(
event_dict=d,
room_version=room_version,
internal_metadata_dict=internal_metadata,
rejected_reason=rejected_reason,
)

return event

# Inform mypy that if allow_none is False (the default) then get_event
# always returns an EventBase.
@overload
Expand Down
57 changes: 45 additions & 12 deletions synapse/storage/databases/main/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,34 @@ async def get_create_event_for_room(self, room_id: str) -> EventBase:
Raises:
NotFoundError if the room is unknown
"""
state_ids = await self.get_current_state_ids(room_id)
return await self.db_pool.runInteraction(
"get_create_event_for_room_txn",
self.get_create_event_for_room_txn,
room_id,
)

def get_create_event_for_room_txn(
self, txn: LoggingTransaction, room_id: str
) -> EventBase:
"""Get the create state event for a room.
Args:
txn: Transaction object
room_id: The room ID.
Returns:
The room creation event.
Raises:
NotFoundError if the room is unknown
"""

state_ids = self.get_current_state_ids_txn(txn, room_id)
create_id = state_ids.get((EventTypes.Create, ""))

# If we can't find the create event, assume we've hit a dead end
if not create_id:
raise NotFoundError("Unknown room %s" % (room_id,))

# Retrieve the room's create event and return
create_event = await self.get_event(create_id)
create_event = self.get_event_txn(txn, create_id)
return create_event

@cached(max_entries=100000, iterable=True)
Expand All @@ -200,21 +219,35 @@ async def get_current_state_ids(self, room_id: str) -> StateMap[str]:
Returns:
The current state of the room.
"""
return await self.db_pool.runInteraction(
"get_current_state_ids_txn",
self.get_current_state_ids_txn,
room_id,
)

def _get_current_state_ids_txn(txn):
txn.execute(
"""SELECT type, state_key, event_id FROM current_state_events
WHERE room_id = ?
""",
(room_id,),
)
def get_current_state_ids_txn(
self, txn: LoggingTransaction, room_id: str
) -> StateMap[str]:
"""Get the current state event ids for a room based on the
current_state_events table.

Args:
txn: Transaction object
room_id: The room to get the state IDs of.

return {(intern_string(r[0]), intern_string(r[1])): r[2] for r in txn}
Returns:
The current state of the room.
"""

return await self.db_pool.runInteraction(
"get_current_state_ids", _get_current_state_ids_txn
txn.execute(
"""SELECT type, state_key, event_id FROM current_state_events
WHERE room_id = ?
""",
(room_id,),
)

return {(intern_string(r[0]), intern_string(r[1])): r[2] for r in txn}

# FIXME: how should this be cached?
async def get_filtered_current_state_ids(
self, room_id: str, state_filter: Optional[StateFilter] = None
Expand Down