4 files changed
+84
-21
crates/cli/src/account/login/process.rs
+61
-21
@@ -25,8 +25,10 @@ use smbcloud_networking::{
25
},
26
smb_base_url_builder,
27
};
28
-use smbcloud_utils::email_validation;
29
-use spinners::Spinner;
28
+use {
29
+ crate::account::signup::process_signup, smbcloud_networking_account::signup::check_email,
30
+ smbcloud_utils::email_validation, spinners::Spinner,
31
+};
32
33
pub async fn process_login(env: Environment) -> Result<CommandResult> {
34
// Check if token file exists
@@ -284,21 +286,40 @@ async fn login_with_email(env: Environment) -> Result<CommandResult> {
286
return Err(error);
287
}
288
};
287
- let password = match Password::with_theme(&ColorfulTheme::default())
288
- .with_prompt("Password")
289
- .interact()
290
- {
291
- Ok(password) => password,
292
- Err(_) => {
293
- let error = anyhow!("Invalid password.");
294
- return Err(error);
289
+ // Check if email is in the database, unconfirmed. Only presents password input if email is found and confirmed.
290
+ let mut spinner = Spinner::new(
291
+ spinners::Spinners::SimpleDotsScrolling,
292
+ succeed_message("Checking email"),
293
+ );
294
+
295
+ match check_email(env, &username).await {
296
+ Ok(auth) => {
297
+ // Only continue with password input if email is found and confirmed.
298
+ if let Some(_) = auth.error_code {
299
+ verify_or_set_password(&env, spinner, auth).await
300
+ } else {
301
+ spinner.stop();
302
+ let password = match Password::with_theme(&ColorfulTheme::default())
303
+ .with_prompt("Password")
304
+ .interact()
305
+ {
306
+ Ok(password) => password,
307
+ Err(_) => {
308
+ let error = anyhow!("Invalid password.");
309
+ return Err(error);
310
+ }
311
+ };
312
+ do_process_login(env, LoginArgs { username, password }).await
313
+ }
314
}
296
- };
297
- do_process_login(env, LoginArgs { username, password }).await
315
+ Err(_) => Err(anyhow!(fail_message(
316
+ "Server error. Please try again later."
317
+ ))),
318
+ }
319
}
320
321
async fn do_process_login(env: Environment, args: LoginArgs) -> Result<CommandResult> {
301
- let mut spinner = Spinner::new(
322
+ let spinner = Spinner::new(
323
spinners::Spinners::SimpleDotsScrolling,
324
succeed_message("Loading"),
325
);
@@ -339,14 +360,10 @@ async fn do_process_login(env: Environment, args: LoginArgs) -> Result<CommandRe
360
})
361
}
362
StatusCode::UNPROCESSABLE_ENTITY => {
342
- spinner.stop_and_persist(
343
- &succeed_symbol(),
344
- succeed_message("Please complete registration"),
345
- );
363
// Account found but email not verified / password not set
364
let result: SmbAuthorization = response.json().await?;
365
// println!("Result: {:#?}", &result);
349
- verify_or_set_password(&env, result).await
366
+ verify_or_set_password(&env, spinner, result).await
367
}
368
_ => Err(anyhow!(fail_message(
369
"Login failed. Check your username and password."
@@ -356,15 +373,38 @@ async fn do_process_login(env: Environment, args: LoginArgs) -> Result<CommandRe
373
374
async fn verify_or_set_password(
375
env: &Environment,
376
+ mut spinner: Spinner,
377
result: SmbAuthorization,
378
) -> Result<CommandResult> {
379
match result.error_code {
380
Some(error_code) => {
381
debug!("{}", error_code);
382
match error_code {
365
- ErrorCode::EmailUnverified => send_email_verification(*env, result.user).await,
366
- ErrorCode::PasswordNotSet => send_reset_password(*env, result.user).await,
367
- _ => Err(anyhow!("Shouldn't be here.")),
383
+ ErrorCode::EmailNotFound => {
384
+ spinner.stop_and_persist(
385
+ &succeed_symbol(),
386
+ succeed_message("Email not found. Please register."),
387
+ );
388
+ process_signup(env.to_owned()).await
389
+ }
390
+ ErrorCode::EmailUnverified => {
391
+ spinner.stop_and_persist(
392
+ &succeed_symbol(),
393
+ succeed_message("Email not verified. Please verify your email."),
394
+ );
395
+ send_email_verification(*env, result.user).await
396
+ }
397
+ ErrorCode::PasswordNotSet => {
398
+ spinner.stop_and_persist(
399
+ &succeed_symbol(),
400
+ succeed_message("Password not set. Please reset your password."),
401
+ );
402
+ send_reset_password(*env, result.user).await
403
+ }
404
+ _ => {
405
+ spinner.stop_and_persist(&fail_symbol(), fail_message("An error occurred."));
406
+ Err(anyhow!("Idk what happened."))
407
+ }
408
}
409
}
410
None => Err(anyhow!("Shouldn't be here.")),
crates/smbcloud-networking-account/src/lib.rs
+1
@@ -1,2 +1,3 @@
1
pub mod login;
2
pub mod me;
3
+pub mod signup;
crates/smbcloud-networking-account/src/signup.rs
new
+21
@@ -0,0 +1,21 @@
1
+use {
2
+ reqwest::Client,
3
+ smbcloud_model::{account::SmbAuthorization, error_codes::ErrorResponse},
4
+ smbcloud_network::{environment::Environment, network::request},
5
+ smbcloud_networking::{constants::PATH_USERS_CHECK_EMAIL, smb_base_url_builder},
6
+};
7
+
8
+pub async fn check_email(env: Environment, email: &str) -> Result<SmbAuthorization, ErrorResponse> {
9
+ let builder = Client::new()
10
+ .get(build_url(env, email))
11
+ .header("Accept", "application/json")
12
+ .header("Content-Type", "application/x-www-form-urlencoded");
13
+ request(builder).await
14
+}
15
+
16
+fn build_url(env: Environment, email: &str) -> String {
17
+ let mut url_builder = smb_base_url_builder(env);
18
+ url_builder.add_route(PATH_USERS_CHECK_EMAIL);
19
+ url_builder.add_param("email", email);
20
+ url_builder.build()
21
+}
crates/smbcloud-networking/src/constants.rs
+1
@@ -11,6 +11,7 @@ pub const SMB_CLIENT_SECRET: &str = "secretttttttt";
11
pub const SMB_USER_AGENT: &str = "smbcloud-cli";
12
13
// Paths
14
+pub const PATH_USERS_CHECK_EMAIL: &str = "v1/check_email";
15
pub const PATH_USERS_ME: &str = "v1/me";
16
pub const PATH_USERS: &str = "v1/users";
17
pub const PATH_USERS_PASSWORD: &str = "v1/users/password";