Skip to content

Commit 5b32e4d

Browse files
committed
Merge branch 'feature/sigit-login-auth' into development
2 parents ed2f6b9 + bf6ec0d commit 5b32e4d

File tree

8 files changed

+182
-81
lines changed

8 files changed

+182
-81
lines changed

crates/cli/src/account/lib.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -224,25 +224,29 @@ pub async fn save_token(env: Environment, response: &Response) -> Result<()> {
224224
match headers.get("Authorization") {
225225
Some(token) => {
226226
debug!("{}", token.to_str()?);
227-
match home::home_dir() {
228-
Some(path) => {
229-
debug!("{}", path.to_str().unwrap());
230-
create_dir_all(path.join(env.smb_dir()))?;
231-
let mut file = OpenOptions::new()
232-
.create(true)
233-
.truncate(true)
234-
.write(true)
235-
.open([path.to_str().unwrap(), "/", &env.smb_dir(), "/token"].join(""))?;
236-
file.write_all(token.to_str()?.as_bytes())?;
237-
Ok(())
238-
}
239-
None => Err(anyhow!("Failed to get home directory.")),
240-
}
227+
store_token(env, token.to_str()?.to_string()).await
241228
}
242229
None => Err(anyhow!("Failed to get token. Probably a backend issue.")),
243230
}
244231
}
245232

233+
pub async fn store_token(env: Environment, token: String) -> Result<()> {
234+
match home::home_dir() {
235+
Some(path) => {
236+
debug!("{}", path.to_str().unwrap());
237+
create_dir_all(path.join(env.smb_dir()))?;
238+
let mut file = OpenOptions::new()
239+
.create(true)
240+
.truncate(true)
241+
.write(true)
242+
.open([path.to_str().unwrap(), "/", &env.smb_dir(), "/token"].join(""))?;
243+
file.write_all(token.as_bytes())?;
244+
Ok(())
245+
}
246+
None => Err(anyhow!("Failed to get home directory.")),
247+
}
248+
}
249+
246250
pub fn is_logged_in(env: Environment) -> bool {
247251
// Check if token file exists
248252
smb_token_file_path(env).is_some()

crates/cli/src/account/login/process.rs

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use {
22
crate::{
33
account::{
4-
lib::{authorize_github, save_token},
4+
lib::{authorize_github, store_token},
55
signup::{do_signup, signup_with_email, SignupMethod},
66
},
77
cli::CommandResult,
@@ -14,12 +14,16 @@ use {
1414
log::debug,
1515
reqwest::{Client, StatusCode},
1616
smbcloud_model::{
17-
account::{ErrorCode, GithubInfo, SmbAuthorization, User},
17+
account::{
18+
ErrorCode as AccountErrorCode, ErrorCode::EmailNotFound, ErrorCode::EmailUnverified,
19+
ErrorCode::GithubNotLinked, ErrorCode::PasswordNotSet, GithubInfo, SmbAuthorization,
20+
User,
21+
},
1822
forgot::{Param, UserUpdatePassword},
19-
login::{LoginArgs, LoginParams, UserParam},
23+
login::{AccountStatus, LoginArgs, LoginParams, UserParam},
2024
signup::{GithubEmail, Provider, SignupGithubParams, SignupUserGithub},
2125
},
22-
smbcloud_network::environment::Environment,
26+
smbcloud_network::{environment::Environment, network::request_login},
2327
smbcloud_networking::{
2428
constants::{
2529
PATH_LINK_GITHUB_ACCOUNT, PATH_RESEND_CONFIRMATION, PATH_RESET_PASSWORD_INSTRUCTIONS,
@@ -91,16 +95,14 @@ async fn process_authorization(env: Environment, auth: SmbAuthorization) -> Resu
9195
if let Some(error_code) = auth.error_code {
9296
debug!("{}", error_code);
9397
match error_code {
94-
ErrorCode::EmailNotFound => {
95-
return create_new_account(env, auth.user_email, auth.user_info).await
96-
}
97-
ErrorCode::EmailUnverified => return send_email_verification(env, auth.user).await,
98-
ErrorCode::PasswordNotSet => {
98+
EmailNotFound => return create_new_account(env, auth.user_email, auth.user_info).await,
99+
EmailUnverified => return send_email_verification(env, auth.user).await,
100+
PasswordNotSet => {
99101
// Only for email and password login
100102
let error = anyhow!("Password not set.");
101103
return Err(error);
102104
}
103-
ErrorCode::GithubNotLinked => return connect_github_account(env, auth).await,
105+
GithubNotLinked => return connect_github_account(env, auth).await,
104106
}
105107
}
106108

@@ -299,7 +301,7 @@ async fn login_with_email(env: Environment) -> Result<CommandResult> {
299301
match check_email(env, &username).await {
300302
Ok(auth) => {
301303
// Only continue with password input if email is found and confirmed.
302-
if let Some(_) = auth.error_code {
304+
if auth.error_code.is_some() {
303305
// Check if email is in the database, unconfirmed. Only presents password input if email is found and confirmed.
304306
let spinner = Spinner::new(
305307
spinners::Spinners::SimpleDotsScrolling,
@@ -339,43 +341,28 @@ async fn do_process_login(env: Environment, args: LoginArgs) -> Result<CommandRe
339341
},
340342
};
341343

342-
let response = match Client::new()
344+
let builder = Client::new()
343345
.post(build_smb_login_url(env))
344-
.json(&login_params)
345-
.send()
346-
.await
347-
{
346+
.json(&login_params);
347+
348+
let account_status = match request_login(builder).await {
348349
Ok(response) => response,
349350
Err(_) => return Err(anyhow!(fail_message("Check your internet connection."))),
350351
};
351352

352-
match response.status() {
353-
StatusCode::OK => {
354-
// Login successful
355-
save_token(env, &response).await?;
353+
match account_status {
354+
AccountStatus::Ready { access_token } => {
355+
store_token(env, access_token).await?;
356356
Ok(CommandResult {
357357
spinner,
358358
symbol: succeed_symbol(),
359359
msg: succeed_message("You are logged in!"),
360360
})
361361
}
362-
StatusCode::NOT_FOUND => {
363-
// Account not found and we show signup option
364-
Ok(CommandResult {
365-
spinner,
366-
symbol: fail_symbol(),
367-
msg: fail_message("Account not found. Please signup!"),
368-
})
369-
}
370-
StatusCode::UNPROCESSABLE_ENTITY => {
371-
// Account found but email not verified / password not set
372-
let result: SmbAuthorization = response.json().await?;
373-
// println!("Result: {:#?}", &result);
374-
after_checking_email_step(&env, spinner, result, None).await
362+
AccountStatus::NotFound => Err(anyhow!(fail_message("Check your internet connection."))),
363+
AccountStatus::Incomplete { status } => {
364+
action_on_account_status(&env, spinner, status, None, None).await
375365
}
376-
_ => Err(anyhow!(fail_message(
377-
"Login failed. Check your username and password."
378-
))),
379366
}
380367
}
381368

@@ -389,7 +376,7 @@ async fn after_checking_email_step(
389376
Some(error_code) => {
390377
debug!("{}", error_code);
391378
match error_code {
392-
ErrorCode::EmailNotFound => {
379+
EmailNotFound => {
393380
spinner.stop_and_persist(
394381
&succeed_symbol(),
395382
succeed_message(
@@ -398,14 +385,14 @@ async fn after_checking_email_step(
398385
);
399386
signup_with_email(env.to_owned(), username).await
400387
}
401-
ErrorCode::EmailUnverified => {
388+
EmailUnverified => {
402389
spinner.stop_and_persist(
403390
&succeed_symbol(),
404391
succeed_message("Email not verified. Please verify your email."),
405392
);
406393
send_email_verification(*env, result.user).await
407394
}
408-
ErrorCode::PasswordNotSet => {
395+
PasswordNotSet => {
409396
spinner.stop_and_persist(
410397
&succeed_symbol(),
411398
succeed_message("Password not set. Please reset your password."),
@@ -422,6 +409,42 @@ async fn after_checking_email_step(
422409
}
423410
}
424411

412+
async fn action_on_account_status(
413+
env: &Environment,
414+
mut spinner: Spinner,
415+
error_code: AccountErrorCode,
416+
username: Option<String>,
417+
user: Option<User>,
418+
) -> Result<CommandResult> {
419+
match error_code {
420+
EmailNotFound => {
421+
spinner.stop_and_persist(
422+
&succeed_symbol(),
423+
succeed_message("Account not found. Please continue with setting up your account."),
424+
);
425+
signup_with_email(env.to_owned(), username).await
426+
}
427+
EmailUnverified => {
428+
spinner.stop_and_persist(
429+
&succeed_symbol(),
430+
succeed_message("Email not verified. Please verify your email."),
431+
);
432+
send_email_verification(*env, user).await
433+
}
434+
PasswordNotSet => {
435+
spinner.stop_and_persist(
436+
&succeed_symbol(),
437+
succeed_message("Password not set. Please reset your password."),
438+
);
439+
send_reset_password(*env, user).await
440+
}
441+
_ => {
442+
spinner.stop_and_persist(&fail_symbol(), fail_message("An error occurred."));
443+
Err(anyhow!("Idk what happened."))
444+
}
445+
}
446+
}
447+
425448
async fn send_reset_password(env: Environment, user: Option<User>) -> Result<CommandResult> {
426449
// Return early if user is null
427450
if let Some(user) = user {

crates/smbcloud-model/src/account.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ pub struct Data {
3232
created_at: String,
3333
}
3434

35-
// This is smb authorization model.
35+
/// This is smbCloud authorization model
36+
/// that is currently tightly coupled with GitHub OAuth model.
3637
#[derive(Debug, Serialize, Deserialize)]
3738
pub struct SmbAuthorization {
3839
pub message: String,

crates/smbcloud-model/src/login.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
use crate::account::{Data, Status};
2-
use serde::{Deserialize, Serialize};
1+
use {
2+
crate::account::{Data, ErrorCode, Status},
3+
serde::{Deserialize, Serialize},
4+
};
35

46
#[derive(Debug, Serialize)]
57
pub struct LoginArgs {
@@ -24,6 +26,14 @@ pub struct LoginResult {
2426
pub data: Data,
2527
}
2628

29+
/// Login endpoint result.
30+
#[derive(Debug, Serialize, Deserialize)]
31+
pub enum AccountStatus {
32+
NotFound,
33+
Ready { access_token: String },
34+
Incomplete { status: ErrorCode },
35+
}
36+
2737
#[cfg(test)]
2838
mod tests {
2939
use super::*;

crates/smbcloud-model/src/runner.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,7 @@ impl Runner {
4646
if repo_path.join("package.json").exists()
4747
&& (next_config_exists(repo_path) || astro_config_exists(repo_path))
4848
{
49-
if next_config_exists(repo_path) {
50-
return Ok(Runner::NodeJs);
51-
} else if astro_config_exists(repo_path) {
52-
return Ok(Runner::NodeJs);
53-
} else {
54-
return Err(ErrorResponse::Error {
55-
error_code: UnsupportedRunner,
56-
message: UnsupportedRunner.message(None).to_string(),
57-
});
58-
};
49+
return Ok(Runner::NodeJs);
5950
}
6051

6152
if repo_path.join("Gemfile").exists() {
@@ -64,10 +55,10 @@ impl Runner {
6455
if repo_path.join("Package.swift").exists() {
6556
return Ok(Runner::Swift);
6657
}
67-
return Err(ErrorResponse::Error {
58+
Err(ErrorResponse::Error {
6859
error_code: UnsupportedRunner,
6960
message: UnsupportedRunner.message(None).to_string(),
70-
});
61+
})
7162
}
7263

7364
pub fn git_host(&self) -> String {

crates/smbcloud-network/src/environment.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
use wasm_bindgen::prelude::wasm_bindgen;
1+
use {
2+
serde::{Deserialize, Serialize},
3+
wasm_bindgen::prelude::wasm_bindgen,
4+
};
25

3-
#[derive(clap::ValueEnum, Clone, Copy)]
6+
#[derive(clap::ValueEnum, Clone, Copy, Serialize, Deserialize)]
47
#[wasm_bindgen]
58
pub enum Environment {
69
Dev,

crates/smbcloud-network/src/network.rs

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
use {
22
log::{debug, error},
3-
reqwest::{RequestBuilder, Response},
3+
reqwest::{RequestBuilder, Response, StatusCode},
44
serde::de::DeserializeOwned,
5-
smbcloud_model::error_codes::{ErrorCode, ErrorResponse},
5+
smbcloud_model::{
6+
account::SmbAuthorization,
7+
error_codes::{ErrorCode, ErrorResponse},
8+
login::AccountStatus,
9+
},
610
};
711

812
//use std::time::Duration;
913
#[cfg(debug_assertions)]
10-
const LOG_RESPONSE_BODY: bool = true; // You know what to do here.
14+
const LOG_RESPONSE_BODY: bool = false; // You know what to do here.
1115
#[cfg(not(debug_assertions))]
1216
const LOG_RESPONSE_BODY: bool = false;
1317

@@ -81,6 +85,66 @@ pub async fn parse_error_response<T: DeserializeOwned>(
8185
Err(e)
8286
}
8387

88+
pub async fn request_login(builder: RequestBuilder) -> Result<AccountStatus, ErrorResponse> {
89+
let response = builder.send().await;
90+
let response = match response {
91+
Ok(response) => response,
92+
Err(e) => {
93+
error!("Failed to get response: {:?}", e);
94+
return Err(ErrorResponse::Error {
95+
error_code: ErrorCode::NetworkError,
96+
message: ErrorCode::NetworkError.message(None).to_string(),
97+
});
98+
}
99+
};
100+
match (response.status(), response.headers().get("Authorization")) {
101+
(StatusCode::OK, Some(token)) => {
102+
// Login successful, let's get the access token for real.
103+
let access_token = match token.to_str() {
104+
Ok(token) => token.to_string(),
105+
Err(_) => {
106+
return Err(ErrorResponse::Error {
107+
error_code: ErrorCode::NetworkError,
108+
message: ErrorCode::NetworkError.message(None).to_string(),
109+
});
110+
}
111+
};
112+
Ok(AccountStatus::Ready { access_token })
113+
}
114+
(StatusCode::NOT_FOUND, _) => {
115+
// Account not found
116+
Ok(AccountStatus::NotFound)
117+
}
118+
(StatusCode::UNPROCESSABLE_ENTITY, _) => {
119+
// Account found but email not verified / password not set.
120+
let result: SmbAuthorization = match response.json().await {
121+
Ok(res) => res,
122+
Err(_) => {
123+
return Err(ErrorResponse::Error {
124+
error_code: ErrorCode::NetworkError,
125+
message: ErrorCode::NetworkError.message(None).to_string(),
126+
});
127+
}
128+
};
129+
// println!("Result: {:#?}", &result);
130+
let error_code = match result.error_code {
131+
Some(code) => code,
132+
None => {
133+
return Err(ErrorResponse::Error {
134+
error_code: ErrorCode::NetworkError,
135+
message: ErrorCode::NetworkError.message(None).to_string(),
136+
});
137+
}
138+
};
139+
Ok(AccountStatus::Incomplete { status: error_code })
140+
}
141+
_ => Err(ErrorResponse::Error {
142+
error_code: ErrorCode::NetworkError,
143+
message: ErrorCode::NetworkError.message(None).to_string(),
144+
}),
145+
}
146+
}
147+
84148
pub async fn request<R: DeserializeOwned>(builder: RequestBuilder) -> Result<R, ErrorResponse> {
85149
// Check internet connection before making the request
86150
if !check_internet_connection().await {

0 commit comments

Comments
 (0)