Added federation test for pleroma comment

pleroma-federation2
Felix Ableitner 2021-10-20 17:26:39 +02:00
parent 60b472e3f0
commit 153ec0d7aa
6 changed files with 106 additions and 27 deletions

View File

@ -21,7 +21,7 @@
"type": "Note",
"id": "https://lemmy.ml/comment/38741",
"attributedTo": "https://lemmy.ml/u/nutomic",
"to": "https://www.w3.org/ns/activitystreams#Public",
"to": ["https://www.w3.org/ns/activitystreams#Public"],
"content": "While I very much get and respect the general sentiment, I think from the perspective of a Central European non-English person in a country with a significant number of, also non-English speaking Nazis, the current approach of filtering slurs based on an English regex is fatally flawed. You can happily use Lemmy to create a hostile far right community where everyone is easily able to use whatever hurtful slurs they want as long as they are not the few specifically blocked English ones. \n\nOn the other hand you create a situation where people feel the need to question the choice of software of their community because they read about censorship or whatever to be used in Lemmy and might stay away and move to other software even though the would maybe never be affected by the slur-filter as the number is not so large and the overlap with other languages not very big.\n\nSo I would argue that this specific implementation of a slur-filter just doesn't achieve what it aims to achieve and should be fundamentally rethought, maybe as configurable per instance.",
"mediaType": "text/html",
"source": {

View File

@ -0,0 +1,36 @@
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://queer.hacktivis.me/schemas/litepub-0.1.jsonld",
{
"@language": "und"
}
],
"actor": "https://queer.hacktivis.me/users/lanodan",
"attachment": [],
"attributedTo": "https://queer.hacktivis.me/users/lanodan",
"cc": [
"https://www.w3.org/ns/activitystreams#Public"
],
"content": "<span class=\"h-card\"><a class=\"u-url mention\" data-user=\"9zkUX4o3WxGM8vGPfU\" href=\"https://pleroma.popolon.org/users/popolon\" rel=\"ugc\">@<span>popolon</span></a></span> Have what?",
"context": "https://queer.hacktivis.me/contexts/34cba3d2-2f35-4169-aeff-56af9bfeb753",
"conversation": "https://queer.hacktivis.me/contexts/34cba3d2-2f35-4169-aeff-56af9bfeb753",
"id": "https://queer.hacktivis.me/objects/8d4973f4-53de-49cd-8c27-df160e16a9c2",
"inReplyTo": "https://lemmy.ml/post/55143",
"published": "2021-10-07T18:06:52.555500Z",
"sensitive": null,
"source": "@popolon@pleroma.popolon.org Have what?",
"summary": "",
"tag": [
{
"href": "https://pleroma.popolon.org/users/popolon",
"name": "@popolon@pleroma.popolon.org",
"type": "Mention"
}
],
"to": [
"https://pleroma.popolon.org/users/popolon",
"https://queer.hacktivis.me/users/lanodan/followers"
],
"type": "Note"
}

View File

@ -5,6 +5,7 @@ use crate::{
generate_moderators_url,
objects::{community::ApubCommunity, person::ApubPerson},
};
use activitystreams::public;
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{traits::ActivityFields, verify::verify_domains_match};
@ -136,6 +137,13 @@ fn verify_add_remove_moderator_target(
Ok(())
}
pub(crate) fn verify_is_public(to: &[Url]) -> Result<(), LemmyError> {
if !to.contains(&public()) {
return Err(anyhow!("Object is not public").into());
}
Ok(())
}
pub(crate) fn check_community_deleted_or_removed(community: &Community) -> Result<(), LemmyError> {
if community.deleted || community.removed {
Err(anyhow!("New post or comment cannot be created in deleted or removed community").into())

View File

@ -1,5 +1,5 @@
use crate::{
activities::verify_person_in_community,
activities::{verify_is_public, verify_person_in_community},
context::lemmy_context,
fetcher::object_id::ObjectId,
migrations::CommentInReplyToMigration,
@ -11,6 +11,7 @@ use activitystreams::{
chrono::NaiveDateTime,
object::{kind::NoteType, Tombstone},
primitives::OneOrMany,
public,
unparsed::Unparsed,
};
use anyhow::{anyhow, Context};
@ -18,7 +19,7 @@ use chrono::{DateTime, FixedOffset};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
traits::{ApubObject, FromApub, ToApub},
values::{MediaTypeHtml, MediaTypeMarkdown, PublicUrl},
values::{MediaTypeHtml, MediaTypeMarkdown},
verify::verify_domains_match,
};
use lemmy_db_schema::{
@ -55,10 +56,10 @@ pub struct Note {
/// Indicates that the object is publicly readable. Unlike [`Post.to`], this one doesn't contain
/// the community ID, as it would be incompatible with Pleroma (and we can get the community from
/// the post in [`in_reply_to`]).
to: PublicUrl,
to: Vec<Url>,
content: String,
media_type: MediaTypeHtml,
source: Source,
media_type: Option<MediaTypeHtml>,
source: SourceCompat,
in_reply_to: CommentInReplyToMigration,
published: Option<DateTime<FixedOffset>>,
updated: Option<DateTime<FixedOffset>>,
@ -66,6 +67,15 @@ pub struct Note {
unparsed: Unparsed,
}
/// Pleroma puts a raw string in the source, so we have to handle it here for deserialization to work
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
enum SourceCompat {
Lemmy(Source),
Pleroma(String),
}
impl Note {
pub(crate) fn id_unchecked(&self) -> &Url {
&self.id
@ -80,10 +90,8 @@ impl Note {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(ApubPost, Option<CommentId>), LemmyError> {
dbg!(10);
match &self.in_reply_to {
CommentInReplyToMigration::Old(in_reply_to) => {
dbg!(11);
// This post, or the parent comment might not yet exist on this server yet, fetch them.
let post_id = in_reply_to.get(0).context(location_info!())?;
let post_id = ObjectId::new(post_id.clone());
@ -91,7 +99,6 @@ impl Note {
// The 2nd item, if it exists, is the parent comment apub_id
// Nested comments will automatically get fetched recursively
dbg!(12);
let parent_id: Option<CommentId> = match in_reply_to.get(1) {
Some(comment_id) => {
let comment_id = ObjectId::<ApubComment>::new(comment_id.clone());
@ -101,16 +108,13 @@ impl Note {
}
None => None,
};
dbg!(13);
Ok((post, parent_id))
}
CommentInReplyToMigration::New(in_reply_to) => {
dbg!(14);
let parent = Box::pin(in_reply_to.dereference(context, request_counter).await?);
match parent.deref() {
PostOrComment::Post(p) => {
dbg!(15);
// Workaround because I cant figure out 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;
@ -118,7 +122,6 @@ impl Note {
Ok((post.into(), None))
}
PostOrComment::Comment(c) => {
dbg!(16);
let post_id = c.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
Ok((post.into(), Some(c.id)))
@ -151,6 +154,7 @@ impl Note {
request_counter,
)
.await?;
verify_is_public(&self.to)?;
Ok(())
}
}
@ -229,13 +233,13 @@ impl ToApub for ApubComment {
r#type: NoteType::Note,
id: self.ap_id.to_owned().into_inner(),
attributed_to: ObjectId::new(creator.actor_id),
to: PublicUrl::Public,
to: vec![public()],
content: self.content.clone(),
media_type: MediaTypeHtml::Html,
source: Source {
media_type: Some(MediaTypeHtml::Html),
source: SourceCompat::Lemmy(Source {
content: self.content.clone(),
media_type: MediaTypeMarkdown::Markdown,
},
}),
in_reply_to: CommentInReplyToMigration::Old(in_reply_to_vec),
published: Some(convert_datetime(self.published)),
updated: self.updated.map(convert_datetime),
@ -269,23 +273,24 @@ impl FromApub for ApubComment {
expected_domain: &Url,
request_counter: &mut i32,
) -> Result<ApubComment, LemmyError> {
dbg!(1);
let ap_id = Some(note.id(expected_domain)?.clone().into());
let creator = note
.attributed_to
.dereference(context, request_counter)
.await?;
dbg!(2);
let (post, parent_comment_id) = note.get_parents(context, request_counter).await?;
dbg!(2.5);
if post.locked {
return Err(anyhow!("Post is locked").into());
}
let content = &note.source.content;
let content = if let SourceCompat::Lemmy(source) = &note.source {
&source.content
} else {
// TODO: convert from html to markdown
&note.content
};
let content_slurs_removed = remove_slurs(content, &context.settings().slur_regex());
dbg!(3);
let form = CommentForm {
creator_id: creator.id,
post_id: post.id,
@ -300,7 +305,6 @@ impl FromApub for ApubComment {
local: Some(false),
};
let comment = blocking(context.pool(), move |conn| Comment::upsert(conn, &form)).await??;
dbg!(4);
Ok(comment.into())
}
}
@ -347,4 +351,30 @@ mod tests {
assert!(!comment.local);
assert_eq!(request_counter, 0);
}
#[actix_rt::test]
#[serial]
async fn test_fetch_pleroma_comment() {
let context = init_context();
let url = Url::parse("https://lemmy.ml/comment/38741").unwrap();
prepare_comment_test(&url, &context).await;
let pleroma_url =
Url::parse("https://queer.hacktivis.me/objects/8d4973f4-53de-49cd-8c27-df160e16a9c2")
.unwrap();
let person_json = file_to_json_object("assets/pleroma-person.json");
ApubPerson::from_apub(&person_json, &context, &pleroma_url, &mut 0)
.await
.unwrap();
let json = file_to_json_object("assets/pleroma-comment.json");
let mut request_counter = 0;
let comment = ApubComment::from_apub(&json, &context, &pleroma_url, &mut request_counter)
.await
.unwrap();
assert_eq!(comment.ap_id.clone().into_inner(), pleroma_url);
assert_eq!(comment.content.len(), 179);
assert!(!comment.local);
assert_eq!(request_counter, 0);
}
}

View File

@ -1,5 +1,5 @@
use crate::{
activities::{extract_community, verify_person_in_community},
activities::{extract_community, verify_is_public, verify_person_in_community},
context::lemmy_context,
fetcher::object_id::ObjectId,
objects::{create_tombstone, person::ApubPerson, ImageObject, Source},
@ -51,7 +51,7 @@ pub struct Page {
r#type: PageType,
id: Url,
pub(crate) attributed_to: ObjectId<ApubPerson>,
to: [Url; 2],
to: Vec<Url>,
name: String,
content: Option<String>,
media_type: Option<MediaTypeHtml>,
@ -109,6 +109,7 @@ impl Page {
request_counter,
)
.await?;
verify_is_public(&self.to.clone())?;
Ok(())
}
}
@ -186,7 +187,7 @@ impl ToApub for ApubPost {
r#type: PageType::Page,
id: self.ap_id.clone().into(),
attributed_to: ObjectId::new(creator.actor_id),
to: [community.actor_id.into(), public()],
to: vec![community.actor_id.into(), public()],
name: self.name.clone(),
content: self.body.as_ref().map(|b| markdown_to_html(b)),
media_type: Some(MediaTypeHtml::Html),

View File

@ -15,6 +15,10 @@ curl -H "Accept: application/activity+json" https://lemmy.ml/comment/38741 | jq
# replace attributed_to user, so that it takes the same one from above
sed -i 's/https:\/\/lemmy.ml\/u\/my_test/https:\/\/lemmy.ml\/u\/nutomic/g' crates/apub/assets/lemmy-comment.json
curl -H "Accept: application/activity+json" https://queer.hacktivis.me/users/lanodan | jq \
> crates/apub/assets/pleroma-person.json
curl -H "Accept: application/activity+json" https://queer.hacktivis.me/objects/8d4973f4-53de-49cd-8c27-df160e16a9c2 | jq \
> crates/apub/assets/pleroma-comment.json
# rewrite comment inReplyTo so that it refers to our post above (cause lemmy doesnt support standalone comments)
sed -i 's/https:\/\/pleroma.popolon.org\/objects\/bf84a0fb-2ec2-4dff-a1d9-6b573f94fb16/https:\/\/lemmy.ml\/post\/55143/g' crates/apub/assets/pleroma-comment.json