X-Git-Url: http://these/git/?a=blobdiff_plain;f=crates%2Fapub%2Fsrc%2Factivities%2Fdeletion%2Fundo_delete.rs;h=541a7455fe376082931f957524c859bcdd357236;hb=e9e76549a88cfbdab36f00d302cceabcaaa24f4c;hp=ea70e5f5e76486a744dd959416ce0281a457d1da;hpb=433ab1e78b9da5c8f75cc9734dd5ce715cf0cc8b;p=lemmy.git diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index ea70e5f5..541a7455 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -1,126 +1,154 @@ use crate::{ activities::{ - comment::send_websocket_message as send_comment_message, - community::send_websocket_message as send_community_message, - deletion::delete::DeletePostCommentOrCommunity, - post::send_websocket_message as send_post_message, - verify_activity, - verify_mod_action, - verify_person_in_community, + deletion::{receive_delete_action, verify_delete_activity, DeletableObjects}, + generate_activity_id, }, - fetcher::{ - community::get_or_fetch_and_upsert_community, - objects::get_or_fetch_and_insert_post_or_comment, - person::get_or_fetch_and_upsert_person, + insert_received_activity, + objects::person::ApubPerson, + protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete}, +}; +use activitypub_federation::{config::Data, kinds::activity::UndoType, traits::ActivityHandler}; +use lemmy_api_common::context::LemmyContext; +use lemmy_db_schema::{ + source::{ + comment::{Comment, CommentUpdateForm}, + community::{Community, CommunityUpdateForm}, + moderator::{ + ModRemoveComment, + ModRemoveCommentForm, + ModRemoveCommunity, + ModRemoveCommunityForm, + ModRemovePost, + ModRemovePostForm, + }, + post::{Post, PostUpdateForm}, }, - CommunityType, - PostOrComment, + traits::Crud, }; -use activitystreams::activity::kind::UndoType; -use lemmy_api_common::blocking; -use lemmy_apub_lib::{values::PublicUrl, verify_urls_match, ActivityCommonFields, ActivityHandler}; -use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_}; -use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post}; -use lemmy_utils::LemmyError; -use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_utils::error::{LemmyError, LemmyErrorType}; use url::Url; -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] -#[serde(rename_all = "camelCase")] -pub struct UndoDeletePostCommentOrCommunity { - to: PublicUrl, - object: DeletePostCommentOrCommunity, - cc: [Url; 1], - #[serde(rename = "type")] - kind: UndoType, - #[serde(flatten)] - common: ActivityCommonFields, -} +#[async_trait::async_trait] +impl ActivityHandler for UndoDelete { + type DataType = LemmyContext; + type Error = LemmyError; -#[async_trait::async_trait(?Send)] -impl ActivityHandler for UndoDeletePostCommentOrCommunity { - async fn verify( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result<(), LemmyError> { - verify_activity(self.common())?; - self.object.verify(context, request_counter).await?; - let object_community = - get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await; - // restoring a community - if object_community.is_ok() { - verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?; - } - // restoring a post or comment - else { - verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter) - .await?; - verify_urls_match(&self.common.actor, &self.object.common().actor)?; - } - Ok(()) + fn id(&self) -> &Url { + &self.id } - async fn receive( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result<(), LemmyError> { - let object_community = - get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await; - // restoring a community - if let Ok(community) = object_community { - if community.local { - // repeat these checks just to be sure - verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter) - .await?; - verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?; - let mod_ = - get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?; - community.send_undo_delete(mod_, context).await?; - } - let deleted_community = blocking(context.pool(), move |conn| { - Community::update_deleted(conn, community.id, false) - }) - .await??; + fn actor(&self) -> &Url { + self.actor.inner() + } - send_community_message( - deleted_community.id, - UserOperationCrud::EditCommunity, + async fn verify(&self, data: &Data) -> Result<(), Self::Error> { + insert_received_activity(&self.id, data).await?; + self.object.verify(data).await?; + verify_delete_activity(&self.object, self.object.summary.is_some(), data).await?; + Ok(()) + } + + #[tracing::instrument(skip_all)] + async fn receive(self, context: &Data) -> Result<(), LemmyError> { + if self.object.summary.is_some() { + UndoDelete::receive_undo_remove_action( + &self.actor.dereference(context).await?, + self.object.object.id(), context, ) .await + } else { + receive_delete_action(self.object.object.id(), &self.actor, false, context).await } - // restoring a post or comment - else { - match get_or_fetch_and_insert_post_or_comment(&self.object.object, context, request_counter) - .await? - { - PostOrComment::Post(post) => { - let deleted_post = blocking(context.pool(), move |conn| { - Post::update_deleted(conn, post.id, false) - }) - .await??; - send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await - } - PostOrComment::Comment(comment) => { - let deleted_comment = blocking(context.pool(), move |conn| { - Comment::update_deleted(conn, comment.id, false) - }) - .await??; - send_comment_message( - deleted_comment.id, - vec![], - UserOperationCrud::EditComment, - context, - ) - .await + } +} + +impl UndoDelete { + #[tracing::instrument(skip_all)] + pub(in crate::activities::deletion) fn new( + actor: &ApubPerson, + object: DeletableObjects, + to: Url, + community: Option<&Community>, + summary: Option, + context: &Data, + ) -> Result { + let object = Delete::new(actor, object, to.clone(), community, summary, context)?; + + let id = generate_activity_id( + UndoType::Undo, + &context.settings().get_protocol_and_hostname(), + )?; + let cc: Option = community.map(|c| c.actor_id.clone().into()); + Ok(UndoDelete { + actor: actor.actor_id.clone().into(), + to: vec![to], + object, + cc: cc.into_iter().collect(), + kind: UndoType::Undo, + id, + audience: community.map(|c| c.actor_id.clone().into()), + }) + } + + #[tracing::instrument(skip_all)] + pub(in crate::activities) async fn receive_undo_remove_action( + actor: &ApubPerson, + object: &Url, + context: &Data, + ) -> Result<(), LemmyError> { + match DeletableObjects::read_from_db(object, context).await? { + DeletableObjects::Community(community) => { + if community.local { + return Err(LemmyErrorType::OnlyLocalAdminCanRestoreCommunity)?; } + let form = ModRemoveCommunityForm { + mod_person_id: actor.id, + community_id: community.id, + removed: Some(false), + reason: None, + expires: None, + }; + ModRemoveCommunity::create(&mut context.pool(), &form).await?; + Community::update( + &mut context.pool(), + community.id, + &CommunityUpdateForm::builder().removed(Some(false)).build(), + ) + .await?; } + DeletableObjects::Post(post) => { + let form = ModRemovePostForm { + mod_person_id: actor.id, + post_id: post.id, + removed: Some(false), + reason: None, + }; + ModRemovePost::create(&mut context.pool(), &form).await?; + Post::update( + &mut context.pool(), + post.id, + &PostUpdateForm::builder().removed(Some(false)).build(), + ) + .await?; + } + DeletableObjects::Comment(comment) => { + let form = ModRemoveCommentForm { + mod_person_id: actor.id, + comment_id: comment.id, + removed: Some(false), + reason: None, + }; + ModRemoveComment::create(&mut context.pool(), &form).await?; + Comment::update( + &mut context.pool(), + comment.id, + &CommentUpdateForm::builder().removed(Some(false)).build(), + ) + .await?; + } + DeletableObjects::PrivateMessage(_) => unimplemented!(), } - } - - fn common(&self) -> &ActivityCommonFields { - &self.common + Ok(()) } }