smbcloud_cli/account/forgot/
mod.rs

1use crate::{
2    cli::CommandResult,
3    ui::{fail_message, fail_symbol, succeed_message, succeed_symbol},
4};
5use anyhow::Result;
6use dialoguer::{theme::ColorfulTheme, Input, Password};
7use reqwest::{Client, StatusCode};
8use serde::{Deserialize, Serialize};
9use smbcloud_model::forgot::{Args, Email, Param, UserUpdatePassword};
10use smbcloud_network::environment::Environment;
11use smbcloud_networking::{constants::PATH_USERS_PASSWORD, smb_base_url_builder};
12use smbcloud_utils::email_validation;
13use spinners::Spinner;
14
15pub async fn process_forgot(env: Environment) -> Result<CommandResult> {
16    println!("Provide your login credentials.");
17    let email = Input::<String>::with_theme(&ColorfulTheme::default())
18        .with_prompt("Email")
19        .validate_with(|email: &String| email_validation(email))
20        .interact()
21        .unwrap();
22    let mut spinner = Spinner::new(
23        spinners::Spinners::SimpleDotsScrolling,
24        succeed_message("Checking email"),
25    );
26
27    let params = Args {
28        user: Email { email },
29    };
30
31    let response = Client::new()
32        .post(build_smb_forgot_url(env))
33        .json(&params)
34        .send()
35        .await?;
36
37    match response.status() {
38        StatusCode::OK => {
39            spinner.stop_and_persist(
40                &succeed_symbol(),
41                succeed_message("Check your email and input your code here."),
42            );
43            input_code(env).await
44        }
45        _ => Ok(CommandResult {
46            spinner,
47            symbol: fail_symbol(),
48            msg: fail_message("Something wrong when trying to reset email."),
49        }),
50    }
51}
52
53async fn input_code(env: Environment) -> Result<CommandResult> {
54    let security_code = Input::<String>::with_theme(&ColorfulTheme::default())
55        .with_prompt("Code")
56        .interact()
57        .unwrap();
58
59    Spinner::new(
60        spinners::Spinners::Hamburger,
61        succeed_message("Checking your code."),
62    )
63    .stop_and_persist("✅", "Great. Now input your new password.".to_owned());
64
65    let new_password = Password::with_theme(&ColorfulTheme::default())
66        .with_prompt("Password")
67        .validate_with(|input: &String| -> Result<(), &str> {
68            if input.len() >= 6 {
69                Ok(())
70            } else {
71                Err("Password must be at least 6 characters")
72            }
73        })
74        .with_confirmation("Confirm password", "Passwords do not match")
75        .interact()
76        .unwrap();
77    let password_confirmation = String::from(&new_password);
78
79    // Should reuse this somehow
80    let params = Param {
81        user: UserUpdatePassword {
82            reset_password_token: security_code,
83            password: new_password,
84            password_confirmation,
85        },
86    };
87
88    let spinner = Spinner::new(
89        spinners::Spinners::Hamburger,
90        succeed_message("Updating your password."),
91    );
92
93    let response = Client::new()
94        .put(build_smb_forgot_url(env))
95        .json(&params)
96        .send()
97        .await?;
98
99    #[derive(Debug, Serialize, Deserialize)]
100    struct Response {
101        status: i32,
102        email: Option<String>,
103    }
104
105    match response.status() {
106        StatusCode::OK => Ok(CommandResult {
107            spinner,
108            symbol: succeed_symbol(),
109            msg: succeed_message("Your password has been updated. Login with your new password."),
110        }),
111        StatusCode::NOT_FOUND => Ok(CommandResult {
112            spinner,
113            symbol: fail_symbol(),
114            msg: fail_message("URL not found."),
115        }),
116        _ => Ok(CommandResult {
117            spinner,
118            symbol: fail_symbol(),
119            msg: fail_message("Something wrong when trying to reset email."),
120        }),
121    }
122}
123
124fn build_smb_forgot_url(env: Environment) -> String {
125    let mut url_builder = smb_base_url_builder(env);
126    url_builder.add_route(PATH_USERS_PASSWORD);
127    url_builder.build()
128}