From 15cf5c610060ee0f6cd007aa9066c1cbf580d24e Mon Sep 17 00:00:00 2001 From: Sebastian Martinez Date: Fri, 20 Oct 2023 15:56:57 +0200 Subject: [PATCH] httpd: Parse git URIs into `Embed` Currently we only handle data Uris, but when a user sends a comment that has a existing git Oid, due to editing a comment we also need to handle this case. Signed-off-by: Sebastian Martinez --- radicle-httpd/src/api.rs | 22 +++++- radicle-httpd/src/api/v1/projects.rs | 107 +++++++++++++-------------- radicle-httpd/src/test.rs | 2 +- 3 files changed, 72 insertions(+), 59 deletions(-) diff --git a/radicle-httpd/src/api.rs b/radicle-httpd/src/api.rs index 9048c1b9a..3694458a7 100644 --- a/radicle-httpd/src/api.rs +++ b/radicle-httpd/src/api.rs @@ -15,11 +15,11 @@ use serde_json::json; use tokio::sync::RwLock; use tower_http::cors::{self, CorsLayer}; -use radicle::cob::patch; use radicle::cob::{issue, Uri}; +use radicle::cob::{patch, Embed}; use radicle::identity::{DocAt, Id}; use radicle::node::routing::Store; -use radicle::storage::{ReadRepository, ReadStorage}; +use radicle::storage::{Oid, ReadRepository, ReadStorage}; use radicle::Profile; mod error; @@ -228,3 +228,21 @@ impl TryFrom<&Uri> for DataUri { Err(value.clone()) } } + +/// Resolve an embed with a URI to one with actual data. +pub fn resolve_embed(repo: &impl ReadRepository, embed: Embed) -> Option>> { + DataUri::try_from(&embed.content) + .ok() + .map(|content| Embed { + name: embed.name.clone(), + content: content.into(), + }) + .or_else(|| { + Oid::try_from(&embed.content).ok().and_then(|oid| { + repo.blob(oid).ok().map(|blob| Embed { + name: embed.name, + content: blob.content().to_vec(), + }) + }) + }) +} diff --git a/radicle-httpd/src/api/v1/projects.rs b/radicle-httpd/src/api/v1/projects.rs index 33e2a2a7f..69e45efc1 100644 --- a/radicle-httpd/src/api/v1/projects.rs +++ b/radicle-httpd/src/api/v1/projects.rs @@ -24,7 +24,7 @@ use radicle_surf::{diff, Glob, Oid, Repository}; use crate::api::error::Error; use crate::api::project::Info; -use crate::api::{self, CobsQuery, Context, DataUri, PaginationQuery}; +use crate::api::{self, resolve_embed, CobsQuery, Context, PaginationQuery}; use crate::axum_extra::{Path, Query}; const CACHE_1_HOUR: &str = "public, max-age=3600, must-revalidate"; @@ -647,13 +647,7 @@ async fn issue_create_handler( let embeds: Vec = issue .embeds .into_iter() - .filter_map(|embed| { - let content = TryInto::::try_into(&embed.content).ok()?; - Some(Embed { - name: embed.name, - content: content.into(), - }) - }) + .filter_map(|embed| resolve_embed(&repo, embed)) .collect(); let mut issues = issue::Issues::open(&repo)?; @@ -702,13 +696,7 @@ async fn issue_update_handler( } => { let embeds: Vec = embeds .into_iter() - .filter_map(|embed| { - let content = TryInto::::try_into(&embed.content).ok()?; - Some(Embed { - name: embed.name, - content: content.into(), - }) - }) + .filter_map(|embed| resolve_embed(&repo, embed)) .collect(); if let Some(to) = reply_to { issue.comment(body, to, embeds, &signer)? @@ -724,13 +712,7 @@ async fn issue_update_handler( issue::Action::CommentEdit { id, body, embeds } => { let embeds: Vec = embeds .into_iter() - .filter_map(|embed| { - let content = TryInto::::try_into(&embed.content).ok()?; - Some(Embed { - name: embed.name, - content: content.into(), - }) - }) + .filter_map(|embed| resolve_embed(&repo, embed)) .collect(); issue.edit_comment(id, body, embeds, &signer)? } @@ -847,13 +829,7 @@ async fn patch_update_handler( } => { let embeds: Vec = embeds .into_iter() - .filter_map(|embed| { - let content = TryInto::::try_into(&embed.content).ok()?; - Some(Embed { - name: embed.name, - content: content.into(), - }) - }) + .filter_map(|embed| resolve_embed(&repo, embed)) .collect(); patch.review_comment(review, body, location, reply_to, embeds, &signer)? } @@ -865,13 +841,7 @@ async fn patch_update_handler( } => { let embeds: Vec = embeds .into_iter() - .filter_map(|embed| { - let content = TryInto::::try_into(&embed.content).ok()?; - Some(Embed { - name: embed.name, - content: content.into(), - }) - }) + .filter_map(|embed| resolve_embed(&repo, embed)) .collect(); patch.edit_review_comment(review, comment, body, embeds, &signer)? } @@ -910,13 +880,7 @@ async fn patch_update_handler( } => { let embeds: Vec = embeds .into_iter() - .filter_map(|embed| { - let content = TryInto::::try_into(&embed.content).ok()?; - Some(Embed { - name: embed.name, - content: content.into(), - }) - }) + .filter_map(|embed| resolve_embed(&repo, embed)) .collect(); patch.comment(revision, body, reply_to, location, embeds, &signer)? } @@ -928,13 +892,7 @@ async fn patch_update_handler( } => { let embeds: Vec = embeds .into_iter() - .filter_map(|embed| { - let content = TryInto::::try_into(&embed.content).ok()?; - Some(Embed { - name: embed.name, - content: content.into(), - }) - }) + .filter_map(|embed| resolve_embed(&repo, embed)) .collect(); patch.comment_edit(revision, comment, body, embeds, &signer)? } @@ -2150,7 +2108,12 @@ mod routes { "type": "comment.edit", "id": ISSUE_DISCUSSION_ID, "body": "EDIT: Change 'hello world' to 'hello anyone'", - "embeds": [] + "embeds": [ + { + "name":"image.jpg", + "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc" + } + ] })) .unwrap(); @@ -2205,7 +2168,12 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "EDIT: Change 'hello world' to 'hello anyone'", - "embeds": [], + "embeds": [ + { + "name": "image.jpg", + "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", + } + ], "reactions": [ [ "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", @@ -2233,6 +2201,12 @@ mod routes { let body = serde_json::to_vec(&json!({ "type": "comment", "body": "This is a reply to the first comment", + "embeds": [ + { + "name": "image.jpg", + "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4//8/AAX+Av4N70a4AAAAAElFTkSuQmCC" + } + ], "replyTo": ISSUE_DISCUSSION_ID, })) .unwrap(); @@ -2286,7 +2260,12 @@ mod routes { "id": CONTRIBUTOR_DID, }, "body": "This is a reply to the first comment", - "embeds": [], + "embeds": [ + { + "name": "image.jpg", + "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", + } + ], "reactions": [], "timestamp": TIMESTAMP, "replyTo": ISSUE_DISCUSSION_ID, @@ -2846,7 +2825,7 @@ mod routes { "embeds": [ { "name": "image.jpg", - "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4//8/AAX+Av4N70a4AAAAAElFTkSuQmCC" + "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", } ], })) @@ -2977,7 +2956,12 @@ mod routes { "type": "review.comment", "review": review_id, "body": "This is a comment on a review", - "embeds": [], + "embeds": [ + { + "name": "image.jpg", + "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4//8/AAX+Av4N70a4AAAAAElFTkSuQmCC" + } + ], "location": { "path": "README.md", "new": { @@ -3003,7 +2987,12 @@ mod routes { "type": "review.comment.edit", "review": review_id, "comment": comment_id, - "embeds": [], + "embeds": [ + { + "name": "image.jpg", + "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", + } + ], "body": "EDIT: This is a comment on a review", })) .unwrap(); @@ -3108,6 +3097,12 @@ mod routes { ], "resolved": true, "body": "EDIT: This is a comment on a review", + "embeds": [ + { + "name": "image.jpg", + "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc", + } + ], }, ]], "timestamp": TIMESTAMP, diff --git a/radicle-httpd/src/test.rs b/radicle-httpd/src/test.rs index 395c7eecf..fe5357f3a 100644 --- a/radicle-httpd/src/test.rs +++ b/radicle-httpd/src/test.rs @@ -36,7 +36,7 @@ pub const INITIAL_COMMIT: &str = "f604ce9fd5b7cc77b7609beda45ea8760bee78f7"; pub const DID: &str = "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"; pub const ISSUE_ID: &str = "4f98396a1ac987af59ec069de9b80d9917b27050"; pub const ISSUE_DISCUSSION_ID: &str = "ceafc6629ec8dc0a17644fb5a66726aaafc3ed1c"; -pub const ISSUE_COMMENT_ID: &str = "59d35e164a21502bc91ad3391ce49baa32ea6a74"; +pub const ISSUE_COMMENT_ID: &str = "ca48480f3de728ffca0861538310c6a9704a73b7"; pub const SESSION_ID: &str = "u9MGAkkfkMOv0uDDB2WeUHBT7HbsO2Dy"; pub const TIMESTAMP: u64 = 1671125284; pub const CONTRIBUTOR_RID: &str = "rad:z4XaCmN3jLSeiMvW15YTDpNbDHFhG";