base_client: replace event if prev_content deserialized from unsigned

master
Devin R 2020-05-22 17:12:58 -04:00
parent 20de6f6aea
commit 2f6bebdd1a
1 changed files with 93 additions and 60 deletions

View File

@ -79,13 +79,32 @@ pub struct AdditionalUnsignedData {
pub prev_content: Option<EventJson<MemberEventContent>>, pub prev_content: Option<EventJson<MemberEventContent>>,
} }
fn room_event_deserializer(event: &EventJson<RoomEvent>) -> Option<AdditionalUnsignedData> { /// If a `prev_content` field is found inside of `unsigned` we move it up to the events `prev_content` field.
serde_json::from_str::<AdditionalEventData>(event.json().get()) fn deserialize_prev_content(event: &EventJson<RoomEvent>) -> Option<EventJson<RoomEvent>> {
let prev_content = serde_json::from_str::<AdditionalEventData>(event.json().get())
.map(|more_unsigned| more_unsigned.unsigned) .map(|more_unsigned| more_unsigned.unsigned)
.map(|additional| additional.prev_content)
.ok() .ok()
.flatten();
if let Ok(mut ev) = event.deserialize() {
if let Some(prev) = prev_content {
match &mut ev {
RoomEvent::RoomMember(ref mut member) => {
member.prev_content = prev.deserialize().ok();
Some(EventJson::from(ev))
}
_ => None,
}
} else {
None
}
} else {
None
}
} }
fn stripped_event_deserializer( fn stripped_deserialize_prev_content(
event: &EventJson<AnyStrippedStateEvent>, event: &EventJson<AnyStrippedStateEvent>,
) -> Option<AdditionalUnsignedData> { ) -> Option<AdditionalUnsignedData> {
serde_json::from_str::<AdditionalEventData>(event.json().get()) serde_json::from_str::<AdditionalEventData>(event.json().get())
@ -505,6 +524,12 @@ impl BaseClient {
room_id: &RoomId, room_id: &RoomId,
event: &mut EventJson<RoomEvent>, event: &mut EventJson<RoomEvent>,
) -> (Option<EventJson<RoomEvent>>, bool) { ) -> (Option<EventJson<RoomEvent>>, bool) {
// if the event is a m.room.member event the server will sometimes
// send the `prev_content` field as part of the unsigned field this extracts and
// places it where everything else expects it.
if let Some(ev) = deserialize_prev_content(event) {
*event = ev;
}
match event.deserialize() { match event.deserialize() {
#[allow(unused_mut)] #[allow(unused_mut)]
Ok(mut e) => { Ok(mut e) => {
@ -528,8 +553,8 @@ impl BaseClient {
let room_lock = self.get_or_create_joined_room(&room_id).await; let room_lock = self.get_or_create_joined_room(&room_id).await;
let mut room = room_lock.write().await; let mut room = room_lock.write().await;
if let RoomEvent::RoomMember(event) = &e { if let RoomEvent::RoomMember(mem_event) = &mut e {
let changed = room.handle_membership(event); let changed = room.handle_membership(mem_event);
// The memberlist of the room changed, invalidate the group session // The memberlist of the room changed, invalidate the group session
// of the room. // of the room.
@ -815,17 +840,11 @@ impl BaseClient {
*event = e; *event = e;
} }
if let Ok(mut e) = event.deserialize() { if let Some(e) = deserialize_prev_content(&event) {
// if the event is a m.room.member event the server will sometimes *event = e;
// send the `prev_content` field as part of the unsigned field.
if let RoomEvent::RoomMember(member) = &mut e {
if let Some(raw_content) = room_event_deserializer(event) {
member.prev_content = match raw_content.prev_content {
Some(json) => json.deserialize().ok(),
None => None,
};
}
} }
if let Ok(e) = event.deserialize() {
self.emit_timeline_event(&room_id, &e, RoomStateType::Joined) self.emit_timeline_event(&room_id, &e, RoomStateType::Joined)
.await; .await;
} }
@ -912,21 +931,15 @@ impl BaseClient {
} }
for event in &mut left_room.timeline.events { for event in &mut left_room.timeline.events {
if let Some(e) = deserialize_prev_content(&event) {
*event = e;
}
if self.receive_left_timeline_event(room_id, &event).await { if self.receive_left_timeline_event(room_id, &event).await {
updated = true; updated = true;
}; };
if let Ok(mut e) = event.deserialize() { if let Ok(e) = event.deserialize() {
// if the event is a m.room.member event the server will sometimes
// send the `prev_content` field as part of the unsigned field.
if let RoomEvent::RoomMember(member) = &mut e {
if let Some(raw_content) = room_event_deserializer(event) {
member.prev_content = match raw_content.prev_content {
Some(json) => json.deserialize().ok(),
None => None,
};
}
}
self.emit_timeline_event(&room_id, &e, RoomStateType::Left) self.emit_timeline_event(&room_id, &e, RoomStateType::Left)
.await; .await;
} }
@ -966,7 +979,7 @@ impl BaseClient {
// if the event is a m.room.member event the server will sometimes // if the event is a m.room.member event the server will sometimes
// send the `prev_content` field as part of the unsigned field. // send the `prev_content` field as part of the unsigned field.
if let AnyStrippedStateEvent::RoomMember(_) = &mut e { if let AnyStrippedStateEvent::RoomMember(_) = &mut e {
if let Some(raw_content) = stripped_event_deserializer(event) { if let Some(raw_content) = stripped_deserialize_prev_content(event) {
let prev_content = match raw_content.prev_content { let prev_content = match raw_content.prev_content {
Some(json) => json.deserialize().ok(), Some(json) => json.deserialize().ok(),
None => None, None => None,
@ -1720,7 +1733,6 @@ mod test {
impl EventEmitter for EE { impl EventEmitter for EE {
async fn on_room_member(&self, room: SyncRoom, event: &MemberEvent) { async fn on_room_member(&self, room: SyncRoom, event: &MemberEvent) {
if let SyncRoom::Joined(_) = room { if let SyncRoom::Joined(_) = room {
println!("joined");
match event.membership_change() { match event.membership_change() {
MembershipChange::Joined => { MembershipChange::Joined => {
self.0.swap(true, Ordering::SeqCst); self.0.swap(true, Ordering::SeqCst);
@ -1729,7 +1741,6 @@ mod test {
}; };
} }
if event.prev_content.is_none() { if event.prev_content.is_none() {
println!("NOT found");
self.0.swap(false, Ordering::SeqCst); self.0.swap(false, Ordering::SeqCst);
} }
} }
@ -1740,42 +1751,64 @@ mod test {
let emitter = EE(Arc::clone(&passed)); let emitter = EE(Arc::clone(&passed));
let mut client = get_client(); let mut client = get_client();
// fake a room event with no EventEmitter to build the correct Room
let mut sync_response = EventBuilder::default()
.add_room_event(EventsFile::Member, RoomEvent::RoomMember)
.build_sync_response();
client
.receive_sync_response(&mut sync_response)
.await
.unwrap();
client.event_emitter = Arc::new(RwLock::new(Some(Box::new(emitter)))); client.event_emitter = Arc::new(RwLock::new(Some(Box::new(emitter))));
let event = serde_json::from_str::<EventJson<RoomEvent>>(include_str!( // This is needed other wise the `EventBuilder` goes through a de/ser cycle and the `prev_content` is lost.
let event = serde_json::from_str::<serde_json::Value>(include_str!(
"../../test_data/events/member.json" "../../test_data/events/member.json"
)) ))
.unwrap(); .unwrap();
let mut joined_rooms: HashMap<RoomId, serde_json::Value> = HashMap::new();
let joined_room = serde_json::json!({
"summary": {},
"account_data": {
"events": [],
},
"ephemeral": {
"events": [],
},
"state": {
"events": [],
},
"timeline": {
"events": vec![ event ],
"limited": true,
"prev_batch": "t392-516_47314_0_7_1_1_1_11444_1"
},
"unread_notifications": {
"highlight_count": 0,
"notification_count": 11
}
});
joined_rooms.insert(room_id, joined_room);
// FIXME since the `SyncResponse` created using EventBuilder doesn't pull out the `prev_content` let empty_room: HashMap<RoomId, serde_json::Value> = HashMap::new();
// from the `unsigned` field we must do this manually. let body = serde_json::json!({
// "device_one_time_keys_count": {},
// this is exactly what happens in `receive_sync_response` "next_batch": "s526_47314_0_7_1_1_1_11444_1",
if let Ok(mut e) = event.deserialize() { "device_lists": {
// if the event is a m.room.member event the server will sometimes "changed": [],
// send the `prev_content` field as part of the unsigned field. "left": []
if let RoomEvent::RoomMember(member) = &mut e { },
if let Some(raw_content) = room_event_deserializer(&event) { "rooms": {
member.prev_content = match raw_content.prev_content { "invite": empty_room,
Some(json) => json.deserialize().ok(), "join": joined_rooms,
None => None, "leave": empty_room,
}; },
} "to_device": {
println!("{:?}", member.prev_content); "events": []
} },
client "presence": {
.emit_timeline_event(&room_id, &e, RoomStateType::Joined) "events": []
.await;
} }
});
let response = http::Response::builder()
.body(serde_json::to_vec(&body).unwrap())
.unwrap();
let mut sync =
matrix_sdk_common::api::r0::sync::sync_events::Response::try_from(response).unwrap();
client.receive_sync_response(&mut sync).await.unwrap();
assert!(passed.load(Ordering::SeqCst)) assert!(passed.load(Ordering::SeqCst))
} }