19
19
from enum import Enum
20
20
from typing import Any , Dict , List , Optional , Tuple
21
21
22
- from synapse .api .constants import EventTypes , JoinRules
22
+ from synapse .api .constants import EventContentFields , EventTypes , JoinRules
23
23
from synapse .api .errors import StoreError
24
24
from synapse .api .room_versions import RoomVersion , RoomVersions
25
+ from synapse .events import EventBase
25
26
from synapse .storage ._base import SQLBaseStore , db_to_json
26
27
from synapse .storage .database import DatabasePool , LoggingTransaction
27
28
from synapse .storage .databases .main .search import SearchStore
@@ -1013,6 +1014,7 @@ class _BackgroundUpdates:
1013
1014
ADD_ROOMS_ROOM_VERSION_COLUMN = "add_rooms_room_version_column"
1014
1015
POPULATE_ROOM_DEPTH_MIN_DEPTH2 = "populate_room_depth_min_depth2"
1015
1016
REPLACE_ROOM_DEPTH_MIN_DEPTH = "replace_room_depth_min_depth"
1017
+ POPULATE_ROOMS_CREATOR_COLUMN = "populate_rooms_creator_column"
1016
1018
1017
1019
1018
1020
_REPLACE_ROOM_DEPTH_SQL_COMMANDS = (
@@ -1054,6 +1056,11 @@ def __init__(self, database: DatabasePool, db_conn, hs):
1054
1056
self ._background_replace_room_depth_min_depth ,
1055
1057
)
1056
1058
1059
+ self .db_pool .updates .register_background_update_handler (
1060
+ _BackgroundUpdates .POPULATE_ROOMS_CREATOR_COLUMN ,
1061
+ self ._background_populate_rooms_creator_column ,
1062
+ )
1063
+
1057
1064
async def _background_insert_retention (self , progress , batch_size ):
1058
1065
"""Retrieves a list of all rooms within a range and inserts an entry for each of
1059
1066
them into the room_retention table.
@@ -1273,7 +1280,7 @@ async def has_auth_chain_index(self, room_id: str) -> bool:
1273
1280
keyvalues = {"room_id" : room_id },
1274
1281
retcol = "MAX(stream_ordering)" ,
1275
1282
allow_none = True ,
1276
- desc = "upsert_room_on_join " ,
1283
+ desc = "has_auth_chain_index_fallback " ,
1277
1284
)
1278
1285
1279
1286
return max_ordering is None
@@ -1343,14 +1350,75 @@ def process(txn: Cursor) -> None:
1343
1350
1344
1351
return 0
1345
1352
1353
+ async def _background_populate_rooms_creator_column (
1354
+ self , progress : dict , batch_size : int
1355
+ ):
1356
+ """Background update to go and add creator information to `rooms`
1357
+ table from `current_state_events` table.
1358
+ """
1359
+
1360
+ last_room_id = progress .get ("room_id" , "" )
1361
+
1362
+ def _background_populate_rooms_creator_column_txn (txn : LoggingTransaction ):
1363
+ sql = """
1364
+ SELECT room_id, json FROM event_json
1365
+ INNER JOIN rooms AS room USING (room_id)
1366
+ INNER JOIN current_state_events AS state_event USING (room_id, event_id)
1367
+ WHERE room_id > ? AND (room.creator IS NULL OR room.creator = '') AND state_event.type = 'm.room.create' AND state_event.state_key = ''
1368
+ ORDER BY room_id
1369
+ LIMIT ?
1370
+ """
1371
+
1372
+ txn .execute (sql , (last_room_id , batch_size ))
1373
+ room_id_to_create_event_results = txn .fetchall ()
1374
+
1375
+ new_last_room_id = ""
1376
+ for room_id , event_json in room_id_to_create_event_results :
1377
+ event_dict = db_to_json (event_json )
1378
+
1379
+ creator = event_dict .get ("content" ).get (EventContentFields .ROOM_CREATOR )
1380
+
1381
+ self .db_pool .simple_update_txn (
1382
+ txn ,
1383
+ table = "rooms" ,
1384
+ keyvalues = {"room_id" : room_id },
1385
+ updatevalues = {"creator" : creator },
1386
+ )
1387
+ new_last_room_id = room_id
1388
+
1389
+ if new_last_room_id == "" :
1390
+ return True
1391
+
1392
+ self .db_pool .updates ._background_update_progress_txn (
1393
+ txn ,
1394
+ _BackgroundUpdates .POPULATE_ROOMS_CREATOR_COLUMN ,
1395
+ {"room_id" : new_last_room_id },
1396
+ )
1397
+
1398
+ return False
1399
+
1400
+ end = await self .db_pool .runInteraction (
1401
+ "_background_populate_rooms_creator_column" ,
1402
+ _background_populate_rooms_creator_column_txn ,
1403
+ )
1404
+
1405
+ if end :
1406
+ await self .db_pool .updates ._end_background_update (
1407
+ _BackgroundUpdates .POPULATE_ROOMS_CREATOR_COLUMN
1408
+ )
1409
+
1410
+ return batch_size
1411
+
1346
1412
1347
1413
class RoomStore (RoomBackgroundUpdateStore , RoomWorkerStore , SearchStore ):
1348
1414
def __init__ (self , database : DatabasePool , db_conn , hs ):
1349
1415
super ().__init__ (database , db_conn , hs )
1350
1416
1351
1417
self .config = hs .config
1352
1418
1353
- async def upsert_room_on_join (self , room_id : str , room_version : RoomVersion ):
1419
+ async def upsert_room_on_join (
1420
+ self , room_id : str , room_version : RoomVersion , auth_events : List [EventBase ]
1421
+ ):
1354
1422
"""Ensure that the room is stored in the table
1355
1423
1356
1424
Called when we join a room over federation, and overwrites any room version
@@ -1361,14 +1429,32 @@ async def upsert_room_on_join(self, room_id: str, room_version: RoomVersion):
1361
1429
# mark the room as having an auth chain cover index.
1362
1430
has_auth_chain_index = await self .has_auth_chain_index (room_id )
1363
1431
1432
+ create_event = None
1433
+ for e in auth_events :
1434
+ if (e .type , e .state_key ) == (EventTypes .Create , "" ):
1435
+ create_event = e
1436
+ break
1437
+
1438
+ if create_event is None :
1439
+ # If the state doesn't have a create event then the room is
1440
+ # invalid, and it would fail auth checks anyway.
1441
+ raise StoreError (400 , "No create event in state" )
1442
+
1443
+ room_creator = create_event .content .get (EventContentFields .ROOM_CREATOR )
1444
+
1445
+ if not isinstance (room_creator , str ):
1446
+ # If the create event does not have a creator then the room is
1447
+ # invalid, and it would fail auth checks anyway.
1448
+ raise StoreError (400 , "No creator defined on the create event" )
1449
+
1364
1450
await self .db_pool .simple_upsert (
1365
1451
desc = "upsert_room_on_join" ,
1366
1452
table = "rooms" ,
1367
1453
keyvalues = {"room_id" : room_id },
1368
1454
values = {"room_version" : room_version .identifier },
1369
1455
insertion_values = {
1370
1456
"is_public" : False ,
1371
- "creator" : "" ,
1457
+ "creator" : room_creator ,
1372
1458
"has_auth_chain_index" : has_auth_chain_index ,
1373
1459
},
1374
1460
# rooms has a unique constraint on room_id, so no need to lock when doing an
@@ -1396,6 +1482,9 @@ async def maybe_store_room_on_outlier_membership(
1396
1482
insertion_values = {
1397
1483
"room_version" : room_version .identifier ,
1398
1484
"is_public" : False ,
1485
+ # We don't worry about setting the `creator` here because
1486
+ # we don't process any messages in a room while a user is
1487
+ # invited (only after the join).
1399
1488
"creator" : "" ,
1400
1489
"has_auth_chain_index" : has_auth_chain_index ,
1401
1490
},
0 commit comments