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            &params.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            &params.project_key.expect("Project Key is required!"),
266            &params.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}