bitwarden_api_key_connector/apis/
user_keys_api.rs1use std::sync::Arc;
2
3use async_trait::async_trait;
4use configuration::Configuration;
5use mockall::automock;
6use reqwest::Method;
7use serde::Serialize;
8
9use crate::{
10 apis::{Error, configuration},
11 models::{
12 user_key_request_model::UserKeyKeyRequestModel,
13 user_key_response_model::UserKeyResponseModel,
14 },
15};
16
17#[automock]
18#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
19#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
20pub trait UserKeysApi: Send + Sync {
21 async fn get_user_key(&self) -> Result<UserKeyResponseModel, Error>;
23
24 async fn post_user_key(&self, request_model: UserKeyKeyRequestModel) -> Result<(), Error>;
26
27 async fn put_user_key(&self, request_model: UserKeyKeyRequestModel) -> Result<(), Error>;
29}
30
31pub struct UserKeysApiClient {
32 configuration: Arc<Configuration>,
33}
34
35impl UserKeysApiClient {
36 pub fn new(configuration: Arc<Configuration>) -> Self {
37 Self { configuration }
38 }
39}
40
41#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
42#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
43impl UserKeysApi for UserKeysApiClient {
44 async fn get_user_key(&self) -> Result<UserKeyResponseModel, Error> {
45 let response = request(&self.configuration, Method::GET, None::<()>).await?;
46
47 let body = response.text().await?;
48 let response_model = serde_json::from_str::<UserKeyResponseModel>(&body)?;
49 Ok(response_model)
50 }
51
52 async fn post_user_key(&self, request_model: UserKeyKeyRequestModel) -> Result<(), Error> {
53 request(&self.configuration, Method::POST, Some(request_model)).await?;
54
55 Ok(())
56 }
57
58 async fn put_user_key(&self, request_model: UserKeyKeyRequestModel) -> Result<(), Error> {
59 request(&self.configuration, Method::PUT, Some(request_model)).await?;
60
61 Ok(())
62 }
63}
64
65async fn request(
66 configuration: &Arc<Configuration>,
67 method: Method,
68 body: Option<impl Serialize>,
69) -> Result<reqwest::Response, Error> {
70 let url = format!("{}/user-keys", configuration.base_path);
71
72 let mut request = configuration
73 .client
74 .request(method, url)
75 .header(reqwest::header::CONTENT_TYPE, "application/json")
76 .header(reqwest::header::ACCEPT, "application/json");
77
78 if let Some(ref user_agent) = configuration.user_agent {
79 request = request.header(reqwest::header::USER_AGENT, user_agent.clone());
80 }
81 if let Some(ref access_token) = configuration.oauth_access_token {
82 request = request.bearer_auth(access_token.clone());
83 }
84 if let Some(ref body) = body {
85 request =
86 request.body(serde_json::to_string(&body).expect("Serialize should be infallible"))
87 }
88
89 let response = request.send().await?;
90
91 Ok(response.error_for_status()?)
92}
93
94#[cfg(test)]
95mod tests {
96 use std::sync::Arc;
97
98 use wiremock::{
99 Mock, MockServer, ResponseTemplate,
100 matchers::{header, method, path},
101 };
102
103 use crate::{
104 apis::{
105 configuration::Configuration,
106 user_keys_api::{UserKeysApi, UserKeysApiClient},
107 },
108 models::user_key_request_model::UserKeyKeyRequestModel,
109 };
110
111 const ACCESS_TOKEN: &str = "test_access_token";
112 const KEY_CONNECTOR_KEY: &str = "test_key_connector_key";
113
114 async fn setup_mock_server_with_auth() -> (MockServer, Configuration) {
115 let server = MockServer::start().await;
116
117 let configuration = Configuration {
118 base_path: format!("http://{}", server.address()),
119 user_agent: Some("Bitwarden Rust-SDK [TEST]".to_string()),
120 client: reqwest::Client::new().into(),
121 oauth_access_token: Some(ACCESS_TOKEN.to_string()),
122 };
123
124 (server, configuration)
125 }
126
127 #[tokio::test]
128 async fn test_get() {
129 let (server, configuration) = setup_mock_server_with_auth().await;
130
131 Mock::given(method("GET"))
132 .and(path("/user-keys"))
133 .and(header("authorization", format!("Bearer {ACCESS_TOKEN}")))
134 .respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
135 "key": KEY_CONNECTOR_KEY.to_string()
136 })))
137 .expect(1)
138 .mount(&server)
139 .await;
140
141 let api_client = UserKeysApiClient::new(Arc::new(configuration));
142
143 let result = api_client.get_user_key().await;
144
145 assert!(result.is_ok());
146 assert_eq!(KEY_CONNECTOR_KEY, result.unwrap().key);
147 }
148
149 #[tokio::test]
150 async fn test_post() {
151 let (server, configuration) = setup_mock_server_with_auth().await;
152
153 Mock::given(method("POST"))
154 .and(path("/user-keys"))
155 .and(header("authorization", format!("Bearer {ACCESS_TOKEN}")))
156 .and(header("content-type", "application/json"))
157 .respond_with(ResponseTemplate::new(200))
158 .expect(1)
159 .mount(&server)
160 .await;
161
162 let request_model = UserKeyKeyRequestModel {
163 key: KEY_CONNECTOR_KEY.to_string(),
164 };
165
166 let api_client = UserKeysApiClient::new(Arc::new(configuration));
167
168 let result = api_client.post_user_key(request_model).await;
169
170 assert!(result.is_ok());
171 }
172
173 #[tokio::test]
174 async fn test_put() {
175 let (server, configuration) = setup_mock_server_with_auth().await;
176
177 Mock::given(method("PUT"))
178 .and(path("/user-keys"))
179 .and(header("authorization", format!("Bearer {ACCESS_TOKEN}")))
180 .and(header("content-type", "application/json"))
181 .respond_with(ResponseTemplate::new(200))
182 .expect(1)
183 .mount(&server)
184 .await;
185
186 let request_model = UserKeyKeyRequestModel {
187 key: KEY_CONNECTOR_KEY.to_string(),
188 };
189
190 let api_client = UserKeysApiClient::new(Arc::new(configuration));
191
192 let result = api_client.put_user_key(request_model).await;
193
194 assert!(result.is_ok());
195 }
196}