Skip to content

Commit 09295c2

Browse files
committed
Merge branch 'feature/check-account-status' into development
2 parents 2602091 + f60fe59 commit 09295c2

File tree

15 files changed

+602
-60
lines changed

15 files changed

+602
-60
lines changed

crates/smbcloud-model/src/account.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub struct SmbAuthorization {
4848
pub error_code: Option<ErrorCode>,
4949
}
5050

51+
/// TODO: Move to ErrorResponse
5152
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq)]
5253
#[repr(u32)]
5354
#[tsync]

crates/smbcloud-model/src/error_codes.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,49 @@ pub enum ErrorCode {
4444
// Account
4545
#[error("Unauthorized access.")]
4646
Unauthorized = 100,
47+
#[error("Invalid params.")]
48+
InvalidParams = 101,
49+
// Account not ready errors.
50+
#[error("Email not found.")]
51+
EmailNotFound = 1000,
52+
#[error("Email unverified.")]
53+
EmailNotVerified = 1001,
54+
#[error("Email confirmation failed.")]
55+
EmailConfirmationFailed = 1002,
56+
#[error("Password is unset.")]
57+
PasswordNotSet = 1003,
58+
#[error("GitHub email is not connected.")]
59+
GitHubEmailNotConnected = 1004,
4760
#[error("Email already exists.")]
4861
EmailAlreadyExist = 1005,
62+
#[error("Invalid password.")]
63+
InvalidPassword = 1006,
4964
// Projects
5065
#[error("Project not found.")]
51-
ProjectNotFound = 1000,
66+
ProjectNotFound = 2000,
5267
#[error("Runner not supported.")]
53-
UnsupportedRunner = 1001,
68+
UnsupportedRunner = 2001,
5469
}
5570

5671
impl ErrorCode {
5772
/// Cannot expose the ErrorCode enum directly to Ruby,
5873
/// so we need to get it from i32.
5974
pub fn from_i32(value: i32) -> Self {
6075
match value {
61-
// Account
76+
// Generic
6277
100 => ErrorCode::Unauthorized,
78+
101 => ErrorCode::InvalidParams,
79+
// Account not ready errors
80+
1000 => ErrorCode::EmailNotFound,
81+
1001 => ErrorCode::EmailNotVerified,
82+
1002 => ErrorCode::EmailConfirmationFailed,
83+
1003 => ErrorCode::PasswordNotSet,
84+
1004 => ErrorCode::GitHubEmailNotConnected,
6385
1005 => ErrorCode::EmailAlreadyExist,
86+
1006 => ErrorCode::InvalidPassword,
6487
// Projects
65-
1000 => ErrorCode::ProjectNotFound,
88+
2000 => ErrorCode::ProjectNotFound, // Projects
89+
2001 => ErrorCode::UnsupportedRunner,
6690
// Generic errors
6791
5 => ErrorCode::Cancel,
6892
4 => ErrorCode::MissingConfig,
@@ -79,19 +103,28 @@ impl ErrorCode {
79103
debug!("Language code: {:?}, {}", l, self);
80104
match self {
81105
ErrorCode::Unknown => "Unknown error.",
82-
ErrorCode::ProjectNotFound => "Project not found.",
106+
// Networking
83107
ErrorCode::ParseError => "Parse error.",
84108
ErrorCode::NetworkError => {
85109
"Network error. Please check your internet connection and try again."
86110
}
87-
// Accounts
111+
// Generic
88112
ErrorCode::Unauthorized => "Unauthorized access.",
113+
ErrorCode::InvalidParams => "Invalid parameters.",
114+
// Account not ready errors
115+
ErrorCode::EmailNotFound => "Email not found.",
116+
ErrorCode::EmailNotVerified => "Email not verified.",
117+
ErrorCode::EmailConfirmationFailed => "Email confirmation faile.",
118+
ErrorCode::PasswordNotSet => "Password is not set.",
119+
ErrorCode::GitHubEmailNotConnected => "GitHub email is not connected.",
89120
ErrorCode::EmailAlreadyExist => "Email already exists.",
90-
121+
ErrorCode::InvalidPassword => "Invalid password.",
122+
// CLI Generic errors
91123
ErrorCode::InputError => "Input error.",
92124
ErrorCode::MissingConfig => "Missing config.",
93125
ErrorCode::Cancel => "Cancelled operation.",
94126
// Projects
127+
ErrorCode::ProjectNotFound => "Project not found.",
95128
ErrorCode::UnsupportedRunner => "Unsupported runner.",
96129
}
97130
}

crates/smbcloud-network/src/network.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub async fn check_internet_connection() -> bool {
5252
pub async fn parse_error_response<T: DeserializeOwned>(
5353
response: Response,
5454
) -> Result<T, ErrorResponse> {
55-
let response_body = match response.text().await {
55+
let error_response_body = match response.text().await {
5656
Ok(body) => body,
5757
Err(e) => {
5858
error!("Failed to get response body: {:?}", e);
@@ -66,13 +66,13 @@ pub async fn parse_error_response<T: DeserializeOwned>(
6666
if LOG_RESPONSE_BODY {
6767
println!();
6868
println!("Parse Error >>>>");
69-
println!("{:?}", serde_json::to_string_pretty(&response_body));
69+
println!("{:?}", serde_json::to_string_pretty(&error_response_body));
7070
println!("Parse Error >>>>");
7171
println!();
7272
}
7373

74-
let e = match serde_json::from_str::<ErrorResponse>(&response_body) {
75-
Ok(json) => json,
74+
let error_response = match serde_json::from_str::<T>(&error_response_body) {
75+
Ok(error_response) => error_response,
7676
Err(e) => {
7777
error!("Failed to parse error response: {:?}", e);
7878
return Err(ErrorResponse::Error {
@@ -81,41 +81,28 @@ pub async fn parse_error_response<T: DeserializeOwned>(
8181
});
8282
}
8383
};
84-
error!("Error response: {:?}", e);
85-
Err(e)
84+
// The parsing itself is succeed.
85+
Ok(error_response)
8686
}
8787

8888
pub async fn request_login(builder: RequestBuilder) -> Result<AccountStatus, ErrorResponse> {
8989
let response = builder.send().await;
9090
let response = match response {
9191
Ok(response) => response,
9292
Err(e) => {
93-
error!("Failed to get response: {:?}", e);
93+
error!("request_login: Failed to get response: {:?}", e);
9494
return Err(ErrorResponse::Error {
9595
error_code: ErrorCode::NetworkError,
9696
message: ErrorCode::NetworkError.message(None).to_string(),
9797
});
9898
}
9999
};
100100

101-
let response = match response.status() {
102-
reqwest::StatusCode::OK
103-
| reqwest::StatusCode::NOT_FOUND
104-
| reqwest::StatusCode::UNPROCESSABLE_ENTITY => response,
105-
status => {
106-
error!(
107-
"Response are neither OK, NOT_FOUND, or UNPROCESSABLE_ENTITY: {:?}",
108-
status
109-
);
110-
return parse_error_response(response).await;
111-
}
112-
};
113-
114101
if LOG_RESPONSE_BODY {
115102
println!();
116-
println!("Parse >>>>");
103+
println!("request_login: Parse >>>>");
117104
println!("{:?}", &response.status());
118-
println!("Parse >>>>");
105+
println!("request_login: Parse >>>>");
119106
println!();
120107
}
121108

@@ -133,6 +120,30 @@ pub async fn request_login(builder: RequestBuilder) -> Result<AccountStatus, Err
133120
};
134121
Ok(AccountStatus::Ready { access_token })
135122
}
123+
(StatusCode::OK, None) => {
124+
// Silent login from oauth. Need improvement.
125+
let error_response = match parse_error_response::<ErrorResponse>(response).await {
126+
Ok(error) => error,
127+
Err(_) => return Ok(AccountStatus::NotFound),
128+
};
129+
match error_response {
130+
ErrorResponse::Error {
131+
error_code,
132+
message,
133+
} => match error_code {
134+
ErrorCode::EmailNotVerified => Ok(AccountStatus::Incomplete {
135+
status: smbcloud_model::account::ErrorCode::EmailUnverified,
136+
}),
137+
ErrorCode::PasswordNotSet => Ok(AccountStatus::Incomplete {
138+
status: smbcloud_model::account::ErrorCode::PasswordNotSet,
139+
}),
140+
ErrorCode::Unknown => Ok(AccountStatus::Ready {
141+
access_token: "tokenization".to_string(),
142+
}),
143+
_ => Ok(AccountStatus::NotFound),
144+
},
145+
}
146+
}
136147
(StatusCode::NOT_FOUND, _) => {
137148
// Account not found
138149
Ok(AccountStatus::NotFound)
@@ -193,6 +204,7 @@ pub async fn request<R: DeserializeOwned>(builder: RequestBuilder) -> Result<R,
193204
reqwest::StatusCode::OK | reqwest::StatusCode::CREATED => response,
194205
status => {
195206
error!("Failed to get response: {:?}", status);
207+
// This should handle parsing the error response.
196208
return parse_error_response(response).await;
197209
}
198210
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use {
2+
reqwest::Client,
3+
smbcloud_model::{error_codes::ErrorResponse, login::AccountStatus},
4+
smbcloud_network::{environment::Environment, network::request_login},
5+
smbcloud_networking::{
6+
constants::PATH_ACCOUNT_STATUS, smb_base_url_builder, smb_client::SmbClient,
7+
},
8+
};
9+
10+
pub async fn get_account_status(
11+
env: Environment,
12+
client: SmbClient,
13+
email: &str,
14+
) -> Result<AccountStatus, ErrorResponse> {
15+
let builder = Client::new()
16+
.get(build_url(env, &client, email))
17+
.header("Accept", "application/json")
18+
.header("Content-Type", "application/x-www-form-urlencoded");
19+
request_login(builder).await
20+
}
21+
22+
fn build_url(env: Environment, client: &SmbClient, email: &str) -> String {
23+
let mut url_builder = smb_base_url_builder(env, client);
24+
url_builder.add_route(PATH_ACCOUNT_STATUS);
25+
url_builder.add_param("email", email);
26+
url_builder.build()
27+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod get_account_status;
12
pub mod get_consent_url;
23
pub mod get_profile;
34
pub mod get_token;

crates/smbcloud-networking/src/constants.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub const SMB_USER_AGENT: &str = "smbcloud-cli";
1212

1313
// Paths
1414
pub const PATH_USERS_CHECK_EMAIL: &str = "v1/check_email";
15+
pub const PATH_ACCOUNT_STATUS: &str = "v1/account_status";
1516
pub const PATH_USERS_ME: &str = "v1/me";
1617
pub const PATH_USERS: &str = "v1/users";
1718
pub const PATH_USERS_PASSWORD: &str = "v1/users/password";

0 commit comments

Comments
 (0)