Skip to content

Commit

Permalink
feat(knocking): use handle_stripped_state_event to check the member…
Browse files Browse the repository at this point in the history
…ship state event
  • Loading branch information
jmartinesp committed Oct 15, 2024
1 parent 839edf0 commit 73bf2f4
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 48 deletions.
10 changes: 8 additions & 2 deletions crates/matrix-sdk-base/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,16 @@ impl BaseClient {
) -> Result<()> {
let mut state_events = BTreeMap::new();

let session_user_id = self
.session_meta()
.expect("Sliding sync shouldn't run without an authenticated user.")
.user_id
.to_owned();

for raw_event in events {
match raw_event.deserialize() {
Ok(e) => {
room_info.handle_stripped_state_event(&e);
room_info.handle_stripped_state_event(&session_user_id, &e);
state_events
.entry(e.event_type())
.or_insert_with(BTreeMap::new)
Expand Down Expand Up @@ -1143,7 +1149,7 @@ impl BaseClient {
);

let mut room_info = room.clone_info();
room_info.mark_as_invited();
room_info.mark_as_knocked();
room_info.mark_state_fully_synced();

self.handle_invited_state(
Expand Down
23 changes: 21 additions & 2 deletions crates/matrix-sdk-base/src/rooms/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,8 +1260,27 @@ impl RoomInfo {
/// Handle the given stripped state event.
///
/// Returns true if the event modified the info, false otherwise.
pub fn handle_stripped_state_event(&mut self, event: &AnyStrippedStateEvent) -> bool {
self.base_info.handle_stripped_state_event(event)
pub fn handle_stripped_state_event(
&mut self,
current_user_id: &UserId,
event: &AnyStrippedStateEvent,
) -> bool {
if let AnyStrippedStateEvent::RoomMember(member) = event {
if member.state_key == current_user_id {
if member.content.membership == MembershipState::Knock {
// If it has a knocked membership, mark it as knocked.
self.mark_as_knocked();
} else {
// Otherwise, assume it's an error and it should be invited instead.
self.mark_as_invited();
}
return true;
}
// If the membership event wasn't for the current user, make no changes.
false
} else {
self.base_info.handle_stripped_state_event(event)
}
}

/// Handle the given redaction.
Expand Down
73 changes: 30 additions & 43 deletions crates/matrix-sdk-base/src/sliding_sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ use ruma::events::AnyToDeviceEvent;
use ruma::{
api::client::sync::sync_events::v3::{self, InvitedRoom, KnockedRoom},
events::{
room::member::MembershipState, AnyRoomAccountDataEvent, AnyStrippedStateEvent,
AnySyncStateEvent, AnySyncTimelineEvent,
AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncStateEvent, AnySyncTimelineEvent,
},
serde::Raw,
JsOption, OwnedRoomId, RoomId, UInt,
Expand Down Expand Up @@ -417,7 +416,7 @@ impl BaseClient {
}

#[allow(unused_mut)] // Required for some feature flag combinations
let (mut room, mut room_info, invited_room, knocked_room) = self
let (mut room, mut room_info, invite_state_events) = self
.process_sliding_sync_room_membership(
room_data.as_ref(),
&state_events,
Expand Down Expand Up @@ -544,9 +543,18 @@ impl BaseClient {
None,
)),

RoomState::Invited => Ok((room_info, None, None, invited_room, None)),
RoomState::Invited => {
let invited_room = InvitedRoom::from(v3::InviteState::from(
invite_state_events.unwrap_or_default(),
));
Ok((room_info, None, None, Some(invited_room), None))
}

RoomState::Knocked => Ok((room_info, None, None, None, knocked_room)),
RoomState::Knocked => {
let knock_state = assign!(v3::KnockState::default(), { events: invite_state_events.unwrap_or_default() });
let knocked_room = assign!(KnockedRoom::default(), { knock_state: knock_state });
Ok((room_info, None, None, None, Some(knocked_room)))
}
}
}

Expand All @@ -562,49 +570,28 @@ impl BaseClient {
store: &Store,
room_id: &RoomId,
room_info_notable_updates: &mut BTreeMap<OwnedRoomId, RoomInfoNotableUpdateReasons>,
) -> (Room, RoomInfo, Option<InvitedRoom>, Option<KnockedRoom>) {
let user_id = self
.session_meta()
.expect("Sliding sync shouldn't run without an authenticated user.")
.user_id
.to_owned();
) -> (Room, RoomInfo, Option<Vec<Raw<AnyStrippedStateEvent>>>) {
if let Some(invite_state) = &room_data.invite_state {
let room = store.get_or_create_room(
room_id,
RoomState::Invited,
self.room_info_notable_update_sender.clone(),
);
let mut room_info = room.clone_info();

// We need to find the membership event since it could be for either an invited
// or knocked room
let membership_event_content = invite_state.iter().find_map(|raw| {
raw.deserialize().ok().iter().find_map(|e| {
if let AnyStrippedStateEvent::RoomMember(membership_event) = e {
if membership_event.sender == user_id {
return Some(membership_event.content.clone());
}
}
None
})
});

if let Some(membership_event_content) = membership_event_content {
if membership_event_content.membership == MembershipState::Knock {
// If we have a `Knock` membership state, set the room as such
room_info.mark_as_knocked();
let knock_state =
assign!(v3::KnockState::default(), { events: invite_state.clone() });
let knocked_room =
assign!(KnockedRoom::default(), { knock_state: knock_state });
return (room, room_info, None, Some(knocked_room));
}
}

// Otherwise assume it's an invited room
room_info.mark_as_invited();
let invited_room = InvitedRoom::from(v3::InviteState::from(invite_state.clone()));
(room, room_info, Some(invited_room), None)
let room_info = room.clone_info();

// We don't actually know what events are inside invite_state. In theory, they
// might not contain an m.room.member event, or they might set the
// membership to something other than invite or knock. This
// would be very weird behaviour by the server, because invite_state
// is supposed to contain an m.room.member. We will call
// handle_invited_state, which will reflect any information found in
// the real events inside invite_state, but we default to
// considering this room invited simply because invite_state exists.
// This is needed in the normal case, because the sliding sync
// server tries to send minimal state, meaning that we normally
// actually just receive {"type": "m.room.member"} with no content
// at all.
(room, room_info, Some(invite_state.clone()))
} else {
let room = store.get_or_create_room(
room_id,
Expand All @@ -630,7 +617,7 @@ impl BaseClient {
room_info_notable_updates,
);

(room, room_info, None, None)
(room, room_info, None)
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/matrix-sdk-base/src/store/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl StateStoreIntegrationTests for DynStateStore {
serde_json::from_value::<Raw<AnyStrippedStateEvent>>(stripped_name_json.clone())
.unwrap();
let stripped_name_event = stripped_name_raw.deserialize().unwrap();
stripped_room.handle_stripped_state_event(&stripped_name_event);
stripped_room.handle_stripped_state_event(user_id, &stripped_name_event);
changes.stripped_state.insert(
stripped_room_id.to_owned(),
BTreeMap::from([(
Expand Down

0 comments on commit 73bf2f4

Please sign in to comment.