rust-sdk: Rework our error handling.
parent
f517ac6f37
commit
7b70cb7e41
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
use futures::future::{BoxFuture, Future, FutureExt};
|
use futures::future::{BoxFuture, Future, FutureExt};
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
use std::result::Result as StdResult;
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use std::sync::{Arc, Mutex, RwLock as SyncLock};
|
use std::sync::{Arc, Mutex, RwLock as SyncLock};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
@ -37,9 +38,9 @@ use ruma_identifiers::RoomId;
|
||||||
use crate::api;
|
use crate::api;
|
||||||
use crate::base_client::Client as BaseClient;
|
use crate::base_client::Client as BaseClient;
|
||||||
use crate::base_client::Room;
|
use crate::base_client::Room;
|
||||||
use crate::error::{Error, InnerError};
|
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
use crate::VERSION;
|
use crate::VERSION;
|
||||||
|
use crate::{Error, Result};
|
||||||
|
|
||||||
type RoomEventCallback = Box<
|
type RoomEventCallback = Box<
|
||||||
dyn FnMut(Arc<SyncLock<Room>>, Arc<EventResult<RoomEvent>>) -> BoxFuture<'static, ()> + Send,
|
dyn FnMut(Arc<SyncLock<Room>>, Arc<EventResult<RoomEvent>>) -> BoxFuture<'static, ()> + Send,
|
||||||
|
@ -105,7 +106,7 @@ impl AsyncClientConfig {
|
||||||
/// .proxy("http://localhost:8080")
|
/// .proxy("http://localhost:8080")
|
||||||
/// .unwrap();
|
/// .unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn proxy(mut self, proxy: &str) -> Result<Self, Error> {
|
pub fn proxy(mut self, proxy: &str) -> Result<Self> {
|
||||||
self.proxy = Some(reqwest::Proxy::all(proxy)?);
|
self.proxy = Some(reqwest::Proxy::all(proxy)?);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
@ -117,7 +118,7 @@ impl AsyncClientConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a custom HTTP user agent for the client.
|
/// Set a custom HTTP user agent for the client.
|
||||||
pub fn user_agent(mut self, user_agent: &str) -> Result<Self, InvalidHeaderValue> {
|
pub fn user_agent(mut self, user_agent: &str) -> StdResult<Self, InvalidHeaderValue> {
|
||||||
self.user_agent = Some(HeaderValue::from_str(user_agent)?);
|
self.user_agent = Some(HeaderValue::from_str(user_agent)?);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
@ -153,7 +154,10 @@ impl SyncSettings {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `timeout` - The time the server is allowed to wait.
|
/// * `timeout` - The time the server is allowed to wait.
|
||||||
pub fn timeout<T: TryInto<UInt>>(mut self, timeout: T) -> Result<Self, js_int::TryFromIntError>
|
pub fn timeout<T: TryInto<UInt>>(
|
||||||
|
mut self,
|
||||||
|
timeout: T,
|
||||||
|
) -> StdResult<Self, js_int::TryFromIntError>
|
||||||
where
|
where
|
||||||
js_int::TryFromIntError:
|
js_int::TryFromIntError:
|
||||||
std::convert::From<<T as std::convert::TryInto<js_int::UInt>>::Error>,
|
std::convert::From<<T as std::convert::TryInto<js_int::UInt>>::Error>,
|
||||||
|
@ -189,10 +193,7 @@ impl AsyncClient {
|
||||||
/// * `homeserver_url` - The homeserver that the client should connect to.
|
/// * `homeserver_url` - The homeserver that the client should connect to.
|
||||||
/// * `session` - If a previous login exists, the access token can be
|
/// * `session` - If a previous login exists, the access token can be
|
||||||
/// reused by giving a session object here.
|
/// reused by giving a session object here.
|
||||||
pub fn new<U: TryInto<Url>>(
|
pub fn new<U: TryInto<Url>>(homeserver_url: U, session: Option<Session>) -> Result<Self> {
|
||||||
homeserver_url: U,
|
|
||||||
session: Option<Session>,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let config = AsyncClientConfig::new();
|
let config = AsyncClientConfig::new();
|
||||||
AsyncClient::new_with_config(homeserver_url, session, config)
|
AsyncClient::new_with_config(homeserver_url, session, config)
|
||||||
}
|
}
|
||||||
|
@ -209,7 +210,7 @@ impl AsyncClient {
|
||||||
homeserver_url: U,
|
homeserver_url: U,
|
||||||
session: Option<Session>,
|
session: Option<Session>,
|
||||||
config: AsyncClientConfig,
|
config: AsyncClientConfig,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self> {
|
||||||
let homeserver: Url = match homeserver_url.try_into() {
|
let homeserver: Url = match homeserver_url.try_into() {
|
||||||
Ok(u) => u,
|
Ok(u) => u,
|
||||||
Err(_e) => panic!("Error parsing homeserver url"),
|
Err(_e) => panic!("Error parsing homeserver url"),
|
||||||
|
@ -242,7 +243,7 @@ impl AsyncClient {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
homeserver,
|
homeserver,
|
||||||
http_client,
|
http_client,
|
||||||
base_client: Arc::new(RwLock::new(BaseClient::new(session))),
|
base_client: Arc::new(RwLock::new(BaseClient::new(session)?)),
|
||||||
transaction_id: Arc::new(AtomicU64::new(0)),
|
transaction_id: Arc::new(AtomicU64::new(0)),
|
||||||
event_callbacks: Arc::new(Mutex::new(Vec::new())),
|
event_callbacks: Arc::new(Mutex::new(Vec::new())),
|
||||||
})
|
})
|
||||||
|
@ -340,7 +341,7 @@ impl AsyncClient {
|
||||||
user: S,
|
user: S,
|
||||||
password: S,
|
password: S,
|
||||||
device_id: Option<S>,
|
device_id: Option<S>,
|
||||||
) -> Result<login::Response, Error> {
|
) -> Result<login::Response> {
|
||||||
let request = login::Request {
|
let request = login::Request {
|
||||||
user: login::UserInfo::MatrixId(user.into()),
|
user: login::UserInfo::MatrixId(user.into()),
|
||||||
login_info: login::LoginInfo::Password {
|
login_info: login::LoginInfo::Password {
|
||||||
|
@ -352,7 +353,7 @@ impl AsyncClient {
|
||||||
|
|
||||||
let response = self.send(request).await?;
|
let response = self.send(request).await?;
|
||||||
let mut client = self.base_client.write().await;
|
let mut client = self.base_client.write().await;
|
||||||
client.receive_login_response(&response).await;
|
client.receive_login_response(&response).await?;
|
||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
@ -365,7 +366,7 @@ impl AsyncClient {
|
||||||
pub async fn sync(
|
pub async fn sync(
|
||||||
&mut self,
|
&mut self,
|
||||||
sync_settings: SyncSettings,
|
sync_settings: SyncSettings,
|
||||||
) -> Result<sync_events::IncomingResponse, Error> {
|
) -> Result<sync_events::IncomingResponse> {
|
||||||
let request = sync_events::Request {
|
let request = sync_events::Request {
|
||||||
filter: None,
|
filter: None,
|
||||||
since: sync_settings.token,
|
since: sync_settings.token,
|
||||||
|
@ -536,7 +537,7 @@ impl AsyncClient {
|
||||||
async fn send<Request: Endpoint>(
|
async fn send<Request: Endpoint>(
|
||||||
&self,
|
&self,
|
||||||
request: Request,
|
request: Request,
|
||||||
) -> Result<<Request::Response as Outgoing>::Incoming, Error>
|
) -> Result<<Request::Response as Outgoing>::Incoming>
|
||||||
where
|
where
|
||||||
Request::Incoming:
|
Request::Incoming:
|
||||||
TryFrom<http::Request<Vec<u8>>, Error = ruma_api::error::FromHttpRequestError>,
|
TryFrom<http::Request<Vec<u8>>, Error = ruma_api::error::FromHttpRequestError>,
|
||||||
|
@ -570,7 +571,7 @@ impl AsyncClient {
|
||||||
if let Some(ref session) = client.session {
|
if let Some(ref session) = client.session {
|
||||||
request_builder.bearer_auth(&session.access_token)
|
request_builder.bearer_auth(&session.access_token)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error(InnerError::AuthenticationRequired));
|
return Err(Error::AuthenticationRequired);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
request_builder
|
request_builder
|
||||||
|
@ -604,7 +605,7 @@ impl AsyncClient {
|
||||||
&mut self,
|
&mut self,
|
||||||
room_id: &str,
|
room_id: &str,
|
||||||
data: MessageEventContent,
|
data: MessageEventContent,
|
||||||
) -> Result<create_message_event::Response, Error> {
|
) -> Result<create_message_event::Response> {
|
||||||
let request = create_message_event::Request {
|
let request = create_message_event::Request {
|
||||||
room_id: RoomId::try_from(room_id).unwrap(),
|
room_id: RoomId::try_from(room_id).unwrap(),
|
||||||
event_type: EventType::RoomMessage,
|
event_type: EventType::RoomMessage,
|
||||||
|
@ -626,7 +627,7 @@ impl AsyncClient {
|
||||||
/// Panics if the client isn't logged in, or if no encryption keys need to
|
/// Panics if the client isn't logged in, or if no encryption keys need to
|
||||||
/// be uploaded.
|
/// be uploaded.
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
async fn keys_upload(&self) -> Result<upload_keys::Response, Error> {
|
async fn keys_upload(&self) -> Result<upload_keys::Response> {
|
||||||
let (device_keys, one_time_keys) = self
|
let (device_keys, one_time_keys) = self
|
||||||
.base_client
|
.base_client
|
||||||
.read()
|
.read()
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
use crate::api::r0 as api;
|
use crate::api::r0 as api;
|
||||||
|
use crate::error::Result;
|
||||||
use crate::events::collections::all::{RoomEvent, StateEvent};
|
use crate::events::collections::all::{RoomEvent, StateEvent};
|
||||||
use crate::events::room::member::{MemberEvent, MembershipState};
|
use crate::events::room::member::{MemberEvent, MembershipState};
|
||||||
use crate::events::EventResult;
|
use crate::events::EventResult;
|
||||||
|
@ -199,20 +201,20 @@ impl Client {
|
||||||
///
|
///
|
||||||
/// * `session` - An optional session if the user already has one from a
|
/// * `session` - An optional session if the user already has one from a
|
||||||
/// previous login call.
|
/// previous login call.
|
||||||
pub fn new(session: Option<Session>) -> Self {
|
pub fn new(session: Option<Session>) -> Result<Self> {
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
let olm = match &session {
|
let olm = match &session {
|
||||||
Some(s) => Some(OlmMachine::new(&s.user_id, &s.device_id)),
|
Some(s) => Some(OlmMachine::new(&s.user_id, &s.device_id)?),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Client {
|
Ok(Client {
|
||||||
session,
|
session,
|
||||||
sync_token: None,
|
sync_token: None,
|
||||||
joined_rooms: HashMap::new(),
|
joined_rooms: HashMap::new(),
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
olm: Arc::new(Mutex::new(olm)),
|
olm: Arc::new(Mutex::new(olm)),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the client logged in.
|
/// Is the client logged in.
|
||||||
|
@ -226,7 +228,10 @@ impl Client {
|
||||||
///
|
///
|
||||||
/// * `response` - A successful login response that contains our access token
|
/// * `response` - A successful login response that contains our access token
|
||||||
/// and device id.
|
/// and device id.
|
||||||
pub async fn receive_login_response(&mut self, response: &api::session::login::Response) {
|
pub async fn receive_login_response(
|
||||||
|
&mut self,
|
||||||
|
response: &api::session::login::Response,
|
||||||
|
) -> Result<()> {
|
||||||
let session = Session {
|
let session = Session {
|
||||||
access_token: response.access_token.clone(),
|
access_token: response.access_token.clone(),
|
||||||
device_id: response.device_id.clone(),
|
device_id: response.device_id.clone(),
|
||||||
|
@ -237,8 +242,10 @@ impl Client {
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
{
|
{
|
||||||
let mut olm = self.olm.lock().await;
|
let mut olm = self.olm.lock().await;
|
||||||
*olm = Some(OlmMachine::new(&response.user_id, &response.device_id));
|
*olm = Some(OlmMachine::new(&response.user_id, &response.device_id)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_or_create_room(&mut self, room_id: &str) -> &mut Arc<RwLock<Room>> {
|
fn get_or_create_room(&mut self, room_id: &str) -> &mut Arc<RwLock<Room>> {
|
||||||
|
@ -331,7 +338,9 @@ impl Client {
|
||||||
///
|
///
|
||||||
/// Returns an empty error if no keys need to be uploaded.
|
/// Returns an empty error if no keys need to be uploaded.
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
pub async fn keys_for_upload(&self) -> Result<(Option<DeviceKeys>, Option<OneTimeKeys>), ()> {
|
pub async fn keys_for_upload(
|
||||||
|
&self,
|
||||||
|
) -> StdResult<(Option<DeviceKeys>, Option<OneTimeKeys>), ()> {
|
||||||
let olm = self.olm.lock().await;
|
let olm = self.olm.lock().await;
|
||||||
|
|
||||||
match &*olm {
|
match &*olm {
|
||||||
|
|
|
@ -13,35 +13,35 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use cjson::Error as CjsonError;
|
use cjson::Error as CjsonError;
|
||||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
use super::store::CryptoStoreError;
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, OlmError>;
|
||||||
|
pub type VerificationResult<T> = std::result::Result<T, SignatureError>;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
pub enum SignatureError {
|
pub enum SignatureError {
|
||||||
|
#[error("the provided JSON value isn't an object")]
|
||||||
NotAnObject,
|
NotAnObject,
|
||||||
|
#[error("the provided JSON object doesn't contain a signatures field")]
|
||||||
NoSignatureFound,
|
NoSignatureFound,
|
||||||
|
#[error("the provided JSON object can't be converted to a canonical representation")]
|
||||||
CanonicalJsonError(CjsonError),
|
CanonicalJsonError(CjsonError),
|
||||||
|
#[error("the signature didn't match the provided key")]
|
||||||
VerificationError,
|
VerificationError,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for SignatureError {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
|
||||||
let message = match self {
|
|
||||||
SignatureError::NotAnObject => "The provided JSON value isn't an object.",
|
|
||||||
SignatureError::NoSignatureFound => {
|
|
||||||
"The provided JSON object doesn't contain a signatures field."
|
|
||||||
}
|
|
||||||
SignatureError::CanonicalJsonError(_) => {
|
|
||||||
"The provided JSON object can't be converted to a canonical representation."
|
|
||||||
}
|
|
||||||
SignatureError::VerificationError => "The signature didn't match the provided key.",
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(f, "{}", message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CjsonError> for SignatureError {
|
impl From<CjsonError> for SignatureError {
|
||||||
fn from(error: CjsonError) -> Self {
|
fn from(error: CjsonError) -> Self {
|
||||||
Self::CanonicalJsonError(error)
|
Self::CanonicalJsonError(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum OlmError {
|
||||||
|
#[error("signature verification failed")]
|
||||||
|
Signature(#[from] SignatureError),
|
||||||
|
#[error("failed to read or write to the crypto store {0}")]
|
||||||
|
Store(#[from] CryptoStoreError),
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,9 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
use super::error::SignatureError;
|
use super::error::{Result, SignatureError, VerificationResult};
|
||||||
use super::olm::Account;
|
use super::olm::Account;
|
||||||
use crate::api;
|
use crate::api;
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ use olm_rs::utility::OlmUtility;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use super::store::CryptoStoreError;
|
||||||
use ruma_client_api::r0::keys::{
|
use ruma_client_api::r0::keys::{
|
||||||
AlgorithmAndDeviceId, DeviceKeys, KeyAlgorithm, OneTimeKey, SignedKey,
|
AlgorithmAndDeviceId, DeviceKeys, KeyAlgorithm, OneTimeKey, SignedKey,
|
||||||
};
|
};
|
||||||
|
@ -38,6 +40,9 @@ use ruma_identifiers::{DeviceId, UserId};
|
||||||
|
|
||||||
pub type OneTimeKeys = HashMap<AlgorithmAndDeviceId, OneTimeKey>;
|
pub type OneTimeKeys = HashMap<AlgorithmAndDeviceId, OneTimeKey>;
|
||||||
|
|
||||||
|
#[cfg(feature = "sqlite-cryptostore")]
|
||||||
|
use super::store::sqlite::SqliteStore;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OlmMachine {
|
pub struct OlmMachine {
|
||||||
/// The unique user id that owns this account.
|
/// The unique user id that owns this account.
|
||||||
|
@ -60,13 +65,13 @@ impl OlmMachine {
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Create a new account.
|
/// Create a new account.
|
||||||
pub fn new(user_id: &UserId, device_id: &str) -> Self {
|
pub fn new(user_id: &UserId, device_id: &str) -> Result<Self> {
|
||||||
OlmMachine {
|
Ok(OlmMachine {
|
||||||
user_id: user_id.clone(),
|
user_id: user_id.clone(),
|
||||||
device_id: device_id.to_owned(),
|
device_id: device_id.to_owned(),
|
||||||
account: Account::new(),
|
account: Account::new(),
|
||||||
uploaded_signed_key_count: None,
|
uploaded_signed_key_count: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Should account or one-time keys be uploaded to the server.
|
/// Should account or one-time keys be uploaded to the server.
|
||||||
|
@ -111,7 +116,7 @@ impl OlmMachine {
|
||||||
///
|
///
|
||||||
/// Returns the number of newly generated one-time keys. If no keys can be
|
/// Returns the number of newly generated one-time keys. If no keys can be
|
||||||
/// generated returns an empty error.
|
/// generated returns an empty error.
|
||||||
fn generate_one_time_keys(&self) -> Result<u64, ()> {
|
fn generate_one_time_keys(&self) -> StdResult<u64, ()> {
|
||||||
match self.uploaded_signed_key_count {
|
match self.uploaded_signed_key_count {
|
||||||
Some(count) => {
|
Some(count) => {
|
||||||
let max_keys = self.account.max_one_time_keys() as u64;
|
let max_keys = self.account.max_one_time_keys() as u64;
|
||||||
|
@ -181,7 +186,7 @@ impl OlmMachine {
|
||||||
/// Generate, sign and prepare one-time keys to be uploaded.
|
/// Generate, sign and prepare one-time keys to be uploaded.
|
||||||
///
|
///
|
||||||
/// If no one-time keys need to be uploaded returns an empty error.
|
/// If no one-time keys need to be uploaded returns an empty error.
|
||||||
fn signed_one_time_keys(&self) -> Result<OneTimeKeys, ()> {
|
fn signed_one_time_keys(&self) -> StdResult<OneTimeKeys, ()> {
|
||||||
let _ = self.generate_one_time_keys()?;
|
let _ = self.generate_one_time_keys()?;
|
||||||
|
|
||||||
let one_time_keys = self.account.one_time_keys();
|
let one_time_keys = self.account.one_time_keys();
|
||||||
|
@ -255,7 +260,7 @@ impl OlmMachine {
|
||||||
device_id: &str,
|
device_id: &str,
|
||||||
user_key: &str,
|
user_key: &str,
|
||||||
json: &mut Value,
|
json: &mut Value,
|
||||||
) -> Result<(), SignatureError> {
|
) -> VerificationResult<()> {
|
||||||
let json_object = json.as_object_mut().ok_or(SignatureError::NotAnObject)?;
|
let json_object = json.as_object_mut().ok_or(SignatureError::NotAnObject)?;
|
||||||
let unsigned = json_object.remove("unsigned");
|
let unsigned = json_object.remove("unsigned");
|
||||||
let signatures = json_object.remove("signatures");
|
let signatures = json_object.remove("signatures");
|
||||||
|
@ -300,7 +305,7 @@ impl OlmMachine {
|
||||||
/// Get a tuple of device and one-time keys that need to be uploaded.
|
/// Get a tuple of device and one-time keys that need to be uploaded.
|
||||||
///
|
///
|
||||||
/// Returns an empty error if no keys need to be uploaded.
|
/// Returns an empty error if no keys need to be uploaded.
|
||||||
pub fn keys_for_upload(&self) -> Result<(Option<DeviceKeys>, Option<OneTimeKeys>), ()> {
|
pub fn keys_for_upload(&self) -> StdResult<(Option<DeviceKeys>, Option<OneTimeKeys>), ()> {
|
||||||
if !self.should_upload_keys() {
|
if !self.should_upload_keys() {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
@ -324,7 +329,7 @@ impl OlmMachine {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `event` - The to-device event that should be decrypted.
|
/// * `event` - The to-device event that should be decrypted.
|
||||||
fn decrypt_to_device_event(&self, _: &ToDeviceEncrypted) -> Result<ToDeviceEvent, ()> {
|
fn decrypt_to_device_event(&self, _: &ToDeviceEncrypted) -> StdResult<ToDeviceEvent, ()> {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,13 +415,13 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_olm_machine() {
|
fn create_olm_machine() {
|
||||||
let machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
let machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
||||||
assert!(machine.should_upload_keys());
|
assert!(machine.should_upload_keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn receive_keys_upload_response() {
|
async fn receive_keys_upload_response() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
||||||
let mut response = keys_upload_response();
|
let mut response = keys_upload_response();
|
||||||
|
|
||||||
response
|
response
|
||||||
|
@ -445,7 +450,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn generate_one_time_keys() {
|
async fn generate_one_time_keys() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
||||||
|
|
||||||
let mut response = keys_upload_response();
|
let mut response = keys_upload_response();
|
||||||
|
|
||||||
|
@ -466,7 +471,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_device_key_signing() {
|
fn test_device_key_signing() {
|
||||||
let machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
let machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
||||||
|
|
||||||
let mut device_keys = machine.device_keys();
|
let mut device_keys = machine.device_keys();
|
||||||
let identity_keys = machine.account.identity_keys();
|
let identity_keys = machine.account.identity_keys();
|
||||||
|
@ -483,7 +488,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_signature() {
|
fn test_invalid_signature() {
|
||||||
let machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
let machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
||||||
|
|
||||||
let mut device_keys = machine.device_keys();
|
let mut device_keys = machine.device_keys();
|
||||||
|
|
||||||
|
@ -498,7 +503,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_one_time_key_signing() {
|
fn test_one_time_key_signing() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
||||||
machine.uploaded_signed_key_count = Some(49);
|
machine.uploaded_signed_key_count = Some(49);
|
||||||
|
|
||||||
let mut one_time_keys = machine.signed_one_time_keys().unwrap();
|
let mut one_time_keys = machine.signed_one_time_keys().unwrap();
|
||||||
|
@ -518,7 +523,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_keys_for_upload() {
|
async fn test_keys_for_upload() {
|
||||||
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID);
|
let mut machine = OlmMachine::new(&user_id(), DEVICE_ID).unwrap();
|
||||||
machine.uploaded_signed_key_count = Some(0);
|
machine.uploaded_signed_key_count = Some(0);
|
||||||
|
|
||||||
let identity_keys = machine.account.identity_keys();
|
let identity_keys = machine.account.identity_keys();
|
||||||
|
|
|
@ -20,4 +20,5 @@ mod machine;
|
||||||
mod olm;
|
mod olm;
|
||||||
mod store;
|
mod store;
|
||||||
|
|
||||||
|
pub use error::OlmError;
|
||||||
pub use machine::{OlmMachine, OneTimeKeys};
|
pub use machine::{OlmMachine, OneTimeKeys};
|
||||||
|
|
|
@ -19,7 +19,7 @@ use sqlx::Error as SqlxError;
|
||||||
pub enum CryptoStoreError {
|
pub enum CryptoStoreError {
|
||||||
#[error("can't read or write from the store")]
|
#[error("can't read or write from the store")]
|
||||||
Io(#[from] IoError),
|
Io(#[from] IoError),
|
||||||
#[error("Olm operation failed")]
|
#[error("can't finish Olm account operation {0}")]
|
||||||
OlmAccountError(#[from] OlmAccountError),
|
OlmAccountError(#[from] OlmAccountError),
|
||||||
#[error("URL can't be parsed")]
|
#[error("URL can't be parsed")]
|
||||||
UrlParse(#[from] ParseError),
|
UrlParse(#[from] ParseError),
|
||||||
|
|
63
src/error.rs
63
src/error.rs
|
@ -15,69 +15,50 @@
|
||||||
|
|
||||||
//! Error conditions.
|
//! Error conditions.
|
||||||
|
|
||||||
use std::error::Error as StdError;
|
|
||||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
|
||||||
|
|
||||||
use reqwest::Error as ReqwestError;
|
use reqwest::Error as ReqwestError;
|
||||||
use ruma_api::error::FromHttpResponseError as RumaResponseError;
|
use ruma_api::error::FromHttpResponseError as RumaResponseError;
|
||||||
use ruma_api::error::IntoHttpError as RumaIntoHttpError;
|
use ruma_api::error::IntoHttpError as RumaIntoHttpError;
|
||||||
|
use thiserror::Error;
|
||||||
use url::ParseError;
|
use url::ParseError;
|
||||||
|
|
||||||
/// An error that can occur during client operations.
|
#[cfg(feature = "encryption")]
|
||||||
#[derive(Debug)]
|
use crate::crypto::OlmError;
|
||||||
pub struct Error(pub(crate) InnerError);
|
|
||||||
|
|
||||||
impl Display for Error {
|
/// Result type of the rust-sdk.
|
||||||
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
let message = match self.0 {
|
|
||||||
InnerError::AuthenticationRequired => "The queried endpoint requires authentication but was called with an anonymous client.",
|
|
||||||
InnerError::Reqwest(_) => "An HTTP error occurred.",
|
|
||||||
InnerError::Uri(_) => "Provided string could not be converted into a URI.",
|
|
||||||
InnerError::RumaResponseError(_) => "An error occurred converting between ruma_client_api and hyper types.",
|
|
||||||
InnerError::IntoHttpError(_) => "An error occurred converting between ruma_client_api and hyper types.",
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(f, "{}", message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StdError for Error {}
|
|
||||||
|
|
||||||
/// Internal representation of errors.
|
/// Internal representation of errors.
|
||||||
#[derive(Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub(crate) enum InnerError {
|
pub enum Error {
|
||||||
/// Queried endpoint requires authentication but was called on an anonymous client.
|
/// Queried endpoint requires authentication but was called on an anonymous client.
|
||||||
|
#[error("the queried endpoint requires authentication but was called before logging in")]
|
||||||
AuthenticationRequired,
|
AuthenticationRequired,
|
||||||
/// An error at the HTTP layer.
|
/// An error at the HTTP layer.
|
||||||
Reqwest(ReqwestError),
|
#[error(transparent)]
|
||||||
|
Reqwest(#[from] ReqwestError),
|
||||||
/// An error when parsing a string as a URI.
|
/// An error when parsing a string as a URI.
|
||||||
Uri(ParseError),
|
#[error("can't parse the provided string as an URL")]
|
||||||
|
Uri(#[from] ParseError),
|
||||||
/// An error converting between ruma_client_api types and Hyper types.
|
/// An error converting between ruma_client_api types and Hyper types.
|
||||||
RumaResponseError(RumaResponseError),
|
#[error("can't parse the JSON response as a Matrix response")]
|
||||||
|
RumaResponse(RumaResponseError),
|
||||||
/// An error converting between ruma_client_api types and Hyper types.
|
/// An error converting between ruma_client_api types and Hyper types.
|
||||||
IntoHttpError(RumaIntoHttpError),
|
#[error("can't convert between ruma_client_api and hyper types.")]
|
||||||
}
|
IntoHttp(RumaIntoHttpError),
|
||||||
|
#[cfg(feature = "encryption")]
|
||||||
impl From<ParseError> for Error {
|
/// An error occured durring a E2EE operation.
|
||||||
fn from(error: ParseError) -> Self {
|
#[error(transparent)]
|
||||||
Self(InnerError::Uri(error))
|
OlmError(#[from] OlmError),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RumaResponseError> for Error {
|
impl From<RumaResponseError> for Error {
|
||||||
fn from(error: RumaResponseError) -> Self {
|
fn from(error: RumaResponseError) -> Self {
|
||||||
Self(InnerError::RumaResponseError(error))
|
Self::RumaResponse(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RumaIntoHttpError> for Error {
|
impl From<RumaIntoHttpError> for Error {
|
||||||
fn from(error: RumaIntoHttpError) -> Self {
|
fn from(error: RumaIntoHttpError) -> Self {
|
||||||
Self(InnerError::IntoHttpError(error))
|
Self::IntoHttp(error)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ReqwestError> for Error {
|
|
||||||
fn from(error: ReqwestError) -> Self {
|
|
||||||
Self(InnerError::Reqwest(error))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
//! This crate implements a [Matrix](https://matrix.org/) client library.
|
//! This crate implements a [Matrix](https://matrix.org/) client library.
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
pub use crate::{error::Error, session::Session};
|
pub use crate::{error::Error, error::Result, session::Session};
|
||||||
pub use reqwest::header::InvalidHeaderValue;
|
pub use reqwest::header::InvalidHeaderValue;
|
||||||
pub use ruma_client_api as api;
|
pub use ruma_client_api as api;
|
||||||
pub use ruma_events as events;
|
pub use ruma_events as events;
|
||||||
|
|
Loading…
Reference in New Issue