1use {
2 log::error,
3 reqwest::{RequestBuilder, Response, StatusCode},
4 serde::de::DeserializeOwned,
5 smbcloud_model::{
6 account::SmbAuthorization,
7 error_codes::{ErrorCode, ErrorResponse},
8 login::AccountStatus,
9 },
10};
11
12#[cfg(not(target_arch = "wasm32"))]
13use log::debug;
14
15#[cfg(debug_assertions)]
17const LOG_RESPONSE_BODY: bool = true; #[cfg(not(debug_assertions))]
19const LOG_RESPONSE_BODY: bool = false;
20
21#[cfg(not(target_arch = "wasm32"))]
27pub async fn check_internet_connection() -> bool {
28 debug!("Checking internet connection");
29 let client = reqwest::Client::builder()
30 .build();
32
33 if let Err(e) = client {
34 error!("Failed to create client for connectivity check: {:?}", e);
35 return false;
36 }
37
38 if let Ok(client) = client {
39 match client.get("https://dns.google").send().await {
40 Ok(response) => {
41 debug!(
42 "Internet connection check successful: {}",
43 response.status()
44 );
45 response.status().is_success()
46 }
47 Err(e) => {
48 error!("Internet connection check failed: {:?}", e);
49 false
50 }
51 }
52 } else {
53 false
54 }
55}
56
57#[cfg(target_arch = "wasm32")]
58pub async fn check_internet_connection() -> bool {
59 true
60}
61
62pub async fn parse_error_response<T: DeserializeOwned>(
63 response: Response,
64) -> Result<T, ErrorResponse> {
65 let error_response_body = match response.text().await {
66 Ok(body) => body,
67 Err(e) => {
68 error!("Failed to get response body: {:?}", e);
69 return Err(ErrorResponse::Error {
70 error_code: ErrorCode::NetworkError,
71 message: ErrorCode::NetworkError.message(None).to_string(),
72 });
73 }
74 };
75
76 if LOG_RESPONSE_BODY {
77 println!();
78 println!("Parse Error >>>>");
79 println!("{:?}", serde_json::to_string_pretty(&error_response_body));
80 println!("Parse Error >>>>");
81 println!();
82 }
83
84 let error_response = match serde_json::from_str(&error_response_body) {
85 Ok(error_response) => error_response,
86 Err(e) => {
87 error!("Failed to parse error response: {:?}", e);
88 return Err(ErrorResponse::Error {
89 error_code: ErrorCode::ParseError,
90 message: ErrorCode::ParseError.message(None).to_string(),
91 });
92 }
93 };
94 Err(error_response)
97}
98
99pub async fn request_login(builder: RequestBuilder) -> Result<AccountStatus, ErrorResponse> {
100 let response = builder.send().await;
101 let response = match response {
102 Ok(response) => response,
103 Err(e) => {
104 error!("request_login: Failed to get response: {:?}", e);
105 return Err(ErrorResponse::Error {
106 error_code: ErrorCode::NetworkError,
107 message: ErrorCode::NetworkError.message(None).to_string(),
108 });
109 }
110 };
111
112 if LOG_RESPONSE_BODY {
113 println!();
114 println!("request_login: Parse >>>>");
115 println!("{:?}", &response.status());
116 println!("request_login: Parse >>>>");
117 println!();
118 }
119
120 match (response.status(), response.headers().get("Authorization")) {
121 (StatusCode::OK, Some(token)) => {
122 let access_token = match token.to_str() {
124 Ok(token) => token.to_string(),
125 Err(_) => {
126 return Err(ErrorResponse::Error {
127 error_code: ErrorCode::NetworkError,
128 message: ErrorCode::NetworkError.message(None).to_string(),
129 });
130 }
131 };
132 Ok(AccountStatus::Ready { access_token })
133 }
134 (StatusCode::OK, None) => {
135 let error_response = match parse_error_response::<ErrorResponse>(response).await {
137 Ok(error) => error,
138 Err(_) => return Ok(AccountStatus::NotFound),
139 };
140 match error_response {
141 ErrorResponse::Error {
142 error_code,
143 message: _,
144 } => match error_code {
145 ErrorCode::EmailNotVerified => Ok(AccountStatus::Incomplete {
146 status: smbcloud_model::account::ErrorCode::EmailUnverified,
147 }),
148 ErrorCode::PasswordNotSet => Ok(AccountStatus::Incomplete {
149 status: smbcloud_model::account::ErrorCode::PasswordNotSet,
150 }),
151 ErrorCode::Unknown => Ok(AccountStatus::Ready {
152 access_token: "tokenization".to_string(),
153 }),
154 _ => Ok(AccountStatus::NotFound),
155 },
156 }
157 }
158 (StatusCode::NOT_FOUND, _) => {
159 Ok(AccountStatus::NotFound)
161 }
162 (StatusCode::UNPROCESSABLE_ENTITY, _) => {
163 let body_text = match response.text().await {
164 Ok(text) => text,
165 Err(_) => {
166 return Err(ErrorResponse::Error {
167 error_code: ErrorCode::NetworkError,
168 message: ErrorCode::NetworkError.message(None).to_string(),
169 });
170 }
171 };
172
173 let result: SmbAuthorization = match serde_json::from_str(&body_text) {
174 Ok(res) => res,
175 Err(_) => {
176 let message = serde_json::from_str::<serde_json::Value>(&body_text)
178 .ok()
179 .and_then(|v| {
180 v.get("message")
181 .and_then(serde_json::Value::as_str)
182 .map(ToOwned::to_owned)
183 })
184 .unwrap_or_else(|| ErrorCode::NetworkError.message(None).to_string());
185 return Err(ErrorResponse::Error {
186 error_code: ErrorCode::NetworkError,
187 message,
188 });
189 }
190 };
191
192 let error_code = match result.error_code {
193 Some(code) => code,
194 None => {
195 return Err(ErrorResponse::Error {
198 error_code: ErrorCode::NetworkError,
199 message: result.message,
200 });
201 }
202 };
203 Ok(AccountStatus::Incomplete { status: error_code })
204 }
205 (StatusCode::UNAUTHORIZED, _) => {
206 let body_text = match response.text().await {
207 Ok(text) => text,
208 Err(_) => {
209 return Err(ErrorResponse::Error {
210 error_code: ErrorCode::NetworkError,
211 message: ErrorCode::NetworkError.message(None).to_string(),
212 });
213 }
214 };
215
216 if let Ok(result) = serde_json::from_str::<SmbAuthorization>(&body_text) {
218 let error_code = match result.error_code {
219 Some(code) => code,
220 None => {
221 return Err(ErrorResponse::Error {
223 error_code: ErrorCode::Unauthorized,
224 message: result.message,
225 });
226 }
227 };
228 return Err(ErrorResponse::Error {
229 error_code: ErrorCode::Unauthorized,
230 message: error_code.to_string(),
231 });
232 }
233
234 if let Ok(generic) = serde_json::from_str::<serde_json::Value>(&body_text) {
236 let extracted = generic
237 .get("message")
238 .or_else(|| generic.get("error"))
239 .and_then(serde_json::Value::as_str)
240 .unwrap_or("Sign in failed.");
241 return Err(ErrorResponse::Error {
242 error_code: ErrorCode::Unauthorized,
243 message: extracted.to_string(),
244 });
245 }
246
247 Err(ErrorResponse::Error {
248 error_code: ErrorCode::Unauthorized,
249 message: "Sign in failed.".to_string(),
250 })
251 }
252 (status, _) => parse_error_response(response)
253 .await
254 .map_err(|_| ErrorResponse::Error {
255 error_code: ErrorCode::NetworkError,
256 message: format!("Unexpected login response status: {}", status),
257 }),
258 }
259}
260
261pub async fn request<R: DeserializeOwned>(builder: RequestBuilder) -> Result<R, ErrorResponse> {
262 if !check_internet_connection().await {
264 error!("No internet connection available");
265 return Err(ErrorResponse::Error {
266 error_code: ErrorCode::NetworkError,
267 message: "No internet connection. Please check your network settings and try again."
268 .to_string(),
269 });
270 }
271
272 let response = builder.send().await;
273 let response = match response {
274 Ok(response) => response,
275 Err(e) => {
276 error!("Failed to get response: {:?}", e);
277 return Err(ErrorResponse::Error {
278 error_code: ErrorCode::NetworkError,
279 message: ErrorCode::NetworkError.message(None).to_string(),
280 });
281 }
282 };
283 let response = match response.status() {
284 reqwest::StatusCode::OK | reqwest::StatusCode::CREATED => response,
285 status => {
286 error!("Failed to get response: {:?}", status);
287 return parse_error_response(response).await;
289 }
290 };
291
292 let response_body = match response.text().await {
293 Ok(body) => body,
294 Err(e) => {
295 error!("Failed to get response body: {:?}", e);
296 return Err(ErrorResponse::Error {
297 error_code: ErrorCode::NetworkError,
298 message: ErrorCode::NetworkError.message(None).to_string(),
299 });
300 }
301 };
302
303 if LOG_RESPONSE_BODY {
304 println!();
305 println!("Parse >>>>");
306 println!("{:?}", serde_json::to_string_pretty(&response_body));
307 println!("Parse >>>>");
308 println!();
309 }
310
311 let response = match serde_json::from_str::<R>(&response_body) {
312 Ok(response) => response,
313 Err(e) => {
314 error!("Failed to parse response: {:?}", e);
315 return Err(ErrorResponse::Error {
316 error_code: ErrorCode::ParseError,
317 message: e.to_string(),
318 });
319 }
320 };
321
322 Ok(response)
323}