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 <me@sebastinez.dev>
This commit is contained in:
Sebastian Martinez 2023-10-20 15:56:57 +02:00 committed by cloudhead
parent 1811c7b8bb
commit 15cf5c6100
No known key found for this signature in database
3 changed files with 72 additions and 59 deletions

View File

@ -15,11 +15,11 @@ use serde_json::json;
use tokio::sync::RwLock; use tokio::sync::RwLock;
use tower_http::cors::{self, CorsLayer}; use tower_http::cors::{self, CorsLayer};
use radicle::cob::patch;
use radicle::cob::{issue, Uri}; use radicle::cob::{issue, Uri};
use radicle::cob::{patch, Embed};
use radicle::identity::{DocAt, Id}; use radicle::identity::{DocAt, Id};
use radicle::node::routing::Store; use radicle::node::routing::Store;
use radicle::storage::{ReadRepository, ReadStorage}; use radicle::storage::{Oid, ReadRepository, ReadStorage};
use radicle::Profile; use radicle::Profile;
mod error; mod error;
@ -228,3 +228,21 @@ impl TryFrom<&Uri> for DataUri {
Err(value.clone()) Err(value.clone())
} }
} }
/// Resolve an embed with a URI to one with actual data.
pub fn resolve_embed(repo: &impl ReadRepository, embed: Embed<Uri>) -> Option<Embed<Vec<u8>>> {
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(),
})
})
})
}

View File

@ -24,7 +24,7 @@ use radicle_surf::{diff, Glob, Oid, Repository};
use crate::api::error::Error; use crate::api::error::Error;
use crate::api::project::Info; 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}; use crate::axum_extra::{Path, Query};
const CACHE_1_HOUR: &str = "public, max-age=3600, must-revalidate"; const CACHE_1_HOUR: &str = "public, max-age=3600, must-revalidate";
@ -647,13 +647,7 @@ async fn issue_create_handler(
let embeds: Vec<Embed> = issue let embeds: Vec<Embed> = issue
.embeds .embeds
.into_iter() .into_iter()
.filter_map(|embed| { .filter_map(|embed| resolve_embed(&repo, embed))
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect(); .collect();
let mut issues = issue::Issues::open(&repo)?; let mut issues = issue::Issues::open(&repo)?;
@ -702,13 +696,7 @@ async fn issue_update_handler(
} => { } => {
let embeds: Vec<Embed> = embeds let embeds: Vec<Embed> = embeds
.into_iter() .into_iter()
.filter_map(|embed| { .filter_map(|embed| resolve_embed(&repo, embed))
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect(); .collect();
if let Some(to) = reply_to { if let Some(to) = reply_to {
issue.comment(body, to, embeds, &signer)? issue.comment(body, to, embeds, &signer)?
@ -724,13 +712,7 @@ async fn issue_update_handler(
issue::Action::CommentEdit { id, body, embeds } => { issue::Action::CommentEdit { id, body, embeds } => {
let embeds: Vec<Embed> = embeds let embeds: Vec<Embed> = embeds
.into_iter() .into_iter()
.filter_map(|embed| { .filter_map(|embed| resolve_embed(&repo, embed))
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect(); .collect();
issue.edit_comment(id, body, embeds, &signer)? issue.edit_comment(id, body, embeds, &signer)?
} }
@ -847,13 +829,7 @@ async fn patch_update_handler(
} => { } => {
let embeds: Vec<Embed> = embeds let embeds: Vec<Embed> = embeds
.into_iter() .into_iter()
.filter_map(|embed| { .filter_map(|embed| resolve_embed(&repo, embed))
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect(); .collect();
patch.review_comment(review, body, location, reply_to, embeds, &signer)? patch.review_comment(review, body, location, reply_to, embeds, &signer)?
} }
@ -865,13 +841,7 @@ async fn patch_update_handler(
} => { } => {
let embeds: Vec<Embed> = embeds let embeds: Vec<Embed> = embeds
.into_iter() .into_iter()
.filter_map(|embed| { .filter_map(|embed| resolve_embed(&repo, embed))
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect(); .collect();
patch.edit_review_comment(review, comment, body, embeds, &signer)? patch.edit_review_comment(review, comment, body, embeds, &signer)?
} }
@ -910,13 +880,7 @@ async fn patch_update_handler(
} => { } => {
let embeds: Vec<Embed> = embeds let embeds: Vec<Embed> = embeds
.into_iter() .into_iter()
.filter_map(|embed| { .filter_map(|embed| resolve_embed(&repo, embed))
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect(); .collect();
patch.comment(revision, body, reply_to, location, embeds, &signer)? patch.comment(revision, body, reply_to, location, embeds, &signer)?
} }
@ -928,13 +892,7 @@ async fn patch_update_handler(
} => { } => {
let embeds: Vec<Embed> = embeds let embeds: Vec<Embed> = embeds
.into_iter() .into_iter()
.filter_map(|embed| { .filter_map(|embed| resolve_embed(&repo, embed))
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect(); .collect();
patch.comment_edit(revision, comment, body, embeds, &signer)? patch.comment_edit(revision, comment, body, embeds, &signer)?
} }
@ -2150,7 +2108,12 @@ mod routes {
"type": "comment.edit", "type": "comment.edit",
"id": ISSUE_DISCUSSION_ID, "id": ISSUE_DISCUSSION_ID,
"body": "EDIT: Change 'hello world' to 'hello anyone'", "body": "EDIT: Change 'hello world' to 'hello anyone'",
"embeds": [] "embeds": [
{
"name":"image.jpg",
"content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc"
}
]
})) }))
.unwrap(); .unwrap();
@ -2205,7 +2168,12 @@ mod routes {
"id": CONTRIBUTOR_DID, "id": CONTRIBUTOR_DID,
}, },
"body": "EDIT: Change 'hello world' to 'hello anyone'", "body": "EDIT: Change 'hello world' to 'hello anyone'",
"embeds": [], "embeds": [
{
"name": "image.jpg",
"content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc",
}
],
"reactions": [ "reactions": [
[ [
"z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8", "z6Mkk7oqY4pPxhMmGEotDYsFo97vhCj85BLY1H256HrJmjN8",
@ -2233,6 +2201,12 @@ mod routes {
let body = serde_json::to_vec(&json!({ let body = serde_json::to_vec(&json!({
"type": "comment", "type": "comment",
"body": "This is a reply to the first 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, "replyTo": ISSUE_DISCUSSION_ID,
})) }))
.unwrap(); .unwrap();
@ -2286,7 +2260,12 @@ mod routes {
"id": CONTRIBUTOR_DID, "id": CONTRIBUTOR_DID,
}, },
"body": "This is a reply to the first comment", "body": "This is a reply to the first comment",
"embeds": [], "embeds": [
{
"name": "image.jpg",
"content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc",
}
],
"reactions": [], "reactions": [],
"timestamp": TIMESTAMP, "timestamp": TIMESTAMP,
"replyTo": ISSUE_DISCUSSION_ID, "replyTo": ISSUE_DISCUSSION_ID,
@ -2846,7 +2825,7 @@ mod routes {
"embeds": [ "embeds": [
{ {
"name": "image.jpg", "name": "image.jpg",
"content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4//8/AAX+Av4N70a4AAAAAElFTkSuQmCC" "content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc",
} }
], ],
})) }))
@ -2977,7 +2956,12 @@ mod routes {
"type": "review.comment", "type": "review.comment",
"review": review_id, "review": review_id,
"body": "This is a comment on a review", "body": "This is a comment on a review",
"embeds": [], "embeds": [
{
"name": "image.jpg",
"content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4//8/AAX+Av4N70a4AAAAAElFTkSuQmCC"
}
],
"location": { "location": {
"path": "README.md", "path": "README.md",
"new": { "new": {
@ -3003,7 +2987,12 @@ mod routes {
"type": "review.comment.edit", "type": "review.comment.edit",
"review": review_id, "review": review_id,
"comment": comment_id, "comment": comment_id,
"embeds": [], "embeds": [
{
"name": "image.jpg",
"content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc",
}
],
"body": "EDIT: This is a comment on a review", "body": "EDIT: This is a comment on a review",
})) }))
.unwrap(); .unwrap();
@ -3108,6 +3097,12 @@ mod routes {
], ],
"resolved": true, "resolved": true,
"body": "EDIT: This is a comment on a review", "body": "EDIT: This is a comment on a review",
"embeds": [
{
"name": "image.jpg",
"content": "git:94381b429d7f7fe87e1bade52d893ab348ae29cc",
}
],
}, },
]], ]],
"timestamp": TIMESTAMP, "timestamp": TIMESTAMP,

View File

@ -36,7 +36,7 @@ pub const INITIAL_COMMIT: &str = "f604ce9fd5b7cc77b7609beda45ea8760bee78f7";
pub const DID: &str = "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"; pub const DID: &str = "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi";
pub const ISSUE_ID: &str = "4f98396a1ac987af59ec069de9b80d9917b27050"; pub const ISSUE_ID: &str = "4f98396a1ac987af59ec069de9b80d9917b27050";
pub const ISSUE_DISCUSSION_ID: &str = "ceafc6629ec8dc0a17644fb5a66726aaafc3ed1c"; 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 SESSION_ID: &str = "u9MGAkkfkMOv0uDDB2WeUHBT7HbsO2Dy";
pub const TIMESTAMP: u64 = 1671125284; pub const TIMESTAMP: u64 = 1671125284;
pub const CONTRIBUTOR_RID: &str = "rad:z4XaCmN3jLSeiMvW15YTDpNbDHFhG"; pub const CONTRIBUTOR_RID: &str = "rad:z4XaCmN3jLSeiMvW15YTDpNbDHFhG";