jirust_cli/runners/cfg_cmd_runner.rs
1use crate::config::config_file::{AuthData, ConfigFile};
2
3use rpassword::read_password;
4use std::{fs, io::BufRead, path::Path};
5
6/// ConfigCmdRunner is a struct that holds the configuration file path
7/// and provides methods to initialize, set, and show the configuration file.
8pub struct ConfigCmdRunner {
9 cfg_file: String,
10}
11
12/// Implementation of ConfigCmdRunner
13///
14/// # Methods
15///
16/// * `new(cfg_file: String) -> ConfigCmdRunner` - creates a new instance of ConfigCmdRunner
17/// * `init_file() -> Result<(), std::io::Error>` - initializes the configuration file
18/// * `set_cfg_auth(cfg: ConfigFile) -> Result<ConfigFile, std::io::Error>` - sets the authentication data in the configuration file
19/// * `set_cfg_jira(cfg: ConfigFile) -> Result<ConfigFile, std::io::Error>` - sets the Jira URL in the configuration file
20/// * `setup_cfg(cfg: ConfigFile) -> Result<(), std::io::Error>` - sets up the configuration file
21/// * `show_cfg(cfg: ConfigFile)` - shows the configuration file
22impl ConfigCmdRunner {
23 /// Creates a new instance of ConfigCmdRunner
24 ///
25 /// # Arguments
26 ///
27 /// * `cfg_file` - a String that holds the path to the configuration file
28 ///
29 /// # Returns
30 ///
31 /// * `ConfigCmdRunner` - a new instance of ConfigCmdRunner
32 ///
33 /// # Examples
34 ///
35 /// ```
36 /// use jirust_cli::runners::cfg_cmd_runner::ConfigCmdRunner;
37 ///
38 /// let cfg_runner = ConfigCmdRunner::new("test_path/to/config/file".to_string());
39 /// ```
40 pub fn new(cfg_file: String) -> ConfigCmdRunner {
41 ConfigCmdRunner { cfg_file }
42 }
43
44 /// Ensure the CLI can create or update the configuration file before asking for input.
45 fn ensure_cfg_writable(&self) -> Result<(), std::io::Error> {
46 let path = Path::new(&self.cfg_file);
47 if let Some(parent) = path.parent() {
48 if !parent.as_os_str().is_empty() && !parent.exists() {
49 fs::create_dir_all(parent)?;
50 }
51 }
52
53 fs::OpenOptions::new()
54 .write(true)
55 .create(true)
56 .open(path)
57 .map(|_| ())
58 }
59
60 /// Initializes the configuration file
61 ///
62 /// # Returns
63 ///
64 /// * `Result<(), std::io::Error>` - a Result that returns an empty tuple or an error
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// use jirust_cli::runners::cfg_cmd_runner::ConfigCmdRunner;
70 ///
71 /// let cfg_runner = ConfigCmdRunner::new("test_path/to/config/file".to_string());
72 /// cfg_runner.init_file();
73 /// ```
74 pub fn init_file(&self) -> Result<(), std::io::Error> {
75 let path = Path::new(&self.cfg_file);
76 fs::create_dir_all(path.parent().unwrap())?;
77 fs::File::create(path)?;
78 Ok(())
79 }
80
81 /// Sets the authentication data in the configuration file
82 ///
83 /// # Arguments
84 ///
85 /// * `cfg` - a ConfigFile that holds the configuration data
86 ///
87 /// # Returns
88 ///
89 /// * `Result<ConfigFile, std::io::Error>` - a Result that returns the updated ConfigFile or an error
90 ///
91 /// # Examples
92 ///
93 /// ```no_run
94 /// use jirust_cli::config::config_file::ConfigFile;
95 /// use jirust_cli::runners::cfg_cmd_runner::ConfigCmdRunner;
96 ///
97 /// let cfg_runner = ConfigCmdRunner::new("test_path/to/config/file".to_string());
98 /// let cfg = ConfigFile::default();
99 ///
100 /// cfg_runner.set_cfg_auth(cfg);
101 /// ```
102 pub fn set_cfg_auth(&self, cfg: ConfigFile) -> Result<ConfigFile, std::io::Error> {
103 self.ensure_cfg_writable()?;
104 println!("Your username: ");
105 let stdin = std::io::stdin();
106 let mut reader = stdin.lock();
107 self.read_auth_from_sources(cfg, &mut reader, read_password)
108 }
109
110 fn read_auth_from_sources<R, P>(
111 &self,
112 mut cfg: ConfigFile,
113 reader: &mut R,
114 mut password_reader: P,
115 ) -> Result<ConfigFile, std::io::Error>
116 where
117 R: BufRead,
118 P: FnMut() -> Result<String, std::io::Error>,
119 {
120 let mut user = String::new();
121 reader.read_line(&mut user)?;
122 println!("Your apikey: ");
123 let apikey = password_reader()?;
124 let config_data = AuthData::new(user, apikey);
125 cfg.set_auth_key(config_data.to_base64());
126 cfg.write_to_file(self.cfg_file.as_str())?;
127 Ok(cfg)
128 }
129
130 /// Sets the Jira URL in the configuration file
131 ///
132 /// # Arguments
133 ///
134 /// * `cfg` - a ConfigFile that holds the configuration data
135 ///
136 /// # Returns
137 ///
138 /// * `Result<ConfigFile, std::io::Error>` - a Result that returns the updated ConfigFile or an error
139 ///
140 /// # Examples
141 ///
142 /// ```no_run
143 /// use jirust_cli::config::config_file::ConfigFile;
144 /// use jirust_cli::runners::cfg_cmd_runner::ConfigCmdRunner;
145 ///
146 /// let cfg_runner = ConfigCmdRunner::new("test_path/to/config/file".to_string());
147 /// let cfg = ConfigFile::default();
148 /// cfg_runner.set_cfg_jira(cfg);
149 /// ```
150 pub fn set_cfg_jira(&self, cfg: ConfigFile) -> Result<ConfigFile, std::io::Error> {
151 self.ensure_cfg_writable()?;
152 println!("Your Jira instance URL: ");
153 let stdin = std::io::stdin();
154 let mut reader = stdin.lock();
155 self.read_jira_from_reader(cfg, &mut reader)
156 }
157
158 fn read_jira_from_reader<R>(
159 &self,
160 mut cfg: ConfigFile,
161 reader: &mut R,
162 ) -> Result<ConfigFile, std::io::Error>
163 where
164 R: BufRead,
165 {
166 let mut read_data = String::new();
167 reader.read_line(&mut read_data)?;
168 cfg.set_jira_url(read_data.clone());
169 read_data.clear();
170 println!("Default Jira issue resolution JSON Value: ");
171 reader.read_line(&mut read_data)?;
172 cfg.set_standard_resolution(read_data.clone());
173 read_data.clear();
174 println!("Default Jira issue resolution comment JSON: ");
175 reader.read_line(&mut read_data)?;
176 cfg.set_standard_resolution_comment(read_data);
177 cfg.write_to_file(self.cfg_file.as_str())?;
178 Ok(cfg)
179 }
180
181 /// Sets up the configuration file
182 ///
183 /// # Arguments
184 ///
185 /// * `cfg` - a ConfigFile that holds the configuration data
186 ///
187 /// # Returns
188 ///
189 /// * `Result<(), std::io::Error>` - a Result that returns an empty tuple or an error
190 ///
191 /// # Examples
192 ///
193 /// ```no_run
194 /// use jirust_cli::config::config_file::ConfigFile;
195 /// use jirust_cli::runners::cfg_cmd_runner::ConfigCmdRunner;
196 ///
197 /// let cfg_runner = ConfigCmdRunner::new("test_path/to/config/file".to_string());
198 /// let cfg = ConfigFile::default();
199 /// cfg_runner.setup_cfg(cfg);
200 /// ```
201 pub fn setup_cfg(&self, mut cfg: ConfigFile) -> Result<(), std::io::Error> {
202 self.init_file()?;
203 cfg = self.set_cfg_jira(cfg)?;
204 self.set_cfg_auth(cfg)?;
205 Ok(())
206 }
207
208 /// Shows the configuration file data
209 ///
210 /// # Arguments
211 ///
212 /// * `cfg` - a ConfigFile that holds the configuration data
213 ///
214 /// # Examples
215 ///
216 /// ```
217 /// use jirust_cli::config::config_file::ConfigFile;
218 /// use jirust_cli::runners::cfg_cmd_runner::ConfigCmdRunner;
219 ///
220 /// let cfg = ConfigFile::default();
221 ///
222 /// let cfg_runner = ConfigCmdRunner::new("test_path/to/config/file".to_string());
223 /// cfg_runner.show_cfg(cfg);
224 /// ```
225 pub fn show_cfg(&self, cfg: ConfigFile) {
226 println!("Auth token: {}", cfg.get_auth_key());
227 println!("Jira URL: {}", cfg.get_jira_url());
228 println!(
229 "Jira default resolution: {:?}",
230 cfg.get_standard_resolution()
231 );
232 println!(
233 "Jira default resolution comment: {:?}",
234 cfg.get_standard_resolution_comment()
235 );
236 }
237
238 #[cfg(test)]
239 pub(crate) fn set_cfg_auth_with_reader<R, P>(
240 &self,
241 cfg: ConfigFile,
242 reader: &mut R,
243 password_reader: P,
244 ) -> Result<ConfigFile, std::io::Error>
245 where
246 R: BufRead,
247 P: FnMut() -> Result<String, std::io::Error>,
248 {
249 self.ensure_cfg_writable()?;
250 self.read_auth_from_sources(cfg, reader, password_reader)
251 }
252
253 #[cfg(test)]
254 pub(crate) fn set_cfg_jira_with_reader<R>(
255 &self,
256 cfg: ConfigFile,
257 reader: &mut R,
258 ) -> Result<ConfigFile, std::io::Error>
259 where
260 R: BufRead,
261 {
262 self.ensure_cfg_writable()?;
263 self.read_jira_from_reader(cfg, reader)
264 }
265}