|
39 | 39 | trace, |
40 | 40 | ) |
41 | 41 | from synapse.storage.databases.main.roommember import extract_heroes_from_room_summary |
| 42 | +from synapse.storage.databases.main.state_deltas import StateDelta |
42 | 43 | from synapse.storage.databases.main.stream import PaginateFunction |
43 | 44 | from synapse.storage.roommember import ( |
44 | 45 | MemberSummary, |
|
48 | 49 | MutableStateMap, |
49 | 50 | PersistedEventPosition, |
50 | 51 | Requester, |
| 52 | + RoomStreamToken, |
51 | 53 | SlidingSyncStreamToken, |
52 | 54 | StateMap, |
53 | 55 | StrCollection, |
@@ -470,6 +472,64 @@ async def get_current_state_at( |
470 | 472 |
|
471 | 473 | return state_map |
472 | 474 |
|
| 475 | + @trace |
| 476 | + async def get_current_state_deltas_for_room( |
| 477 | + self, |
| 478 | + room_id: str, |
| 479 | + room_membership_for_user_at_to_token: RoomsForUserType, |
| 480 | + from_token: RoomStreamToken, |
| 481 | + to_token: RoomStreamToken, |
| 482 | + ) -> List[StateDelta]: |
| 483 | + """ |
| 484 | + Get the state deltas between two tokens taking into account the user's |
| 485 | + membership. If the user is LEAVE/BAN, we will only get the state deltas up to |
| 486 | + their LEAVE/BAN event (inclusive). |
| 487 | +
|
| 488 | + (> `from_token` and <= `to_token`) |
| 489 | + """ |
| 490 | + membership = room_membership_for_user_at_to_token.membership |
| 491 | + # We don't know how to handle `membership` values other than these. The |
| 492 | + # code below would need to be updated. |
| 493 | + assert membership in ( |
| 494 | + Membership.JOIN, |
| 495 | + Membership.INVITE, |
| 496 | + Membership.KNOCK, |
| 497 | + Membership.LEAVE, |
| 498 | + Membership.BAN, |
| 499 | + ) |
| 500 | + |
| 501 | + # People shouldn't see past their leave/ban event |
| 502 | + if membership in ( |
| 503 | + Membership.LEAVE, |
| 504 | + Membership.BAN, |
| 505 | + ): |
| 506 | + to_bound = ( |
| 507 | + room_membership_for_user_at_to_token.event_pos.to_room_stream_token() |
| 508 | + ) |
| 509 | + # If we are participating in the room, we can get the latest current state in |
| 510 | + # the room |
| 511 | + elif membership == Membership.JOIN: |
| 512 | + to_bound = to_token |
| 513 | + # We can only rely on the stripped state included in the invite/knock event |
| 514 | + # itself so there will never be any state deltas to send down. |
| 515 | + elif membership in (Membership.INVITE, Membership.KNOCK): |
| 516 | + return [] |
| 517 | + else: |
| 518 | + # We don't know how to handle this type of membership yet |
| 519 | + # |
| 520 | + # FIXME: We should use `assert_never` here but for some reason |
| 521 | + # the exhaustive matching doesn't recognize the `Never` here. |
| 522 | + # assert_never(membership) |
| 523 | + raise AssertionError( |
| 524 | + f"Unexpected membership {membership} that we don't know how to handle yet" |
| 525 | + ) |
| 526 | + |
| 527 | + return await self.store.get_current_state_deltas_for_room( |
| 528 | + room_id=room_id, |
| 529 | + from_token=from_token, |
| 530 | + to_token=to_bound, |
| 531 | + ) |
| 532 | + |
473 | 533 | @trace |
474 | 534 | async def get_room_sync_data( |
475 | 535 | self, |
@@ -755,13 +815,19 @@ async def get_room_sync_data( |
755 | 815 |
|
756 | 816 | stripped_state = [] |
757 | 817 | if invite_or_knock_event.membership == Membership.INVITE: |
758 | | - stripped_state.extend( |
759 | | - invite_or_knock_event.unsigned.get("invite_room_state", []) |
| 818 | + invite_state = invite_or_knock_event.unsigned.get( |
| 819 | + "invite_room_state", [] |
760 | 820 | ) |
| 821 | + if not isinstance(invite_state, list): |
| 822 | + invite_state = [] |
| 823 | + |
| 824 | + stripped_state.extend(invite_state) |
761 | 825 | elif invite_or_knock_event.membership == Membership.KNOCK: |
762 | | - stripped_state.extend( |
763 | | - invite_or_knock_event.unsigned.get("knock_room_state", []) |
764 | | - ) |
| 826 | + knock_state = invite_or_knock_event.unsigned.get("knock_room_state", []) |
| 827 | + if not isinstance(knock_state, list): |
| 828 | + knock_state = [] |
| 829 | + |
| 830 | + stripped_state.extend(knock_state) |
765 | 831 |
|
766 | 832 | stripped_state.append(strip_event(invite_or_knock_event)) |
767 | 833 |
|
@@ -790,8 +856,9 @@ async def get_room_sync_data( |
790 | 856 | # TODO: Limit the number of state events we're about to send down |
791 | 857 | # the room, if its too many we should change this to an |
792 | 858 | # `initial=True`? |
793 | | - deltas = await self.store.get_current_state_deltas_for_room( |
| 859 | + deltas = await self.get_current_state_deltas_for_room( |
794 | 860 | room_id=room_id, |
| 861 | + room_membership_for_user_at_to_token=room_membership_for_user_at_to_token, |
795 | 862 | from_token=from_bound, |
796 | 863 | to_token=to_token.room_key, |
797 | 864 | ) |
|
0 commit comments