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 15 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
1 change: 1 addition & 0 deletions changelog.d/10697.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ensure `rooms.creator` field is always populated for easy lookup in [MSC2716](https://github.com/matrix-org/matrix-doc/pull/2716) usage later.
11 changes: 9 additions & 2 deletions synapse/handlers/federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,9 +796,15 @@ 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 not self.hs.config.experimental.msc2716_enabled
erikjohnston marked this conversation as resolved.
Show resolved Hide resolved
or marker_event.sender != room_creator
):
return

logger.debug("_handle_marker_event: received %s", marker_event)
Expand Down Expand Up @@ -1690,6 +1696,7 @@ async def do_invite_join(
await self.store.upsert_room_on_join(
room_id=room_id,
room_version=room_version_obj,
auth_events=auth_chain,
)

max_stream_id = await self._persist_auth_tree(
Expand Down
28 changes: 25 additions & 3 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,9 @@ async def persist_and_notify_client_event(
allow_none=True,
)

room_version = await self.store.get_room_version_id(event.room_id)
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

# we can make some additional checks now if we have the original event.
if original_event:
if original_event.type == EventTypes.Create:
Expand All @@ -1387,16 +1390,35 @@ async def persist_and_notify_client_event(
if original_event.type == EventTypes.ServerACL:
raise AuthError(403, "Redacting server ACL events is not permitted")

# Add a little safety stop-gap to prevent people from trying to
# redact MSC2716 related events when they're in a room version
# which does not support it yet. We allow people to use MSC2716
# events in existing room versions but only from the room
# creator since it does not require any changes to the auth
# rules and in effect, the redaction algorithm . In the
# supported room version, we add the `historical` power level to
# auth the MSC2716 related events and adjust the redaction
# algorthim to keep the `historical` field around (redacting an
# event should only strip fields which don't affect the
# structural protocol level).
is_msc2716_event = (
original_event.type == EventTypes.MSC2716_INSERTION
or original_event.type == EventTypes.MSC2716_CHUNK
or original_event.type == EventTypes.MSC2716_MARKER
)
if not room_version_obj.msc2716_historical and is_msc2716_event:
raise AuthError(
403,
"Redacting MSC2716 events is not supported in this room version",
)

prev_state_ids = await context.get_prev_state_ids()
auth_events_ids = self._event_auth_handler.compute_auth_events(
event, prev_state_ids, for_verification=True
)
auth_events_map = await self.store.get_events(auth_events_ids)
auth_events = {(e.type, e.state_key): e for e in auth_events_map.values()}

room_version = await self.store.get_room_version_id(event.room_id)
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

if event_auth.check_redaction(
room_version_obj, event, auth_events=auth_events
):
Expand Down
32 changes: 27 additions & 5 deletions synapse/storage/databases/main/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1770,10 +1770,21 @@ 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:
room_creator = self.db_pool.simple_select_one_onecol_txn(
txn,
table="rooms",
keyvalues={"room_id": event.room_id},
retcol="creator",
allow_none=True,
)
if (
not room_version.msc2716_historical
or not self.hs.config.experimental.msc2716_enabled
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
or event.sender != room_creator
):
return

next_chunk_id = event.content.get(EventContentFields.MSC2716_NEXT_CHUNK_ID)
Expand Down Expand Up @@ -1822,9 +1833,20 @@ 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:
room_creator = self.db_pool.simple_select_one_onecol_txn(
txn,
table="rooms",
keyvalues={"room_id": event.room_id},
retcol="creator",
allow_none=True,
)
if (
not room_version.msc2716_historical
or not self.hs.config.experimental.msc2716_enabled
or event.sender != room_creator
):
return

chunk_id = event.content.get(EventContentFields.MSC2716_CHUNK_ID)
Expand Down
90 changes: 86 additions & 4 deletions synapse/storage/databases/main/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from synapse.api.constants import EventTypes, JoinRules
from synapse.api.errors import StoreError
from synapse.api.room_versions import RoomVersion, RoomVersions
from synapse.events import EventBase
from synapse.storage._base import SQLBaseStore, db_to_json
from synapse.storage.database import DatabasePool, LoggingTransaction
from synapse.storage.databases.main.search import SearchStore
Expand Down Expand Up @@ -1011,6 +1012,7 @@ def get_rooms_for_retention_period_in_range_txn(txn):
class _BackgroundUpdates:
REMOVE_TOMESTONED_ROOMS_BG_UPDATE = "remove_tombstoned_rooms_from_directory"
ADD_ROOMS_ROOM_VERSION_COLUMN = "add_rooms_room_version_column"
POPULATE_ROOMS_CREATOR_COLUMN = "populate_rooms_creator_column"
POPULATE_ROOM_DEPTH_MIN_DEPTH2 = "populate_room_depth_min_depth2"
REPLACE_ROOM_DEPTH_MIN_DEPTH = "replace_room_depth_min_depth"

Expand Down Expand Up @@ -1044,6 +1046,11 @@ def __init__(self, database: DatabasePool, db_conn, hs):
self._background_add_rooms_room_version_column,
)

self.db_pool.updates.register_background_update_handler(
_BackgroundUpdates.POPULATE_ROOMS_CREATOR_COLUMN,
self._background_populate_rooms_creator_column,
)

# BG updates to change the type of room_depth.min_depth
self.db_pool.updates.register_background_update_handler(
_BackgroundUpdates.POPULATE_ROOM_DEPTH_MIN_DEPTH2,
Expand Down Expand Up @@ -1191,6 +1198,63 @@ def _background_add_rooms_room_version_column_txn(txn: LoggingTransaction):

return batch_size

async def _background_populate_rooms_creator_column(
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
self, progress: dict, batch_size: int
):
"""Background update to go and add creator information to `rooms`
table from `current_state_events` table.
"""
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved

last_room_id = progress.get("room_id", "")

def _background_populate_rooms_creator_column_txn(txn: LoggingTransaction):
sql = """
SELECT room_id, json FROM current_state_events
INNER JOIN event_json USING (room_id, event_id)
WHERE room_id > ? AND type = 'm.room.create' AND state_key = ''
ORDER BY room_id
LIMIT ?
"""

txn.execute(sql, (last_room_id, batch_size))

new_last_room_id = ""
for room_id, event_json in txn:
event_dict = db_to_json(event_json)

creator = event_dict.get("content").get("creator")

self.db_pool.simple_update_txn(
txn,
table="rooms",
keyvalues={"room_id": room_id},
updatevalues={"creator": creator},
)
new_last_room_id = room_id

if new_last_room_id == "":
return True

self.db_pool.updates._background_update_progress_txn(
txn,
_BackgroundUpdates.POPULATE_ROOMS_CREATOR_COLUMN,
{"room_id": new_last_room_id},
)

return False

end = await self.db_pool.runInteraction(
"_background_populate_rooms_creator_column",
_background_populate_rooms_creator_column_txn,
)

if end:
await self.db_pool.updates._end_background_update(
_BackgroundUpdates.POPULATE_ROOMS_CREATOR_COLUMN
)

return batch_size

async def _remove_tombstoned_rooms_from_directory(
self, progress, batch_size
) -> int:
Expand Down Expand Up @@ -1273,7 +1337,7 @@ async def has_auth_chain_index(self, room_id: str) -> bool:
keyvalues={"room_id": room_id},
retcol="MAX(stream_ordering)",
allow_none=True,
desc="upsert_room_on_join",
desc="has_auth_chain_index_fallback",
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
)

return max_ordering is None
Expand Down Expand Up @@ -1350,7 +1414,9 @@ def __init__(self, database: DatabasePool, db_conn, hs):

self.config = hs.config

async def upsert_room_on_join(self, room_id: str, room_version: RoomVersion):
async def upsert_room_on_join(
self, room_id: str, room_version: RoomVersion, auth_events: List[EventBase]
):
"""Ensure that the room is stored in the table

Called when we join a room over federation, and overwrites any room version
Expand All @@ -1361,14 +1427,27 @@ async def upsert_room_on_join(self, room_id: str, room_version: RoomVersion):
# mark the room as having an auth chain cover index.
has_auth_chain_index = await self.has_auth_chain_index(room_id)

create_event = None
for e in auth_events:
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
if (e.type, e.state_key) == (EventTypes.Create, ""):
create_event = e
break

if create_event is None:
# If the state doesn't have a create event then the room is
# invalid, and it would fail auth checks anyway.
raise StoreError(400, "No create event in state")

room_creator = create_event.content.get("creator", None)

await self.db_pool.simple_upsert(
desc="upsert_room_on_join",
table="rooms",
keyvalues={"room_id": room_id},
values={"room_version": room_version.identifier},
insertion_values={
"is_public": False,
"creator": "",
"creator": room_creator,
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
"has_auth_chain_index": has_auth_chain_index,
},
# rooms has a unique constraint on room_id, so no need to lock when doing an
Expand All @@ -1388,6 +1467,9 @@ async def maybe_store_room_on_outlier_membership(
# mark the room as having an auth chain cover index.
has_auth_chain_index = await self.has_auth_chain_index(room_id)

create_event = await self.get_create_event_for_room(room_id)
room_creator = create_event.content.get("creator", None)
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved

await self.db_pool.simple_upsert(
desc="maybe_store_room_on_outlier_membership",
table="rooms",
Expand All @@ -1396,7 +1478,7 @@ async def maybe_store_room_on_outlier_membership(
insertion_values={
"room_version": room_version.identifier,
"is_public": False,
"creator": "",
"creator": room_creator,
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
"has_auth_chain_index": has_auth_chain_index,
},
# rooms has a unique constraint on room_id, so no need to lock when doing an
Expand Down
17 changes: 17 additions & 0 deletions synapse/storage/schema/main/delta/63/02populate-rooms-creator.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* Copyright 2021 The Matrix.org Foundation C.I.C
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

INSERT into background_updates (update_name, progress_json)
VALUES ('populate_rooms_creator_column', '{}');
Loading