smbcloud_network/
network.rs1use {
2 log::{debug, 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(debug_assertions)]
14const LOG_RESPONSE_BODY: bool = true; #[cfg(not(debug_assertions))]
16const LOG_RESPONSE_BODY: bool = false;
17
18pub async fn check_internet_connection() -> bool {
23 debug!("Checking internet connection");
24 let client = reqwest::Client::builder()
25 .build();
27
28 if let Err(e) = client {
29 error!("Failed to create client for connectivity check: {:?}", e);
30 return false;
31 }
32
33 if let Ok(client) = client {
34 match client.get("https://dns.google").send().await {
35 Ok(response) => {
36 debug!(
37 "Internet connection check successful: {}",
38 response.status()
39 );
40 response.status().is_success()
41 }
42 Err(e) => {
43 error!("Internet connection check failed: {:?}", e);
44 false
45 }
46 }
47 } else {
48 false
49 }
50}
51
52pub async fn parse_error_response<T: DeserializeOwned>(
53 response: Response,
54) -> Result<T, ErrorResponse> {
55 let error_response_body = match response.text().await {
56 Ok(body) => body,
57 Err(e) => {
58 error!("Failed to get response body: {:?}", e);
59 return Err(ErrorResponse::Error {
60 error_code: ErrorCode::NetworkError,
61 message: ErrorCode::NetworkError.message(None).to_string(),
62 });
63 }
64 };
65
66 if LOG_RESPONSE_BODY {
67 println!();
68 println!("Parse Error >>>>");
69 println!("{:?}", serde_json::to_string_pretty(&error_response_body));
70 println!("Parse Error >>>>");
71 println!();
72 }
73
74 let error_response = match serde_json::from_str(&error_response_body) {
75 Ok(error_response) => error_response,
76 Err(e) => {
77 error!("Failed to parse error response: {:?}", e);
78 return Err(ErrorResponse::Error {
79 error_code: ErrorCode::ParseError,
80 message: ErrorCode::ParseError.message(None).to_string(),
81 });
82 }
83 };
84 Err(error_response)
87}
88
89pub async fn request_login(builder: RequestBuilder) -> Result<AccountStatus, ErrorResponse> {
90 let response = builder.send().await;
91 let response = match response {
92 Ok(response) => response,
93 Err(e) => {
94 error!("request_login: Failed to get response: {:?}", e);
95 return Err(ErrorResponse::Error {
96 error_code: ErrorCode::NetworkError,
97 message: ErrorCode::NetworkError.message(None).to_string(),
98 });
99 }
100 };
101
102 if LOG_RESPONSE_BODY {
103 println!();
104 println!("request_login: Parse >>>>");
105 println!("{:?}", &response.status());
106 println!("request_login: Parse >>>>");
107 println!();
108 }
109
110 match (response.status(), response.headers().get("Authorization")) {
111 (StatusCode::OK, Some(token)) => {
112 let access_token = match token.to_str() {
114 Ok(token) => token.to_string(),
115 Err(_) => {
116 return Err(ErrorResponse::Error {
117 error_code: ErrorCode::NetworkError,
118 message: ErrorCode::NetworkError.message(None).to_string(),
119 });
120 }
121 };
122 Ok(AccountStatus::Ready { access_token })
123 }
124 (StatusCode::OK, None) => {
125 let error_response = match parse_error_response::<ErrorResponse>(response).await {
127 Ok(error) => error,
128 Err(_) => return Ok(AccountStatus::NotFound),
129 };
130 match error_response {
131 ErrorResponse::Error {
132 error_code,
133 message,
134 } => match error_code {
135 ErrorCode::EmailNotVerified => Ok(AccountStatus::Incomplete {
136 status: smbcloud_model::account::ErrorCode::EmailUnverified,
137 }),
138 ErrorCode::PasswordNotSet => Ok(AccountStatus::Incomplete {
139 status: smbcloud_model::account::ErrorCode::PasswordNotSet,
140 }),
141 ErrorCode::Unknown => Ok(AccountStatus::Ready {
142 access_token: "tokenization".to_string(),
143 }),
144 _ => Ok(AccountStatus::NotFound),
145 },
146 }
147 }
148 (StatusCode::NOT_FOUND, _) => {
149 Ok(AccountStatus::NotFound)
151 }
152 (StatusCode::UNPROCESSABLE_ENTITY, _) => {
153 let result: SmbAuthorization = match response.json().await {
155 Ok(res) => res,
156 Err(_) => {
157 return Err(ErrorResponse::Error {
158 error_code: ErrorCode::NetworkError,
159 message: ErrorCode::NetworkError.message(None).to_string(),
160 });
161 }
162 };
163 let error_code = match result.error_code {
165 Some(code) => code,
166 None => {
167 return Err(ErrorResponse::Error {
168 error_code: ErrorCode::NetworkError,
169 message: ErrorCode::NetworkError.message(None).to_string(),
170 });
171 }
172 };
173 Ok(AccountStatus::Incomplete { status: error_code })
174 }
175 _ => Err(ErrorResponse::Error {
176 error_code: ErrorCode::NetworkError,
177 message: ErrorCode::NetworkError.message(None).to_string(),
178 }),
179 }
180}
181
182pub async fn request<R: DeserializeOwned>(builder: RequestBuilder) -> Result<R, ErrorResponse> {
183 if !check_internet_connection().await {
185 error!("No internet connection available");
186 return Err(ErrorResponse::Error {
187 error_code: ErrorCode::NetworkError,
188 message: "No internet connection. Please check your network settings and try again."
189 .to_string(),
190 });
191 }
192
193 let response = builder.send().await;
194 let response = match response {
195 Ok(response) => response,
196 Err(e) => {
197 error!("Failed to get response: {:?}", e);
198 return Err(ErrorResponse::Error {
199 error_code: ErrorCode::NetworkError,
200 message: ErrorCode::NetworkError.message(None).to_string(),
201 });
202 }
203 };
204 let response = match response.status() {
205 reqwest::StatusCode::OK | reqwest::StatusCode::CREATED => response,
206 status => {
207 error!("Failed to get response: {:?}", status);
208 return parse_error_response(response).await;
210 }
211 };
212
213 let response_body = match response.text().await {
214 Ok(body) => body,
215 Err(e) => {
216 error!("Failed to get response body: {:?}", e);
217 return Err(ErrorResponse::Error {
218 error_code: ErrorCode::NetworkError,
219 message: ErrorCode::NetworkError.message(None).to_string(),
220 });
221 }
222 };
223
224 if LOG_RESPONSE_BODY {
225 println!();
226 println!("Parse >>>>");
227 println!("{:?}", serde_json::to_string_pretty(&response_body));
228 println!("Parse >>>>");
229 println!();
230 }
231
232 let response = match serde_json::from_str::<R>(&response_body) {
233 Ok(response) => response,
234 Err(e) => {
235 error!("Failed to parse response: {:?}", e);
236 return Err(ErrorResponse::Error {
237 error_code: ErrorCode::ParseError,
238 message: e.to_string(),
239 });
240 }
241 };
242
243 Ok(response)
244}