Add issue comment editing

This commit is contained in:
Georg Bauer
2026-07-31 15:17:09 +02:00
parent 33f9eb809c
commit da0a3aecb4
10 changed files with 451 additions and 12 deletions

View File

@@ -466,14 +466,16 @@ pub async fn load_issue(
let client =
Client::new(&server.url, Some(&server.token)).map_err(|error| error.to_string())?;
let configuration = client.configuration();
let (issue, comments) = tokio::join!(
let (issue, comments, viewer) = tokio::join!(
apis::issue_api::issue_get_issue(&configuration, owner, repository, number),
load_issue_comments(&configuration, owner, repository, number, page),
client.current_user(),
);
Ok(IssueDetails {
issue: issue.map_err(|error| error.to_string())?,
has_more: false,
comments: comments?,
viewer_id: viewer.map_err(|error| error.to_string())?.id,
})
}
@@ -492,6 +494,67 @@ async fn load_issue_comments(
.map_err(|error| error.to_string())
}
pub async fn save_issue_comment(
server: &Server,
owner: &str,
repository: &str,
number: i64,
comment_id: Option<i64>,
body: String,
) -> Result<(), String> {
let client =
Client::new(&server.url, Some(&server.token)).map_err(|error| error.to_string())?;
let configuration = client.configuration();
match comment_id {
Some(id) => {
let (comment, viewer) = tokio::join!(
apis::issue_api::issue_get_comment(&configuration, owner, repository, id),
client.current_user(),
);
let comment = comment.map_err(|error| error.to_string())?;
let viewer = viewer.map_err(|error| error.to_string())?;
let owned = matches!(
(comment.user.as_ref().and_then(|user| user.id), viewer.id),
(Some(author), Some(viewer)) if author == viewer
);
if !owned || !comment_belongs_to_issue(&comment, number) {
return Err("You can only edit your own comments.".into());
}
apis::issue_api::issue_edit_comment(
&configuration,
owner,
repository,
id,
Some(models::EditIssueCommentOption::new(body)),
)
.await
.map_err(|error| error.to_string())?;
}
None => {
apis::issue_api::issue_create_comment(
&configuration,
owner,
repository,
number,
Some(models::CreateIssueCommentOption::new(body)),
)
.await
.map_err(|error| error.to_string())?;
}
}
Ok(())
}
fn comment_belongs_to_issue(comment: &models::Comment, number: i64) -> bool {
comment
.issue_url
.as_deref()
.map(|url| url.trim_end_matches('/'))
.and_then(|url| url.rsplit('/').next())
.and_then(|index| index.parse().ok())
== Some(number)
}
pub async fn load_issue_editor(
server: &Server,
owner: &str,
@@ -1041,4 +1104,15 @@ mod tests {
assert_eq!(edit.milestone, Some(0));
assert_eq!(edit.unset_due_date, Some(true));
}
#[test]
fn scopes_comment_edits_to_the_selected_issue() {
let comment = models::Comment {
issue_url: Some("https://gitea.example/api/v1/repos/o/r/issues/4/".into()),
..Default::default()
};
assert!(comment_belongs_to_issue(&comment, 4));
assert!(!comment_belongs_to_issue(&comment, 5));
assert!(!comment_belongs_to_issue(&models::Comment::default(), 4));
}
}