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