improvement: log bad database errors automatically
This commit is contained in:
		
							parent
							
								
									2368a90584
								
							
						
					
					
						commit
						56d4742201
					
				
					 13 changed files with 278 additions and 208 deletions
				
			
		|  | @ -362,17 +362,14 @@ pub fn get_pushrules_all_route( | |||
|             "PushRules event not found.", | ||||
|         ))? | ||||
|         .deserialize() | ||||
|         .map_err(|_| Error::BadRequest( | ||||
|             ErrorKind::NotFound, | ||||
|             "PushRules event in db is invalid.", | ||||
|         ))? | ||||
|         .map_err(|_| Error::BadRequest(ErrorKind::NotFound, "PushRules event in db is invalid."))? | ||||
|     { | ||||
|         Ok(get_pushrules_all::Response { | ||||
|             global: pushrules.content.global, | ||||
|         } | ||||
|         .into()) | ||||
|     } else { | ||||
|         Err(Error::BadDatabase("Pushrules event has wrong content.")) | ||||
|         Err(Error::bad_database("Pushrules event has wrong content.")) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -507,15 +504,17 @@ pub fn set_displayname_route( | |||
|                     db.rooms | ||||
|                         .room_state(&room_id)? | ||||
|                         .get(&(EventType::RoomMember, user_id.to_string())) | ||||
|                         .ok_or(Error::BadDatabase( | ||||
|                             "Tried to send displayname update for user not in the room.", | ||||
|                         ))? | ||||
|                         .ok_or_else(|| { | ||||
|                             Error::bad_database( | ||||
|                                 "Tried to send displayname update for user not in the room.", | ||||
|                             ) | ||||
|                         })? | ||||
|                         .content | ||||
|                         .clone(), | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Database contains invalid PDU."))? | ||||
|                 .map_err(|_| Error::bad_database("Database contains invalid PDU."))? | ||||
|                 .deserialize() | ||||
|                 .map_err(|_| Error::BadDatabase("Database contains invalid PDU."))? | ||||
|                 .map_err(|_| Error::bad_database("Database contains invalid PDU."))? | ||||
|             }) | ||||
|             .expect("event is valid, we just created it"), | ||||
|             None, | ||||
|  | @ -596,15 +595,17 @@ pub fn set_avatar_url_route( | |||
|                     db.rooms | ||||
|                         .room_state(&room_id)? | ||||
|                         .get(&(EventType::RoomMember, user_id.to_string())) | ||||
|                         .ok_or(Error::BadDatabase( | ||||
|                             "Tried to send avatar url update for user not in the room.", | ||||
|                         ))? | ||||
|                         .ok_or_else(|| { | ||||
|                             Error::bad_database( | ||||
|                                 "Tried to send avatar url update for user not in the room.", | ||||
|                             ) | ||||
|                         })? | ||||
|                         .content | ||||
|                         .clone(), | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Database contains invalid PDU."))? | ||||
|                 .map_err(|_| Error::bad_database("Database contains invalid PDU."))? | ||||
|                 .deserialize() | ||||
|                 .map_err(|_| Error::BadDatabase("Database contains invalid PDU."))? | ||||
|                 .map_err(|_| Error::bad_database("Database contains invalid PDU."))? | ||||
|             }) | ||||
|             .expect("event is valid, we just created it"), | ||||
|             None, | ||||
|  | @ -744,9 +745,12 @@ pub fn get_keys_route( | |||
|             for result in db.users.all_device_keys(&user_id.clone()) { | ||||
|                 let (device_id, mut keys) = result?; | ||||
| 
 | ||||
|                 let metadata = db.users.get_device_metadata(user_id, &device_id)?.ok_or( | ||||
|                     Error::BadDatabase("all_device_keys contained nonexistent device."), | ||||
|                 )?; | ||||
|                 let metadata = db | ||||
|                     .users | ||||
|                     .get_device_metadata(user_id, &device_id)? | ||||
|                     .ok_or_else(|| { | ||||
|                         Error::bad_database("all_device_keys contained nonexistent device.") | ||||
|                     })?; | ||||
| 
 | ||||
|                 keys.unsigned = Some(keys::UnsignedDeviceInfo { | ||||
|                     device_display_name: metadata.display_name, | ||||
|  | @ -912,7 +916,7 @@ pub fn create_room_route( | |||
|     let user_id = body.user_id.as_ref().expect("user is authenticated"); | ||||
| 
 | ||||
|     let room_id = RoomId::new(db.globals.server_name()) | ||||
|         .map_err(|_| Error::BadDatabase("Server name is invalid."))?; | ||||
|         .map_err(|_| Error::bad_database("Server name is invalid."))?; | ||||
| 
 | ||||
|     let alias = body | ||||
|         .room_alias_name | ||||
|  | @ -1281,9 +1285,9 @@ pub fn join_room_by_id_route( | |||
|                 let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>( | ||||
|                     pdu.content.clone(), | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid member event in db."))? | ||||
|                 .map_err(|_| Error::bad_database("Invalid member event in db."))? | ||||
|                 .deserialize() | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid member event in db."))?; | ||||
|                 .map_err(|_| Error::bad_database("Invalid member event in db."))?; | ||||
|                 event.membership = member::MembershipState::Join; | ||||
|                 event.displayname = db.users.displayname(&user_id)?; | ||||
|                 event.avatar_url = db.users.avatar_url(&user_id)?; | ||||
|  | @ -1356,9 +1360,9 @@ pub fn leave_room_route( | |||
|             .content | ||||
|             .clone(), | ||||
|     ) | ||||
|     .map_err(|_| Error::BadDatabase("Invalid member event in database."))? | ||||
|     .map_err(|_| Error::bad_database("Invalid member event in database."))? | ||||
|     .deserialize() | ||||
|     .map_err(|_| Error::BadDatabase("Invalid member event in database."))?; | ||||
|     .map_err(|_| Error::bad_database("Invalid member event in database."))?; | ||||
| 
 | ||||
|     event.membership = member::MembershipState::Leave; | ||||
| 
 | ||||
|  | @ -1396,9 +1400,9 @@ pub fn kick_user_route( | |||
|                 .content | ||||
|                 .clone(), | ||||
|         ) | ||||
|         .map_err(|_| Error::BadDatabase("Invalid member event in database."))? | ||||
|         .map_err(|_| Error::bad_database("Invalid member event in database."))? | ||||
|         .deserialize() | ||||
|         .map_err(|_| Error::BadDatabase("Invalid member event in database."))?; | ||||
|         .map_err(|_| Error::bad_database("Invalid member event in database."))?; | ||||
| 
 | ||||
|     event.membership = ruma::events::room::member::MembershipState::Leave; | ||||
|     // TODO: reason
 | ||||
|  | @ -1442,9 +1446,9 @@ pub fn ban_user_route( | |||
|                 let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>( | ||||
|                     event.content.clone(), | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid member event in database."))? | ||||
|                 .map_err(|_| Error::bad_database("Invalid member event in database."))? | ||||
|                 .deserialize() | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid member event in database."))?; | ||||
|                 .map_err(|_| Error::bad_database("Invalid member event in database."))?; | ||||
|                 event.membership = ruma::events::room::member::MembershipState::Ban; | ||||
|                 Ok(event) | ||||
|             }, | ||||
|  | @ -1484,9 +1488,9 @@ pub fn unban_user_route( | |||
|                 .content | ||||
|                 .clone(), | ||||
|         ) | ||||
|         .map_err(|_| Error::BadDatabase("Invalid member event in database."))? | ||||
|         .map_err(|_| Error::bad_database("Invalid member event in database."))? | ||||
|         .deserialize() | ||||
|         .map_err(|_| Error::BadDatabase("Invalid member event in database."))?; | ||||
|         .map_err(|_| Error::bad_database("Invalid member event in database."))?; | ||||
| 
 | ||||
|     event.membership = ruma::events::room::member::MembershipState::Leave; | ||||
| 
 | ||||
|  | @ -1646,18 +1650,18 @@ pub async fn get_public_rooms_filtered_route( | |||
|                     Ok(serde_json::from_value::< | ||||
|                             EventJson<ruma::events::room::canonical_alias::CanonicalAliasEventContent>, | ||||
|                         >(s.content.clone()) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid canonical alias event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid canonical alias event in database."))? | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid canonical alias event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid canonical alias event in database."))? | ||||
|                         .alias) | ||||
|                 })?, | ||||
|                 name: state.get(&(EventType::RoomName, "".to_owned())).map_or(Ok::<_, Error>(None), |s| { | ||||
|                     Ok(serde_json::from_value::<EventJson<ruma::events::room::name::NameEventContent>>( | ||||
|                         s.content.clone(), | ||||
|                     ) | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid room name event in database."))? | ||||
|                     .map_err(|_| Error::bad_database("Invalid room name event in database."))? | ||||
|                     .deserialize() | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid room name event in database."))? | ||||
|                     .map_err(|_| Error::bad_database("Invalid room name event in database."))? | ||||
|                     .name() | ||||
|                     .map(|n| n.to_owned())) | ||||
|                 })?, | ||||
|  | @ -1667,36 +1671,36 @@ pub async fn get_public_rooms_filtered_route( | |||
|                     Ok(Some(serde_json::from_value::< | ||||
|                             EventJson<ruma::events::room::topic::TopicEventContent>, | ||||
|                         >(s.content.clone()) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room topic event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room topic event in database."))? | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room topic event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room topic event in database."))? | ||||
|                         .topic)) | ||||
|                 })?, | ||||
|                 world_readable: state.get(&(EventType::RoomHistoryVisibility, "".to_owned())).map_or(Ok::<_, Error>(false), |s| { | ||||
|                     Ok(serde_json::from_value::< | ||||
|                             EventJson<ruma::events::room::history_visibility::HistoryVisibilityEventContent>, | ||||
|                         >(s.content.clone()) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room history visibility event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room history visibility event in database."))? | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room history visibility event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room history visibility event in database."))? | ||||
|                         .history_visibility == history_visibility::HistoryVisibility::WorldReadable) | ||||
|                 })?, | ||||
|                 guest_can_join: state.get(&(EventType::RoomGuestAccess, "".to_owned())).map_or(Ok::<_, Error>(false), |s| { | ||||
|                     Ok(serde_json::from_value::< | ||||
|                             EventJson<ruma::events::room::guest_access::GuestAccessEventContent>, | ||||
|                         >(s.content.clone()) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room guest access event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room guest access event in database."))? | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room guest access event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room guest access event in database."))? | ||||
|                         .guest_access == guest_access::GuestAccess::CanJoin) | ||||
|                 })?, | ||||
|                 avatar_url: state.get(&(EventType::RoomAvatar, "".to_owned())).map_or( Ok::<_, Error>(None),|s| { | ||||
|                     Ok(Some(serde_json::from_value::< | ||||
|                             EventJson<ruma::events::room::avatar::AvatarEventContent>, | ||||
|                         >(s.content.clone()) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room avatar event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room avatar event in database."))? | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid room avatar event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid room avatar event in database."))? | ||||
|                         .url)) | ||||
|                 })?, | ||||
|             }; | ||||
|  | @ -1986,7 +1990,7 @@ pub fn get_state_events_for_key_route( | |||
| 
 | ||||
|     Ok(get_state_events_for_key::Response { | ||||
|         content: serde_json::value::to_raw_value(&event.content) | ||||
|             .map_err(|_| Error::BadDatabase("Invalid event content in database"))?, | ||||
|             .map_err(|_| Error::bad_database("Invalid event content in database"))?, | ||||
|     } | ||||
|     .into()) | ||||
| } | ||||
|  | @ -2021,7 +2025,7 @@ pub fn get_state_events_for_empty_key_route( | |||
| 
 | ||||
|     Ok(get_state_events_for_empty_key::Response { | ||||
|         content: serde_json::value::to_raw_value(event) | ||||
|             .map_err(|_| Error::BadDatabase("Invalid event content in database"))?, | ||||
|             .map_err(|_| Error::bad_database("Invalid event content in database"))?, | ||||
|     } | ||||
|     .into()) | ||||
| } | ||||
|  | @ -2064,9 +2068,9 @@ pub fn sync_route( | |||
|                     let content = serde_json::from_value::< | ||||
|                         EventJson<ruma::events::room::member::MemberEventContent>, | ||||
|                     >(pdu.content.clone()) | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid PDU in database."))? | ||||
|                     .map_err(|_| Error::bad_database("Invalid PDU in database."))? | ||||
|                     .deserialize() | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid PDU in database."))?; | ||||
|                     .map_err(|_| Error::bad_database("Invalid PDU in database."))?; | ||||
|                     if content.membership == ruma::events::room::member::MembershipState::Join { | ||||
|                         joined_since_last_sync = true; | ||||
|                         // Both send_member_count and joined_since_last_sync are set. There's nothing more
 | ||||
|  | @ -2099,9 +2103,9 @@ pub fn sync_route( | |||
|                         let content = serde_json::from_value::< | ||||
|                             EventJson<ruma::events::room::member::MemberEventContent>, | ||||
|                         >(pdu.content.clone()) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid member event in database."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid member event in database."))? | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid member event in database."))?; | ||||
|                         .map_err(|_| Error::bad_database("Invalid member event in database."))?; | ||||
| 
 | ||||
|                         if let Some(state_key) = &pdu.state_key { | ||||
|                             let current_content = serde_json::from_value::< | ||||
|  | @ -2109,15 +2113,19 @@ pub fn sync_route( | |||
|                             >( | ||||
|                                 state | ||||
|                                     .get(&(EventType::RoomMember, state_key.clone())) | ||||
|                                     .ok_or(Error::BadDatabase( | ||||
|                                         "A user that joined once has no member event anymore.", | ||||
|                                     ))? | ||||
|                                     .ok_or_else(|| { | ||||
|                                         Error::bad_database( | ||||
|                                             "A user that joined once has no member event anymore.", | ||||
|                                         ) | ||||
|                                     })? | ||||
|                                     .content | ||||
|                                     .clone(), | ||||
|                             ) | ||||
|                             .map_err(|_| Error::BadDatabase("Invalid member event in database."))? | ||||
|                             .map_err(|_| Error::bad_database("Invalid member event in database."))? | ||||
|                             .deserialize() | ||||
|                             .map_err(|_| Error::BadDatabase("Invalid member event in database."))?; | ||||
|                             .map_err(|_| { | ||||
|                                 Error::bad_database("Invalid member event in database.") | ||||
|                             })?; | ||||
| 
 | ||||
|                             // The membership was and still is invite or join
 | ||||
|                             if matches!( | ||||
|  | @ -2192,7 +2200,7 @@ pub fn sync_route( | |||
|             Ok(Some( | ||||
|                 db.rooms | ||||
|                     .get_pdu_count(&e.event_id)? | ||||
|                     .ok_or(Error::BadDatabase("Can't find count from event in db."))? | ||||
|                     .ok_or_else(|| Error::bad_database("Can't find count from event in db."))? | ||||
|                     .to_string(), | ||||
|             )) | ||||
|         })?; | ||||
|  | @ -2355,7 +2363,7 @@ pub fn sync_route( | |||
|                 .map(|edu| { | ||||
|                     let mut edu = edu? | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("EDU in database is invalid."))?; | ||||
|                         .map_err(|_| Error::bad_database("EDU in database is invalid."))?; | ||||
|                     if let Some(timestamp) = edu.content.last_active_ago { | ||||
|                         let last_active_ago = | ||||
|                             js_int::UInt::try_from(utils::millis_since_unix_epoch()) | ||||
|  | @ -2444,7 +2452,7 @@ pub fn get_context_route( | |||
|         Ok::<_, Error>(Some( | ||||
|             db.rooms | ||||
|                 .get_pdu_count(&e.event_id)? | ||||
|                 .ok_or(Error::BadDatabase("Can't find count from event in db."))? | ||||
|                 .ok_or_else(|| Error::bad_database("Can't find count from event in db."))? | ||||
|                 .to_string(), | ||||
|         )) | ||||
|     })?; | ||||
|  | @ -2470,7 +2478,7 @@ pub fn get_context_route( | |||
|         Ok::<_, Error>(Some( | ||||
|             db.rooms | ||||
|                 .get_pdu_count(&e.event_id)? | ||||
|                 .ok_or(Error::BadDatabase("Can't find count from event in db."))? | ||||
|                 .ok_or_else(|| Error::bad_database("Can't find count from event in db."))? | ||||
|                 .to_string(), | ||||
|         )) | ||||
|     })?; | ||||
|  | @ -2534,7 +2542,7 @@ pub fn get_message_events_route( | |||
|                 Ok(Some( | ||||
|                     db.rooms | ||||
|                         .get_pdu_count(&e.event_id)? | ||||
|                         .ok_or(Error::BadDatabase("Can't find count from event in db."))? | ||||
|                         .ok_or_else(|| Error::bad_database("Can't find count from event in db."))? | ||||
|                         .to_string(), | ||||
|                 )) | ||||
|             })?; | ||||
|  | @ -2569,7 +2577,7 @@ pub fn get_message_events_route( | |||
|                 Ok(Some( | ||||
|                     db.rooms | ||||
|                         .get_pdu_count(&e.event_id)? | ||||
|                         .ok_or(Error::BadDatabase("Can't find count from event in db."))? | ||||
|                         .ok_or_else(|| Error::bad_database("Can't find count from event in db."))? | ||||
|                         .to_string(), | ||||
|                 )) | ||||
|             })?; | ||||
|  |  | |||
|  | @ -115,16 +115,14 @@ impl AccountData { | |||
|             .map(|(k, v)| { | ||||
|                 Ok::<_, Error>(( | ||||
|                     EventType::try_from( | ||||
|                         utils::string_from_bytes( | ||||
|                             k.rsplit(|&b| b == 0xff) | ||||
|                                 .next() | ||||
|                                 .ok_or(Error::BadDatabase("RoomUserData ID in db is invalid."))?, | ||||
|                         ) | ||||
|                         .map_err(|_| Error::BadDatabase("RoomUserData ID in db is invalid."))?, | ||||
|                         utils::string_from_bytes(k.rsplit(|&b| b == 0xff).next().ok_or_else( | ||||
|                             || Error::bad_database("RoomUserData ID in db is invalid."), | ||||
|                         )?) | ||||
|                         .map_err(|_| Error::bad_database("RoomUserData ID in db is invalid."))?, | ||||
|                     ) | ||||
|                     .map_err(|_| Error::BadDatabase("RoomUserData ID in db is invalid."))?, | ||||
|                     .map_err(|_| Error::bad_database("RoomUserData ID in db is invalid."))?, | ||||
|                     serde_json::from_slice::<EventJson<EduEvent>>(&v).map_err(|_| { | ||||
|                         Error::BadDatabase("Database contains invalid account data.") | ||||
|                         Error::bad_database("Database contains invalid account data.") | ||||
|                     })?, | ||||
|                 )) | ||||
|             }) | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ impl GlobalEdus { | |||
|             .filter_map(|r| r.ok()) | ||||
|             .map(|(_, v)| { | ||||
|                 Ok(serde_json::from_slice(&v) | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid presence event in db."))?) | ||||
|                     .map_err(|_| Error::bad_database("Invalid presence event in db."))?) | ||||
|             })) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ impl Globals { | |||
|                 .expect("utils::generate_keypair always returns Some"), | ||||
|             "key1".to_owned(), | ||||
|         ) | ||||
|         .map_err(|_| Error::BadDatabase("Private or public keys are invalid."))?; | ||||
|         .map_err(|_| Error::bad_database("Private or public keys are invalid."))?; | ||||
| 
 | ||||
|         Ok(Self { | ||||
|             globals, | ||||
|  | @ -49,13 +49,13 @@ impl Globals { | |||
|                 .update_and_fetch(COUNTER, utils::increment)? | ||||
|                 .expect("utils::increment will always put in a value"), | ||||
|         ) | ||||
|         .map_err(|_| Error::BadDatabase("Count has invalid bytes."))?) | ||||
|         .map_err(|_| Error::bad_database("Count has invalid bytes."))?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn current_count(&self) -> Result<u64> { | ||||
|         self.globals.get(COUNTER)?.map_or(Ok(0_u64), |bytes| { | ||||
|             Ok(utils::u64_from_bytes(&bytes) | ||||
|                 .map_err(|_| Error::BadDatabase("Count has invalid bytes."))?) | ||||
|                 .map_err(|_| Error::bad_database("Count has invalid bytes."))?) | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -43,21 +43,20 @@ impl Media { | |||
|             let content_type = utils::string_from_bytes( | ||||
|                 parts | ||||
|                     .next() | ||||
|                     .ok_or(Error::BadDatabase("Invalid Media ID in db"))?, | ||||
|                     .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?, | ||||
|             ) | ||||
|             .map_err(|_| Error::BadDatabase("Invalid content type in db."))?; | ||||
|             .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; | ||||
| 
 | ||||
|             let filename_bytes = parts | ||||
|                 .next() | ||||
|                 .ok_or(Error::BadDatabase("Media ID in db is invalid."))?; | ||||
|                 .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; | ||||
| 
 | ||||
|             let filename = if filename_bytes.is_empty() { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some( | ||||
|                     utils::string_from_bytes(filename_bytes) | ||||
|                         .map_err(|_| Error::BadDatabase("Filename in db is invalid."))?, | ||||
|                 ) | ||||
|                 Some(utils::string_from_bytes(filename_bytes).map_err(|_| { | ||||
|                     Error::bad_database("Filename in mediaid_file is invalid unicode.") | ||||
|                 })?) | ||||
|             }; | ||||
| 
 | ||||
|             Ok(Some((filename, content_type, file.to_vec()))) | ||||
|  | @ -94,20 +93,20 @@ impl Media { | |||
|             let content_type = utils::string_from_bytes( | ||||
|                 parts | ||||
|                     .next() | ||||
|                     .ok_or(Error::BadDatabase("Invalid Media ID in db"))?, | ||||
|                     .ok_or_else(|| Error::bad_database("Invalid Media ID in db"))?, | ||||
|             ) | ||||
|             .map_err(|_| Error::BadDatabase("Invalid content type in db."))?; | ||||
|             .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; | ||||
| 
 | ||||
|             let filename_bytes = parts | ||||
|                 .next() | ||||
|                 .ok_or(Error::BadDatabase("Media ID in db is invalid."))?; | ||||
|                 .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; | ||||
| 
 | ||||
|             let filename = if filename_bytes.is_empty() { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some( | ||||
|                     utils::string_from_bytes(filename_bytes) | ||||
|                         .map_err(|_| Error::BadDatabase("Filename in db is invalid."))?, | ||||
|                         .map_err(|_| Error::bad_database("Filename in db is invalid."))?, | ||||
|                 ) | ||||
|             }; | ||||
| 
 | ||||
|  | @ -120,21 +119,20 @@ impl Media { | |||
|             let content_type = utils::string_from_bytes( | ||||
|                 parts | ||||
|                     .next() | ||||
|                     .ok_or(Error::BadDatabase("Media ID in db is invalid"))?, | ||||
|                     .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?, | ||||
|             ) | ||||
|             .map_err(|_| Error::BadDatabase("Invalid content type in db."))?; | ||||
|             .map_err(|_| Error::bad_database("Content type in mediaid_file is invalid unicode."))?; | ||||
| 
 | ||||
|             let filename_bytes = parts | ||||
|                 .next() | ||||
|                 .ok_or(Error::BadDatabase("Media ID in db is invalid"))?; | ||||
|                 .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; | ||||
| 
 | ||||
|             let filename = if filename_bytes.is_empty() { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some( | ||||
|                     utils::string_from_bytes(filename_bytes) | ||||
|                         .map_err(|_| Error::BadDatabase("Filename in db is invalid."))?, | ||||
|                 ) | ||||
|                 Some(utils::string_from_bytes(filename_bytes).map_err(|_| { | ||||
|                     Error::bad_database("Filename in mediaid_file is invalid unicode.") | ||||
|                 })?) | ||||
|             }; | ||||
| 
 | ||||
|             if let Ok(image) = image::load_from_memory(&file) { | ||||
|  | @ -147,7 +145,7 @@ impl Media { | |||
|                 let width_index = thumbnail_key | ||||
|                     .iter() | ||||
|                     .position(|&b| b == 0xff) | ||||
|                     .ok_or(Error::BadDatabase("mediaid is invalid"))? | ||||
|                     .ok_or_else(|| Error::bad_database("Media in db is invalid."))? | ||||
|                     + 1; | ||||
|                 let mut widthheight = width.to_be_bytes().to_vec(); | ||||
|                 widthheight.extend_from_slice(&height.to_be_bytes()); | ||||
|  |  | |||
|  | @ -65,14 +65,14 @@ impl Rooms { | |||
|             .map(|value| { | ||||
|                 Ok::<_, Error>( | ||||
|                     serde_json::from_slice::<PduEvent>(&value?) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid PDU in db."))?, | ||||
|                         .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|                 ) | ||||
|             }) | ||||
|         { | ||||
|             let pdu = pdu?; | ||||
|             let state_key = pdu.state_key.clone().ok_or(Error::BadDatabase( | ||||
|                 "Room state contains event without state_key.", | ||||
|             ))?; | ||||
|             let state_key = pdu.state_key.clone().ok_or_else(|| { | ||||
|                 Error::bad_database("Room state contains event without state_key.") | ||||
|             })?; | ||||
|             hashmap.insert((pdu.kind.clone(), state_key), pdu); | ||||
|         } | ||||
|         Ok(hashmap) | ||||
|  | @ -87,7 +87,7 @@ impl Rooms { | |||
|                     utils::u64_from_bytes( | ||||
|                         &pdu_id[pdu_id.len() - mem::size_of::<u64>()..pdu_id.len()], | ||||
|                     ) | ||||
|                     .map_err(|_| Error::BadDatabase("PDU has invalid count bytes."))?, | ||||
|                     .map_err(|_| Error::bad_database("PDU has invalid count bytes."))?, | ||||
|                 )) | ||||
|             }) | ||||
|     } | ||||
|  | @ -98,10 +98,10 @@ impl Rooms { | |||
|             .get(event_id.to_string().as_bytes())? | ||||
|             .map_or(Ok(None), |pdu_id| { | ||||
|                 Ok(Some( | ||||
|                     serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or( | ||||
|                         Error::BadDatabase("eventid_pduid points to nonexistent pdu."), | ||||
|                     )?) | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid PDU in db."))?, | ||||
|                     serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or_else(|| { | ||||
|                         Error::bad_database("eventid_pduid points to nonexistent pdu.") | ||||
|                     })?) | ||||
|                     .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|                 )) | ||||
|             }) | ||||
|     } | ||||
|  | @ -119,10 +119,10 @@ impl Rooms { | |||
|             .get(event_id.to_string().as_bytes())? | ||||
|             .map_or(Ok(None), |pdu_id| { | ||||
|                 Ok(Some( | ||||
|                     serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or( | ||||
|                         Error::BadDatabase("eventid_pduid points to nonexistent pdu."), | ||||
|                     )?) | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid PDU in db."))?, | ||||
|                     serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or_else(|| { | ||||
|                         Error::bad_database("eventid_pduid points to nonexistent pdu.") | ||||
|                     })?) | ||||
|                     .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|                 )) | ||||
|             }) | ||||
|     } | ||||
|  | @ -131,7 +131,7 @@ impl Rooms { | |||
|         self.pduid_pdu.get(pdu_id)?.map_or(Ok(None), |pdu| { | ||||
|             Ok(Some( | ||||
|                 serde_json::from_slice(&pdu) | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid PDU in db."))?, | ||||
|                     .map_err(|_| Error::bad_database("Invalid PDU in db."))?, | ||||
|             )) | ||||
|         }) | ||||
|     } | ||||
|  | @ -165,8 +165,10 @@ impl Rooms { | |||
|             .values() | ||||
|             .map(|bytes| { | ||||
|                 Ok::<_, Error>( | ||||
|                     serde_json::from_slice(&bytes?) | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid EventID in roomid_pduleaves."))?, | ||||
|                     EventId::try_from(utils::string_from_bytes(&bytes?).map_err(|_| { | ||||
|                         Error::bad_database("EventID in roomid_pduleaves is invalid unicode.") | ||||
|                     })?) | ||||
|                     .map_err(|_| Error::bad_database("EventId in roomid_pduleaves is invalid."))?, | ||||
|                 ) | ||||
|             }) | ||||
|         { | ||||
|  | @ -237,7 +239,7 @@ impl Rooms { | |||
|                             ) | ||||
|                             .expect("EventJson::from_value always works.") | ||||
|                             .deserialize() | ||||
|                             .map_err(|_| Error::BadDatabase("Invalid PowerLevels event in db."))?, | ||||
|                             .map_err(|_| Error::bad_database("Invalid PowerLevels event in db."))?, | ||||
|                         ) | ||||
|                     }, | ||||
|                 )?; | ||||
|  | @ -251,7 +253,7 @@ impl Rooms { | |||
|                         ) | ||||
|                         .expect("EventJson::from_value always works.") | ||||
|                         .deserialize() | ||||
|                         .map_err(|_| Error::BadDatabase("Invalid Member event in db."))? | ||||
|                         .map_err(|_| Error::bad_database("Invalid Member event in db."))? | ||||
|                         .membership, | ||||
|                     ) | ||||
|                 })?; | ||||
|  | @ -287,7 +289,7 @@ impl Rooms { | |||
|                                 ) | ||||
|                                 .expect("EventJson::from_value always works.") | ||||
|                                 .deserialize() | ||||
|                                 .map_err(|_| Error::BadDatabase("Invalid Member event in db."))? | ||||
|                                 .map_err(|_| Error::bad_database("Invalid Member event in db."))? | ||||
|                                 .membership, | ||||
|                             ) | ||||
|                         })?; | ||||
|  | @ -297,7 +299,7 @@ impl Rooms { | |||
|                     >(content.clone()) | ||||
|                     .expect("EventJson::from_value always works.") | ||||
|                     .deserialize() | ||||
|                     .map_err(|_| Error::BadDatabase("Invalid Member event in db."))? | ||||
|                     .map_err(|_| Error::bad_database("Invalid Member event in db."))? | ||||
|                     .membership; | ||||
| 
 | ||||
|                     let target_power = power_levels.users.get(&target_user_id).map_or_else( | ||||
|  | @ -322,7 +324,7 @@ impl Rooms { | |||
|                                 .expect("EventJson::from_value always works.") | ||||
|                                 .deserialize() | ||||
|                                 .map_err(|_| { | ||||
|                                     Error::BadDatabase("Database contains invalid JoinRules event") | ||||
|                                     Error::bad_database("Database contains invalid JoinRules event") | ||||
|                                 })? | ||||
|                                 .join_rule) | ||||
|                             })?; | ||||
|  | @ -334,7 +336,9 @@ impl Rooms { | |||
|                                 ErrorKind::Unknown, | ||||
|                                 "Membership can't be the first event", | ||||
|                             ))?)? | ||||
|                             .ok_or(Error::BadDatabase("PDU leaf points to invalid event!"))?; | ||||
|                             .ok_or_else(|| { | ||||
|                                 Error::bad_database("PDU leaf points to invalid event!") | ||||
|                             })?; | ||||
|                         if prev_event.kind == EventType::RoomCreate | ||||
|                             && prev_event.prev_events.is_empty() | ||||
|                         { | ||||
|  | @ -466,7 +470,7 @@ impl Rooms { | |||
|             prev_events, | ||||
|             depth: depth | ||||
|                 .try_into() | ||||
|                 .map_err(|_| Error::BadDatabase("Depth is invalid"))?, | ||||
|                 .map_err(|_| Error::bad_database("Depth is invalid"))?, | ||||
|             auth_events: Vec::new(), | ||||
|             redacts: redacts.clone(), | ||||
|             unsigned, | ||||
|  | @ -588,7 +592,7 @@ impl Rooms { | |||
|             .take_while(move |(k, _)| k.starts_with(&prefix)) | ||||
|             .map(|(_, v)| { | ||||
|                 Ok(serde_json::from_slice(&v) | ||||
|                     .map_err(|_| Error::BadDatabase("PDU in db is invalid."))?) | ||||
|                     .map_err(|_| Error::bad_database("PDU in db is invalid."))?) | ||||
|             })) | ||||
|     } | ||||
| 
 | ||||
|  | @ -615,7 +619,7 @@ impl Rooms { | |||
|             .take_while(move |(k, _)| k.starts_with(&prefix)) | ||||
|             .map(|(_, v)| { | ||||
|                 Ok(serde_json::from_slice(&v) | ||||
|                     .map_err(|_| Error::BadDatabase("PDU in db is invalid."))?) | ||||
|                     .map_err(|_| Error::bad_database("PDU in db is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -641,7 +645,7 @@ impl Rooms { | |||
|             .take_while(move |(k, _)| k.starts_with(&prefix)) | ||||
|             .map(|(_, v)| { | ||||
|                 Ok(serde_json::from_slice(&v) | ||||
|                     .map_err(|_| Error::BadDatabase("PDU in db is invalid."))?) | ||||
|                     .map_err(|_| Error::bad_database("PDU in db is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -650,7 +654,7 @@ impl Rooms { | |||
|         if let Some(pdu_id) = self.get_pdu_id(event_id)? { | ||||
|             let mut pdu = self | ||||
|                 .get_pdu_from_id(&pdu_id)? | ||||
|                 .ok_or(Error::BadDatabase("PDU ID points to invalid PDU."))?; | ||||
|                 .ok_or_else(|| Error::bad_database("PDU ID points to invalid PDU."))?; | ||||
|             pdu.redact()?; | ||||
|             self.replace_pdu(&pdu_id, &pdu)?; | ||||
|             Ok(()) | ||||
|  | @ -751,9 +755,12 @@ impl Rooms { | |||
|         self.alias_roomid | ||||
|             .get(alias.alias())? | ||||
|             .map_or(Ok(None), |bytes| { | ||||
|                 Ok(Some(serde_json::from_slice(&bytes).map_err(|_| { | ||||
|                     Error::BadDatabase("Room ID in alias_roomid is invalid.") | ||||
|                 })?)) | ||||
|                 Ok(Some( | ||||
|                     RoomId::try_from(utils::string_from_bytes(&bytes).map_err(|_| { | ||||
|                         Error::bad_database("Room ID in alias_roomid is invalid unicode.") | ||||
|                     })?) | ||||
|                     .map_err(|_| Error::bad_database("Room ID in alias_roomid is invalid."))?, | ||||
|                 )) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -766,7 +773,7 @@ impl Rooms { | |||
|             .values() | ||||
|             .map(|bytes| { | ||||
|                 Ok(serde_json::from_slice(&bytes?) | ||||
|                     .map_err(|_| Error::BadDatabase("Alias in aliasid_alias is invalid."))?) | ||||
|                     .map_err(|_| Error::bad_database("Alias in aliasid_alias is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -786,56 +793,75 @@ impl Rooms { | |||
| 
 | ||||
|     pub fn public_rooms(&self) -> impl Iterator<Item = Result<RoomId>> { | ||||
|         self.publicroomids.iter().keys().map(|bytes| { | ||||
|             Ok(serde_json::from_slice(&bytes?) | ||||
|                 .map_err(|_| Error::BadDatabase("Room ID in publicroomids is invalid."))?) | ||||
|             Ok( | ||||
|                 RoomId::try_from(utils::string_from_bytes(&bytes?).map_err(|_| { | ||||
|                     Error::bad_database("Room ID in publicroomids is invalid unicode.") | ||||
|                 })?) | ||||
|                 .map_err(|_| Error::bad_database("Room ID in publicroomids is invalid."))?, | ||||
|             ) | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns an iterator over all rooms a user joined.
 | ||||
|     /// Returns an iterator over all joined members of a room.
 | ||||
|     pub fn room_members(&self, room_id: &RoomId) -> impl Iterator<Item = Result<UserId>> { | ||||
|         self.roomuserid_joined | ||||
|             .scan_prefix(room_id.to_string()) | ||||
|             .values() | ||||
|             .keys() | ||||
|             .map(|key| { | ||||
|                 Ok(serde_json::from_slice( | ||||
|                     &key? | ||||
|                         .rsplit(|&b| b == 0xff) | ||||
|                         .next() | ||||
|                         .ok_or(Error::BadDatabase("RoomUser ID is invalid."))?, | ||||
|                 Ok(UserId::try_from( | ||||
|                     utils::string_from_bytes( | ||||
|                         &key? | ||||
|                             .rsplit(|&b| b == 0xff) | ||||
|                             .next() | ||||
|                             .expect("rsplit always returns an element"), | ||||
|                     ) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("User ID in roomuserid_joined is invalid unicode.") | ||||
|                     })?, | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid User ID in db."))?) | ||||
|                 .map_err(|_| Error::bad_database("User ID in roomuserid_joined is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns an iterator over all rooms a user joined.
 | ||||
|     /// Returns an iterator over all invited members of a room.
 | ||||
|     pub fn room_members_invited(&self, room_id: &RoomId) -> impl Iterator<Item = Result<UserId>> { | ||||
|         self.roomuserid_invited | ||||
|             .scan_prefix(room_id.to_string()) | ||||
|             .keys() | ||||
|             .map(|key| { | ||||
|                 Ok(serde_json::from_slice( | ||||
|                     &key? | ||||
|                         .rsplit(|&b| b == 0xff) | ||||
|                         .next() | ||||
|                         .ok_or(Error::BadDatabase("RoomUser ID is invalid."))?, | ||||
|                 Ok(UserId::try_from( | ||||
|                     utils::string_from_bytes( | ||||
|                         &key? | ||||
|                             .rsplit(|&b| b == 0xff) | ||||
|                             .next() | ||||
|                             .expect("rsplit always returns an element"), | ||||
|                     ) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("User ID in roomuserid_invited is invalid unicode.") | ||||
|                     })?, | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid User ID in db."))?) | ||||
|                 .map_err(|_| Error::bad_database("User ID in roomuserid_invited is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns an iterator over all rooms a user joined.
 | ||||
|     /// Returns an iterator over all left members of a room.
 | ||||
|     pub fn rooms_joined(&self, user_id: &UserId) -> impl Iterator<Item = Result<RoomId>> { | ||||
|         self.userroomid_joined | ||||
|             .scan_prefix(user_id.to_string()) | ||||
|             .keys() | ||||
|             .map(|key| { | ||||
|                 Ok(serde_json::from_slice( | ||||
|                     &key? | ||||
|                         .rsplit(|&b| b == 0xff) | ||||
|                         .next() | ||||
|                         .ok_or(Error::BadDatabase("UserRoom ID is invalid."))?, | ||||
|                 Ok(RoomId::try_from( | ||||
|                     utils::string_from_bytes( | ||||
|                         &key? | ||||
|                             .rsplit(|&b| b == 0xff) | ||||
|                             .next() | ||||
|                             .expect("rsplit always returns an element"), | ||||
|                     ) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("Room ID in userroomid_joined is invalid unicode.") | ||||
|                     })?, | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid Room ID in db."))?) | ||||
|                 .map_err(|_| Error::bad_database("Room ID in userroomid_joined is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -845,13 +871,18 @@ impl Rooms { | |||
|             .scan_prefix(&user_id.to_string()) | ||||
|             .keys() | ||||
|             .map(|key| { | ||||
|                 Ok(serde_json::from_slice( | ||||
|                     &key? | ||||
|                         .rsplit(|&b| b == 0xff) | ||||
|                         .next() | ||||
|                         .ok_or(Error::BadDatabase("UserRoom ID is invalid."))?, | ||||
|                 Ok(RoomId::try_from( | ||||
|                     utils::string_from_bytes( | ||||
|                         &key? | ||||
|                             .rsplit(|&b| b == 0xff) | ||||
|                             .next() | ||||
|                             .expect("rsplit always returns an element"), | ||||
|                     ) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("Room ID in userroomid_invited is invalid unicode.") | ||||
|                     })?, | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid Room ID in db."))?) | ||||
|                 .map_err(|_| Error::bad_database("Room ID in userroomid_invited is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -861,13 +892,18 @@ impl Rooms { | |||
|             .scan_prefix(&user_id.to_string()) | ||||
|             .keys() | ||||
|             .map(|key| { | ||||
|                 Ok(serde_json::from_slice( | ||||
|                     &key? | ||||
|                         .rsplit(|&b| b == 0xff) | ||||
|                         .next() | ||||
|                         .ok_or(Error::BadDatabase("UserRoom ID is invalid."))?, | ||||
|                 Ok(RoomId::try_from( | ||||
|                     utils::string_from_bytes( | ||||
|                         &key? | ||||
|                             .rsplit(|&b| b == 0xff) | ||||
|                             .next() | ||||
|                             .expect("rsplit always returns an element"), | ||||
|                     ) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("Room ID in userroomid_left is invalid unicode.") | ||||
|                     })?, | ||||
|                 ) | ||||
|                 .map_err(|_| Error::BadDatabase("Invalid Room ID in db."))?) | ||||
|                 .map_err(|_| Error::bad_database("Room ID in userroomid_left is invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -74,8 +74,9 @@ impl RoomEdus { | |||
|             .filter_map(|r| r.ok()) | ||||
|             .take_while(move |(k, _)| k.starts_with(&prefix)) | ||||
|             .map(|(_, v)| { | ||||
|                 Ok(serde_json::from_slice(&v) | ||||
|                     .map_err(|_| Error::BadDatabase("Read receipt in db is invalid."))?) | ||||
|                 Ok(serde_json::from_slice(&v).map_err(|_| { | ||||
|                     Error::bad_database("Read receipt in roomlatestid_roomlatest is invalid.") | ||||
|                 })?) | ||||
|             })) | ||||
|     } | ||||
| 
 | ||||
|  | @ -164,10 +165,10 @@ impl RoomEdus { | |||
|                 let key = key?; | ||||
|                 Ok::<_, Error>(( | ||||
|                     key.clone(), | ||||
|                     utils::u64_from_bytes(key.split(|&b| b == 0xff).nth(1).ok_or( | ||||
|                         Error::BadDatabase("RoomActive has invalid timestamp or delimiters."), | ||||
|                     )?) | ||||
|                     .map_err(|_| Error::BadDatabase("RoomActive has invalid timestamp bytes."))?, | ||||
|                     utils::u64_from_bytes(key.split(|&b| b == 0xff).nth(1).ok_or_else(|| { | ||||
|                         Error::bad_database("RoomActive has invalid timestamp or delimiters.") | ||||
|                     })?) | ||||
|                     .map_err(|_| Error::bad_database("RoomActive has invalid timestamp bytes."))?, | ||||
|                 )) | ||||
|             }) | ||||
|             .filter_map(|r| r.ok()) | ||||
|  | @ -200,9 +201,9 @@ impl RoomEdus { | |||
|             .roomid_lastroomactiveupdate | ||||
|             .get(&room_id.to_string().as_bytes())? | ||||
|             .map_or(Ok::<_, Error>(None), |bytes| { | ||||
|                 Ok(Some( | ||||
|                     utils::u64_from_bytes(&bytes).map_err(|_| Error::BadDatabase(""))?, | ||||
|                 )) | ||||
|                 Ok(Some(utils::u64_from_bytes(&bytes).map_err(|_| { | ||||
|                     Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.") | ||||
|                 })?)) | ||||
|             })? | ||||
|             .unwrap_or(0)) | ||||
|     } | ||||
|  | @ -219,9 +220,14 @@ impl RoomEdus { | |||
|             .scan_prefix(prefix) | ||||
|             .values() | ||||
|             .map(|user_id| { | ||||
|                 Ok::<_, Error>(serde_json::from_slice(&user_id?).map_err(|_| { | ||||
|                     Error::BadDatabase("User ID in roomactiveid_userid is invalid.") | ||||
|                 })?) | ||||
|                 Ok::<_, Error>( | ||||
|                     UserId::try_from(utils::string_from_bytes(&user_id?).map_err(|_| { | ||||
|                         Error::bad_database("User ID in roomactiveid_userid is invalid unicode.") | ||||
|                     })?) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("User ID in roomactiveid_userid is invalid.") | ||||
|                     })?, | ||||
|                 ) | ||||
|             }) | ||||
|         { | ||||
|             user_ids.push(user_id?); | ||||
|  | @ -252,7 +258,7 @@ impl RoomEdus { | |||
| 
 | ||||
|         self.roomuserid_lastread.get(key)?.map_or(Ok(None), |v| { | ||||
|             Ok(Some(utils::u64_from_bytes(&v).map_err(|_| { | ||||
|                 Error::BadDatabase("Invalid private read marker bytes") | ||||
|                 Error::bad_database("Invalid private read marker bytes") | ||||
|             })?)) | ||||
|         }) | ||||
|     } | ||||
|  |  | |||
|  | @ -178,7 +178,7 @@ impl Uiaa { | |||
|                     "UIAA session does not exist.", | ||||
|                 ))?, | ||||
|         ) | ||||
|         .map_err(|_| Error::BadDatabase("UiaaInfo in userdeviceid_uiaainfo is invalid."))?; | ||||
|         .map_err(|_| Error::bad_database("UiaaInfo in userdeviceid_uiaainfo is invalid."))?; | ||||
| 
 | ||||
|         if uiaainfo | ||||
|             .session | ||||
|  |  | |||
|  | @ -43,19 +43,22 @@ impl Users { | |||
|             .get(token)? | ||||
|             .map_or(Ok(None), |bytes| { | ||||
|                 let mut parts = bytes.split(|&b| b == 0xff); | ||||
|                 let user_bytes = parts.next().ok_or(Error::BadDatabase( | ||||
|                     "token_userdeviceid value in db is invalid.", | ||||
|                 ))?; | ||||
|                 let device_bytes = parts.next().ok_or(Error::BadDatabase( | ||||
|                     "token_userdeviceid value in db is invalid.", | ||||
|                 ))?; | ||||
|                 let user_bytes = parts.next().ok_or_else(|| { | ||||
|                     Error::bad_database("User ID in token_userdeviceid is invalid.") | ||||
|                 })?; | ||||
|                 let device_bytes = parts.next().ok_or_else(|| { | ||||
|                     Error::bad_database("Device ID in token_userdeviceid is invalid.") | ||||
|                 })?; | ||||
| 
 | ||||
|                 Ok(Some(( | ||||
|                     serde_json::from_slice(&user_bytes).map_err(|_| { | ||||
|                         Error::BadDatabase("User ID in token_userdeviceid is invalid.") | ||||
|                     UserId::try_from(utils::string_from_bytes(&user_bytes).map_err(|_| { | ||||
|                         Error::bad_database("User ID in token_userdeviceid is invalid unicode.") | ||||
|                     })?) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("User ID in token_userdeviceid is invalid.") | ||||
|                     })?, | ||||
|                     utils::string_from_bytes(&device_bytes).map_err(|_| { | ||||
|                         Error::BadDatabase("Device ID in token_userdeviceid is invalid.") | ||||
|                         Error::bad_database("Device ID in token_userdeviceid is invalid.") | ||||
|                     })?, | ||||
|                 ))) | ||||
|             }) | ||||
|  | @ -64,8 +67,12 @@ impl Users { | |||
|     /// Returns an iterator over all users on this homeserver.
 | ||||
|     pub fn iter(&self) -> impl Iterator<Item = Result<UserId>> { | ||||
|         self.userid_password.iter().keys().map(|bytes| { | ||||
|             Ok(serde_json::from_slice(&bytes?) | ||||
|                 .map_err(|_| Error::BadDatabase("User ID bytes in db are invalid."))?) | ||||
|             Ok( | ||||
|                 UserId::try_from(utils::string_from_bytes(&bytes?).map_err(|_| { | ||||
|                     Error::bad_database("User ID in userid_password is invalid unicode.") | ||||
|                 })?) | ||||
|                 .map_err(|_| Error::bad_database("User ID in userid_password is invalid."))?, | ||||
|             ) | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -75,7 +82,7 @@ impl Users { | |||
|             .get(user_id.to_string())? | ||||
|             .map_or(Ok(None), |bytes| { | ||||
|                 Ok(Some(utils::string_from_bytes(&bytes).map_err(|_| { | ||||
|                     Error::BadDatabase("Password hash in db is not valid string.") | ||||
|                     Error::bad_database("Password hash in db is not valid string.") | ||||
|                 })?)) | ||||
|             }) | ||||
|     } | ||||
|  | @ -86,7 +93,7 @@ impl Users { | |||
|             .get(user_id.to_string())? | ||||
|             .map_or(Ok(None), |bytes| { | ||||
|                 Ok(Some(utils::string_from_bytes(&bytes).map_err(|_| { | ||||
|                     Error::BadDatabase("Displayname in db is invalid.") | ||||
|                     Error::bad_database("Displayname in db is invalid.") | ||||
|                 })?)) | ||||
|             }) | ||||
|     } | ||||
|  | @ -109,7 +116,7 @@ impl Users { | |||
|             .get(user_id.to_string())? | ||||
|             .map_or(Ok(None), |bytes| { | ||||
|                 Ok(Some(utils::string_from_bytes(&bytes).map_err(|_| { | ||||
|                     Error::BadDatabase("Avatar URL in db is invalid.") | ||||
|                     Error::bad_database("Avatar URL in db is invalid.") | ||||
|                 })?)) | ||||
|             }) | ||||
|     } | ||||
|  | @ -200,10 +207,10 @@ impl Users { | |||
|                     &*bytes? | ||||
|                         .rsplit(|&b| b == 0xff) | ||||
|                         .next() | ||||
|                         .ok_or(Error::BadDatabase("UserDevice ID in db is invalid."))?, | ||||
|                         .ok_or_else(|| Error::bad_database("UserDevice ID in db is invalid."))?, | ||||
|                 ) | ||||
|                 .map_err(|_| { | ||||
|                     Error::BadDatabase("Device ID in userdeviceid_metadata is invalid.") | ||||
|                     Error::bad_database("Device ID in userdeviceid_metadata is invalid.") | ||||
|                 })?) | ||||
|             }) | ||||
|     } | ||||
|  | @ -289,11 +296,11 @@ impl Users { | |||
|                         &*key | ||||
|                             .rsplit(|&b| b == 0xff) | ||||
|                             .next() | ||||
|                             .ok_or(Error::BadDatabase("OneTimeKeyId in db is invalid."))?, | ||||
|                             .ok_or_else(|| Error::bad_database("OneTimeKeyId in db is invalid."))?, | ||||
|                     ) | ||||
|                     .map_err(|_| Error::BadDatabase("OneTimeKeyId in db is invalid."))?, | ||||
|                     .map_err(|_| Error::bad_database("OneTimeKeyId in db is invalid."))?, | ||||
|                     serde_json::from_slice(&*value) | ||||
|                         .map_err(|_| Error::BadDatabase("OneTimeKeys in db are invalid."))?, | ||||
|                         .map_err(|_| Error::bad_database("OneTimeKeys in db are invalid."))?, | ||||
|                 )) | ||||
|             }) | ||||
|             .transpose() | ||||
|  | @ -317,12 +324,11 @@ impl Users { | |||
|             .map(|bytes| { | ||||
|                 Ok::<_, Error>( | ||||
|                     serde_json::from_slice::<AlgorithmAndDeviceId>( | ||||
|                         &*bytes? | ||||
|                             .rsplit(|&b| b == 0xff) | ||||
|                             .next() | ||||
|                             .ok_or(Error::BadDatabase("OneTimeKey ID in db is invalid."))?, | ||||
|                         &*bytes?.rsplit(|&b| b == 0xff).next().ok_or_else(|| { | ||||
|                             Error::bad_database("OneTimeKey ID in db is invalid.") | ||||
|                         })?, | ||||
|                     ) | ||||
|                     .map_err(|_| Error::BadDatabase("AlgorithmAndDeviceID in db is invalid."))? | ||||
|                     .map_err(|_| Error::bad_database("AlgorithmAndDeviceID in db is invalid."))? | ||||
|                     .0, | ||||
|                 ) | ||||
|             }) | ||||
|  | @ -369,7 +375,7 @@ impl Users { | |||
|             .values() | ||||
|             .map(|bytes| { | ||||
|                 Ok(serde_json::from_slice(&bytes?) | ||||
|                     .map_err(|_| Error::BadDatabase("DeviceKeys in db are invalid."))?) | ||||
|                     .map_err(|_| Error::bad_database("DeviceKeys in db are invalid."))?) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -378,9 +384,16 @@ impl Users { | |||
|             .range(since.to_be_bytes()..) | ||||
|             .values() | ||||
|             .map(|bytes| { | ||||
|                 Ok(serde_json::from_slice(&bytes?).map_err(|_| { | ||||
|                     Error::BadDatabase("User ID in devicekeychangeid_userid is invalid.") | ||||
|                 })?) | ||||
|                 Ok( | ||||
|                     UserId::try_from(utils::string_from_bytes(&bytes?).map_err(|_| { | ||||
|                         Error::bad_database( | ||||
|                             "User ID in devicekeychangeid_userid is invalid unicode.", | ||||
|                         ) | ||||
|                     })?) | ||||
|                     .map_err(|_| { | ||||
|                         Error::bad_database("User ID in devicekeychangeid_userid is invalid.") | ||||
|                     })?, | ||||
|                 ) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -396,13 +409,13 @@ impl Users { | |||
|             let userdeviceid = utils::string_from_bytes( | ||||
|                 key.rsplit(|&b| b == 0xff) | ||||
|                     .next() | ||||
|                     .ok_or(Error::BadDatabase("UserDeviceID in db is invalid."))?, | ||||
|                     .ok_or_else(|| Error::bad_database("UserDeviceID in db is invalid."))?, | ||||
|             ) | ||||
|             .map_err(|_| Error::BadDatabase("UserDeviceId in db is invalid."))?; | ||||
|             .map_err(|_| Error::bad_database("UserDeviceId in db is invalid."))?; | ||||
|             Ok(( | ||||
|                 userdeviceid, | ||||
|                 serde_json::from_slice(&*value) | ||||
|                     .map_err(|_| Error::BadDatabase("DeviceKeys in db are invalid."))?, | ||||
|                     .map_err(|_| Error::bad_database("DeviceKeys in db are invalid."))?, | ||||
|             )) | ||||
|         }) | ||||
|     } | ||||
|  | @ -452,7 +465,7 @@ impl Users { | |||
|             let (key, value) = result?; | ||||
|             events.push( | ||||
|                 serde_json::from_slice(&*value) | ||||
|                     .map_err(|_| Error::BadDatabase("Event in todeviceid_events is invalid."))?, | ||||
|                     .map_err(|_| Error::bad_database("Event in todeviceid_events is invalid."))?, | ||||
|             ); | ||||
|             self.todeviceid_events.remove(key)?; | ||||
|         } | ||||
|  | @ -493,7 +506,7 @@ impl Users { | |||
|             .get(&userdeviceid)? | ||||
|             .map_or(Ok(None), |bytes| { | ||||
|                 Ok(Some(serde_json::from_slice(&bytes).map_err(|_| { | ||||
|                     Error::BadDatabase("Metadata in userdeviceid_metadata is invalid.") | ||||
|                     Error::bad_database("Metadata in userdeviceid_metadata is invalid.") | ||||
|                 })?)) | ||||
|             }) | ||||
|     } | ||||
|  | @ -507,7 +520,7 @@ impl Users { | |||
|             .values() | ||||
|             .map(|bytes| { | ||||
|                 Ok(serde_json::from_slice::<Device>(&bytes?).map_err(|_| { | ||||
|                     Error::BadDatabase("Device in userdeviceid_metadata is invalid.") | ||||
|                     Error::bad_database("Device in userdeviceid_metadata is invalid.") | ||||
|                 })?) | ||||
|             }) | ||||
|     } | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| use crate::RumaResponse; | ||||
| use http::StatusCode; | ||||
| use log::error; | ||||
| use rocket::{ | ||||
|     response::{self, Responder}, | ||||
|     Request, | ||||
|  | @ -27,6 +28,7 @@ pub enum Error { | |||
|     #[error("{0}")] | ||||
|     BadConfig(&'static str), | ||||
|     #[error("{0}")] | ||||
|     /// Don't create this directly. Use Error::bad_database instead.
 | ||||
|     BadDatabase(&'static str), | ||||
|     #[error("uiaa")] | ||||
|     Uiaa(UiaaInfo), | ||||
|  | @ -37,6 +39,13 @@ pub enum Error { | |||
|     Conflict(&'static str), // This is only needed for when a room alias already exists
 | ||||
| } | ||||
| 
 | ||||
| impl Error { | ||||
|     pub fn bad_database(message: &'static str) -> Self { | ||||
|         error!("BadDatabase: {}", message); | ||||
|         Self::BadDatabase(message) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[rocket::async_trait] | ||||
| impl<'r> Responder<'r> for Error { | ||||
|     async fn respond_to(self, r: &'r Request<'_>) -> response::Result<'r> { | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ impl PduEvent { | |||
|         let old_content = self | ||||
|             .content | ||||
|             .as_object_mut() | ||||
|             .ok_or(Error::BadDatabase("PDU has invalid content"))?; | ||||
|             .ok_or_else(|| Error::bad_database("PDU in db has invalid content."))?; | ||||
| 
 | ||||
|         let mut new_content = serde_json::Map::new(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,7 +42,10 @@ impl<'a, T: Endpoint> FromData<'a> for Ruma<T> { | |||
|             let data = rocket::try_outcome!(outcome.owned()); | ||||
| 
 | ||||
|             let (user_id, device_id) = if T::METADATA.requires_authentication { | ||||
|                 let db = request.guard::<State<'_, crate::Database>>().await.expect("database was loaded"); | ||||
|                 let db = request | ||||
|                     .guard::<State<'_, crate::Database>>() | ||||
|                     .await | ||||
|                     .expect("database was loaded"); | ||||
| 
 | ||||
|                 // Get token from header or query value
 | ||||
|                 let token = match request | ||||
|  |  | |||
|  | @ -35,8 +35,6 @@ POST /rooms/:room_id/invite can send an invite | |||
| PUT /rooms/:room_id/state/m.room.power_levels can set levels | ||||
| PUT power_levels should not explode if the old power levels were empty | ||||
| Both GET and PUT work | ||||
| Room creation reports m.room.create to myself | ||||
| Room creation reports m.room.member to myself | ||||
| Version responds 200 OK with valid structure | ||||
| PUT /profile/:user_id/displayname sets my name | ||||
| GET /profile/:user_id/displayname publicly accessible | ||||
|  | @ -78,3 +76,4 @@ User directory correctly update on display name change | |||
| User in shared private room does appear in user directory | ||||
| User in dir while user still shares private rooms | ||||
| POST /rooms/:room_id/ban can ban a user | ||||
| Alternative server names do not cause a routing loop | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue