bitwarden_core/
error.rs

1//! Errors that can occur when using this SDK
2
3use std::fmt::Debug;
4
5use bitwarden_api_api::apis::Error as ApiApisError;
6use bitwarden_api_identity::apis::Error as IdentityError;
7#[cfg(feature = "internal")]
8use bitwarden_error::bitwarden_error;
9use reqwest::StatusCode;
10use thiserror::Error;
11
12macro_rules! impl_bitwarden_error {
13    ($name:ident, $error:ident) => {
14        impl<T> From<$name<T>> for $error {
15            fn from(e: $name<T>) -> Self {
16                match e {
17                    $name::Reqwest(e) => Self::Reqwest(e),
18                    $name::ResponseError(e) => Self::ResponseContent {
19                        status: e.status,
20                        message: e.content,
21                    },
22                    $name::Serde(e) => Self::Serde(e),
23                    $name::Io(e) => Self::Io(e),
24                }
25            }
26        }
27    };
28}
29
30/// Errors from performing network requests.
31#[allow(missing_docs)]
32#[derive(Debug, Error)]
33#[cfg_attr(feature = "uniffi", derive(uniffi::Error), uniffi(flat_error))]
34pub enum ApiError {
35    #[error(transparent)]
36    Reqwest(#[from] reqwest::Error),
37    #[error(transparent)]
38    Serde(#[from] serde_json::Error),
39    #[error(transparent)]
40    Io(#[from] std::io::Error),
41
42    #[error("Received error message from server: [{}] {}", .status, .message)]
43    ResponseContent { status: StatusCode, message: String },
44}
45
46impl_bitwarden_error!(ApiApisError, ApiError);
47impl_bitwarden_error!(IdentityError, ApiError);
48
49/// Client is not authenticated or the session has expired.
50#[derive(Debug, Error)]
51#[error("The client is not authenticated or the session has expired")]
52pub struct NotAuthenticatedError;
53
54/// Client's user ID is already set.
55#[derive(Debug, Error)]
56#[error("The client user ID is already set")]
57pub struct UserIdAlreadySetError;
58
59/// Missing required field.
60#[derive(Debug, Error)]
61#[error("The response received was missing a required field: {0}")]
62pub struct MissingFieldError(pub &'static str);
63
64/// Wrong password.
65#[derive(Debug, thiserror::Error)]
66#[error("Wrong password")]
67pub struct WrongPasswordError;
68
69/// Missing private key.
70#[derive(Debug, thiserror::Error)]
71#[error("Missing private key")]
72pub struct MissingPrivateKeyError;
73
74/// Signifies that the state is invalid from a cryptographic perspective, such as a required
75/// security value missing, or being invalid
76#[cfg(feature = "internal")]
77#[bitwarden_error(flat)]
78#[derive(Debug, thiserror::Error)]
79pub enum StatefulCryptoError {
80    /// The security state is not present, but required for this user. V2 users must always
81    /// have a security state, V1 users cannot have a security state.
82    #[error("Security state is required, but missing")]
83    MissingSecurityState,
84    /// The function expected a user in a account cryptography version, but got a different one.
85    #[error("Expected user in account cryptography version {expected}, but got {got}")]
86    WrongAccountCryptoVersion {
87        /// The expected account cryptography version. This can include a range, such as `2+`.
88        expected: String,
89        /// The actual account cryptography version.
90        got: u32,
91    },
92    #[error("Crypto error, {0}")]
93    Crypto(#[from] bitwarden_crypto::CryptoError),
94}
95
96/// This macro is used to require that a value is present or return an error otherwise.
97/// It is equivalent to using `val.ok_or(Error::MissingFields)?`, but easier to use and
98/// with a more descriptive error message.
99/// Note that this macro will return early from the function if the value is not present.
100#[macro_export]
101macro_rules! require {
102    ($val:expr) => {
103        match $val {
104            Some(val) => val,
105            None => return Err($crate::MissingFieldError(stringify!($val)).into()),
106        }
107    };
108}