fix: send state in /sync, element displays wrong membership changes
This commit is contained in:
		
							parent
							
								
									6606e41dde
								
							
						
					
					
						commit
						f12fbca3c5
					
				
					 4 changed files with 55 additions and 18 deletions
				
			
		|  | @ -686,7 +686,7 @@ async fn join_room_by_id_helper( | |||
|             pdu_id.extend_from_slice(&count.to_be_bytes()); | ||||
|             db.rooms.append_pdu( | ||||
|                 &PduEvent::from(&**pdu), | ||||
|                 &utils::to_canonical_object(&**pdu).expect("Pdu is valid canonical object"), | ||||
|                 utils::to_canonical_object(&**pdu).expect("Pdu is valid canonical object"), | ||||
|                 count, | ||||
|                 pdu_id.clone().into(), | ||||
|                 &db.globals, | ||||
|  |  | |||
|  | @ -91,15 +91,7 @@ pub async fn sync_events_route( | |||
| 
 | ||||
|         // They /sync response doesn't always return all messages, so we say the output is
 | ||||
|         // limited unless there are events in non_timeline_pdus
 | ||||
|         let mut limited = false; | ||||
| 
 | ||||
|         let mut state_pdus = Vec::new(); | ||||
|         for (_, pdu) in non_timeline_pdus { | ||||
|             if pdu.state_key.is_some() { | ||||
|                 state_pdus.push(pdu); | ||||
|             } | ||||
|             limited = true; | ||||
|         } | ||||
|         let limited = non_timeline_pdus.next().is_some(); | ||||
| 
 | ||||
|         // Database queries:
 | ||||
| 
 | ||||
|  | @ -342,7 +334,7 @@ pub async fn sync_events_route( | |||
|             })?; | ||||
| 
 | ||||
|         let room_events = timeline_pdus | ||||
|             .into_iter() | ||||
|             .iter() | ||||
|             .map(|(_, pdu)| pdu.to_sync_room_event()) | ||||
|             .collect::<Vec<_>>(); | ||||
| 
 | ||||
|  | @ -392,7 +384,6 @@ pub async fn sync_events_route( | |||
|                 prev_batch, | ||||
|                 events: room_events, | ||||
|             }, | ||||
|             // TODO: state before timeline
 | ||||
|             state: sync_events::State { | ||||
|                 events: if joined_since_last_sync { | ||||
|                     db.rooms | ||||
|  | @ -401,7 +392,26 @@ pub async fn sync_events_route( | |||
|                         .map(|(_, pdu)| pdu.to_sync_state_event()) | ||||
|                         .collect() | ||||
|                 } else { | ||||
|                     Vec::new() | ||||
|                     match since_state { | ||||
|                         None => Vec::new(), | ||||
|                         Some(Some(since_state)) => current_state | ||||
|                             .iter() | ||||
|                             .filter(|(key, value)| { | ||||
|                                 since_state.get(key).map(|e| &e.event_id) != Some(&value.event_id) | ||||
|                             }) | ||||
|                             .filter(|(_, value)| { | ||||
|                                 !timeline_pdus.iter().any(|(_, timeline_pdu)| { | ||||
|                                     timeline_pdu.kind == value.kind | ||||
|                                         && timeline_pdu.state_key == value.state_key | ||||
|                                 }) | ||||
|                             }) | ||||
|                             .map(|(_, pdu)| pdu.to_sync_state_event()) | ||||
|                             .collect(), | ||||
|                         Some(None) => current_state | ||||
|                             .iter() | ||||
|                             .map(|(_, pdu)| pdu.to_sync_state_event()) | ||||
|                             .collect(), | ||||
|                     } | ||||
|                 }, | ||||
|             }, | ||||
|             ephemeral: sync_events::Ephemeral { events: edus }, | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ use ruma::{ | |||
|         }, | ||||
|         EventType, | ||||
|     }, | ||||
|     serde::{to_canonical_value, CanonicalJsonObject, Raw}, | ||||
|     serde::{to_canonical_value, CanonicalJsonObject, CanonicalJsonValue, Raw}, | ||||
|     EventId, RoomAliasId, RoomId, RoomVersionId, ServerName, UserId, | ||||
| }; | ||||
| use sled::IVec; | ||||
|  | @ -444,13 +444,40 @@ impl Rooms { | |||
|     pub fn append_pdu( | ||||
|         &self, | ||||
|         pdu: &PduEvent, | ||||
|         pdu_json: &CanonicalJsonObject, | ||||
|         mut pdu_json: CanonicalJsonObject, | ||||
|         count: u64, | ||||
|         pdu_id: IVec, | ||||
|         globals: &super::globals::Globals, | ||||
|         account_data: &super::account_data::AccountData, | ||||
|         admin: &super::admin::Admin, | ||||
|     ) -> Result<()> { | ||||
|         // Make unsigned fields correct. This is not properly documented in the spec, but state
 | ||||
|         // events need to have previous content in the unsigned field, so clients can easily
 | ||||
|         // interpret things like membership changes
 | ||||
|         if let Some(state_key) = &pdu.state_key { | ||||
|             if let CanonicalJsonValue::Object(unsigned) = pdu_json | ||||
|                 .entry("unsigned".to_owned()) | ||||
|                 .or_insert_with(|| CanonicalJsonValue::Object(Default::default())) | ||||
|             { | ||||
|                 if let Some(prev_state_hash) = self.pdu_state_hash(&pdu_id).unwrap() { | ||||
|                     if let Some(prev_state) = self | ||||
|                         .state_get(&pdu.room_id, &prev_state_hash, &pdu.kind, &state_key) | ||||
|                         .unwrap() | ||||
|                     { | ||||
|                         unsigned.insert( | ||||
|                             "prev_content".to_owned(), | ||||
|                             CanonicalJsonValue::Object( | ||||
|                                 utils::to_canonical_object(prev_state.1.content) | ||||
|                                     .expect("event is valid, we just created it"), | ||||
|                             ), | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 error!("Invalid unsigned type in pdu."); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         self.replace_pdu_leaves(&pdu.room_id, &pdu.event_id)?; | ||||
| 
 | ||||
|         // Mark as read first so the sending client doesn't get a notification even if appending
 | ||||
|  | @ -460,7 +487,7 @@ impl Rooms { | |||
| 
 | ||||
|         self.pduid_pdu.insert( | ||||
|             &pdu_id, | ||||
|             &*serde_json::to_string(pdu_json) | ||||
|             &*serde_json::to_string(&pdu_json) | ||||
|                 .expect("CanonicalJsonObject is always a valid String"), | ||||
|         )?; | ||||
| 
 | ||||
|  | @ -905,7 +932,7 @@ impl Rooms { | |||
| 
 | ||||
|         self.append_pdu( | ||||
|             &pdu, | ||||
|             &pdu_json, | ||||
|             pdu_json, | ||||
|             count, | ||||
|             pdu_id.clone().into(), | ||||
|             globals, | ||||
|  |  | |||
|  | @ -494,7 +494,7 @@ pub async fn send_transaction_message_route<'a>( | |||
| 
 | ||||
|         db.rooms.append_pdu( | ||||
|             &pdu, | ||||
|             &value, | ||||
|             value, | ||||
|             count, | ||||
|             pdu_id.clone().into(), | ||||
|             &db.globals, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue