From 53c08f5d26f4ba71e60dba5fe74dce620fcaa841 Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Tue, 12 Dec 2023 15:23:31 +0100 Subject: [PATCH] httpd: Cleaning up `api::json` and review comments --- radicle-httpd/src/api/json.rs | 172 +++++++++++---------------- radicle-httpd/src/api/v1/projects.rs | 98 ++++++++------- radicle-httpd/src/test.rs | 2 - 3 files changed, 125 insertions(+), 147 deletions(-) diff --git a/radicle-httpd/src/api/json.rs b/radicle-httpd/src/api/json.rs index 995f22b8..11b28fe5 100644 --- a/radicle-httpd/src/api/json.rs +++ b/radicle-httpd/src/api/json.rs @@ -4,16 +4,13 @@ use std::path::Path; use std::str; use base64::prelude::{Engine, BASE64_STANDARD}; -use serde::Serialize; +use radicle::patch::CodeLocation; use serde_json::{json, Value}; use radicle::cob::issue::{Issue, IssueId}; -use radicle::cob::patch::Merge; -use radicle::cob::patch::Review; -use radicle::cob::patch::{Patch, PatchId}; -use radicle::cob::thread; -use radicle::cob::thread::CommentId; -use radicle::cob::{ActorId, Author, Embed, Reaction, Timestamp, Uri}; +use radicle::cob::patch::{Merge, Patch, PatchId, Review}; +use radicle::cob::thread::{Comment, CommentId}; +use radicle::cob::{ActorId, Author}; use radicle::git::RefString; use radicle::node::{Alias, AliasStore}; use radicle::prelude::NodeId; @@ -106,10 +103,7 @@ pub(crate) fn issue(id: IssueId, issue: Issue, aliases: &impl AliasStore) -> Val "title": issue.title(), "state": issue.state(), "assignees": issue.assignees().collect::>(), - "discussion": issue - .comments() - .map(|(id, comment)| Comment::new(id, comment, aliases)) - .collect::>(), + "discussion": issue.comments().map(|(id, c)| comment(id, c, aliases)).collect::>(), "labels": issue.labels().collect::>(), }) } @@ -128,7 +122,7 @@ pub(crate) fn patch( "state": patch.state(), "target": patch.target(), "labels": patch.labels().collect::>(), - "merges": patch.merges().map(|(nid, m)| merge(m, nid, aliases.alias(nid))).collect::>(), + "merges": patch.merges().map(|(nid, m)| merge(nid, m, aliases)).collect::>(), "assignees": patch.assignees().collect::>(), "revisions": patch.revisions().map(|(id, rev)| { json!({ @@ -138,11 +132,9 @@ pub(crate) fn patch( "base": rev.base(), "oid": rev.head(), "refs": get_refs(repo, patch.author().id(), &rev.head()).unwrap_or_default(), - "discussions": rev.discussion().comments() - .map(|(id, comment)| Comment::new(id, comment, aliases)) - .collect::>(), + "discussions": rev.discussion().comments().map(|(id, c)| comment(id, c, aliases)).collect::>(), "timestamp": rev.timestamp().as_secs(), - "reviews": rev.reviews().map(|(nid, _review)| review(nid, aliases.alias(nid), _review)).collect::>(), + "reviews": rev.reviews().map(|(nid, r)| review(nid, r, aliases)).collect::>(), }) }).collect::>(), }) @@ -160,51 +152,73 @@ fn author(author: &Author, alias: Option) -> Value { } /// Returns JSON for a patch `Merge` and fills in `alias` when present. -fn merge(merge: &Merge, nid: &NodeId, alias: Option) -> Value { - match alias { - Some(alias) => json!({ - "author": { - "id": nid, - "alias": alias, - }, - "commit": merge.commit, - "timestamp": merge.timestamp.as_secs(), - "revision": merge.revision, - }), - None => json!({ - "author": { - "id": nid, - }, - "commit": merge.commit, - "timestamp": merge.timestamp.as_secs(), - "revision": merge.revision, - }), - } +fn merge(nid: &NodeId, merge: &Merge, aliases: &impl AliasStore) -> Value { + json!({ + "author": author(&Author::from(*nid), aliases.alias(nid)), + "commit": merge.commit, + "timestamp": merge.timestamp.as_secs(), + "revision": merge.revision, + }) } /// Returns JSON for a patch `Review` and fills in `alias` when present. -fn review(nid: &NodeId, alias: Option, review: &Review) -> Value { - match alias { - Some(alias) => json!({ - "author": { - "id": nid, - "alias": alias, - }, - "verdict": review.verdict(), - "summary": review.summary(), - "comments": review.comments().collect::>(), - "timestamp": review.timestamp().as_secs(), - }), - None => json!({ - "author": { - "id": nid, - }, - "verdict": review.verdict(), - "summary": review.summary(), - "comments": review.comments().collect::>(), - "timestamp": review.timestamp().as_secs(), - }), - } +fn review(nid: &NodeId, review: &Review, aliases: &impl AliasStore) -> Value { + json!({ + "author": author(&Author::from(*nid), aliases.alias(nid)), + "verdict": review.verdict(), + "summary": review.summary(), + "comments": review.comments().map(|(id, c)| review_comment(id, c, aliases)).collect::>(), + "timestamp": review.timestamp().as_secs(), + }) +} + +/// Returns JSON for a `Comment`. +fn comment(id: &CommentId, comment: &Comment, aliases: &impl AliasStore) -> Value { + json!({ + "id": *id, + "author": author(&Author::from(comment.author()), aliases.alias(&comment.author())), + "body": comment.body(), + "edits": comment.edits().map(|edit| { + json!({ + "author": author(&Author::from(edit.author), aliases.alias(&edit.author)), + "body": edit.body, + "timestamp": edit.timestamp.as_secs(), + "embeds": edit.embeds, + }) + }).collect::>(), + "embeds": comment.embeds().to_vec(), + "reactions": comment.reactions().collect::>(), + "timestamp": comment.timestamp().as_secs(), + "replyTo": comment.reply_to(), + "resolved": comment.resolved(), + }) +} + +/// Returns JSON for a `Review`. +fn review_comment( + id: &CommentId, + comment: &Comment, + aliases: &impl AliasStore, +) -> Value { + json!({ + "id": *id, + "author": author(&Author::from(comment.author()), aliases.alias(&comment.author())), + "body": comment.body(), + "edits": comment.edits().map(|edit| { + json!({ + "author": author(&Author::from(edit.author), aliases.alias(&edit.author)), + "body": edit.body, + "timestamp": edit.timestamp.as_secs(), + "embeds": edit.embeds, + }) + }).collect::>(), + "embeds": comment.embeds().to_vec(), + "reactions": comment.reactions().collect::>(), + "timestamp": comment.timestamp().as_secs(), + "replyTo": comment.reply_to(), + "location": comment.location(), + "resolved": comment.resolved(), + }) } /// Returns the name part of a path string. @@ -235,45 +249,3 @@ fn get_refs( Ok(refs) } - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct Comment<'a> { - id: CommentId, - author: Value, - body: &'a str, - edits: Vec, - embeds: Vec>, - reactions: Vec<(&'a ActorId, &'a Reaction)>, - #[serde(with = "radicle::serde_ext::localtime::time")] - timestamp: Timestamp, - reply_to: Option, - resolved: bool, -} - -impl<'a> Comment<'a> { - fn new(id: &'a CommentId, comment: &'a thread::Comment, aliases: &impl AliasStore) -> Self { - let comment_author = Author::new(comment.author()); - Self { - id: *id, - author: author(&comment_author, aliases.alias(comment_author.id())), - body: comment.body(), - edits: comment - .edits() - .map(|edit| { - json!({ - "author": author(&Author::from(edit.author), aliases.alias(&edit.author)), - "body": edit.body, - "timestamp": edit.timestamp, - "embeds": edit.embeds, - }) - }) - .collect::>(), - embeds: comment.embeds().to_vec(), - reactions: comment.reactions().collect::>(), - timestamp: comment.timestamp(), - reply_to: comment.reply_to(), - resolved: comment.resolved(), - } - } -} diff --git a/radicle-httpd/src/api/v1/projects.rs b/radicle-httpd/src/api/v1/projects.rs index 1ccfd629..d8f411cb 100644 --- a/radicle-httpd/src/api/v1/projects.rs +++ b/radicle-httpd/src/api/v1/projects.rs @@ -2001,7 +2001,7 @@ mod routes { "id": DID, }, "body": "Change 'hello world' to 'hello everyone'", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [], }, ], @@ -2086,7 +2086,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "Change 'hello world' to 'hello everyone'", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [ { "name": "example.html", @@ -2234,7 +2234,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "Change 'hello world' to 'hello everyone'", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [], }, { @@ -2242,7 +2242,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "EDIT: Change 'hello world' to 'hello anyone'", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [ { "name": "image.jpg", @@ -2337,7 +2337,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "Change 'hello world' to 'hello everyone'", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [], }, ], @@ -2359,7 +2359,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "This is a reply to the first comment", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [ { "name": "image.jpg", @@ -3010,7 +3010,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "This is a root level comment", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [ { "name": "image.jpg", @@ -3023,7 +3023,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "EDIT: This is a root level comment", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [ { "name": "image.jpg", @@ -3055,7 +3055,7 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "This is a root level comment", - "timestamp": COMMENT_TIMESTAMP, + "timestamp": TIMESTAMP, "embeds": [], }, ], @@ -3216,49 +3216,37 @@ mod routes { "reviews": [ { "author": { - "id": CONTRIBUTOR_NID, + "id": CONTRIBUTOR_DID, }, "verdict": "accept", "summary": "A small review", - "comments": [[ - comment_id, + "comments": [ { - "author": CONTRIBUTOR_NID, - "location": { - "path": "README.md", - "old": null, - "new": { - "type": "lines", - "range": { - "start": 2, - "end": 4, - } - } + "id": "b108acfd2117480fd87012a5ab7cb69a0651d933", + "author": { + "id": "did:key:z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", }, - "reactions": [ - [ - "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", - "🚀", - ], - ], - "resolved": true, "body": "EDIT: This is a comment on a review", "edits": [ { - "author": "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", - "timestamp": COMMENT_TIMESTAMP, + "author": { + "id": "did:key:z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", + }, "body": "This is a comment on a review", + "timestamp": 1671125284, "embeds": [ - { - "name": "image.jpg", - "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", - }, + { + "name": "image.jpg", + "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", + }, ], }, { - "author": "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", - "timestamp": COMMENT_TIMESTAMP, + "author": { + "id": "did:key:z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", + }, "body": "EDIT: This is a comment on a review", + "timestamp": 1671125284, "embeds": [ { "name": "image.jpg", @@ -3271,11 +3259,31 @@ mod routes { { "name": "image.jpg", "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", - } + }, ], - }, - ]], - "timestamp": TIMESTAMP, + "reactions": [ + [ + "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", + "🚀", + ], + ], + "timestamp": 1671125284, + "replyTo": null, + "location": { + "path": "README.md", + "old": null, + "new": { + "type": "lines", + "range": { + "start": 2, + "end": 4, + }, + }, + }, + "resolved": true, + } + ], + "timestamp": 1671125284, }, ], }, @@ -3329,20 +3337,20 @@ mod routes { "labels": [], "merges": [{ "author": { - "id": CONTRIBUTOR_NID, + "id": CONTRIBUTOR_DID, }, - "revision": CONTRIBUTOR_PATCH_ID, "commit": PARENT, "timestamp": TIMESTAMP, + "revision": CONTRIBUTOR_PATCH_ID, }], "assignees": [], "revisions": [ { "id": CONTRIBUTOR_PATCH_ID, - "description": "change `hello world` in README to something else", "author": { "id": CONTRIBUTOR_DID, }, + "description": "change `hello world` in README to something else", "base": PARENT, "oid": HEAD, "refs": [ diff --git a/radicle-httpd/src/test.rs b/radicle-httpd/src/test.rs index 0145bdde..c227af01 100644 --- a/radicle-httpd/src/test.rs +++ b/radicle-httpd/src/test.rs @@ -37,10 +37,8 @@ pub const ISSUE_DISCUSSION_ID: &str = "d11b03464c9bf58b09460713c8e2c74f0725d3bd" pub const ISSUE_COMMENT_ID: &str = "e3aa754cb47d2299781fed49cc91c4b41e06c219"; pub const SESSION_ID: &str = "u9MGAkkfkMOv0uDDB2WeUHBT7HbsO2Dy"; pub const TIMESTAMP: u64 = 1671125284; -pub const COMMENT_TIMESTAMP: u64 = 1671125284000; pub const CONTRIBUTOR_RID: &str = "rad:z4XaCmN3jLSeiMvW15YTDpNbDHFhG"; pub const CONTRIBUTOR_DID: &str = "did:key:z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8"; -pub const CONTRIBUTOR_NID: &str = "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8"; pub const CONTRIBUTOR_PATCH_ID: &str = "0867c6389ee073304da0854a83885f47b1d7f5ed"; /// Create a new profile.