smbcloud_cli/account/forgot/
mod.rs

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