From 9a7b1e7d2c8e1976a20365dd8f4d6e4acc7a68d7 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Thu, 14 Oct 2021 17:36:27 +0200 Subject: [PATCH] Federate reports --- crates/api/src/comment_report.rs | 10 ++ crates/api/src/post_report.rs | 10 ++ crates/apub/src/activities/mod.rs | 1 + crates/apub/src/activities/report.rs | 168 +++++++++++++++++++++++++++ crates/apub/src/http/community.rs | 2 + 5 files changed, 191 insertions(+) create mode 100644 crates/apub/src/activities/report.rs diff --git a/crates/api/src/comment_report.rs b/crates/api/src/comment_report.rs index 67bc42acc..de7b00f86 100644 --- a/crates/api/src/comment_report.rs +++ b/crates/api/src/comment_report.rs @@ -7,6 +7,7 @@ use lemmy_api_common::{ get_local_user_view_from_jwt, is_mod_or_admin, }; +use lemmy_apub::{activities::report::Report, fetcher::object_id::ObjectId}; use lemmy_db_queries::Reportable; use lemmy_db_schema::source::comment_report::*; use lemmy_db_views::{ @@ -77,6 +78,15 @@ impl Perform for CreateCommentReport { websocket_id, }); + Report::send( + ObjectId::new(comment_view.comment.ap_id), + &local_user_view.person, + comment_view.community.id, + reason.to_string(), + context, + ) + .await?; + Ok(res) } } diff --git a/crates/api/src/post_report.rs b/crates/api/src/post_report.rs index 8f5c72afa..e6ce3c8c6 100644 --- a/crates/api/src/post_report.rs +++ b/crates/api/src/post_report.rs @@ -13,6 +13,7 @@ use lemmy_api_common::{ ResolvePostReport, }, }; +use lemmy_apub::{activities::report::Report, fetcher::object_id::ObjectId}; use lemmy_db_queries::Reportable; use lemmy_db_schema::source::post_report::{PostReport, PostReportForm}; use lemmy_db_views::{ @@ -83,6 +84,15 @@ impl Perform for CreatePostReport { websocket_id, }); + Report::send( + ObjectId::new(post_view.post.ap_id), + &local_user_view.person, + post_view.community.id, + reason.to_string(), + context, + ) + .await?; + Ok(res) } } diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 5c775f801..dca36d9ae 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -22,6 +22,7 @@ pub mod deletion; pub mod following; pub mod post; pub mod private_message; +pub mod report; pub mod undo_remove; pub mod voting; diff --git a/crates/apub/src/activities/report.rs b/crates/apub/src/activities/report.rs new file mode 100644 index 000000000..13d9735d7 --- /dev/null +++ b/crates/apub/src/activities/report.rs @@ -0,0 +1,168 @@ +use crate::{ + activities::{generate_activity_id, verify_activity, verify_person_in_community}, + context::lemmy_context, + fetcher::object_id::ObjectId, + send_lemmy_activity, + PostOrComment, +}; +use activitystreams::{ + activity::kind::FlagType, + base::AnyBase, + primitives::OneOrMany, + unparsed::Unparsed, +}; +use lemmy_api_common::{blocking, comment::CommentReportResponse, post::PostReportResponse}; +use lemmy_apub_lib::{ + data::Data, + traits::{ActivityFields, ActivityHandler, ActorType}, +}; +use lemmy_db_queries::{Crud, Reportable}; +use lemmy_db_schema::{ + source::{ + comment_report::{CommentReport, CommentReportForm}, + community::Community, + person::Person, + post_report::{PostReport, PostReportForm}, + }, + CommunityId, +}; +use lemmy_db_views::{comment_report_view::CommentReportView, post_report_view::PostReportView}; +use lemmy_utils::LemmyError; +use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation}; +use serde::{Deserialize, Serialize}; +use url::Url; + +#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[serde(rename_all = "camelCase")] +pub struct Report { + actor: ObjectId, + to: [ObjectId; 1], + object: ObjectId, + summary: String, + #[serde(rename = "type")] + kind: FlagType, + id: Url, + #[serde(rename = "@context")] + context: OneOrMany, + #[serde(flatten)] + unparsed: Unparsed, +} + +impl Report { + pub async fn send( + object_id: ObjectId, + actor: &Person, + community_id: CommunityId, + reason: String, + context: &LemmyContext, + ) -> Result<(), LemmyError> { + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; + let kind = FlagType::Flag; + let id = generate_activity_id( + kind.clone(), + &context.settings().get_protocol_and_hostname(), + )?; + let report = Report { + actor: ObjectId::new(actor.actor_id()), + to: [ObjectId::new(community.actor_id())], + object: object_id, + summary: reason, + kind, + id: id.clone(), + context: lemmy_context(), + unparsed: Default::default(), + }; + send_lemmy_activity( + context, + &report, + &id, + actor, + vec![community.shared_inbox_or_inbox_url()], + false, + ) + .await + } +} + +#[async_trait::async_trait(?Send)] +impl ActivityHandler for Report { + type DataType = LemmyContext; + async fn verify( + &self, + context: &Data, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + verify_activity(self, &context.settings())?; + verify_person_in_community(&self.actor, &self.to[0], context, request_counter).await?; + Ok(()) + } + + async fn receive( + self, + context: &Data, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + let actor = self.actor.dereference(context, request_counter).await?; + match self.object.dereference(context, request_counter).await? { + PostOrComment::Post(post) => { + let report_form = PostReportForm { + creator_id: actor.id, + post_id: post.id, + original_post_name: post.name, + original_post_url: post.url, + reason: self.summary, + original_post_body: None, + }; + + let report = blocking(context.pool(), move |conn| { + PostReport::report(conn, &report_form) + }) + .await??; + + let post_report_view = blocking(context.pool(), move |conn| { + PostReportView::read(conn, report.id, actor.id) + }) + .await??; + + context.chat_server().do_send(SendModRoomMessage { + op: UserOperation::CreateCommentReport, + response: PostReportResponse { post_report_view }, + community_id: post.community_id, + websocket_id: None, + }); + } + PostOrComment::Comment(comment) => { + let report_form = CommentReportForm { + creator_id: actor.id, + comment_id: comment.id, + original_comment_text: comment.content, + reason: self.summary, + }; + + let report = blocking(context.pool(), move |conn| { + CommentReport::report(conn, &report_form) + }) + .await??; + + let comment_report_view = blocking(context.pool(), move |conn| { + CommentReportView::read(conn, report.id, actor.id) + }) + .await??; + let community_id = comment_report_view.community.id; + + context.chat_server().do_send(SendModRoomMessage { + op: UserOperation::CreateCommentReport, + response: CommentReportResponse { + comment_report_view, + }, + community_id, + websocket_id: None, + }); + } + }; + Ok(()) + } +} diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index 119dfe263..3f74b622a 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -3,6 +3,7 @@ use crate::{ community::announce::{AnnouncableActivities, AnnounceActivity}, extract_community, following::{follow::FollowCommunity, undo::UndoFollowCommunity}, + report::Report, }, context::lemmy_context, generate_moderators_url, @@ -65,6 +66,7 @@ pub enum GroupInboxActivities { FollowCommunity(FollowCommunity), UndoFollowCommunity(UndoFollowCommunity), AnnouncableActivities(AnnouncableActivities), + Report(Report), } /// Handler for all incoming receive to community inboxes.