cleanup some error callsites

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-15 04:19:43 +00:00
parent b903b46d16
commit d67f19a55d
9 changed files with 96 additions and 144 deletions

View file

@ -2,11 +2,8 @@ use std::{mem, ops::Deref};
use axum::{async_trait, body::Body, extract::FromRequest}; use axum::{async_trait, body::Body, extract::FromRequest};
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use conduit::{debug, debug_warn, trace, warn, Error, Result}; use conduit::{debug, err, trace, Error, Result};
use ruma::{ use ruma::{api::IncomingRequest, CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId};
api::{client::error::ErrorKind, IncomingRequest},
CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId,
};
use super::{auth, auth::Auth, request, request::Request}; use super::{auth, auth::Auth, request, request::Request};
use crate::{service::appservice::RegistrationInfo, services}; use crate::{service::appservice::RegistrationInfo, services};
@ -103,21 +100,14 @@ where
let mut http_request = hyper::Request::builder() let mut http_request = hyper::Request::builder()
.uri(request.parts.uri.clone()) .uri(request.parts.uri.clone())
.method(request.parts.method.clone()); .method(request.parts.method.clone());
*http_request.headers_mut().unwrap() = request.parts.headers.clone(); *http_request.headers_mut().expect("mutable http headers") = request.parts.headers.clone();
let http_request = http_request.body(body).unwrap(); let http_request = http_request.body(body).expect("http request body");
debug!(
"{:?} {:?} {:?}",
http_request.method(),
http_request.uri(),
http_request.headers()
);
trace!("{:?} {:?} {:?}", http_request.method(), http_request.uri(), json_body); let headers = http_request.headers();
let body = T::try_from_http_request(http_request, &request.path).map_err(|e| { let method = http_request.method();
warn!("try_from_http_request failed: {e:?}",); let uri = http_request.uri();
debug_warn!("JSON body: {:?}", json_body); debug!("{method:?} {uri:?} {headers:?}");
Error::BadRequest(ErrorKind::BadJson, "Failed to deserialize request.") trace!("{method:?} {uri:?} {json_body:?}");
})?;
Ok(body) T::try_from_http_request(http_request, &request.path).map_err(|e| err!(Request(BadJson(debug_warn!("{e}")))))
} }

View file

@ -2,11 +2,11 @@ use std::str;
use axum::{extract::Path, RequestExt, RequestPartsExt}; use axum::{extract::Path, RequestExt, RequestPartsExt};
use bytes::Bytes; use bytes::Bytes;
use conduit::err;
use http::request::Parts; use http::request::Parts;
use ruma::api::client::error::ErrorKind;
use serde::Deserialize; use serde::Deserialize;
use crate::{services, Error, Result}; use crate::{services, Result};
#[derive(Deserialize)] #[derive(Deserialize)]
pub(super) struct QueryParams { pub(super) struct QueryParams {
@ -26,14 +26,15 @@ pub(super) async fn from(request: hyper::Request<axum::body::Body>) -> Result<Re
let (mut parts, body) = limited.into_parts(); let (mut parts, body) = limited.into_parts();
let path: Path<Vec<String>> = parts.extract().await?; let path: Path<Vec<String>> = parts.extract().await?;
let query = serde_html_form::from_str(parts.uri.query().unwrap_or_default()) let query = parts.uri.query().unwrap_or_default();
.map_err(|_| Error::BadRequest(ErrorKind::Unknown, "Failed to read query parameters"))?; let query =
serde_html_form::from_str(query).map_err(|e| err!(Request(Unknown("Failed to read query parameters: {e}"))))?;
let max_body_size = services().globals.config.max_request_size; let max_body_size = services().globals.config.max_request_size;
let body = axum::body::to_bytes(body, max_body_size) let body = axum::body::to_bytes(body, max_body_size)
.await .await
.map_err(|_| Error::BadRequest(ErrorKind::TooLarge, "Request body too large"))?; .map_err(|e| err!(Request(TooLarge("Request body too large: {e}"))))?;
Ok(Request { Ok(Request {
path, path,

View file

@ -1,7 +1,7 @@
use std::{collections::BTreeMap, net::IpAddr, time::Instant}; use std::{collections::BTreeMap, net::IpAddr, time::Instant};
use axum_client_ip::InsecureClientIp; use axum_client_ip::InsecureClientIp;
use conduit::debug_warn; use conduit::{debug, debug_warn, err, trace, warn, Err};
use ruma::{ use ruma::{
api::{ api::{
client::error::ErrorKind, client::error::ErrorKind,
@ -18,7 +18,6 @@ use ruma::{
OwnedEventId, ServerName, OwnedEventId, ServerName,
}; };
use tokio::sync::RwLock; use tokio::sync::RwLock;
use tracing::{debug, error, trace, warn};
use crate::{ use crate::{
service::rooms::event_handler::parse_incoming_pdu, service::rooms::event_handler::parse_incoming_pdu,
@ -39,24 +38,17 @@ pub(crate) async fn send_transaction_message_route(
let origin = body.origin.as_ref().expect("server is authenticated"); let origin = body.origin.as_ref().expect("server is authenticated");
if *origin != body.body.origin { if *origin != body.body.origin {
return Err(Error::BadRequest( return Err!(Request(Forbidden(
ErrorKind::forbidden(), "Not allowed to send transactions on behalf of other servers"
"Not allowed to send transactions on behalf of other servers", )));
));
} }
if body.pdus.len() > 50_usize { if body.pdus.len() > 50_usize {
return Err(Error::BadRequest( return Err!(Request(Forbidden("Not allowed to send more than 50 PDUs in one transaction")));
ErrorKind::forbidden(),
"Not allowed to send more than 50 PDUs in one transaction",
));
} }
if body.edus.len() > 100_usize { if body.edus.len() > 100_usize {
return Err(Error::BadRequest( return Err!(Request(Forbidden("Not allowed to send more than 100 EDUs in one transaction")));
ErrorKind::forbidden(),
"Not allowed to send more than 100 EDUs in one transaction",
));
} }
let txn_start_time = Instant::now(); let txn_start_time = Instant::now();
@ -392,10 +384,9 @@ async fn handle_edu_direct_to_device(
target_user_id, target_user_id,
target_device_id, target_device_id,
&ev_type.to_string(), &ev_type.to_string(),
event.deserialize_as().map_err(|e| { event
error!("To-Device event is invalid: {event:?} {e}"); .deserialize_as()
Error::BadRequest(ErrorKind::InvalidParam, "Event is invalid") .map_err(|e| err!(Request(InvalidParam(error!("To-Device event is invalid: {e}")))))?,
})?,
)?; )?;
}, },
@ -408,7 +399,7 @@ async fn handle_edu_direct_to_device(
&ev_type.to_string(), &ev_type.to_string(),
event event
.deserialize_as() .deserialize_as()
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Event is invalid"))?, .map_err(|e| err!(Request(InvalidParam("Event is invalid: {e}"))))?,
)?; )?;
} }
}, },

View file

@ -31,6 +31,7 @@
//! Err(Database(error!("problem with db: {msg}")))` logs the error at the //! Err(Database(error!("problem with db: {msg}")))` logs the error at the
//! callsite and then returns the error with the same string. Caller has the //! callsite and then returns the error with the same string. Caller has the
//! option of replacing `error!` with `debug_error!`. //! option of replacing `error!` with `debug_error!`.
#[macro_export] #[macro_export]
macro_rules! Err { macro_rules! Err {
($($args:tt)*) => { ($($args:tt)*) => {

View file

@ -78,7 +78,7 @@ pub enum Error {
// conduwuit // conduwuit
#[error("Arithmetic operation failed: {0}")] #[error("Arithmetic operation failed: {0}")]
Arithmetic(&'static str), Arithmetic(Cow<'static, str>),
#[error("There was a problem with the '{0}' directive in your configuration: {1}")] #[error("There was a problem with the '{0}' directive in your configuration: {1}")]
Config(&'static str, Cow<'static, str>), Config(&'static str, Cow<'static, str>),
#[error("{0}")] #[error("{0}")]

View file

@ -2,14 +2,14 @@ use std::{cmp, time::Duration};
pub use checked_ops::checked_ops; pub use checked_ops::checked_ops;
use crate::{Error, Result}; use crate::{Err, Error, Result};
/// Checked arithmetic expression. Returns a Result<R, Error::Arithmetic> /// Checked arithmetic expression. Returns a Result<R, Error::Arithmetic>
#[macro_export] #[macro_export]
macro_rules! checked { macro_rules! checked {
($($input:tt)*) => { ($($input:tt)*) => {
$crate::utils::math::checked_ops!($($input)*) $crate::utils::math::checked_ops!($($input)*)
.ok_or_else(|| $crate::Error::Arithmetic("operation overflowed or result invalid")) .ok_or_else(|| $crate::err!(Arithmetic("operation overflowed or result invalid")))
} }
} }
@ -21,7 +21,7 @@ macro_rules! validated {
($($input:tt)*) => { ($($input:tt)*) => {
//#[allow(clippy::arithmetic_side_effects)] { //#[allow(clippy::arithmetic_side_effects)] {
//Some($($input)*) //Some($($input)*)
// .ok_or_else(|| $crate::Error::Arithmetic("this error should never been seen")) // .ok_or_else(|| $crate::err!(Arithmetic("this error should never been seen")))
//} //}
//NOTE: remove me when stmt_expr_attributes is stable //NOTE: remove me when stmt_expr_attributes is stable
@ -57,7 +57,7 @@ pub fn continue_exponential_backoff(min: Duration, max: Duration, elapsed: Durat
#[allow(clippy::as_conversions)] #[allow(clippy::as_conversions)]
pub fn usize_from_f64(val: f64) -> Result<usize, Error> { pub fn usize_from_f64(val: f64) -> Result<usize, Error> {
if val < 0.0 { if val < 0.0 {
return Err(Error::Arithmetic("Converting negative float to unsigned integer")); return Err!(Arithmetic("Converting negative float to unsigned integer"));
} }
//SAFETY: <https://doc.rust-lang.org/std/primitive.f64.html#method.to_int_unchecked> //SAFETY: <https://doc.rust-lang.org/std/primitive.f64.html#method.to_int_unchecked>

View file

@ -9,7 +9,7 @@ use std::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use conduit::{debug, error, Error, Result}; use conduit::{debug, error, error::default_log, Error, Result};
pub use create::create_admin_room; pub use create::create_admin_room;
pub use grant::make_user_admin; pub use grant::make_user_admin;
use loole::{Receiver, Sender}; use loole::{Receiver, Sender};
@ -239,9 +239,9 @@ async fn respond_to_room(content: RoomMessageEventContent, room_id: &RoomId, use
.build_and_append_pdu(response_pdu, user_id, room_id, &state_lock) .build_and_append_pdu(response_pdu, user_id, room_id, &state_lock)
.await .await
{ {
if let Err(e) = handle_response_error(e, room_id, user_id, &state_lock).await { handle_response_error(e, room_id, user_id, &state_lock)
error!("{e}"); .await
} .unwrap_or_else(default_log);
} }
} }

View file

@ -6,7 +6,7 @@ use std::{collections::HashMap, path::PathBuf, sync::Arc, time::SystemTime};
use async_trait::async_trait; use async_trait::async_trait;
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use conduit::{debug, debug_error, err, error, utils, Result, Server}; use conduit::{debug, debug_error, err, error, utils, Err, Result, Server};
use data::{Data, Metadata}; use data::{Data, Metadata};
use ruma::{OwnedMxcUri, OwnedUserId}; use ruma::{OwnedMxcUri, OwnedUserId};
use serde::Serialize; use serde::Serialize;
@ -100,10 +100,9 @@ impl Service {
Ok(()) Ok(())
} else { } else {
error!("Failed to find any media keys for MXC \"{mxc}\" in our database (MXC does not exist)"); Err!(Database(error!(
Err(Error::bad_database( "Failed to find any media keys for MXC {mxc:?} in our database."
"Failed to find any media keys for the provided MXC in our database (MXC does not exist)", )))
))
} }
} }
@ -137,23 +136,16 @@ impl Service {
let all_keys = self.db.get_all_media_keys(); let all_keys = self.db.get_all_media_keys();
let user_duration: SystemTime = match cyborgtime::parse_duration(&time) { let user_duration: SystemTime = match cyborgtime::parse_duration(&time) {
Ok(duration) => { Err(e) => return Err!(Database(error!("Failed to parse specified time duration: {e}"))),
debug!("Parsed duration: {:?}", duration); Ok(duration) => SystemTime::now()
debug!("System time now: {:?}", SystemTime::now()); .checked_sub(duration)
SystemTime::now().checked_sub(duration).ok_or_else(|| { .ok_or(err!(Arithmetic("Duration {duration:?} is too large")))?,
Error::bad_database("Duration specified is not valid against the current system time")
})?
},
Err(e) => {
error!("Failed to parse user-specified time duration: {}", e);
return Err(Error::bad_database("Failed to parse user-specified time duration."));
},
}; };
let mut remote_mxcs: Vec<String> = vec![]; let mut remote_mxcs: Vec<String> = vec![];
for key in all_keys { for key in all_keys {
debug!("Full MXC key from database: {:?}", key); debug!("Full MXC key from database: {key:?}");
// we need to get the MXC URL from the first part of the key (the first 0xff / // we need to get the MXC URL from the first part of the key (the first 0xff /
// 255 push). this is all necessary because of conduit using magic keys for // 255 push). this is all necessary because of conduit using magic keys for
@ -162,24 +154,19 @@ impl Service {
let mxc = parts let mxc = parts
.next() .next()
.map(|bytes| { .map(|bytes| {
utils::string_from_bytes(bytes).map_err(|e| { utils::string_from_bytes(bytes)
error!("Failed to parse MXC unicode bytes from our database: {}", e); .map_err(|e| err!(Database(error!("Failed to parse MXC unicode bytes from our database: {e}"))))
Error::bad_database("Failed to parse MXC unicode bytes from our database")
})
}) })
.transpose()?; .transpose()?;
let Some(mxc_s) = mxc else { let Some(mxc_s) = mxc else {
return Err(Error::bad_database( return Err!(Database("Parsed MXC URL unicode bytes from database but still is None"));
"Parsed MXC URL unicode bytes from database but still is None",
));
}; };
debug!("Parsed MXC key to URL: {}", mxc_s); debug!("Parsed MXC key to URL: {mxc_s}");
let mxc = OwnedMxcUri::from(mxc_s); let mxc = OwnedMxcUri::from(mxc_s);
if mxc.server_name() == Ok(services().globals.server_name()) { if mxc.server_name() == Ok(services().globals.server_name()) {
debug!("Ignoring local media MXC: {}", mxc); debug!("Ignoring local media MXC: {mxc}");
// ignore our own MXC URLs as this would be local media. // ignore our own MXC URLs as this would be local media.
continue; continue;
} }
@ -198,14 +185,14 @@ impl Service {
}, },
Err(err) => { Err(err) => {
if force { if force {
error!("Could not delete MXC path {:?}: {:?}. Skipping...", path, err); error!("Could not delete MXC path {path:?}: {err:?}. Skipping...");
continue; continue;
} }
return Err(err.into()); return Err(err.into());
}, },
}; };
debug!("File created at: {:?}", file_created_at);
debug!("File created at: {file_created_at:?}");
if file_created_at <= user_duration { if file_created_at <= user_duration {
debug!("File is within user duration, pushing to list of file paths and keys to delete."); debug!("File is within user duration, pushing to list of file paths and keys to delete.");
remote_mxcs.push(mxc.to_string()); remote_mxcs.push(mxc.to_string());
@ -215,15 +202,12 @@ impl Service {
debug!( debug!(
"Finished going through all our media in database for eligible keys to delete, checking if these are empty" "Finished going through all our media in database for eligible keys to delete, checking if these are empty"
); );
if remote_mxcs.is_empty() { if remote_mxcs.is_empty() {
return Err(Error::bad_database("Did not found any eligible MXCs to delete.")); return Err!(Database("Did not found any eligible MXCs to delete."));
} }
debug!("Deleting media now in the past \"{:?}\".", user_duration); debug!("Deleting media now in the past {user_duration:?}.");
let mut deletion_count: usize = 0; let mut deletion_count: usize = 0;
for mxc in remote_mxcs { for mxc in remote_mxcs {
debug!("Deleting MXC {mxc} from database and filesystem"); debug!("Deleting MXC {mxc} from database and filesystem");
self.delete(&mxc).await?; self.delete(&mxc).await?;

View file

@ -1,6 +1,6 @@
use std::{collections::BTreeMap, mem::size_of, sync::Arc}; use std::{collections::BTreeMap, mem::size_of, sync::Arc};
use conduit::{debug_info, utils, warn, Error, Result}; use conduit::{debug_info, err, utils, warn, Err, Error, Result};
use database::{Database, Map}; use database::{Database, Map};
use ruma::{ use ruma::{
api::client::{device::Device, error::ErrorKind, filter::FilterDefinition}, api::client::{device::Device, error::ErrorKind, filter::FilterDefinition},
@ -87,19 +87,19 @@ impl Data {
let mut parts = bytes.split(|&b| b == 0xFF); let mut parts = bytes.split(|&b| b == 0xFF);
let user_bytes = parts let user_bytes = parts
.next() .next()
.ok_or_else(|| Error::bad_database("User ID in token_userdeviceid is invalid."))?; .ok_or_else(|| err!(Database("User ID in token_userdeviceid is invalid.")))?;
let device_bytes = parts let device_bytes = parts
.next() .next()
.ok_or_else(|| Error::bad_database("Device ID in token_userdeviceid is invalid."))?; .ok_or_else(|| err!(Database("Device ID in token_userdeviceid is invalid.")))?;
Ok(Some(( Ok(Some((
UserId::parse( UserId::parse(
utils::string_from_bytes(user_bytes) utils::string_from_bytes(user_bytes)
.map_err(|_| Error::bad_database("User ID in token_userdeviceid is invalid unicode."))?, .map_err(|e| err!(Database("User ID in token_userdeviceid is invalid unicode. {e}")))?,
) )
.map_err(|_| Error::bad_database("User ID in token_userdeviceid is invalid."))?, .map_err(|e| err!(Database("User ID in token_userdeviceid is invalid. {e}")))?,
utils::string_from_bytes(device_bytes) utils::string_from_bytes(device_bytes)
.map_err(|_| Error::bad_database("Device ID in token_userdeviceid is invalid."))?, .map_err(|e| err!(Database("Device ID in token_userdeviceid is invalid. {e}")))?,
))) )))
}) })
} }
@ -109,9 +109,9 @@ impl Data {
Box::new(self.userid_password.iter().map(|(bytes, _)| { Box::new(self.userid_password.iter().map(|(bytes, _)| {
UserId::parse( UserId::parse(
utils::string_from_bytes(&bytes) utils::string_from_bytes(&bytes)
.map_err(|_| Error::bad_database("User ID in userid_password is invalid unicode."))?, .map_err(|e| err!(Database("User ID in userid_password is invalid unicode. {e}")))?,
) )
.map_err(|_| Error::bad_database("User ID in userid_password is invalid.")) .map_err(|e| err!(Database("User ID in userid_password is invalid. {e}")))
})) }))
} }
@ -165,7 +165,7 @@ impl Data {
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
Ok(Some( Ok(Some(
utils::string_from_bytes(&bytes) utils::string_from_bytes(&bytes)
.map_err(|_| Error::bad_database("Displayname in db is invalid."))?, .map_err(|e| err!(Database("Displayname in db is invalid. {e}")))?,
)) ))
}) })
} }
@ -188,10 +188,8 @@ impl Data {
self.userid_avatarurl self.userid_avatarurl
.get(user_id.as_bytes())? .get(user_id.as_bytes())?
.map(|bytes| { .map(|bytes| {
let s_bytes = utils::string_from_bytes(&bytes).map_err(|e| { let s_bytes = utils::string_from_bytes(&bytes)
warn!("Avatar URL in db is invalid: {}", e); .map_err(|e| err!(Database(warn!("Avatar URL in db is invalid: {e}"))))?;
Error::bad_database("Avatar URL in db is invalid.")
})?;
let mxc_uri: OwnedMxcUri = s_bytes.into(); let mxc_uri: OwnedMxcUri = s_bytes.into();
Ok(mxc_uri) Ok(mxc_uri)
}) })
@ -215,10 +213,7 @@ impl Data {
self.userid_blurhash self.userid_blurhash
.get(user_id.as_bytes())? .get(user_id.as_bytes())?
.map(|bytes| { .map(|bytes| {
let s = utils::string_from_bytes(&bytes) utils::string_from_bytes(&bytes).map_err(|e| err!(Database("Avatar URL in db is invalid. {e}")))
.map_err(|_| Error::bad_database("Avatar URL in db is invalid."))?;
Ok(s)
}) })
.transpose() .transpose()
} }
@ -314,9 +309,9 @@ impl Data {
bytes bytes
.rsplit(|&b| b == 0xFF) .rsplit(|&b| b == 0xFF)
.next() .next()
.ok_or_else(|| Error::bad_database("UserDevice ID in db is invalid."))?, .ok_or_else(|| err!(Database("UserDevice ID in db is invalid.")))?,
) )
.map_err(|_| Error::bad_database("Device ID in userdeviceid_metadata is invalid."))? .map_err(|e| err!(Database("Device ID in userdeviceid_metadata is invalid. {e}")))?
.into()) .into())
}), }),
) )
@ -330,13 +325,9 @@ impl Data {
// should not be None, but we shouldn't assert either lol... // should not be None, but we shouldn't assert either lol...
if self.userdeviceid_metadata.get(&userdeviceid)?.is_none() { if self.userdeviceid_metadata.get(&userdeviceid)?.is_none() {
warn!( return Err!(Database(error!(
"Called set_token for a non-existent user \"{}\" and/or device ID \"{}\" with no metadata in database", "User {user_id:?} does not exist or device ID {device_id:?} has no metadata."
user_id, device_id )));
);
return Err(Error::bad_database(
"User does not exist or device ID has no metadata in database.",
));
} }
// Remove old token // Remove old token
@ -366,14 +357,9 @@ impl Data {
// Only existing devices should be able to call this, but we shouldn't assert // Only existing devices should be able to call this, but we shouldn't assert
// either... // either...
if self.userdeviceid_metadata.get(&key)?.is_none() { if self.userdeviceid_metadata.get(&key)?.is_none() {
warn!( return Err!(Database(error!(
"Called add_one_time_key for a non-existent user \"{}\" and/or device ID \"{}\" with no metadata in \ "User {user_id:?} does not exist or device ID {device_id:?} has no metadata."
database", )));
user_id, device_id
);
return Err(Error::bad_database(
"User does not exist or device ID has no metadata in database.",
));
} }
key.push(0xFF); key.push(0xFF);
@ -401,7 +387,7 @@ impl Data {
.get(user_id.as_bytes())? .get(user_id.as_bytes())?
.map_or(Ok(0), |bytes| { .map_or(Ok(0), |bytes| {
utils::u64_from_bytes(&bytes) utils::u64_from_bytes(&bytes)
.map_err(|_| Error::bad_database("Count in roomid_lastroomactiveupdate is invalid.")) .map_err(|e| err!(Database("Count in roomid_lastroomactiveupdate is invalid. {e}")))
}) })
} }
@ -429,11 +415,10 @@ impl Data {
serde_json::from_slice( serde_json::from_slice(
key.rsplit(|&b| b == 0xFF) key.rsplit(|&b| b == 0xFF)
.next() .next()
.ok_or_else(|| Error::bad_database("OneTimeKeyId in db is invalid."))?, .ok_or_else(|| err!(Database("OneTimeKeyId in db is invalid.")))?,
) )
.map_err(|_| Error::bad_database("OneTimeKeyId in db is invalid."))?, .map_err(|e| err!(Database("OneTimeKeyId in db is invalid. {e}")))?,
serde_json::from_slice(&value) serde_json::from_slice(&value).map_err(|e| err!(Database("OneTimeKeys in db are invalid. {e}")))?,
.map_err(|_| Error::bad_database("OneTimeKeys in db are invalid."))?,
)) ))
}) })
.transpose() .transpose()
@ -457,9 +442,9 @@ impl Data {
bytes bytes
.rsplit(|&b| b == 0xFF) .rsplit(|&b| b == 0xFF)
.next() .next()
.ok_or_else(|| Error::bad_database("OneTimeKey ID in db is invalid."))?, .ok_or_else(|| err!(Database("OneTimeKey ID in db is invalid.")))?,
) )
.map_err(|_| Error::bad_database("DeviceKeyId in db is invalid."))? .map_err(|e| err!(Database("DeviceKeyId in db is invalid. {e}")))?
.algorithm(), .algorithm(),
) )
}) { }) {
@ -581,19 +566,19 @@ impl Data {
.get(&key)? .get(&key)?
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Tried to sign nonexistent key."))?, .ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Tried to sign nonexistent key."))?,
) )
.map_err(|_| Error::bad_database("key in keyid_key is invalid."))?; .map_err(|e| err!(Database("key in keyid_key is invalid. {e}")))?;
let signatures = cross_signing_key let signatures = cross_signing_key
.get_mut("signatures") .get_mut("signatures")
.ok_or_else(|| Error::bad_database("key in keyid_key has no signatures field."))? .ok_or_else(|| err!(Database("key in keyid_key has no signatures field.")))?
.as_object_mut() .as_object_mut()
.ok_or_else(|| Error::bad_database("key in keyid_key has invalid signatures field."))? .ok_or_else(|| err!(Database("key in keyid_key has invalid signatures field.")))?
.entry(sender_id.to_string()) .entry(sender_id.to_string())
.or_insert_with(|| serde_json::Map::new().into()); .or_insert_with(|| serde_json::Map::new().into());
signatures signatures
.as_object_mut() .as_object_mut()
.ok_or_else(|| Error::bad_database("signatures in keyid_key for a user is invalid."))? .ok_or_else(|| err!(Database("signatures in keyid_key for a user is invalid.")))?
.insert(signature.0, signature.1.into()); .insert(signature.0, signature.1.into());
self.keyid_key.insert( self.keyid_key.insert(
@ -640,7 +625,7 @@ impl Data {
Error::bad_database("User ID in devicekeychangeid_userid is invalid unicode.") Error::bad_database("User ID in devicekeychangeid_userid is invalid unicode.")
})?, })?,
) )
.map_err(|_| Error::bad_database("User ID in devicekeychangeid_userid is invalid.")) .map_err(|e| err!(Database("User ID in devicekeychangeid_userid is invalid. {e}")))
}), }),
) )
} }
@ -685,7 +670,7 @@ impl Data {
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| { self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| {
Ok(Some( Ok(Some(
serde_json::from_slice(&bytes).map_err(|_| Error::bad_database("DeviceKeys in db are invalid."))?, serde_json::from_slice(&bytes).map_err(|e| err!(Database("DeviceKeys in db are invalid. {e}")))?,
)) ))
}) })
} }
@ -719,7 +704,7 @@ impl Data {
) -> Result<Option<Raw<CrossSigningKey>>> { ) -> Result<Option<Raw<CrossSigningKey>>> {
self.keyid_key.get(key)?.map_or(Ok(None), |bytes| { self.keyid_key.get(key)?.map_or(Ok(None), |bytes| {
let mut cross_signing_key = serde_json::from_slice::<serde_json::Value>(&bytes) let mut cross_signing_key = serde_json::from_slice::<serde_json::Value>(&bytes)
.map_err(|_| Error::bad_database("CrossSigningKey in db is invalid."))?; .map_err(|e| err!(Database("CrossSigningKey in db is invalid. {e}")))?;
clean_signatures(&mut cross_signing_key, sender_user, user_id, allowed_signatures)?; clean_signatures(&mut cross_signing_key, sender_user, user_id, allowed_signatures)?;
Ok(Some(Raw::from_json( Ok(Some(Raw::from_json(
@ -751,7 +736,7 @@ impl Data {
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| { self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| {
Ok(Some( Ok(Some(
serde_json::from_slice(&bytes) serde_json::from_slice(&bytes)
.map_err(|_| Error::bad_database("CrossSigningKey in db is invalid."))?, .map_err(|e| err!(Database("CrossSigningKey in db is invalid. {e}")))?,
)) ))
}) })
}) })
@ -792,7 +777,7 @@ impl Data {
for (_, value) in self.todeviceid_events.scan_prefix(prefix) { for (_, value) in self.todeviceid_events.scan_prefix(prefix) {
events.push( events.push(
serde_json::from_slice(&value) serde_json::from_slice(&value)
.map_err(|_| Error::bad_database("Event in todeviceid_events is invalid."))?, .map_err(|e| err!(Database("Event in todeviceid_events is invalid. {e}")))?,
); );
} }
@ -816,7 +801,7 @@ impl Data {
Ok::<_, Error>(( Ok::<_, Error>((
key.clone(), key.clone(),
utils::u64_from_bytes(&key[key.len().saturating_sub(size_of::<u64>())..key.len()]) utils::u64_from_bytes(&key[key.len().saturating_sub(size_of::<u64>())..key.len()])
.map_err(|_| Error::bad_database("ToDeviceId has invalid count bytes."))?, .map_err(|e| err!(Database("ToDeviceId has invalid count bytes. {e}")))?,
)) ))
}) })
.filter_map(Result::ok) .filter_map(Result::ok)
@ -877,7 +862,7 @@ impl Data {
.get(user_id.as_bytes())? .get(user_id.as_bytes())?
.map_or(Ok(None), |bytes| { .map_or(Ok(None), |bytes| {
utils::u64_from_bytes(&bytes) utils::u64_from_bytes(&bytes)
.map_err(|_| Error::bad_database("Invalid devicelistversion in db.")) .map_err(|e| err!(Database("Invalid devicelistversion in db. {e}")))
.map(Some) .map(Some)
}) })
} }
@ -893,7 +878,7 @@ impl Data {
.scan_prefix(key) .scan_prefix(key)
.map(|(_, bytes)| { .map(|(_, bytes)| {
serde_json::from_slice::<Device>(&bytes) serde_json::from_slice::<Device>(&bytes)
.map_err(|_| Error::bad_database("Device in userdeviceid_metadata is invalid.")) .map_err(|e| err!(Database("Device in userdeviceid_metadata is invalid. {e}")))
}), }),
) )
} }
@ -920,7 +905,7 @@ impl Data {
let raw = self.userfilterid_filter.get(&key)?; let raw = self.userfilterid_filter.get(&key)?;
if let Some(raw) = raw { if let Some(raw) = raw {
serde_json::from_slice(&raw).map_err(|_| Error::bad_database("Invalid filter event in db.")) serde_json::from_slice(&raw).map_err(|e| err!(Database("Invalid filter event in db. {e}")))
} else { } else {
Ok(None) Ok(None)
} }
@ -954,7 +939,7 @@ impl Data {
let expires_at = u64::from_be_bytes( let expires_at = u64::from_be_bytes(
expires_at_bytes expires_at_bytes
.try_into() .try_into()
.map_err(|_| Error::bad_database("expires_at in openid_userid is invalid u64."))?, .map_err(|e| err!(Database("expires_at in openid_userid is invalid u64. {e}")))?,
); );
if expires_at < utils::millis_since_unix_epoch() { if expires_at < utils::millis_since_unix_epoch() {
@ -966,9 +951,9 @@ impl Data {
UserId::parse( UserId::parse(
utils::string_from_bytes(user_bytes) utils::string_from_bytes(user_bytes)
.map_err(|_| Error::bad_database("User ID in openid_userid is invalid unicode."))?, .map_err(|e| err!(Database("User ID in openid_userid is invalid unicode. {e}")))?,
) )
.map_err(|_| Error::bad_database("User ID in openid_userid is invalid.")) .map_err(|e| err!(Database("User ID in openid_userid is invalid. {e}")))
} }
} }