|
47 | 47 | FederationError, |
48 | 48 | FederationPullAttemptBackoffError, |
49 | 49 | HttpResponseException, |
| 50 | + PartialStateConflictError, |
50 | 51 | RequestSendFailed, |
51 | 52 | SynapseError, |
52 | 53 | ) |
|
74 | 75 | ReplicationFederationSendEventsRestServlet, |
75 | 76 | ) |
76 | 77 | from synapse.state import StateResolutionStore |
77 | | -from synapse.storage.databases.main.events import PartialStateConflictError |
78 | 78 | from synapse.storage.databases.main.events_worker import EventRedactBehaviour |
79 | 79 | from synapse.types import ( |
80 | 80 | PersistedEventPosition, |
@@ -441,16 +441,17 @@ async def check_join_restrictions( |
441 | 441 | # Check if the user is already in the room or invited to the room. |
442 | 442 | user_id = event.state_key |
443 | 443 | prev_member_event_id = prev_state_ids.get((EventTypes.Member, user_id), None) |
444 | | - prev_member_event = None |
| 444 | + prev_membership = None |
445 | 445 | if prev_member_event_id: |
446 | 446 | prev_member_event = await self._store.get_event(prev_member_event_id) |
| 447 | + prev_membership = prev_member_event.membership |
447 | 448 |
|
448 | 449 | # Check if the member should be allowed access via membership in a space. |
449 | 450 | await self._event_auth_handler.check_restricted_join_rules( |
450 | 451 | prev_state_ids, |
451 | 452 | event.room_version, |
452 | 453 | user_id, |
453 | | - prev_member_event, |
| 454 | + prev_membership, |
454 | 455 | ) |
455 | 456 |
|
456 | 457 | @trace |
@@ -526,11 +527,57 @@ async def process_remote_join( |
526 | 527 | "Peristing join-via-remote %s (partial_state: %s)", event, partial_state |
527 | 528 | ) |
528 | 529 | with nested_logging_context(suffix=event.event_id): |
| 530 | + if partial_state: |
| 531 | + # When handling a second partial state join into a partial state room, |
| 532 | + # the returned state will exclude the membership from the first join. To |
| 533 | + # preserve prior memberships, we try to compute the partial state before |
| 534 | + # the event ourselves if we know about any of the prev events. |
| 535 | + # |
| 536 | + # When we don't know about any of the prev events, it's fine to just use |
| 537 | + # the returned state, since the new join will create a new forward |
| 538 | + # extremity, and leave the forward extremity containing our prior |
| 539 | + # memberships alone. |
| 540 | + prev_event_ids = set(event.prev_event_ids()) |
| 541 | + seen_event_ids = await self._store.have_events_in_timeline( |
| 542 | + prev_event_ids |
| 543 | + ) |
| 544 | + missing_event_ids = prev_event_ids - seen_event_ids |
| 545 | + |
| 546 | + state_maps_to_resolve: List[StateMap[str]] = [] |
| 547 | + |
| 548 | + # Fetch the state after the prev events that we know about. |
| 549 | + state_maps_to_resolve.extend( |
| 550 | + ( |
| 551 | + await self._state_storage_controller.get_state_groups_ids( |
| 552 | + room_id, seen_event_ids, await_full_state=False |
| 553 | + ) |
| 554 | + ).values() |
| 555 | + ) |
| 556 | + |
| 557 | + # When there are prev events we do not have the state for, we state |
| 558 | + # resolve with the state returned by the remote homeserver. |
| 559 | + if missing_event_ids or len(state_maps_to_resolve) == 0: |
| 560 | + state_maps_to_resolve.append( |
| 561 | + {(e.type, e.state_key): e.event_id for e in state} |
| 562 | + ) |
| 563 | + |
| 564 | + state_ids_before_event = ( |
| 565 | + await self._state_resolution_handler.resolve_events_with_store( |
| 566 | + event.room_id, |
| 567 | + room_version.identifier, |
| 568 | + state_maps_to_resolve, |
| 569 | + event_map=None, |
| 570 | + state_res_store=StateResolutionStore(self._store), |
| 571 | + ) |
| 572 | + ) |
| 573 | + else: |
| 574 | + state_ids_before_event = { |
| 575 | + (e.type, e.state_key): e.event_id for e in state |
| 576 | + } |
| 577 | + |
529 | 578 | context = await self._state_handler.compute_event_context( |
530 | 579 | event, |
531 | | - state_ids_before_event={ |
532 | | - (e.type, e.state_key): e.event_id for e in state |
533 | | - }, |
| 580 | + state_ids_before_event=state_ids_before_event, |
534 | 581 | partial_state=partial_state, |
535 | 582 | ) |
536 | 583 |
|
|
0 commit comments