iggy_cli/commands/binary_users/
change_password.rs1use crate::commands::cli_command::{CliCommand, PRINT_TARGET};
20use anyhow::Context;
21use async_trait::async_trait;
22use iggy_common::Client;
23use iggy_common::Identifier;
24use passterm::{Stream, isatty, prompt_password_tty};
25use tracing::{Level, event};
26
27pub struct ChangePasswordCmd {
28 user_id: Identifier,
29 current_password: Option<String>,
30 new_password: Option<String>,
31}
32
33impl ChangePasswordCmd {
34 pub fn new(
35 user_id: Identifier,
36 current_password: Option<String>,
37 new_password: Option<String>,
38 ) -> Self {
39 Self {
40 user_id,
41 current_password,
42 new_password,
43 }
44 }
45
46 fn use_tracing(&self) -> bool {
47 self.current_password.is_some() || self.new_password.is_some()
48 }
49}
50
51#[async_trait]
52impl CliCommand for ChangePasswordCmd {
53 fn explain(&self) -> String {
54 format!("change password for user with ID: {}", self.user_id,)
55 }
56
57 fn use_tracing(&self) -> bool {
58 self.use_tracing()
59 }
60
61 async fn execute_cmd(&mut self, client: &dyn Client) -> anyhow::Result<(), anyhow::Error> {
62 let current_password = match &self.current_password {
63 Some(password) => password.clone(),
64 None => {
65 if isatty(Stream::Stdin) {
66 prompt_password_tty(Some("Current password: "))?
67 } else {
68 let mut pwd = String::new();
69 std::io::stdin().read_line(&mut pwd)?;
70 pwd.trim_end_matches(['\n', '\r']).to_string()
71 }
72 }
73 };
74
75 let new_password = match &self.new_password {
76 Some(password) => password.clone(),
77 None => {
78 if isatty(Stream::Stdin) {
79 prompt_password_tty(Some("New password: "))?
80 } else {
81 let mut pwd = String::new();
82 std::io::stdin().read_line(&mut pwd)?;
83 pwd.trim_end_matches(['\n', '\r']).to_string()
84 }
85 }
86 };
87
88 client
89 .change_password(&self.user_id, ¤t_password, &new_password)
90 .await
91 .with_context(|| {
92 format!(
93 "Problem changing password for user with ID: {}",
94 self.user_id,
95 )
96 })?;
97
98 if self.use_tracing() {
99 event!(target: PRINT_TARGET, Level::INFO, "Password for user with ID: {} changed", self.user_id);
100 } else {
101 println!("Password for user with ID: {} changed", self.user_id);
102 }
103
104 Ok(())
105 }
106}