Migrate comment inReplyTo field to single value (ref #1454)

This commit is contained in:
Felix Ableitner 2021-08-05 13:00:29 +02:00
parent 7b8cbbba85
commit b2937223df
3 changed files with 71 additions and 23 deletions

View file

@ -6,6 +6,7 @@ pub mod activity_queue;
pub mod extensions; pub mod extensions;
pub mod fetcher; pub mod fetcher;
pub mod http; pub mod http;
pub mod migrations;
pub mod objects; pub mod objects;
use crate::{ use crate::{

View file

@ -0,0 +1,17 @@
use serde::{Deserialize, Serialize};
use url::Url;
/// Migrate comment.in_reply_to field from containing post and parent comment ID, to only containing
/// the direct parent (whether its a post or comment). This is for compatibility with Pleroma and
/// Smithereen.
/// [https://github.com/LemmyNet/lemmy/issues/1454]
///
/// v0.12: receive both, send old (compatible with v0.11)
/// v0.13 receive both, send new (compatible with v0.12+, incompatible with v0.11)
/// v0.14: only send and receive new, remove migration (compatible with v0.13+)
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum CommentInReplyToMigration {
Old(Vec<Url>),
New(Url),
}

View file

@ -1,9 +1,15 @@
use crate::{ use crate::{
activities::verify_person_in_community, activities::verify_person_in_community,
extensions::context::lemmy_context, extensions::context::lemmy_context,
fetcher::objects::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post}, fetcher::objects::{
get_or_fetch_and_insert_comment,
get_or_fetch_and_insert_post,
get_or_fetch_and_insert_post_or_comment,
},
migrations::CommentInReplyToMigration,
objects::{create_tombstone, get_or_fetch_and_upsert_person, FromApub, Source, ToApub}, objects::{create_tombstone, get_or_fetch_and_upsert_person, FromApub, Source, ToApub},
ActorType, ActorType,
PostOrComment,
}; };
use activitystreams::{ use activitystreams::{
base::AnyBase, base::AnyBase,
@ -35,6 +41,7 @@ use lemmy_utils::{
}; };
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::ops::Deref;
use url::Url; use url::Url;
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
@ -52,7 +59,7 @@ pub struct Note {
content: String, content: String,
media_type: MediaTypeHtml, media_type: MediaTypeHtml,
source: Source, source: Source,
in_reply_to: Vec<Url>, in_reply_to: CommentInReplyToMigration,
published: DateTime<FixedOffset>, published: DateTime<FixedOffset>,
updated: Option<DateTime<FixedOffset>>, updated: Option<DateTime<FixedOffset>>,
#[serde(flatten)] #[serde(flatten)]
@ -65,8 +72,10 @@ impl Note {
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(Post, Option<CommentId>), LemmyError> { ) -> Result<(Post, Option<CommentId>), LemmyError> {
match &self.in_reply_to {
CommentInReplyToMigration::Old(in_reply_to) => {
// This post, or the parent comment might not yet exist on this server yet, fetch them. // This post, or the parent comment might not yet exist on this server yet, fetch them.
let post_id = self.in_reply_to.get(0).context(location_info!())?; let post_id = in_reply_to.get(0).context(location_info!())?;
let post = Box::pin(get_or_fetch_and_insert_post( let post = Box::pin(get_or_fetch_and_insert_post(
post_id, post_id,
context, context,
@ -76,7 +85,7 @@ impl Note {
// The 2nd item, if it exists, is the parent comment apub_id // The 2nd item, if it exists, is the parent comment apub_id
// Nested comments will automatically get fetched recursively // Nested comments will automatically get fetched recursively
let parent_id: Option<CommentId> = match self.in_reply_to.get(1) { let parent_id: Option<CommentId> = match in_reply_to.get(1) {
Some(parent_comment_uri) => { Some(parent_comment_uri) => {
let parent_comment = Box::pin(get_or_fetch_and_insert_comment( let parent_comment = Box::pin(get_or_fetch_and_insert_comment(
parent_comment_uri, parent_comment_uri,
@ -92,6 +101,27 @@ impl Note {
Ok((post, parent_id)) Ok((post, parent_id))
} }
CommentInReplyToMigration::New(in_reply_to) => {
let parent = Box::pin(
get_or_fetch_and_insert_post_or_comment(in_reply_to, context, request_counter).await?,
);
match parent.deref() {
PostOrComment::Post(p) => {
// Workaround because I cant figure ut how to get the post out of the box (and we dont
// want to stackoverflow in a deep comment hierarchy).
let post_id = p.id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
Ok((post, None))
}
PostOrComment::Comment(c) => {
let post_id = c.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
Ok((post, Some(c.id)))
}
}
}
}
}
pub(crate) async fn verify( pub(crate) async fn verify(
&self, &self,
@ -153,7 +183,7 @@ impl ToApub for Comment {
content: self.content.clone(), content: self.content.clone(),
media_type: MediaTypeMarkdown::Markdown, media_type: MediaTypeMarkdown::Markdown,
}, },
in_reply_to: in_reply_to_vec, in_reply_to: CommentInReplyToMigration::Old(in_reply_to_vec),
published: convert_datetime(self.published), published: convert_datetime(self.published),
updated: self.updated.map(convert_datetime), updated: self.updated.map(convert_datetime),
unparsed: Default::default(), unparsed: Default::default(),