2020-05-08 10:39:36 +00:00
|
|
|
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
//! Error conditions.
|
|
|
|
|
2021-05-12 10:56:29 +00:00
|
|
|
use std::io::Error as IoError;
|
|
|
|
|
2021-01-31 20:10:30 +00:00
|
|
|
use http::StatusCode;
|
2021-05-12 10:56:29 +00:00
|
|
|
#[cfg(feature = "encryption")]
|
|
|
|
use matrix_sdk_base::crypto::store::CryptoStoreError;
|
2021-01-18 16:31:33 +00:00
|
|
|
use matrix_sdk_base::{Error as MatrixError, StoreError};
|
2020-08-02 12:05:43 +00:00
|
|
|
use matrix_sdk_common::{
|
2020-10-16 15:27:00 +00:00
|
|
|
api::{
|
|
|
|
r0::uiaa::{UiaaInfo, UiaaResponse as UiaaError},
|
2021-05-08 13:01:02 +00:00
|
|
|
Error as RumaClientApiError,
|
2020-10-16 15:27:00 +00:00
|
|
|
},
|
2021-04-11 10:04:53 +00:00
|
|
|
identifiers::Error as IdentifierError,
|
2021-05-08 13:01:02 +00:00
|
|
|
FromHttpResponseError, IntoHttpError, MatrixError as RumaApiError, ServerError,
|
2020-07-30 23:22:48 +00:00
|
|
|
};
|
2020-05-08 10:39:36 +00:00
|
|
|
use reqwest::Error as ReqwestError;
|
|
|
|
use serde_json::Error as JsonError;
|
|
|
|
use thiserror::Error;
|
2021-05-13 11:13:58 +00:00
|
|
|
use url::ParseError as UrlParseError;
|
2020-05-08 10:39:36 +00:00
|
|
|
|
|
|
|
/// Result type of the rust-sdk.
|
|
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
|
|
|
2021-01-31 17:09:03 +00:00
|
|
|
/// An HTTP error, representing either a connection error or an error while
|
|
|
|
/// converting the raw HTTP response into a Matrix response.
|
2020-05-08 10:39:36 +00:00
|
|
|
#[derive(Error, Debug)]
|
2021-01-31 17:09:03 +00:00
|
|
|
pub enum HttpError {
|
|
|
|
/// An error at the HTTP layer.
|
|
|
|
#[error(transparent)]
|
|
|
|
Reqwest(#[from] ReqwestError),
|
|
|
|
|
2021-05-12 15:00:47 +00:00
|
|
|
/// Queried endpoint requires authentication but was called on an anonymous
|
|
|
|
/// client.
|
2020-05-08 10:39:36 +00:00
|
|
|
#[error("the queried endpoint requires authentication but was called before logging in")]
|
|
|
|
AuthenticationRequired,
|
|
|
|
|
2021-05-12 15:00:47 +00:00
|
|
|
/// Client tried to force authentication but did not provide an access
|
|
|
|
/// token.
|
2021-04-26 15:31:25 +00:00
|
|
|
#[error("tried to force authentication but no access token was provided")]
|
|
|
|
ForcedAuthenticationWithoutAccessToken,
|
|
|
|
|
2020-09-29 15:23:14 +00:00
|
|
|
/// Queried endpoint is not meant for clients.
|
|
|
|
#[error("the queried endpoint is not meant for clients")]
|
|
|
|
NotClientRequest,
|
|
|
|
|
2021-05-08 13:01:02 +00:00
|
|
|
/// An error converting between ruma_*_api types and Hyper types.
|
|
|
|
#[error(transparent)]
|
|
|
|
Api(#[from] FromHttpResponseError<RumaApiError>),
|
|
|
|
|
2021-01-31 17:09:03 +00:00
|
|
|
/// An error converting between ruma_client_api types and Hyper types.
|
2020-05-08 10:39:36 +00:00
|
|
|
#[error(transparent)]
|
2021-05-08 13:01:02 +00:00
|
|
|
ClientApi(#[from] FromHttpResponseError<RumaClientApiError>),
|
2021-01-31 17:09:03 +00:00
|
|
|
|
|
|
|
/// An error converting between ruma_client_api types and Hyper types.
|
|
|
|
#[error(transparent)]
|
|
|
|
IntoHttp(#[from] IntoHttpError),
|
|
|
|
|
|
|
|
/// An error occurred while authenticating.
|
|
|
|
///
|
2021-05-12 15:00:47 +00:00
|
|
|
/// When registering or authenticating the Matrix server can send a
|
|
|
|
/// `UiaaResponse` as the error type, this is a User-Interactive
|
|
|
|
/// Authentication API response. This represents an error with
|
|
|
|
/// information about how to authenticate the user.
|
2021-01-31 17:09:03 +00:00
|
|
|
#[error(transparent)]
|
|
|
|
UiaaError(#[from] FromHttpResponseError<UiaaError>),
|
2021-01-31 20:10:30 +00:00
|
|
|
|
|
|
|
/// The server returned a status code that should be retried.
|
|
|
|
#[error("Server returned an error {0}")]
|
|
|
|
Server(StatusCode),
|
|
|
|
|
|
|
|
/// The given request can't be cloned and thus can't be retried.
|
|
|
|
#[error("The request cannot be cloned")]
|
|
|
|
UnableToCloneRequest,
|
2021-04-29 11:28:08 +00:00
|
|
|
|
|
|
|
/// Tried to send a request without `user_id` in the `Session`
|
|
|
|
#[error("missing user_id in session")]
|
|
|
|
#[cfg(feature = "appservice")]
|
|
|
|
UserIdRequired,
|
2021-01-31 17:09:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Internal representation of errors.
|
|
|
|
#[derive(Error, Debug)]
|
|
|
|
pub enum Error {
|
|
|
|
/// Error doing an HTTP request.
|
|
|
|
#[error(transparent)]
|
|
|
|
Http(#[from] HttpError),
|
|
|
|
|
2021-05-12 15:00:47 +00:00
|
|
|
/// Queried endpoint requires authentication but was called on an anonymous
|
|
|
|
/// client.
|
2021-01-31 17:09:03 +00:00
|
|
|
#[error("the queried endpoint requires authentication but was called before logging in")]
|
|
|
|
AuthenticationRequired,
|
2020-05-08 10:39:36 +00:00
|
|
|
|
|
|
|
/// An error de/serializing type for the `StateStore`
|
|
|
|
#[error(transparent)]
|
|
|
|
SerdeJson(#[from] JsonError),
|
|
|
|
|
2020-09-15 15:16:16 +00:00
|
|
|
/// An IO error happened.
|
|
|
|
#[error(transparent)]
|
2021-03-30 11:05:13 +00:00
|
|
|
Io(#[from] IoError),
|
2020-09-15 15:16:16 +00:00
|
|
|
|
2020-06-02 18:57:56 +00:00
|
|
|
/// An error occurred in the Matrix client library.
|
2020-05-08 10:39:36 +00:00
|
|
|
#[error(transparent)]
|
|
|
|
MatrixError(#[from] MatrixError),
|
2020-06-02 11:55:24 +00:00
|
|
|
|
2020-08-03 10:38:43 +00:00
|
|
|
/// An error occurred in the crypto store.
|
2020-08-03 13:40:39 +00:00
|
|
|
#[cfg(feature = "encryption")]
|
2020-08-03 10:38:43 +00:00
|
|
|
#[error(transparent)]
|
|
|
|
CryptoStoreError(#[from] CryptoStoreError),
|
|
|
|
|
2021-01-18 16:31:33 +00:00
|
|
|
/// An error occured in the state store.
|
|
|
|
#[error(transparent)]
|
|
|
|
StateStore(#[from] StoreError),
|
2021-04-11 10:04:53 +00:00
|
|
|
|
2021-04-11 14:39:49 +00:00
|
|
|
/// An error encountered when trying to parse an identifier.
|
2021-04-11 10:04:53 +00:00
|
|
|
#[error(transparent)]
|
|
|
|
Identifier(#[from] IdentifierError),
|
2021-05-13 11:13:58 +00:00
|
|
|
|
|
|
|
/// An error encountered when trying to parse a url.
|
|
|
|
#[error(transparent)]
|
|
|
|
Url(#[from] UrlParseError),
|
2020-06-02 11:55:24 +00:00
|
|
|
}
|
|
|
|
|
2020-10-16 15:27:00 +00:00
|
|
|
impl Error {
|
|
|
|
/// Try to destructure the error into an universal interactive auth info.
|
|
|
|
///
|
|
|
|
/// Some requests require universal interactive auth, doing such a request
|
|
|
|
/// will always fail the first time with a 401 status code, the response
|
|
|
|
/// body will contain info how the client can authenticate.
|
|
|
|
///
|
|
|
|
/// The request will need to be retried, this time containing additional
|
|
|
|
/// authentication data.
|
|
|
|
///
|
|
|
|
/// This method is an convenience method to get to the info the server
|
|
|
|
/// returned on the first, failed request.
|
|
|
|
pub fn uiaa_response(&self) -> Option<&UiaaInfo> {
|
2021-01-31 17:09:03 +00:00
|
|
|
if let Error::Http(HttpError::UiaaError(FromHttpResponseError::Http(ServerError::Known(
|
2020-10-16 15:27:00 +00:00
|
|
|
UiaaError::AuthResponse(i),
|
2021-01-31 17:09:03 +00:00
|
|
|
)))) = self
|
2020-10-16 15:27:00 +00:00
|
|
|
{
|
|
|
|
Some(i)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-31 17:09:03 +00:00
|
|
|
impl From<ReqwestError> for Error {
|
|
|
|
fn from(e: ReqwestError) -> Self {
|
|
|
|
Error::Http(HttpError::Reqwest(e))
|
2020-05-08 10:39:36 +00:00
|
|
|
}
|
|
|
|
}
|