improvement: log bad database errors automatically

This commit is contained in:
timokoesters 2020-06-11 10:03:08 +02:00
parent 2368a90584
commit 56d4742201
No known key found for this signature in database
GPG key ID: 24DA7517711A2BA4
13 changed files with 278 additions and 208 deletions

View file

@ -362,17 +362,14 @@ pub fn get_pushrules_all_route(
"PushRules event not found.", "PushRules event not found.",
))? ))?
.deserialize() .deserialize()
.map_err(|_| Error::BadRequest( .map_err(|_| Error::BadRequest(ErrorKind::NotFound, "PushRules event in db is invalid."))?
ErrorKind::NotFound,
"PushRules event in db is invalid.",
))?
{ {
Ok(get_pushrules_all::Response { Ok(get_pushrules_all::Response {
global: pushrules.content.global, global: pushrules.content.global,
} }
.into()) .into())
} else { } 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 db.rooms
.room_state(&room_id)? .room_state(&room_id)?
.get(&(EventType::RoomMember, user_id.to_string())) .get(&(EventType::RoomMember, user_id.to_string()))
.ok_or(Error::BadDatabase( .ok_or_else(|| {
Error::bad_database(
"Tried to send displayname update for user not in the room.", "Tried to send displayname update for user not in the room.",
))? )
})?
.content .content
.clone(), .clone(),
) )
.map_err(|_| Error::BadDatabase("Database contains invalid PDU."))? .map_err(|_| Error::bad_database("Database contains invalid PDU."))?
.deserialize() .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"), .expect("event is valid, we just created it"),
None, None,
@ -596,15 +595,17 @@ pub fn set_avatar_url_route(
db.rooms db.rooms
.room_state(&room_id)? .room_state(&room_id)?
.get(&(EventType::RoomMember, user_id.to_string())) .get(&(EventType::RoomMember, user_id.to_string()))
.ok_or(Error::BadDatabase( .ok_or_else(|| {
Error::bad_database(
"Tried to send avatar url update for user not in the room.", "Tried to send avatar url update for user not in the room.",
))? )
})?
.content .content
.clone(), .clone(),
) )
.map_err(|_| Error::BadDatabase("Database contains invalid PDU."))? .map_err(|_| Error::bad_database("Database contains invalid PDU."))?
.deserialize() .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"), .expect("event is valid, we just created it"),
None, None,
@ -744,9 +745,12 @@ pub fn get_keys_route(
for result in db.users.all_device_keys(&user_id.clone()) { for result in db.users.all_device_keys(&user_id.clone()) {
let (device_id, mut keys) = result?; let (device_id, mut keys) = result?;
let metadata = db.users.get_device_metadata(user_id, &device_id)?.ok_or( let metadata = db
Error::BadDatabase("all_device_keys contained nonexistent device."), .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 { keys.unsigned = Some(keys::UnsignedDeviceInfo {
device_display_name: metadata.display_name, 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 user_id = body.user_id.as_ref().expect("user is authenticated");
let room_id = RoomId::new(db.globals.server_name()) 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 let alias = body
.room_alias_name .room_alias_name
@ -1281,9 +1285,9 @@ pub fn join_room_by_id_route(
let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>( let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>(
pdu.content.clone(), pdu.content.clone(),
) )
.map_err(|_| Error::BadDatabase("Invalid member event in db."))? .map_err(|_| Error::bad_database("Invalid member event in db."))?
.deserialize() .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.membership = member::MembershipState::Join;
event.displayname = db.users.displayname(&user_id)?; event.displayname = db.users.displayname(&user_id)?;
event.avatar_url = db.users.avatar_url(&user_id)?; event.avatar_url = db.users.avatar_url(&user_id)?;
@ -1356,9 +1360,9 @@ pub fn leave_room_route(
.content .content
.clone(), .clone(),
) )
.map_err(|_| Error::BadDatabase("Invalid member event in database."))? .map_err(|_| Error::bad_database("Invalid member event in database."))?
.deserialize() .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; event.membership = member::MembershipState::Leave;
@ -1396,9 +1400,9 @@ pub fn kick_user_route(
.content .content
.clone(), .clone(),
) )
.map_err(|_| Error::BadDatabase("Invalid member event in database."))? .map_err(|_| Error::bad_database("Invalid member event in database."))?
.deserialize() .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; event.membership = ruma::events::room::member::MembershipState::Leave;
// TODO: reason // TODO: reason
@ -1442,9 +1446,9 @@ pub fn ban_user_route(
let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>( let mut event = serde_json::from_value::<EventJson<member::MemberEventContent>>(
event.content.clone(), event.content.clone(),
) )
.map_err(|_| Error::BadDatabase("Invalid member event in database."))? .map_err(|_| Error::bad_database("Invalid member event in database."))?
.deserialize() .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; event.membership = ruma::events::room::member::MembershipState::Ban;
Ok(event) Ok(event)
}, },
@ -1484,9 +1488,9 @@ pub fn unban_user_route(
.content .content
.clone(), .clone(),
) )
.map_err(|_| Error::BadDatabase("Invalid member event in database."))? .map_err(|_| Error::bad_database("Invalid member event in database."))?
.deserialize() .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; 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::< Ok(serde_json::from_value::<
EventJson<ruma::events::room::canonical_alias::CanonicalAliasEventContent>, EventJson<ruma::events::room::canonical_alias::CanonicalAliasEventContent>,
>(s.content.clone()) >(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() .deserialize()
.map_err(|_| Error::BadDatabase("Invalid canonical alias event in database."))? .map_err(|_| Error::bad_database("Invalid canonical alias event in database."))?
.alias) .alias)
})?, })?,
name: state.get(&(EventType::RoomName, "".to_owned())).map_or(Ok::<_, Error>(None), |s| { name: state.get(&(EventType::RoomName, "".to_owned())).map_or(Ok::<_, Error>(None), |s| {
Ok(serde_json::from_value::<EventJson<ruma::events::room::name::NameEventContent>>( Ok(serde_json::from_value::<EventJson<ruma::events::room::name::NameEventContent>>(
s.content.clone(), 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() .deserialize()
.map_err(|_| Error::BadDatabase("Invalid room name event in database."))? .map_err(|_| Error::bad_database("Invalid room name event in database."))?
.name() .name()
.map(|n| n.to_owned())) .map(|n| n.to_owned()))
})?, })?,
@ -1667,36 +1671,36 @@ pub async fn get_public_rooms_filtered_route(
Ok(Some(serde_json::from_value::< Ok(Some(serde_json::from_value::<
EventJson<ruma::events::room::topic::TopicEventContent>, EventJson<ruma::events::room::topic::TopicEventContent>,
>(s.content.clone()) >(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() .deserialize()
.map_err(|_| Error::BadDatabase("Invalid room topic event in database."))? .map_err(|_| Error::bad_database("Invalid room topic event in database."))?
.topic)) .topic))
})?, })?,
world_readable: state.get(&(EventType::RoomHistoryVisibility, "".to_owned())).map_or(Ok::<_, Error>(false), |s| { world_readable: state.get(&(EventType::RoomHistoryVisibility, "".to_owned())).map_or(Ok::<_, Error>(false), |s| {
Ok(serde_json::from_value::< Ok(serde_json::from_value::<
EventJson<ruma::events::room::history_visibility::HistoryVisibilityEventContent>, EventJson<ruma::events::room::history_visibility::HistoryVisibilityEventContent>,
>(s.content.clone()) >(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() .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) .history_visibility == history_visibility::HistoryVisibility::WorldReadable)
})?, })?,
guest_can_join: state.get(&(EventType::RoomGuestAccess, "".to_owned())).map_or(Ok::<_, Error>(false), |s| { guest_can_join: state.get(&(EventType::RoomGuestAccess, "".to_owned())).map_or(Ok::<_, Error>(false), |s| {
Ok(serde_json::from_value::< Ok(serde_json::from_value::<
EventJson<ruma::events::room::guest_access::GuestAccessEventContent>, EventJson<ruma::events::room::guest_access::GuestAccessEventContent>,
>(s.content.clone()) >(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() .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) .guest_access == guest_access::GuestAccess::CanJoin)
})?, })?,
avatar_url: state.get(&(EventType::RoomAvatar, "".to_owned())).map_or( Ok::<_, Error>(None),|s| { avatar_url: state.get(&(EventType::RoomAvatar, "".to_owned())).map_or( Ok::<_, Error>(None),|s| {
Ok(Some(serde_json::from_value::< Ok(Some(serde_json::from_value::<
EventJson<ruma::events::room::avatar::AvatarEventContent>, EventJson<ruma::events::room::avatar::AvatarEventContent>,
>(s.content.clone()) >(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() .deserialize()
.map_err(|_| Error::BadDatabase("Invalid room avatar event in database."))? .map_err(|_| Error::bad_database("Invalid room avatar event in database."))?
.url)) .url))
})?, })?,
}; };
@ -1986,7 +1990,7 @@ pub fn get_state_events_for_key_route(
Ok(get_state_events_for_key::Response { Ok(get_state_events_for_key::Response {
content: serde_json::value::to_raw_value(&event.content) 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()) .into())
} }
@ -2021,7 +2025,7 @@ pub fn get_state_events_for_empty_key_route(
Ok(get_state_events_for_empty_key::Response { Ok(get_state_events_for_empty_key::Response {
content: serde_json::value::to_raw_value(event) 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()) .into())
} }
@ -2064,9 +2068,9 @@ pub fn sync_route(
let content = serde_json::from_value::< let content = serde_json::from_value::<
EventJson<ruma::events::room::member::MemberEventContent>, EventJson<ruma::events::room::member::MemberEventContent>,
>(pdu.content.clone()) >(pdu.content.clone())
.map_err(|_| Error::BadDatabase("Invalid PDU in database."))? .map_err(|_| Error::bad_database("Invalid PDU in database."))?
.deserialize() .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 { if content.membership == ruma::events::room::member::MembershipState::Join {
joined_since_last_sync = true; joined_since_last_sync = true;
// Both send_member_count and joined_since_last_sync are set. There's nothing more // 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::< let content = serde_json::from_value::<
EventJson<ruma::events::room::member::MemberEventContent>, EventJson<ruma::events::room::member::MemberEventContent>,
>(pdu.content.clone()) >(pdu.content.clone())
.map_err(|_| Error::BadDatabase("Invalid member event in database."))? .map_err(|_| Error::bad_database("Invalid member event in database."))?
.deserialize() .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 { if let Some(state_key) = &pdu.state_key {
let current_content = serde_json::from_value::< let current_content = serde_json::from_value::<
@ -2109,15 +2113,19 @@ pub fn sync_route(
>( >(
state state
.get(&(EventType::RoomMember, state_key.clone())) .get(&(EventType::RoomMember, state_key.clone()))
.ok_or(Error::BadDatabase( .ok_or_else(|| {
Error::bad_database(
"A user that joined once has no member event anymore.", "A user that joined once has no member event anymore.",
))? )
})?
.content .content
.clone(), .clone(),
) )
.map_err(|_| Error::BadDatabase("Invalid member event in database."))? .map_err(|_| Error::bad_database("Invalid member event in database."))?
.deserialize() .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 // The membership was and still is invite or join
if matches!( if matches!(
@ -2192,7 +2200,7 @@ pub fn sync_route(
Ok(Some( Ok(Some(
db.rooms db.rooms
.get_pdu_count(&e.event_id)? .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(), .to_string(),
)) ))
})?; })?;
@ -2355,7 +2363,7 @@ pub fn sync_route(
.map(|edu| { .map(|edu| {
let mut edu = edu? let mut edu = edu?
.deserialize() .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 { if let Some(timestamp) = edu.content.last_active_ago {
let last_active_ago = let last_active_ago =
js_int::UInt::try_from(utils::millis_since_unix_epoch()) js_int::UInt::try_from(utils::millis_since_unix_epoch())
@ -2444,7 +2452,7 @@ pub fn get_context_route(
Ok::<_, Error>(Some( Ok::<_, Error>(Some(
db.rooms db.rooms
.get_pdu_count(&e.event_id)? .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(), .to_string(),
)) ))
})?; })?;
@ -2470,7 +2478,7 @@ pub fn get_context_route(
Ok::<_, Error>(Some( Ok::<_, Error>(Some(
db.rooms db.rooms
.get_pdu_count(&e.event_id)? .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(), .to_string(),
)) ))
})?; })?;
@ -2534,7 +2542,7 @@ pub fn get_message_events_route(
Ok(Some( Ok(Some(
db.rooms db.rooms
.get_pdu_count(&e.event_id)? .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(), .to_string(),
)) ))
})?; })?;
@ -2569,7 +2577,7 @@ pub fn get_message_events_route(
Ok(Some( Ok(Some(
db.rooms db.rooms
.get_pdu_count(&e.event_id)? .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(), .to_string(),
)) ))
})?; })?;

View file

@ -115,16 +115,14 @@ impl AccountData {
.map(|(k, v)| { .map(|(k, v)| {
Ok::<_, Error>(( Ok::<_, Error>((
EventType::try_from( EventType::try_from(
utils::string_from_bytes( utils::string_from_bytes(k.rsplit(|&b| b == 0xff).next().ok_or_else(
k.rsplit(|&b| b == 0xff) || Error::bad_database("RoomUserData ID in db is invalid."),
.next() )?)
.ok_or(Error::BadDatabase("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."))?,
)
.map_err(|_| Error::BadDatabase("RoomUserData ID in db is invalid."))?,
serde_json::from_slice::<EventJson<EduEvent>>(&v).map_err(|_| { serde_json::from_slice::<EventJson<EduEvent>>(&v).map_err(|_| {
Error::BadDatabase("Database contains invalid account data.") Error::bad_database("Database contains invalid account data.")
})?, })?,
)) ))
}) })

View file

@ -57,7 +57,7 @@ impl GlobalEdus {
.filter_map(|r| r.ok()) .filter_map(|r| r.ok())
.map(|(_, v)| { .map(|(_, v)| {
Ok(serde_json::from_slice(&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."))?)
})) }))
} }
} }

View file

@ -18,7 +18,7 @@ impl Globals {
.expect("utils::generate_keypair always returns Some"), .expect("utils::generate_keypair always returns Some"),
"key1".to_owned(), "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 { Ok(Self {
globals, globals,
@ -49,13 +49,13 @@ impl Globals {
.update_and_fetch(COUNTER, utils::increment)? .update_and_fetch(COUNTER, utils::increment)?
.expect("utils::increment will always put in a value"), .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> { pub fn current_count(&self) -> Result<u64> {
self.globals.get(COUNTER)?.map_or(Ok(0_u64), |bytes| { self.globals.get(COUNTER)?.map_or(Ok(0_u64), |bytes| {
Ok(utils::u64_from_bytes(&bytes) Ok(utils::u64_from_bytes(&bytes)
.map_err(|_| Error::BadDatabase("Count has invalid bytes."))?) .map_err(|_| Error::bad_database("Count has invalid bytes."))?)
}) })
} }

View file

@ -43,21 +43,20 @@ impl Media {
let content_type = utils::string_from_bytes( let content_type = utils::string_from_bytes(
parts parts
.next() .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 let filename_bytes = parts
.next() .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() { let filename = if filename_bytes.is_empty() {
None None
} else { } else {
Some( Some(utils::string_from_bytes(filename_bytes).map_err(|_| {
utils::string_from_bytes(filename_bytes) Error::bad_database("Filename in mediaid_file is invalid unicode.")
.map_err(|_| Error::BadDatabase("Filename in db is invalid."))?, })?)
)
}; };
Ok(Some((filename, content_type, file.to_vec()))) Ok(Some((filename, content_type, file.to_vec())))
@ -94,20 +93,20 @@ impl Media {
let content_type = utils::string_from_bytes( let content_type = utils::string_from_bytes(
parts parts
.next() .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 let filename_bytes = parts
.next() .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() { let filename = if filename_bytes.is_empty() {
None None
} else { } else {
Some( Some(
utils::string_from_bytes(filename_bytes) 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( let content_type = utils::string_from_bytes(
parts parts
.next() .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 let filename_bytes = parts
.next() .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() { let filename = if filename_bytes.is_empty() {
None None
} else { } else {
Some( Some(utils::string_from_bytes(filename_bytes).map_err(|_| {
utils::string_from_bytes(filename_bytes) Error::bad_database("Filename in mediaid_file is invalid unicode.")
.map_err(|_| Error::BadDatabase("Filename in db is invalid."))?, })?)
)
}; };
if let Ok(image) = image::load_from_memory(&file) { if let Ok(image) = image::load_from_memory(&file) {
@ -147,7 +145,7 @@ impl Media {
let width_index = thumbnail_key let width_index = thumbnail_key
.iter() .iter()
.position(|&b| b == 0xff) .position(|&b| b == 0xff)
.ok_or(Error::BadDatabase("mediaid is invalid"))? .ok_or_else(|| Error::bad_database("Media in db is invalid."))?
+ 1; + 1;
let mut widthheight = width.to_be_bytes().to_vec(); let mut widthheight = width.to_be_bytes().to_vec();
widthheight.extend_from_slice(&height.to_be_bytes()); widthheight.extend_from_slice(&height.to_be_bytes());

View file

@ -65,14 +65,14 @@ impl Rooms {
.map(|value| { .map(|value| {
Ok::<_, Error>( Ok::<_, Error>(
serde_json::from_slice::<PduEvent>(&value?) 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 pdu = pdu?;
let state_key = pdu.state_key.clone().ok_or(Error::BadDatabase( let state_key = pdu.state_key.clone().ok_or_else(|| {
"Room state contains event without state_key.", Error::bad_database("Room state contains event without state_key.")
))?; })?;
hashmap.insert((pdu.kind.clone(), state_key), pdu); hashmap.insert((pdu.kind.clone(), state_key), pdu);
} }
Ok(hashmap) Ok(hashmap)
@ -87,7 +87,7 @@ impl Rooms {
utils::u64_from_bytes( utils::u64_from_bytes(
&pdu_id[pdu_id.len() - mem::size_of::<u64>()..pdu_id.len()], &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())? .get(event_id.to_string().as_bytes())?
.map_or(Ok(None), |pdu_id| { .map_or(Ok(None), |pdu_id| {
Ok(Some( Ok(Some(
serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or( serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or_else(|| {
Error::BadDatabase("eventid_pduid points to nonexistent pdu."), Error::bad_database("eventid_pduid points to nonexistent pdu.")
)?) })?)
.map_err(|_| Error::BadDatabase("Invalid PDU in db."))?, .map_err(|_| Error::bad_database("Invalid PDU in db."))?,
)) ))
}) })
} }
@ -119,10 +119,10 @@ impl Rooms {
.get(event_id.to_string().as_bytes())? .get(event_id.to_string().as_bytes())?
.map_or(Ok(None), |pdu_id| { .map_or(Ok(None), |pdu_id| {
Ok(Some( Ok(Some(
serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or( serde_json::from_slice(&self.pduid_pdu.get(pdu_id)?.ok_or_else(|| {
Error::BadDatabase("eventid_pduid points to nonexistent pdu."), Error::bad_database("eventid_pduid points to nonexistent pdu.")
)?) })?)
.map_err(|_| Error::BadDatabase("Invalid PDU in db."))?, .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| { self.pduid_pdu.get(pdu_id)?.map_or(Ok(None), |pdu| {
Ok(Some( Ok(Some(
serde_json::from_slice(&pdu) 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() .values()
.map(|bytes| { .map(|bytes| {
Ok::<_, Error>( Ok::<_, Error>(
serde_json::from_slice(&bytes?) EventId::try_from(utils::string_from_bytes(&bytes?).map_err(|_| {
.map_err(|_| Error::BadDatabase("Invalid EventID in roomid_pduleaves."))?, 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.") .expect("EventJson::from_value always works.")
.deserialize() .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.") .expect("EventJson::from_value always works.")
.deserialize() .deserialize()
.map_err(|_| Error::BadDatabase("Invalid Member event in db."))? .map_err(|_| Error::bad_database("Invalid Member event in db."))?
.membership, .membership,
) )
})?; })?;
@ -287,7 +289,7 @@ impl Rooms {
) )
.expect("EventJson::from_value always works.") .expect("EventJson::from_value always works.")
.deserialize() .deserialize()
.map_err(|_| Error::BadDatabase("Invalid Member event in db."))? .map_err(|_| Error::bad_database("Invalid Member event in db."))?
.membership, .membership,
) )
})?; })?;
@ -297,7 +299,7 @@ impl Rooms {
>(content.clone()) >(content.clone())
.expect("EventJson::from_value always works.") .expect("EventJson::from_value always works.")
.deserialize() .deserialize()
.map_err(|_| Error::BadDatabase("Invalid Member event in db."))? .map_err(|_| Error::bad_database("Invalid Member event in db."))?
.membership; .membership;
let target_power = power_levels.users.get(&target_user_id).map_or_else( 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.") .expect("EventJson::from_value always works.")
.deserialize() .deserialize()
.map_err(|_| { .map_err(|_| {
Error::BadDatabase("Database contains invalid JoinRules event") Error::bad_database("Database contains invalid JoinRules event")
})? })?
.join_rule) .join_rule)
})?; })?;
@ -334,7 +336,9 @@ impl Rooms {
ErrorKind::Unknown, ErrorKind::Unknown,
"Membership can't be the first event", "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 if prev_event.kind == EventType::RoomCreate
&& prev_event.prev_events.is_empty() && prev_event.prev_events.is_empty()
{ {
@ -466,7 +470,7 @@ impl Rooms {
prev_events, prev_events,
depth: depth depth: depth
.try_into() .try_into()
.map_err(|_| Error::BadDatabase("Depth is invalid"))?, .map_err(|_| Error::bad_database("Depth is invalid"))?,
auth_events: Vec::new(), auth_events: Vec::new(),
redacts: redacts.clone(), redacts: redacts.clone(),
unsigned, unsigned,
@ -588,7 +592,7 @@ impl Rooms {
.take_while(move |(k, _)| k.starts_with(&prefix)) .take_while(move |(k, _)| k.starts_with(&prefix))
.map(|(_, v)| { .map(|(_, v)| {
Ok(serde_json::from_slice(&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)) .take_while(move |(k, _)| k.starts_with(&prefix))
.map(|(_, v)| { .map(|(_, v)| {
Ok(serde_json::from_slice(&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)) .take_while(move |(k, _)| k.starts_with(&prefix))
.map(|(_, v)| { .map(|(_, v)| {
Ok(serde_json::from_slice(&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)? { if let Some(pdu_id) = self.get_pdu_id(event_id)? {
let mut pdu = self let mut pdu = self
.get_pdu_from_id(&pdu_id)? .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()?; pdu.redact()?;
self.replace_pdu(&pdu_id, &pdu)?; self.replace_pdu(&pdu_id, &pdu)?;
Ok(()) Ok(())
@ -751,9 +755,12 @@ impl Rooms {
self.alias_roomid self.alias_roomid
.get(alias.alias())? .get(alias.alias())?
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
Ok(Some(serde_json::from_slice(&bytes).map_err(|_| { Ok(Some(
Error::BadDatabase("Room ID in alias_roomid is invalid.") 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() .values()
.map(|bytes| { .map(|bytes| {
Ok(serde_json::from_slice(&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>> { pub fn public_rooms(&self) -> impl Iterator<Item = Result<RoomId>> {
self.publicroomids.iter().keys().map(|bytes| { self.publicroomids.iter().keys().map(|bytes| {
Ok(serde_json::from_slice(&bytes?) Ok(
.map_err(|_| Error::BadDatabase("Room ID in publicroomids is invalid."))?) 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>> { pub fn room_members(&self, room_id: &RoomId) -> impl Iterator<Item = Result<UserId>> {
self.roomuserid_joined self.roomuserid_joined
.scan_prefix(room_id.to_string()) .scan_prefix(room_id.to_string())
.values() .keys()
.map(|key| { .map(|key| {
Ok(serde_json::from_slice( Ok(UserId::try_from(
utils::string_from_bytes(
&key? &key?
.rsplit(|&b| b == 0xff) .rsplit(|&b| b == 0xff)
.next() .next()
.ok_or(Error::BadDatabase("RoomUser ID is invalid."))?, .expect("rsplit always returns an element"),
) )
.map_err(|_| Error::BadDatabase("Invalid User ID in db."))?) .map_err(|_| {
Error::bad_database("User ID in roomuserid_joined is invalid unicode.")
})?,
)
.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>> { pub fn room_members_invited(&self, room_id: &RoomId) -> impl Iterator<Item = Result<UserId>> {
self.roomuserid_invited self.roomuserid_invited
.scan_prefix(room_id.to_string()) .scan_prefix(room_id.to_string())
.keys() .keys()
.map(|key| { .map(|key| {
Ok(serde_json::from_slice( Ok(UserId::try_from(
utils::string_from_bytes(
&key? &key?
.rsplit(|&b| b == 0xff) .rsplit(|&b| b == 0xff)
.next() .next()
.ok_or(Error::BadDatabase("RoomUser ID is invalid."))?, .expect("rsplit always returns an element"),
) )
.map_err(|_| Error::BadDatabase("Invalid User ID in db."))?) .map_err(|_| {
Error::bad_database("User ID in roomuserid_invited is invalid unicode.")
})?,
)
.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>> { pub fn rooms_joined(&self, user_id: &UserId) -> impl Iterator<Item = Result<RoomId>> {
self.userroomid_joined self.userroomid_joined
.scan_prefix(user_id.to_string()) .scan_prefix(user_id.to_string())
.keys() .keys()
.map(|key| { .map(|key| {
Ok(serde_json::from_slice( Ok(RoomId::try_from(
utils::string_from_bytes(
&key? &key?
.rsplit(|&b| b == 0xff) .rsplit(|&b| b == 0xff)
.next() .next()
.ok_or(Error::BadDatabase("UserRoom ID is invalid."))?, .expect("rsplit always returns an element"),
) )
.map_err(|_| Error::BadDatabase("Invalid Room ID in db."))?) .map_err(|_| {
Error::bad_database("Room ID in userroomid_joined is invalid unicode.")
})?,
)
.map_err(|_| Error::bad_database("Room ID in userroomid_joined is invalid."))?)
}) })
} }
@ -845,13 +871,18 @@ impl Rooms {
.scan_prefix(&user_id.to_string()) .scan_prefix(&user_id.to_string())
.keys() .keys()
.map(|key| { .map(|key| {
Ok(serde_json::from_slice( Ok(RoomId::try_from(
utils::string_from_bytes(
&key? &key?
.rsplit(|&b| b == 0xff) .rsplit(|&b| b == 0xff)
.next() .next()
.ok_or(Error::BadDatabase("UserRoom ID is invalid."))?, .expect("rsplit always returns an element"),
) )
.map_err(|_| Error::BadDatabase("Invalid Room ID in db."))?) .map_err(|_| {
Error::bad_database("Room ID in userroomid_invited is invalid unicode.")
})?,
)
.map_err(|_| Error::bad_database("Room ID in userroomid_invited is invalid."))?)
}) })
} }
@ -861,13 +892,18 @@ impl Rooms {
.scan_prefix(&user_id.to_string()) .scan_prefix(&user_id.to_string())
.keys() .keys()
.map(|key| { .map(|key| {
Ok(serde_json::from_slice( Ok(RoomId::try_from(
utils::string_from_bytes(
&key? &key?
.rsplit(|&b| b == 0xff) .rsplit(|&b| b == 0xff)
.next() .next()
.ok_or(Error::BadDatabase("UserRoom ID is invalid."))?, .expect("rsplit always returns an element"),
) )
.map_err(|_| Error::BadDatabase("Invalid Room ID in db."))?) .map_err(|_| {
Error::bad_database("Room ID in userroomid_left is invalid unicode.")
})?,
)
.map_err(|_| Error::bad_database("Room ID in userroomid_left is invalid."))?)
}) })
} }

View file

@ -74,8 +74,9 @@ impl RoomEdus {
.filter_map(|r| r.ok()) .filter_map(|r| r.ok())
.take_while(move |(k, _)| k.starts_with(&prefix)) .take_while(move |(k, _)| k.starts_with(&prefix))
.map(|(_, v)| { .map(|(_, v)| {
Ok(serde_json::from_slice(&v) Ok(serde_json::from_slice(&v).map_err(|_| {
.map_err(|_| Error::BadDatabase("Read receipt in db is invalid."))?) Error::bad_database("Read receipt in roomlatestid_roomlatest is invalid.")
})?)
})) }))
} }
@ -164,10 +165,10 @@ impl RoomEdus {
let key = key?; let key = key?;
Ok::<_, Error>(( Ok::<_, Error>((
key.clone(), key.clone(),
utils::u64_from_bytes(key.split(|&b| b == 0xff).nth(1).ok_or( utils::u64_from_bytes(key.split(|&b| b == 0xff).nth(1).ok_or_else(|| {
Error::BadDatabase("RoomActive has invalid timestamp or delimiters."), Error::bad_database("RoomActive has invalid timestamp or delimiters.")
)?) })?)
.map_err(|_| Error::BadDatabase("RoomActive has invalid timestamp bytes."))?, .map_err(|_| Error::bad_database("RoomActive has invalid timestamp bytes."))?,
)) ))
}) })
.filter_map(|r| r.ok()) .filter_map(|r| r.ok())
@ -200,9 +201,9 @@ impl RoomEdus {
.roomid_lastroomactiveupdate .roomid_lastroomactiveupdate
.get(&room_id.to_string().as_bytes())? .get(&room_id.to_string().as_bytes())?
.map_or(Ok::<_, Error>(None), |bytes| { .map_or(Ok::<_, Error>(None), |bytes| {
Ok(Some( Ok(Some(utils::u64_from_bytes(&bytes).map_err(|_| {
utils::u64_from_bytes(&bytes).map_err(|_| Error::BadDatabase(""))?, Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.")
)) })?))
})? })?
.unwrap_or(0)) .unwrap_or(0))
} }
@ -219,9 +220,14 @@ impl RoomEdus {
.scan_prefix(prefix) .scan_prefix(prefix)
.values() .values()
.map(|user_id| { .map(|user_id| {
Ok::<_, Error>(serde_json::from_slice(&user_id?).map_err(|_| { Ok::<_, Error>(
Error::BadDatabase("User ID in roomactiveid_userid is invalid.") 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?); user_ids.push(user_id?);
@ -252,7 +258,7 @@ impl RoomEdus {
self.roomuserid_lastread.get(key)?.map_or(Ok(None), |v| { self.roomuserid_lastread.get(key)?.map_or(Ok(None), |v| {
Ok(Some(utils::u64_from_bytes(&v).map_err(|_| { Ok(Some(utils::u64_from_bytes(&v).map_err(|_| {
Error::BadDatabase("Invalid private read marker bytes") Error::bad_database("Invalid private read marker bytes")
})?)) })?))
}) })
} }

View file

@ -178,7 +178,7 @@ impl Uiaa {
"UIAA session does not exist.", "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 if uiaainfo
.session .session

View file

@ -43,19 +43,22 @@ impl Users {
.get(token)? .get(token)?
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
let mut parts = bytes.split(|&b| b == 0xff); let mut parts = bytes.split(|&b| b == 0xff);
let user_bytes = parts.next().ok_or(Error::BadDatabase( let user_bytes = parts.next().ok_or_else(|| {
"token_userdeviceid value in db is invalid.", Error::bad_database("User ID in token_userdeviceid is invalid.")
))?; })?;
let device_bytes = parts.next().ok_or(Error::BadDatabase( let device_bytes = parts.next().ok_or_else(|| {
"token_userdeviceid value in db is invalid.", Error::bad_database("Device ID in token_userdeviceid is invalid.")
))?; })?;
Ok(Some(( Ok(Some((
serde_json::from_slice(&user_bytes).map_err(|_| { UserId::try_from(utils::string_from_bytes(&user_bytes).map_err(|_| {
Error::BadDatabase("User ID in token_userdeviceid is invalid.") 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(|_| { 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. /// Returns an iterator over all users on this homeserver.
pub fn iter(&self) -> impl Iterator<Item = Result<UserId>> { pub fn iter(&self) -> impl Iterator<Item = Result<UserId>> {
self.userid_password.iter().keys().map(|bytes| { self.userid_password.iter().keys().map(|bytes| {
Ok(serde_json::from_slice(&bytes?) Ok(
.map_err(|_| Error::BadDatabase("User ID bytes in db are invalid."))?) 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())? .get(user_id.to_string())?
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
Ok(Some(utils::string_from_bytes(&bytes).map_err(|_| { 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())? .get(user_id.to_string())?
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
Ok(Some(utils::string_from_bytes(&bytes).map_err(|_| { 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())? .get(user_id.to_string())?
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
Ok(Some(utils::string_from_bytes(&bytes).map_err(|_| { 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? &*bytes?
.rsplit(|&b| b == 0xff) .rsplit(|&b| b == 0xff)
.next() .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(|_| { .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 &*key
.rsplit(|&b| b == 0xff) .rsplit(|&b| b == 0xff)
.next() .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) 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() .transpose()
@ -317,12 +324,11 @@ impl Users {
.map(|bytes| { .map(|bytes| {
Ok::<_, Error>( Ok::<_, Error>(
serde_json::from_slice::<AlgorithmAndDeviceId>( serde_json::from_slice::<AlgorithmAndDeviceId>(
&*bytes? &*bytes?.rsplit(|&b| b == 0xff).next().ok_or_else(|| {
.rsplit(|&b| b == 0xff) Error::bad_database("OneTimeKey ID in db is invalid.")
.next() })?,
.ok_or(Error::BadDatabase("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, .0,
) )
}) })
@ -369,7 +375,7 @@ impl Users {
.values() .values()
.map(|bytes| { .map(|bytes| {
Ok(serde_json::from_slice(&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()..) .range(since.to_be_bytes()..)
.values() .values()
.map(|bytes| { .map(|bytes| {
Ok(serde_json::from_slice(&bytes?).map_err(|_| { Ok(
Error::BadDatabase("User ID in devicekeychangeid_userid is invalid.") 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( let userdeviceid = utils::string_from_bytes(
key.rsplit(|&b| b == 0xff) key.rsplit(|&b| b == 0xff)
.next() .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(( Ok((
userdeviceid, userdeviceid,
serde_json::from_slice(&*value) 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?; let (key, value) = result?;
events.push( events.push(
serde_json::from_slice(&*value) 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)?; self.todeviceid_events.remove(key)?;
} }
@ -493,7 +506,7 @@ impl Users {
.get(&userdeviceid)? .get(&userdeviceid)?
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
Ok(Some(serde_json::from_slice(&bytes).map_err(|_| { 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() .values()
.map(|bytes| { .map(|bytes| {
Ok(serde_json::from_slice::<Device>(&bytes?).map_err(|_| { 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.")
})?) })?)
}) })
} }

View file

@ -1,5 +1,6 @@
use crate::RumaResponse; use crate::RumaResponse;
use http::StatusCode; use http::StatusCode;
use log::error;
use rocket::{ use rocket::{
response::{self, Responder}, response::{self, Responder},
Request, Request,
@ -27,6 +28,7 @@ pub enum Error {
#[error("{0}")] #[error("{0}")]
BadConfig(&'static str), BadConfig(&'static str),
#[error("{0}")] #[error("{0}")]
/// Don't create this directly. Use Error::bad_database instead.
BadDatabase(&'static str), BadDatabase(&'static str),
#[error("uiaa")] #[error("uiaa")]
Uiaa(UiaaInfo), Uiaa(UiaaInfo),
@ -37,6 +39,13 @@ pub enum Error {
Conflict(&'static str), // This is only needed for when a room alias already exists 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] #[rocket::async_trait]
impl<'r> Responder<'r> for Error { impl<'r> Responder<'r> for Error {
async fn respond_to(self, r: &'r Request<'_>) -> response::Result<'r> { async fn respond_to(self, r: &'r Request<'_>) -> response::Result<'r> {

View file

@ -60,7 +60,7 @@ impl PduEvent {
let old_content = self let old_content = self
.content .content
.as_object_mut() .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(); let mut new_content = serde_json::Map::new();

View file

@ -42,7 +42,10 @@ impl<'a, T: Endpoint> FromData<'a> for Ruma<T> {
let data = rocket::try_outcome!(outcome.owned()); let data = rocket::try_outcome!(outcome.owned());
let (user_id, device_id) = if T::METADATA.requires_authentication { 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 // Get token from header or query value
let token = match request let token = match request

View file

@ -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 /rooms/:room_id/state/m.room.power_levels can set levels
PUT power_levels should not explode if the old power levels were empty PUT power_levels should not explode if the old power levels were empty
Both GET and PUT work 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 Version responds 200 OK with valid structure
PUT /profile/:user_id/displayname sets my name PUT /profile/:user_id/displayname sets my name
GET /profile/:user_id/displayname publicly accessible 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 shared private room does appear in user directory
User in dir while user still shares private rooms User in dir while user still shares private rooms
POST /rooms/:room_id/ban can ban a user POST /rooms/:room_id/ban can ban a user
Alternative server names do not cause a routing loop