Skip to content

Commit

Permalink
Improve Jira Handling
Browse files Browse the repository at this point in the history
Add apiKey option in order to use API Keys instead of username and
password.

Additionally, an empty dashboard with active Jira configuration resulted
in an HTTP 500 error because the Jira query failed on the Jira API
level. If no applications are available, there is no need to query the
Jira API.
  • Loading branch information
schrieveslaach committed Dec 19, 2023
1 parent 68ecdf7 commit aaac56b
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
6 changes: 6 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ Application names are compared to issues which will be linked to cards on the fr

Currently, Jira as a tracking system is supported.

```toml
[jira]
host = 'https://jira.example.com'
apiKey = ''
```

```toml
[jira]
host = 'https://jira.example.com'
Expand Down
66 changes: 59 additions & 7 deletions api/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,21 @@ impl figment::Provider for CliArgs {
#[derive(Clone, Deserialize)]
pub struct JiraConfig {
host: String,
user: String,
password: SecUtf8,
#[serde(flatten)]
auth: JiraAuth,
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum JiraAuth {
Basic {
user: String,
password: SecUtf8,
},
#[serde(rename_all = "camelCase")]
ApiKey {
api_key: SecUtf8,
},
}

#[derive(Clone, Deserialize)]
Expand Down Expand Up @@ -242,11 +255,8 @@ impl JiraConfig {
pub fn host(&self) -> &String {
&self.host
}
pub fn user(&self) -> &String {
&self.user
}
pub fn password(&self) -> &SecUtf8 {
&self.password
pub fn auth(&self) -> &JiraAuth {
&self.auth
}
}

Expand Down Expand Up @@ -690,4 +700,46 @@ mod tests {
);
});
}

#[test]
fn should_parse_jira_config_with_username_and_password() {
let config = config_from_str!(
r#"
[jira]
host = 'http://jira.example.com'
user = 'user'
password = 'pass'
"#
);

let jira_config = config.jira_config().unwrap();
assert_eq!(jira_config.host(), "http://jira.example.com");
assert_eq!(
jira_config.auth(),
&JiraAuth::Basic {
user: String::from("user"),
password: SecUtf8::from_str("pass").unwrap()
}
);
}

#[test]
fn should_parse_jira_config_with_api_key() {
let config = config_from_str!(
r#"
[jira]
host = 'http://jira.example.com'
apiKey = 'key'
"#
);

let jira_config = config.jira_config().unwrap();
assert_eq!(jira_config.host(), "http://jira.example.com");
assert_eq!(
jira_config.auth(),
&JiraAuth::ApiKey {
api_key: SecUtf8::from_str("key").unwrap()
}
);
}
}
15 changes: 11 additions & 4 deletions api/src/tickets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,20 @@ pub async fn tickets(
}
Some(jira_config) => {
let services = apps_service.get_apps().await?;
if services.is_empty() {
return Ok(Json(tickets));
}

let pw = String::from(jira_config.password().unsecure());
let jira = JiraInstance::at(jira_config.host().clone())
.unwrap()
.authenticate(jira_query::Auth::Basic {
user: jira_config.user().clone(),
password: pw,
.authenticate(match jira_config.auth() {
crate::config::JiraAuth::Basic { user, password } => jira_query::Auth::Basic {
user: user.clone(),
password: password.unsecure().to_string(),
},
crate::config::JiraAuth::ApiKey { api_key } => {
jira_query::Auth::ApiKey(api_key.unsecure().to_string())
}
});

let issue_keys = services
Expand Down

0 comments on commit aaac56b

Please sign in to comment.