bitwarden_api_identity/apis/
mod.rs

1use std::{error, fmt};
2
3#[derive(Debug, Clone)]
4pub struct ResponseContent<T> {
5    pub status: reqwest::StatusCode,
6    pub content: String,
7    pub entity: Option<T>,
8}
9
10#[derive(Debug)]
11pub enum Error<T> {
12    Reqwest(reqwest::Error),
13    Serde(serde_json::Error),
14    Io(std::io::Error),
15    ResponseError(ResponseContent<T>),
16}
17
18impl<T> fmt::Display for Error<T> {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        let (module, e) = match self {
21            Error::Reqwest(e) => ("reqwest", e.to_string()),
22            Error::Serde(e) => ("serde", e.to_string()),
23            Error::Io(e) => ("IO", e.to_string()),
24            Error::ResponseError(e) => ("response", format!("status code {}", e.status)),
25        };
26        write!(f, "error in {}: {}", module, e)
27    }
28}
29
30impl<T: fmt::Debug> error::Error for Error<T> {
31    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
32        Some(match self {
33            Error::Reqwest(e) => e,
34            Error::Serde(e) => e,
35            Error::Io(e) => e,
36            Error::ResponseError(_) => return None,
37        })
38    }
39}
40
41impl<T> From<reqwest::Error> for Error<T> {
42    fn from(e: reqwest::Error) -> Self {
43        Error::Reqwest(e)
44    }
45}
46
47impl<T> From<serde_json::Error> for Error<T> {
48    fn from(e: serde_json::Error) -> Self {
49        Error::Serde(e)
50    }
51}
52
53impl<T> From<std::io::Error> for Error<T> {
54    fn from(e: std::io::Error) -> Self {
55        Error::Io(e)
56    }
57}
58
59pub fn urlencode<T: AsRef<str>>(s: T) -> String {
60    ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect()
61}
62
63pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> {
64    if let serde_json::Value::Object(object) = value {
65        let mut params = vec![];
66
67        for (key, value) in object {
68            match value {
69                serde_json::Value::Object(_) => params.append(&mut parse_deep_object(
70                    &format!("{}[{}]", prefix, key),
71                    value,
72                )),
73                serde_json::Value::Array(array) => {
74                    for (i, value) in array.iter().enumerate() {
75                        params.append(&mut parse_deep_object(
76                            &format!("{}[{}][{}]", prefix, key, i),
77                            value,
78                        ));
79                    }
80                }
81                serde_json::Value::String(s) => {
82                    params.push((format!("{}[{}]", prefix, key), s.clone()))
83                }
84                _ => params.push((format!("{}[{}]", prefix, key), value.to_string())),
85            }
86        }
87
88        return params;
89    }
90
91    unimplemented!("Only objects are supported with style=deepObject")
92}
93
94/// Internal use only
95/// A content type supported by this client.
96#[allow(dead_code)]
97enum ContentType {
98    Json,
99    Text,
100    Unsupported(String),
101}
102
103impl From<&str> for ContentType {
104    fn from(content_type: &str) -> Self {
105        if content_type.starts_with("application") && content_type.contains("json") {
106            return Self::Json;
107        } else if content_type.starts_with("text/plain") {
108            return Self::Text;
109        } else {
110            return Self::Unsupported(content_type.to_string());
111        }
112    }
113}
114
115pub mod accounts_api;
116pub mod info_api;
117pub mod sso_api;
118
119pub mod configuration;
120
121use std::sync::Arc;
122
123#[allow(clippy::large_enum_variant, private_interfaces)]
124pub enum ApiClient {
125    Real(ApiClientReal),
126    #[cfg(feature = "mockall")]
127    Mock(ApiClientMock),
128}
129
130struct ApiClientReal {
131    accounts_api: accounts_api::AccountsApiClient,
132    info_api: info_api::InfoApiClient,
133    sso_api: sso_api::SsoApiClient,
134}
135
136#[cfg(feature = "mockall")]
137pub struct ApiClientMock {
138    pub accounts_api: accounts_api::MockAccountsApi,
139    pub info_api: info_api::MockInfoApi,
140    pub sso_api: sso_api::MockSsoApi,
141}
142
143impl ApiClient {
144    pub fn new(configuration: &Arc<configuration::Configuration>) -> Self {
145        Self::Real(ApiClientReal {
146            accounts_api: accounts_api::AccountsApiClient::new(configuration.clone()),
147            info_api: info_api::InfoApiClient::new(configuration.clone()),
148            sso_api: sso_api::SsoApiClient::new(configuration.clone()),
149        })
150    }
151
152    #[cfg(feature = "mockall")]
153    pub fn new_mocked(func: impl FnOnce(&mut ApiClientMock)) -> Self {
154        let mut mock = ApiClientMock {
155            accounts_api: accounts_api::MockAccountsApi::new(),
156            info_api: info_api::MockInfoApi::new(),
157            sso_api: sso_api::MockSsoApi::new(),
158        };
159        func(&mut mock);
160        Self::Mock(mock)
161    }
162}
163
164impl ApiClient {
165    pub fn accounts_api(&self) -> &dyn accounts_api::AccountsApi {
166        match self {
167            ApiClient::Real(real) => &real.accounts_api,
168            #[cfg(feature = "mockall")]
169            ApiClient::Mock(mock) => &mock.accounts_api,
170        }
171    }
172    pub fn info_api(&self) -> &dyn info_api::InfoApi {
173        match self {
174            ApiClient::Real(real) => &real.info_api,
175            #[cfg(feature = "mockall")]
176            ApiClient::Mock(mock) => &mock.info_api,
177        }
178    }
179    pub fn sso_api(&self) -> &dyn sso_api::SsoApi {
180        match self {
181            ApiClient::Real(real) => &real.sso_api,
182            #[cfg(feature = "mockall")]
183            ApiClient::Mock(mock) => &mock.sso_api,
184        }
185    }
186}