jirust_cli/runners/jira_cmd_runners/project_cmd_runner.rs
1use crate::args::commands::ProjectArgs;
2use crate::config::config_file::{AuthData, ConfigFile};
3use jira_v3_openapi::apis::configuration::Configuration;
4use jira_v3_openapi::apis::issues_api::{
5 get_create_issue_meta_issue_type_id, get_create_issue_meta_issue_types,
6};
7use jira_v3_openapi::apis::projects_api::{create_project, search_projects};
8use jira_v3_openapi::models::create_project_details::{AssigneeType, ProjectTypeKey};
9use jira_v3_openapi::models::{CreateProjectDetails, ProjectIdentifiers};
10use jira_v3_openapi::models::{
11 FieldCreateMetadata, IssueTypeIssueCreateMetadata, project::Project,
12};
13
14/// Project command runner struct.
15///
16/// This struct is responsible for holding the project commands parameters
17/// and it is used to pass the parameters to the project commands runner.
18pub struct ProjectCmdRunner {
19 cfg: Configuration,
20}
21
22/// Project command runner implementation.
23///
24/// # Methods
25///
26/// * `new` - Creates a new instance of the ProjectCmdRunner struct.
27/// * `list_jira_projects` - Lists Jira projects.
28/// * `get_jira_project_issue_types` - Gets Jira project issue types.
29/// * `get_jira_project_issue_type_id` - Gets Jira project issue fields by issue type ID.
30impl ProjectCmdRunner {
31 /// Creates a new instance of the ProjectCmdRunner struct.
32 ///
33 /// # Arguments
34 ///
35 /// * `cfg_file` - A ConfigFile struct.
36 ///
37 /// # Returns
38 ///
39 /// * A new instance of the ProjectCmdRunner struct.
40 ///
41 /// # Examples
42 ///
43 /// ```
44 /// use jirust_cli::config::config_file::ConfigFile;
45 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::ProjectCmdRunner;
46 /// use toml::Table;
47 ///
48 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
49 ///
50 /// let project_cmd_runner = ProjectCmdRunner::new(cfg_file);
51 /// ```
52 pub fn new(cfg_file: ConfigFile) -> ProjectCmdRunner {
53 let mut config = Configuration::new();
54 let auth_data = AuthData::from_base64(cfg_file.get_auth_key());
55 config.base_path = cfg_file.get_jira_url().to_string();
56 config.basic_auth = Some((auth_data.0, Some(auth_data.1)));
57 ProjectCmdRunner { cfg: config }
58 }
59
60 /// Create a new Jira project using the provided parameters.
61 ///
62 /// # Arguments
63 /// * `params` - The parameters for creating the project.
64 ///
65 /// # Returns
66 /// A `Result` containing the project identifiers if successful, or an error if failed.
67 ///
68 /// # Examples
69 ///
70 /// ```no_run
71 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::{ProjectCmdRunner, ProjectCmdParams};
72 /// use jirust_cli::config::config_file::ConfigFile;
73 /// use toml::Table;
74 ///
75 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
76 /// # tokio_test::block_on(async {
77 /// let cfg_file = ConfigFile::new("auth_token".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
78 /// let project_cmd_runner = ProjectCmdRunner::new(cfg_file);
79 ///
80 /// let mut params = ProjectCmdParams::new();
81 /// params.project_key = Some("TEST".to_string());
82 /// params.project_name = Some("Test Project".to_string());
83 /// params.project_description = Some("This is a test project".to_string());
84 /// params.project_field_configuration_id = Some(12345);
85 /// params.project_issue_security_scheme_id = Some(67890);
86 /// params.project_issue_type_scheme_id = Some(54321);
87 ///
88 /// let projects = project_cmd_runner.create_jira_project(params).await?;
89 ///
90 /// # Ok(())
91 /// # })
92 /// # }
93 /// ```
94 pub async fn create_jira_project(
95 &self,
96 params: ProjectCmdParams,
97 ) -> Result<ProjectIdentifiers, Box<dyn std::error::Error>> {
98 let mut project_data = CreateProjectDetails::new(
99 params.project_key.expect("Project key is required!"),
100 params.project_name.expect("Project name is required!"),
101 );
102 project_data.description = params.project_description;
103 project_data.field_configuration_scheme = params.project_field_configuration_id;
104 project_data.issue_security_scheme = params.project_issue_security_scheme_id;
105 project_data.issue_type_scheme = params.project_issue_type_scheme_id;
106 project_data.issue_type_screen_scheme = params.project_issue_type_screen_scheme_id;
107 project_data.notification_scheme = params.project_notification_scheme_id;
108 project_data.permission_scheme = params.project_permission_scheme_id;
109 project_data.workflow_scheme = params.project_workflow_scheme_id;
110 project_data.lead_account_id = params.project_lead_account_id;
111 project_data.assignee_type = if params
112 .project_assignee_type
113 .unwrap_or("unassigned".to_string())
114 == "lead"
115 {
116 Some(AssigneeType::ProjectLead)
117 } else {
118 Some(AssigneeType::Unassigned)
119 };
120 project_data.project_type_key = Some(ProjectTypeKey::Software);
121 Ok(create_project(&self.cfg, project_data).await?)
122 }
123
124 /// Lists Jira projects.
125 ///
126 /// # Arguments
127 ///
128 /// * `params` - A ProjectCmdParams struct.
129 ///
130 /// # Returns
131 ///
132 /// * A Result with a vector of Project structs or an error message.
133 ///
134 /// # Examples
135 ///
136 /// ```no_run
137 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::{ProjectCmdRunner, ProjectCmdParams};
138 /// use jirust_cli::config::config_file::ConfigFile;
139 /// use toml::Table;
140 ///
141 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
142 /// # tokio_test::block_on(async {
143 /// let cfg_file = ConfigFile::new("auth_token".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
144 /// let project_cmd_runner = ProjectCmdRunner::new(cfg_file);
145 /// let params = ProjectCmdParams::new();
146 ///
147 /// let projects = project_cmd_runner.list_jira_projects(params).await?;
148 /// # Ok(())
149 /// # })
150 /// # }
151 /// ```
152 pub async fn list_jira_projects(
153 &self,
154 params: ProjectCmdParams,
155 ) -> Result<Vec<Project>, Box<dyn std::error::Error>> {
156 let page_size = Some(params.projects_page_size.unwrap_or(10));
157 let page_offset = Some(i64::from(params.projects_page_offset.unwrap_or(0)));
158 match search_projects(
159 &self.cfg,
160 page_offset,
161 page_size,
162 None,
163 None,
164 None,
165 None,
166 None,
167 None,
168 None,
169 None,
170 None,
171 None,
172 None,
173 )
174 .await?
175 .values
176 {
177 Some(values) => Ok(values),
178 None => Ok(vec![]),
179 }
180 }
181
182 /// Gets Jira project issue types.
183 ///
184 /// # Arguments
185 ///
186 /// * `params` - A ProjectCmdParams struct.
187 ///
188 /// # Returns
189 /// * A Result with a vector of IssueTypeIssueCreateMetadata structs or an error message.
190 ///
191 /// # Examples
192 ///
193 /// ```no_run
194 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::{ProjectCmdRunner, ProjectCmdParams};
195 /// use jirust_cli::config::config_file::ConfigFile;
196 /// use toml::Table;
197 ///
198 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
199 /// # tokio_test::block_on(async {
200 /// let cfg_file = ConfigFile::new("auth_token".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
201 /// let project_cmd_runner = ProjectCmdRunner::new(cfg_file);
202 /// let params = ProjectCmdParams::new();
203 ///
204 /// let issue_types = project_cmd_runner.get_jira_project_issue_types(params).await?;
205 /// # Ok(())
206 /// # })
207 /// # }
208 /// ```
209 pub async fn get_jira_project_issue_types(
210 &self,
211 params: ProjectCmdParams,
212 ) -> Result<Vec<IssueTypeIssueCreateMetadata>, Box<dyn std::error::Error>> {
213 let page_size = Some(params.projects_page_size.unwrap_or(10));
214 let page_offset = Some(params.projects_page_offset.unwrap_or(0));
215 match get_create_issue_meta_issue_types(
216 &self.cfg,
217 ¶ms.project_key.expect("Project Key is required!"),
218 page_offset,
219 page_size,
220 )
221 .await?
222 .issue_types
223 {
224 Some(issue_types) => Ok(issue_types),
225 None => Ok(vec![]),
226 }
227 }
228
229 /// Gets Jira project issue fields by issue type id.
230 ///
231 /// # Arguments
232 ///
233 /// * `params` - A ProjectCmdParams struct.
234 ///
235 /// # Returns
236 ///
237 /// * A Result with a vector of FieldCreateMetadata structs or an error message.
238 ///
239 /// # Examples
240 ///
241 /// ```no_run
242 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::{ProjectCmdRunner, ProjectCmdParams};
243 /// use jirust_cli::config::config_file::ConfigFile;
244 /// use toml::Table;
245 ///
246 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
247 /// # tokio_test::block_on(async {
248 /// let cfg_file = ConfigFile::new("auth_token".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
249 /// let project_cmd_runner = ProjectCmdRunner::new(cfg_file);
250 /// let params = ProjectCmdParams::new();
251 ///
252 /// let issue_fields = project_cmd_runner.get_jira_project_issue_type_id(params).await?;
253 /// # Ok(())
254 /// # })
255 /// # }
256 /// ```
257 pub async fn get_jira_project_issue_type_id(
258 &self,
259 params: ProjectCmdParams,
260 ) -> Result<Vec<FieldCreateMetadata>, Box<dyn std::error::Error>> {
261 let page_size = Some(params.projects_page_size.unwrap_or(10));
262 let page_offset = Some(params.projects_page_offset.unwrap_or(0));
263 match get_create_issue_meta_issue_type_id(
264 &self.cfg,
265 ¶ms.project_key.expect("Project Key is required!"),
266 ¶ms.project_issue_type.expect("Issue Type is required!"),
267 page_offset,
268 page_size,
269 )
270 .await?
271 .fields
272 {
273 Some(id) => Ok(id),
274 None => Ok(vec![]),
275 }
276 }
277}
278
279/// This struct defines the parameters for the Project commands
280///
281/// # Fields
282///
283/// * `project_key` - The project key, **required** for get project issue types and issue fields commands.
284/// * `project_issue_type` - The project issue type, **required** for get issue fields command.
285/// * `projects_page_size` - The page size for the project command, optional.
286/// * `projects_page_offset` - The page offset for the project command, optional.
287pub struct ProjectCmdParams {
288 pub project_key: Option<String>,
289 pub project_issue_type: Option<String>,
290 pub project_name: Option<String>,
291 pub project_description: Option<String>,
292 pub project_field_configuration_id: Option<i64>,
293 pub project_issue_security_scheme_id: Option<i64>,
294 pub project_issue_type_scheme_id: Option<i64>,
295 pub project_issue_type_screen_scheme_id: Option<i64>,
296 pub project_notification_scheme_id: Option<i64>,
297 pub project_permission_scheme_id: Option<i64>,
298 pub project_workflow_scheme_id: Option<i64>,
299 pub project_lead_account_id: Option<String>,
300 pub project_assignee_type: Option<String>,
301 pub projects_page_size: Option<i32>,
302 pub projects_page_offset: Option<i32>,
303}
304
305/// Implementation of the ProjectCmdParams struct
306///
307/// # Methods
308///
309/// * `new` - Creates a new ProjectCmdParams struct.
310///
311impl ProjectCmdParams {
312 /// Creates a new ProjectCmdParams struct instance.
313 ///
314 /// # Returns
315 ///
316 /// * A ProjectCmdParams struct instance.
317 ///
318 /// # Examples
319 ///
320 /// ```
321 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::ProjectCmdParams;
322 ///
323 /// let params = ProjectCmdParams::new();
324 /// ```
325 pub fn new() -> ProjectCmdParams {
326 ProjectCmdParams {
327 project_key: None,
328 project_issue_type: None,
329 project_name: None,
330 project_description: None,
331 project_field_configuration_id: None,
332 project_issue_security_scheme_id: None,
333 project_issue_type_scheme_id: None,
334 project_issue_type_screen_scheme_id: None,
335 project_notification_scheme_id: None,
336 project_permission_scheme_id: None,
337 project_workflow_scheme_id: None,
338 project_lead_account_id: None,
339 project_assignee_type: None,
340 projects_page_size: None,
341 projects_page_offset: None,
342 }
343 }
344}
345
346/// Implementation of the From trait for the ProjectCmdParams struct
347/// to convert from ProjectArgs to ProjectCmdParams.
348impl From<&ProjectArgs> for ProjectCmdParams {
349 /// Converts from ProjectArgs to ProjectCmdParams.
350 ///
351 /// # Arguments
352 ///
353 /// * `value` - A ProjectArgs struct.
354 ///
355 /// # Returns
356 ///
357 /// * A ProjectCmdParams struct instance.
358 ///
359 /// # Examples
360 ///
361 /// ```
362 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::ProjectCmdParams;
363 /// use jirust_cli::args::commands::{ProjectArgs, ProjectActionValues, PaginationArgs, OutputArgs};
364 ///
365 /// let project_args = ProjectArgs {
366 /// project_act: ProjectActionValues::GetIssueTypeFields,
367 /// project_key: Some("project_key".to_string()),
368 /// project_issue_type: Some("project_issue_type".to_string()),
369 /// project_name: None,
370 /// project_description: None,
371 /// project_field_configuration_id: None,
372 /// project_issue_security_scheme_id: None,
373 /// project_issue_type_scheme_id: None,
374 /// project_issue_type_screen_scheme_id: None,
375 /// project_notification_scheme_id: None,
376 /// project_permission_scheme_id: None,
377 /// project_workflow_scheme_id: None,
378 /// project_lead_account_id: None,
379 /// project_assignee_type: None,
380 /// pagination: PaginationArgs { page_size: Some(10), page_offset: None },
381 /// output: OutputArgs { output_format: None, output_type: None },
382 /// };
383 ///
384 /// let params = ProjectCmdParams::from(&project_args);
385 ///
386 /// assert_eq!(params.project_key, Some("project_key".to_string()));
387 /// assert_eq!(params.project_issue_type, Some("project_issue_type".to_string()));
388 /// assert_eq!(params.projects_page_size, Some(10));
389 /// assert_eq!(params.projects_page_offset, Some(0));
390 /// ```
391 fn from(value: &ProjectArgs) -> Self {
392 ProjectCmdParams {
393 project_key: value.project_key.clone(),
394 project_issue_type: value.project_issue_type.clone(),
395 project_name: value.project_name.clone(),
396 project_description: value.project_description.clone(),
397 project_field_configuration_id: value.project_field_configuration_id,
398 project_issue_security_scheme_id: value.project_issue_security_scheme_id,
399 project_issue_type_scheme_id: value.project_issue_type_scheme_id,
400 project_issue_type_screen_scheme_id: value.project_issue_type_screen_scheme_id,
401 project_notification_scheme_id: value.project_notification_scheme_id,
402 project_permission_scheme_id: value.project_permission_scheme_id,
403 project_workflow_scheme_id: value.project_workflow_scheme_id,
404 project_lead_account_id: value.project_lead_account_id.clone(),
405 project_assignee_type: value.project_assignee_type.clone(),
406 projects_page_size: value.pagination.page_size,
407 projects_page_offset: Some(
408 i32::try_from(value.pagination.page_offset.unwrap_or(0))
409 .expect("Invalid page offset, should fit an i32!"),
410 ),
411 }
412 }
413}
414
415/// Implementation of the Default trait for the ProjectCmdParams struct
416impl Default for ProjectCmdParams {
417 /// Creates a default ProjectCmdParams struct instance.
418 ///
419 /// # Returns
420 ///
421 /// * A ProjectCmdParams struct instance with default values.
422 ///
423 /// # Examples
424 ///
425 /// ```
426 /// use jirust_cli::runners::jira_cmd_runners::project_cmd_runner::ProjectCmdParams;
427 ///
428 /// let params = ProjectCmdParams::default();
429 ///
430 /// assert_eq!(params.project_key, None);
431 /// assert_eq!(params.project_issue_type, None);
432 /// assert_eq!(params.projects_page_size, None);
433 /// assert_eq!(params.projects_page_offset, None);
434 /// ```
435 fn default() -> Self {
436 ProjectCmdParams::new()
437 }
438}