From c0281dfb1cca2b77c74a180d14859b852a324054 Mon Sep 17 00:00:00 2001 From: "Aode (lion)" Date: Mon, 15 Nov 2021 18:58:15 -0600 Subject: [PATCH] Support mastodon deletes --- crates/apub/src/activities/deletion/delete.rs | 31 ++++++++++++++----- .../src/activities/deletion/undo_delete.rs | 6 ++-- crates/apub/src/activities/mod.rs | 2 +- .../protocol/activities/deletion/delete.rs | 31 +++++++++++++++++-- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index cec8ab9a3..596685ceb 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -8,7 +8,7 @@ use crate::{ }, activity_lists::AnnouncableActivities, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::deletion::delete::Delete, + protocol::activities::deletion::delete::{Delete, ObjectOrTombstone}, }; use activitystreams::{activity::kind::DeleteType, public}; use anyhow::anyhow; @@ -50,11 +50,12 @@ impl ActivityHandler for Delete { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to, &self.cc)?; + let cc = self.cc.as_deref().unwrap_or(&[]); + verify_is_public(&self.to, cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_delete_activity( - &self.object, + self.object.as_url(), &self.actor, &community, self.summary.is_some(), @@ -78,9 +79,23 @@ impl ActivityHandler for Delete { } else { Some(reason) }; - receive_remove_action(&self.actor, &self.object, reason, context, request_counter).await + receive_remove_action( + &self.actor, + self.object.as_url(), + reason, + context, + request_counter, + ) + .await } else { - receive_delete_action(&self.object, &self.actor, true, context, request_counter).await + receive_delete_action( + self.object.as_url(), + &self.actor, + true, + context, + request_counter, + ) + .await } } } @@ -96,8 +111,8 @@ impl Delete { Ok(Delete { actor: ObjectId::new(actor.actor_id()), to: vec![public()], - object: object_id, - cc: vec![community.actor_id()], + object: ObjectOrTombstone::Url(object_id), + cc: Some(vec![community.actor_id()]), kind: DeleteType::Delete, summary, id: generate_activity_id( @@ -201,7 +216,7 @@ impl GetCommunity for Delete { context: &LemmyContext, _request_counter: &mut i32, ) -> Result { - let community_id = match DeletableObjects::read_from_db(&self.object, context).await? { + let community_id = match DeletableObjects::read_from_db(self.object.as_url(), context).await? { DeletableObjects::Community(c) => c.id, DeletableObjects::Comment(c) => { let post = blocking(context.pool(), move |conn| Post::read(conn, c.post_id)).await??; diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index c6e5ddfc0..09e0853c9 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -40,7 +40,7 @@ impl ActivityHandler for UndoDelete { self.object.verify(context, request_counter).await?; let community = self.get_community(context, request_counter).await?; verify_delete_activity( - &self.object.object, + self.object.object.as_url(), &self.actor, &community, self.object.summary.is_some(), @@ -57,10 +57,10 @@ impl ActivityHandler for UndoDelete { request_counter: &mut i32, ) -> Result<(), LemmyError> { if self.object.summary.is_some() { - UndoDelete::receive_undo_remove_action(&self.object.object, context).await + UndoDelete::receive_undo_remove_action(self.object.object.as_url(), context).await } else { receive_delete_action( - &self.object.object, + self.object.object.as_url(), &self.actor, false, context, diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 4d1dc147e..f27a034ef 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -117,7 +117,7 @@ fn verify_add_remove_moderator_target( } pub(crate) fn verify_is_public(to: &[Url], cc: &[Url]) -> Result<(), LemmyError> { - if !to.contains(&public()) && !cc.contains(&public()) { + if ![to, cc].iter().any(|set| set.contains(&public())) { return Err(anyhow!("Object is not public").into()); } Ok(()) diff --git a/crates/apub/src/protocol/activities/deletion/delete.rs b/crates/apub/src/protocol/activities/deletion/delete.rs index 7e2275153..865ae02a7 100644 --- a/crates/apub/src/protocol/activities/deletion/delete.rs +++ b/crates/apub/src/protocol/activities/deletion/delete.rs @@ -1,18 +1,34 @@ use crate::objects::person::ApubPerson; -use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed}; +use activitystreams::{ + activity::kind::DeleteType, + object::kind::TombstoneType, + unparsed::Unparsed, +}; use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use url::Url; +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] +#[serde(rename_all = "camelCase")] +pub enum ObjectOrTombstone { + Url(Url), + Tombstone { + id: Url, + #[serde(rename = "type")] + kind: TombstoneType, + }, +} + #[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Delete { pub(crate) actor: ObjectId, pub(crate) to: Vec, - pub(crate) object: Url, - pub(crate) cc: Vec, + pub(crate) object: ObjectOrTombstone, + pub(crate) cc: Option>, #[serde(rename = "type")] pub(crate) kind: DeleteType, /// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user @@ -22,3 +38,12 @@ pub struct Delete { #[serde(flatten)] pub(crate) unparsed: Unparsed, } + +impl ObjectOrTombstone { + pub fn as_url(&self) -> &Url { + match self { + Self::Url(ref url) => url, + Self::Tombstone { ref id, .. } => id, + } + } +}