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