Rewrite delete activities

This commit is contained in:
Felix Ableitner 2021-08-12 22:24:36 +02:00
parent e65897a350
commit bc6294a834
16 changed files with 501 additions and 721 deletions

View file

@ -8,9 +8,9 @@ use lemmy_api_common::{
is_mod_or_admin,
send_local_notifs,
};
use lemmy_apub::ApubObjectType;
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
use lemmy_db_queries::{source::comment::Comment_, Crud, DeleteableOrRemoveable};
use lemmy_db_schema::source::{comment::*, moderator::*};
use lemmy_db_schema::source::{comment::*, community::Community, moderator::*};
use lemmy_db_views::comment_view::CommentView;
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperationCrud};
@ -47,23 +47,25 @@ impl PerformCrud for DeleteComment {
// Do the delete
let deleted = data.deleted;
let mut updated_comment = blocking(context.pool(), move |conn| {
let updated_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment_id, deleted)
})
.await?
.map_err(|_| ApiError::err("couldnt_update_comment"))?;
// Send the apub message
if deleted {
updated_comment = updated_comment.blank_out_deleted_or_removed_info();
updated_comment
.send_delete(&local_user_view.person, context)
.await?;
} else {
updated_comment
.send_undo_delete(&local_user_view.person, context)
.await?;
}
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_comment.post.community_id)
})
.await??;
send_apub_delete(
&local_user_view.person,
&community,
updated_comment.ap_id.clone().into(),
deleted,
context,
)
.await?;
// Refetch it
let comment_id = data.comment_id;
@ -142,7 +144,7 @@ impl PerformCrud for RemoveComment {
// Do the remove
let removed = data.removed;
let mut updated_comment = blocking(context.pool(), move |conn| {
let updated_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment_id, removed)
})
.await?
@ -161,16 +163,19 @@ impl PerformCrud for RemoveComment {
.await??;
// Send the apub message
if removed {
updated_comment = updated_comment.blank_out_deleted_or_removed_info();
updated_comment
.send_remove(&local_user_view.person, context)
.await?;
} else {
updated_comment
.send_undo_remove(&local_user_view.person, context)
.await?;
}
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_comment.post.community_id)
})
.await??;
send_apub_remove(
&local_user_view.person,
&community,
updated_comment.ap_id.clone().into(),
data.reason.clone().unwrap_or_else(|| "".to_string()),
removed,
context,
)
.await?;
// Refetch it
let comment_id = data.comment_id;

View file

@ -1,7 +1,7 @@
use crate::{community::send_community_websocket, PerformCrud};
use actix_web::web::Data;
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt, is_admin};
use lemmy_apub::CommunityType;
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
use lemmy_db_queries::{source::community::Community_, Crud, DeleteableOrRemoveable};
use lemmy_db_schema::source::{
community::*,
@ -48,16 +48,14 @@ impl PerformCrud for DeleteCommunity {
.map_err(|_| ApiError::err("couldnt_update_community"))?;
// Send apub messages
if deleted {
updated_community
.blank_out_deleted_or_removed_info()
.send_delete(local_user_view.person.to_owned(), context)
.await?;
} else {
updated_community
.send_undo_delete(local_user_view.person.to_owned(), context)
.await?;
}
send_apub_delete(
&local_user_view.person,
&updated_community,
updated_community.actor_id.clone().into(),
deleted,
context,
)
.await?;
let community_id = data.community_id;
let person_id = local_user_view.person.id;
@ -123,14 +121,15 @@ impl PerformCrud for RemoveCommunity {
.await??;
// Apub messages
if removed {
updated_community
.blank_out_deleted_or_removed_info()
.send_remove(context)
.await?;
} else {
updated_community.send_undo_remove(context).await?;
}
send_apub_remove(
&local_user_view.person,
&updated_community,
updated_community.actor_id.clone().into(),
data.reason.clone().unwrap_or_else(|| "".to_string()),
removed,
context,
)
.await?;
let community_id = data.community_id;
let person_id = local_user_view.person.id;

View file

@ -7,9 +7,9 @@ use lemmy_api_common::{
is_mod_or_admin,
post::*,
};
use lemmy_apub::ApubObjectType;
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
use lemmy_db_queries::{source::post::Post_, Crud, DeleteableOrRemoveable};
use lemmy_db_schema::source::{moderator::*, post::*};
use lemmy_db_schema::source::{community::Community, moderator::*, post::*};
use lemmy_db_views::post_view::PostView;
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperationCrud};
@ -50,16 +50,18 @@ impl PerformCrud for DeletePost {
.await??;
// apub updates
if deleted {
updated_post
.blank_out_deleted_or_removed_info()
.send_delete(&local_user_view.person, context)
.await?;
} else {
updated_post
.send_undo_delete(&local_user_view.person, context)
.await?;
}
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_post.community_id)
})
.await??;
send_apub_delete(
&local_user_view.person,
&community,
updated_post.ap_id.into(),
deleted,
context,
)
.await?;
// Refetch the post
let post_id = data.post_id;
@ -135,16 +137,19 @@ impl PerformCrud for RemovePost {
.await??;
// apub updates
if removed {
updated_post
.blank_out_deleted_or_removed_info()
.send_remove(&local_user_view.person, context)
.await?;
} else {
updated_post
.send_undo_remove(&local_user_view.person, context)
.await?;
}
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_post.community_id)
})
.await??;
send_apub_remove(
&local_user_view.person,
&community,
updated_post.ap_id.into(),
data.reason.clone().unwrap_or_else(|| "".to_string()),
removed,
context,
)
.await?;
// Refetch the post
let post_id = data.post_id;

View file

@ -7,16 +7,10 @@ use crate::{
list_community_follower_inboxes,
undo_block_user::UndoBlockUserFromCommunity,
},
deletion::{
delete::DeletePostCommentOrCommunity,
undo_delete::UndoDeletePostCommentOrCommunity,
},
deletion::{delete::Delete, undo_delete::UndoDelete},
generate_activity_id,
post::create_or_update::CreateOrUpdatePost,
removal::{
remove::RemovePostCommentCommunityOrMod,
undo_remove::UndoRemovePostCommentOrCommunity,
},
removal::{remove::RemoveMod, undo_remove::UndoRemovePostCommentOrCommunity},
verify_activity,
verify_community,
voting::{undo_vote::UndoVote, vote::Vote},
@ -43,13 +37,13 @@ pub enum AnnouncableActivities {
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
Vote(Vote),
UndoVote(UndoVote),
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
RemovePostCommentCommunityOrMod(RemovePostCommentCommunityOrMod),
Delete(Delete),
UndoDelete(UndoDelete),
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]

View file

@ -1,19 +1,42 @@
use crate::{
activities::{
comment::send_websocket_message as send_comment_message,
community::send_websocket_message as send_community_message,
deletion::{verify_delete_activity, DeletableObjects},
community::{
announce::AnnouncableActivities,
send_websocket_message as send_community_message,
},
deletion::{send_apub_delete, verify_delete_activity, DeletableObjects},
generate_activity_id,
post::send_websocket_message as send_post_message,
verify_activity,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
fetcher::person::get_or_fetch_and_upsert_person,
CommunityType,
ActorType,
};
use activitystreams::activity::kind::DeleteType;
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{values::PublicUrl, 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_db_queries::{
source::{comment::Comment_, community::Community_, post::Post_},
Crud,
};
use lemmy_db_schema::source::{
comment::Comment,
community::Community,
moderator::{
ModRemoveComment,
ModRemoveCommentForm,
ModRemoveCommunity,
ModRemoveCommunityForm,
ModRemovePost,
ModRemovePostForm,
},
person::Person,
post::Post,
};
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
@ -28,18 +51,21 @@ use url::Url;
/// wrapping it in an announce just like other activities, instead of having the community send it.
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeletePostCommentOrCommunity {
to: PublicUrl,
pub struct Delete {
pub(in crate::activities::deletion) to: PublicUrl,
pub(in crate::activities::deletion) object: Url,
cc: [Url; 1],
pub(in crate::activities::deletion) cc: [Url; 1],
#[serde(rename = "type")]
kind: DeleteType,
pub(in crate::activities::deletion) kind: DeleteType,
/// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user
/// deleting their own content.
pub(in crate::activities::deletion) summary: Option<String>,
#[serde(flatten)]
common: ActivityCommonFields,
pub(in crate::activities::deletion) common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for DeletePostCommentOrCommunity {
impl ActivityHandler for Delete {
async fn verify(
&self,
context: &LemmyContext,
@ -50,6 +76,7 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
&self.object,
&self.cc[0],
&self.common,
self.summary.is_some(),
context,
request_counter,
)
@ -61,6 +88,59 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
if let Some(reason) = self.summary {
receive_remove_action(
&self.common.actor,
&self.object,
Some(reason),
context,
request_counter,
)
.await
} else {
self.receive_delete_action(context, request_counter).await
}
}
fn common(&self) -> &ActivityCommonFields {
&self.common
}
}
impl Delete {
pub(in crate::activities::deletion) async fn send(
actor: &Person,
community: &Community,
object_id: Url,
summary: Option<String>,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let id = generate_activity_id(DeleteType::Delete)?;
let delete = Delete {
to: PublicUrl::Public,
object: object_id,
cc: [community.actor_id()],
kind: DeleteType::Delete,
summary,
common: ActivityCommonFields {
context: lemmy_context(),
id: id.clone(),
actor: actor.actor_id(),
unparsed: Default::default(),
},
};
let activity = AnnouncableActivities::Delete(delete);
send_to_community_new(activity, &id, actor, community, vec![], context).await
}
// TODO: would be nice if we could merge this and receive_delete_action() into a single method
// (or merge with receive_undo_delete_action() instead)
async fn receive_delete_action(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
use UserOperationCrud::*;
match DeletableObjects::read_from_db(&self.object, context).await? {
@ -68,7 +148,8 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
if community.local {
let mod_ =
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
community.send_delete(mod_, context).await?;
let object = community.actor_id();
send_apub_delete(&mod_, &community.clone(), object, true, context).await?;
}
let deleted_community = blocking(context.pool(), move |conn| {
@ -82,19 +163,85 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
Post::update_deleted(conn, post.id, true)
})
.await??;
send_post_message(deleted_post.id, EditPost, context).await
send_post_message(deleted_post.id, DeletePost, context).await
}
DeletableObjects::Comment(comment) => {
let deleted_comment = blocking(context.pool(), move |conn| {
Comment::update_deleted(conn, comment.id, true)
})
.await??;
send_comment_message(deleted_comment.id, vec![], EditComment, context).await
send_comment_message(deleted_comment.id, vec![], DeleteComment, context).await
}
}
}
}
fn common(&self) -> &ActivityCommonFields {
&self.common
// TODO: reason is optional for compat with v0.11, make it mandatory after removing the migration
pub(in crate::activities) async fn receive_remove_action(
actor: &Url,
object: &Url,
reason: Option<String>,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
use UserOperationCrud::*;
match DeletableObjects::read_from_db(object, context).await? {
DeletableObjects::Community(community) => {
if community.local {
return Err(anyhow!("Only local admin can remove community").into());
}
let form = ModRemoveCommunityForm {
mod_person_id: actor.id,
community_id: community.id,
removed: Some(true),
reason,
expires: None,
};
blocking(context.pool(), move |conn| {
ModRemoveCommunity::create(conn, &form)
})
.await??;
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, true)
})
.await??;
send_community_message(deleted_community.id, RemoveCommunity, context).await
}
DeletableObjects::Post(post) => {
let form = ModRemovePostForm {
mod_person_id: actor.id,
post_id: post.id,
removed: Some(true),
reason,
};
blocking(context.pool(), move |conn| {
ModRemovePost::create(conn, &form)
})
.await??;
let removed_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post.id, true)
})
.await??;
send_post_message(removed_post.id, RemovePost, context).await
}
DeletableObjects::Comment(comment) => {
let form = ModRemoveCommentForm {
mod_person_id: actor.id,
comment_id: comment.id,
removed: Some(true),
reason,
};
blocking(context.pool(), move |conn| {
ModRemoveComment::create(conn, &form)
})
.await??;
let removed_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment.id, true)
})
.await??;
send_comment_message(removed_comment.id, vec![], RemoveComment, context).await
}
}
}

View file

@ -1,12 +1,16 @@
use crate::{
activities::{verify_mod_action, verify_person_in_community},
activities::{
deletion::{delete::Delete, undo_delete::UndoDelete},
verify_mod_action,
verify_person_in_community,
},
ActorType,
};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields};
use lemmy_db_queries::ApubObject;
use lemmy_db_schema::{
source::{comment::Comment, community::Community, post::Post},
source::{comment::Comment, community::Community, person::Person, post::Post},
DbUrl,
};
use lemmy_utils::LemmyError;
@ -16,6 +20,37 @@ use url::Url;
pub mod delete;
pub mod undo_delete;
pub async fn send_apub_delete(
actor: &Person,
community: &Community,
object_id: Url,
deleted: bool,
context: &LemmyContext,
) -> Result<(), LemmyError> {
if deleted {
Delete::send(actor, community, object_id, None, context).await
} else {
UndoDelete::send(actor, community, object_id, None, context).await
}
}
// TODO: remove reason is actually optional in lemmy. we set an empty string in that case, but its
// ugly
pub async fn send_apub_remove(
actor: &Person,
community: &Community,
object_id: Url,
reason: String,
removed: bool,
context: &LemmyContext,
) -> Result<(), LemmyError> {
if removed {
Delete::send(actor, community, object_id, Some(reason), context).await
} else {
UndoDelete::send(actor, community, object_id, Some(reason), context).await
}
}
pub enum DeletableObjects {
Community(Box<Community>),
Comment(Box<Comment>),
@ -53,10 +88,11 @@ impl DeletableObjects {
}
}
pub(in crate::activities::deletion) async fn verify_delete_activity(
pub(in crate::activities) async fn verify_delete_activity(
object: &Url,
cc: &Url,
common: &ActivityCommonFields,
is_mod_action: bool,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
@ -68,17 +104,49 @@ pub(in crate::activities::deletion) async fn verify_delete_activity(
// deleted community (which fails)
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
}
// community deletion is always a mod (or admin) action
verify_mod_action(&common.actor, c.actor_id(), context).await?;
}
DeletableObjects::Post(p) => {
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
verify_domains_match(&common.actor, &p.ap_id.into())?;
verify_delete_activity_post_or_comment(
cc,
common,
&p.ap_id.into(),
is_mod_action,
context,
request_counter,
)
.await?;
}
DeletableObjects::Comment(c) => {
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
verify_domains_match(&common.actor, &c.ap_id.into())?;
verify_delete_activity_post_or_comment(
cc,
common,
&c.ap_id.into(),
is_mod_action,
context,
request_counter,
)
.await?;
}
}
Ok(())
}
async fn verify_delete_activity_post_or_comment(
cc: &Url,
common: &ActivityCommonFields,
object_id: &Url,
is_mod_action: bool,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
if is_mod_action {
verify_mod_action(&common.actor, cc.clone(), context).await?;
} else {
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
verify_domains_match(&common.actor, object_id)?;
}
Ok(())
}

View file

@ -1,28 +1,35 @@
use crate::{
activities::{
comment::send_websocket_message as send_comment_message,
community::send_websocket_message as send_community_message,
deletion::{delete::DeletePostCommentOrCommunity, verify_delete_activity, DeletableObjects},
community::{
announce::AnnouncableActivities,
send_websocket_message as send_community_message,
},
deletion::{delete::Delete, send_apub_delete, verify_delete_activity, DeletableObjects},
generate_activity_id,
post::send_websocket_message as send_post_message,
verify_activity,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
fetcher::person::get_or_fetch_and_upsert_person,
CommunityType,
ActorType,
};
use activitystreams::activity::kind::UndoType;
use activitystreams::activity::kind::{DeleteType, UndoType};
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{values::PublicUrl, 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_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDeletePostCommentOrCommunity {
pub struct UndoDelete {
to: PublicUrl,
object: DeletePostCommentOrCommunity,
object: Delete,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
@ -31,7 +38,7 @@ pub struct UndoDeletePostCommentOrCommunity {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for UndoDeletePostCommentOrCommunity {
impl ActivityHandler for UndoDelete {
async fn verify(
&self,
context: &LemmyContext,
@ -43,6 +50,7 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
&self.object.object,
&self.cc[0],
&self.common,
self.object.summary.is_some(),
context,
request_counter,
)
@ -54,6 +62,64 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
if self.object.summary.is_some() {
UndoDelete::receive_undo_remove_action(&self.object.object, context).await
} else {
self
.receive_undo_delete_action(context, request_counter)
.await
}
}
fn common(&self) -> &ActivityCommonFields {
&self.common
}
}
impl UndoDelete {
pub(in crate::activities::deletion) async fn send(
actor: &Person,
community: &Community,
object_id: Url,
summary: Option<String>,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let delete = Delete {
to: PublicUrl::Public,
object: object_id,
cc: [community.actor_id()],
kind: DeleteType::Delete,
summary,
common: ActivityCommonFields {
context: lemmy_context(),
id: generate_activity_id(DeleteType::Delete)?,
actor: actor.actor_id(),
unparsed: Default::default(),
},
};
let id = generate_activity_id(UndoType::Undo)?;
let undo = UndoDelete {
to: PublicUrl::Public,
object: delete,
cc: [community.actor_id()],
kind: UndoType::Undo,
common: ActivityCommonFields {
context: lemmy_context(),
id: id.clone(),
actor: actor.actor_id(),
unparsed: Default::default(),
},
};
let activity = AnnouncableActivities::UndoDelete(undo);
send_to_community_new(activity, &id, actor, community, vec![], context).await
}
async fn receive_undo_delete_action(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
use UserOperationCrud::*;
let object = DeletableObjects::read_from_db(&self.object.object, context).await?;
@ -62,7 +128,14 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
if community.local {
let mod_ =
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
community.send_undo_delete(mod_, context).await?;
send_apub_delete(
&mod_,
&community.clone(),
community.actor_id(),
false,
context,
)
.await?;
}
let deleted_community = blocking(context.pool(), move |conn| {
@ -88,7 +161,37 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
}
}
fn common(&self) -> &ActivityCommonFields {
&self.common
pub(in crate::activities) async fn receive_undo_remove_action(
object: &Url,
context: &LemmyContext,
) -> Result<(), LemmyError> {
use UserOperationCrud::*;
match DeletableObjects::read_from_db(object, context).await? {
DeletableObjects::Community(community) => {
if community.local {
return Err(anyhow!("Only local admin can restore community").into());
}
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, false)
})
.await??;
send_community_message(deleted_community.id, EditCommunity, context).await
}
DeletableObjects::Post(post) => {
let removed_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post.id, false)
})
.await??;
send_post_message(removed_post.id, EditPost, context).await
}
DeletableObjects::Comment(comment) => {
let removed_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment.id, false)
})
.await??;
send_comment_message(removed_comment.id, vec![], EditComment, context).await
}
}
}
}

View file

@ -1,77 +1,59 @@
use crate::{
activities::{
comment::send_websocket_message as send_comment_message,
community::send_websocket_message as send_community_message,
post::send_websocket_message as send_post_message,
deletion::{delete::receive_remove_action, verify_delete_activity},
verify_activity,
verify_add_remove_moderator_target,
verify_mod_action,
verify_person_in_community,
},
fetcher::{
community::get_or_fetch_and_upsert_community,
objects::get_or_fetch_and_insert_post_or_comment,
person::get_or_fetch_and_upsert_person,
},
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
CommunityType,
PostOrComment,
};
use activitystreams::{activity::kind::RemoveType, base::AnyBase};
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
use lemmy_db_queries::{
source::{comment::Comment_, community::Community_, post::Post_},
Joinable,
};
use lemmy_db_schema::source::{
comment::Comment,
community::{Community, CommunityModerator, CommunityModeratorForm},
post::Post,
};
use lemmy_db_queries::Joinable;
use lemmy_db_schema::source::community::{CommunityModerator, CommunityModeratorForm};
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use lemmy_websocket::LemmyContext;
use url::Url;
// TODO: we can probably deduplicate a bunch of code between this and DeletePostCommentOrCommunity
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RemovePostCommentCommunityOrMod {
pub struct RemoveMod {
to: PublicUrl,
pub(in crate::activities::removal) object: Url,
cc: [Url; 1],
#[serde(rename = "type")]
kind: RemoveType,
// if target is set, this is means remove mod from community
target: Option<Url>,
pub(in crate::activities::removal) target: Option<Url>,
#[serde(flatten)]
common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for RemovePostCommentCommunityOrMod {
impl ActivityHandler for RemoveMod {
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
let object_community =
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
// removing a community
if object_community.is_ok() {
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
}
// removing community mod
else if let Some(target) = &self.target {
if let Some(target) = &self.target {
verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
verify_add_remove_moderator_target(target, self.cc[0].clone())?;
}
// removing a post or comment
else {
verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
} else {
verify_delete_activity(
&self.object,
&self.cc[0],
self.common(),
true,
context,
request_counter,
)
.await?;
}
Ok(())
}
@ -81,27 +63,7 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let object_community =
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
// removing a community
if let Ok(community) = object_community {
if community.local {
return Err(anyhow!("Only local admin can remove community").into());
}
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, true)
})
.await??;
send_community_message(
deleted_community.id,
UserOperationCrud::RemoveCommunity,
context,
)
.await
}
// removing community mod
else if self.target.is_some() {
if self.target.is_some() {
let community =
get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
let remove_mod =
@ -121,31 +83,15 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod {
.await?;
// TODO: send websocket notification about removed mod
Ok(())
}
// removing a post or comment
else {
match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {
PostOrComment::Post(post) => {
let removed_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post.id, true)
})
.await??;
send_post_message(removed_post.id, UserOperationCrud::EditPost, context).await
}
PostOrComment::Comment(comment) => {
let removed_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment.id, true)
})
.await??;
send_comment_message(
removed_comment.id,
vec![],
UserOperationCrud::EditComment,
context,
)
.await
}
}
} else {
receive_remove_action(
&self.common.actor,
&self.object,
None,
context,
request_counter,
)
.await
}
}

View file

@ -1,34 +1,20 @@
use crate::{
activities::{
comment::send_websocket_message as send_comment_message,
community::send_websocket_message as send_community_message,
post::send_websocket_message as send_post_message,
removal::remove::RemovePostCommentCommunityOrMod,
verify_activity,
verify_mod_action,
verify_person_in_community,
},
fetcher::{
community::get_or_fetch_and_upsert_community,
objects::get_or_fetch_and_insert_post_or_comment,
},
PostOrComment,
use crate::activities::{
deletion::{undo_delete::UndoDelete, verify_delete_activity},
removal::remove::RemoveMod,
verify_activity,
};
use activitystreams::activity::kind::UndoType;
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{values::PublicUrl, 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_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoRemovePostCommentOrCommunity {
to: PublicUrl,
object: RemovePostCommentCommunityOrMod,
// Note, there is no such thing as Undo/Remove/Mod, so we ignore that
object: RemoveMod,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
@ -44,74 +30,26 @@ impl ActivityHandler for UndoRemovePostCommentOrCommunity {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
let object_community =
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
// removing a community
if object_community.is_ok() {
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
}
// removing a post or comment
else {
verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
}
self.object.verify(context, request_counter).await?;
// dont check that actor and object.actor are identical, so that one mod can
// undo the action of another
verify_delete_activity(
&self.object.object,
&self.cc[0],
self.common(),
true,
context,
request_counter,
)
.await?;
Ok(())
}
async fn receive(
self,
context: &LemmyContext,
request_counter: &mut i32,
_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 {
return Err(anyhow!("Only local admin can undo remove community").into());
}
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, false)
})
.await??;
send_community_message(
deleted_community.id,
UserOperationCrud::EditCommunity,
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 removed_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post.id, false)
})
.await??;
send_post_message(removed_post.id, UserOperationCrud::EditPost, context).await
}
PostOrComment::Comment(comment) => {
let removed_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment.id, false)
})
.await??;
send_comment_message(
removed_comment.id,
vec![],
UserOperationCrud::EditComment,
context,
)
.await
}
}
}
UndoDelete::receive_undo_remove_action(&self.object.object, context).await
}
fn common(&self) -> &ActivityCommonFields {

View file

@ -1,153 +0,0 @@
use crate::{
activities::generate_activity_id,
activity_queue::send_to_community,
extensions::context::lemmy_context,
ActorType,
ApubObjectType,
};
use activitystreams::{
activity::{
kind::{DeleteType, RemoveType, UndoType},
Delete,
Remove,
Undo,
},
prelude::*,
public,
};
use lemmy_api_common::blocking;
use lemmy_db_queries::Crud;
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
#[async_trait::async_trait(?Send)]
impl ApubObjectType for Comment {
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let community_id = post.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(delete, creator, &community, None, context).await?;
Ok(())
}
async fn send_undo_delete(
&self,
creator: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let community_id = post.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
// Generate a fake delete activity, with the correct object
let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
// Undo that fake activity
let mut undo = Undo::new(
creator.actor_id.to_owned().into_inner(),
delete.into_any_base()?,
);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(UndoType::Undo)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(undo, creator, &community, None, context).await?;
Ok(())
}
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let community_id = post.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut remove = Remove::new(
mod_.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
remove
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(RemoveType::Remove)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(remove, mod_, &community, None, context).await?;
Ok(())
}
async fn send_undo_remove(
&self,
mod_: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let post_id = self.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let community_id = post.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
// Generate a fake delete activity, with the correct object
let mut remove = Remove::new(
mod_.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
remove
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(RemoveType::Remove)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
// Undo that fake activity
let mut undo = Undo::new(
mod_.actor_id.to_owned().into_inner(),
remove.into_any_base()?,
);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(UndoType::Undo)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(undo, mod_, &community, None, context).await?;
Ok(())
}
}

View file

@ -12,20 +12,10 @@ use crate::{
};
use activitystreams::{
activity::{
kind::{
AddType,
AnnounceType,
BlockType,
DeleteType,
LikeType,
RemoveType,
UndoType,
UpdateType,
},
kind::{AddType, AnnounceType, BlockType, RemoveType, UndoType, UpdateType},
Add,
Announce,
Block,
Delete,
OptTargetRefExt,
Remove,
Undo,
@ -97,112 +87,6 @@ impl CommunityType for Community {
Ok(())
}
/// If the creator of a community deletes the community, send this to all followers.
///
/// We need to handle deletion by a remote mod separately.
async fn send_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError> {
// Local mod, send directly from community to followers
if self.local {
let mut delete = Delete::new(self.actor_id(), self.actor_id());
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![self.followers_url()]);
send_to_community_followers(delete, self, None, context).await?;
}
// Remote mod, send from mod to community
else {
let mut delete = Delete::new(mod_.actor_id(), self.actor_id());
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![self.actor_id()]);
send_to_community(delete, &mod_, self, None, context).await?;
}
Ok(())
}
/// If the creator of a community reverts the deletion of a community, send this to all followers.
///
/// We need to handle undelete by a remote mod separately.
async fn send_undo_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError> {
// Local mod, send directly from community to followers
if self.local {
let mut delete = Delete::new(self.actor_id(), self.actor_id());
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![self.followers_url()]);
let mut undo = Undo::new(self.actor_id(), delete.into_any_base()?);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(UndoType::Undo)?)
.set_to(public())
.set_many_ccs(vec![self.followers_url()]);
send_to_community_followers(undo, self, None, context).await?;
}
// Remote mod, send from mod to community
else {
let mut delete = Delete::new(mod_.actor_id(), self.actor_id());
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![self.actor_id()]);
let mut undo = Undo::new(mod_.actor_id(), delete.into_any_base()?);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(UndoType::Undo)?)
.set_to(public())
.set_many_ccs(vec![self.actor_id()]);
send_to_community(undo, &mod_, self, None, context).await?;
}
Ok(())
}
/// If an admin removes a community, send this to all followers.
async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
let mut remove = Remove::new(self.actor_id(), self.actor_id());
remove
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(RemoveType::Remove)?)
.set_to(public())
.set_many_ccs(vec![self.followers_url()]);
send_to_community_followers(remove, self, None, context).await?;
Ok(())
}
/// If an admin reverts the removal of a community, send this to all followers.
async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
let mut remove = Remove::new(self.actor_id(), self.actor_id());
remove
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(RemoveType::Remove)?)
.set_to(public())
.set_many_ccs(vec![self.followers_url()]);
// Undo that fake activity
let mut undo = Undo::new(self.actor_id(), remove.into_any_base()?);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(LikeType::Like)?)
.set_to(public())
.set_many_ccs(vec![self.followers_url()]);
send_to_community_followers(undo, self, None, context).await?;
Ok(())
}
/// Wraps an activity sent to the community in an announce, and then sends the announce to all
/// community followers.
///

View file

@ -1,4 +1,2 @@
pub(crate) mod comment;
pub(crate) mod community;
pub(crate) mod person;
pub(crate) mod post;

View file

@ -1,139 +0,0 @@
use crate::{
activities::generate_activity_id,
activity_queue::send_to_community,
extensions::context::lemmy_context,
ActorType,
ApubObjectType,
};
use activitystreams::{
activity::{
kind::{DeleteType, RemoveType, UndoType},
Delete,
Remove,
Undo,
},
prelude::*,
public,
};
use lemmy_api_common::blocking;
use lemmy_db_queries::Crud;
use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
#[async_trait::async_trait(?Send)]
impl ApubObjectType for Post {
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(delete, creator, &community, None, context).await?;
Ok(())
}
async fn send_undo_delete(
&self,
creator: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut delete = Delete::new(
creator.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
delete
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
// Undo that fake activity
let mut undo = Undo::new(
creator.actor_id.to_owned().into_inner(),
delete.into_any_base()?,
);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(UndoType::Undo)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(undo, creator, &community, None, context).await?;
Ok(())
}
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut remove = Remove::new(
mod_.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
remove
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(RemoveType::Remove)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(remove, mod_, &community, None, context).await?;
Ok(())
}
async fn send_undo_remove(
&self,
mod_: &Person,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let community_id = self.community_id;
let community = blocking(context.pool(), move |conn| {
Community::read(conn, community_id)
})
.await??;
let mut remove = Remove::new(
mod_.actor_id.to_owned().into_inner(),
self.ap_id.to_owned().into_inner(),
);
remove
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(RemoveType::Remove)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
// Undo that fake activity
let mut undo = Undo::new(
mod_.actor_id.to_owned().into_inner(),
remove.into_any_base()?,
);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(UndoType::Undo)?)
.set_to(public())
.set_many_ccs(vec![community.actor_id()]);
send_to_community(undo, mod_, &community, None, context).await?;
Ok(())
}
}

View file

@ -7,7 +7,7 @@ use crate::activities::{
undo_block_user::UndoBlockUserFromCommunity,
update::UpdateCommunity,
},
deletion::{delete::DeletePostCommentOrCommunity, undo_delete::UndoDeletePostCommentOrCommunity},
deletion::{delete::Delete, undo_delete::UndoDelete},
following::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity},
post::create_or_update::CreateOrUpdatePost,
private_message::{
@ -15,10 +15,7 @@ use crate::activities::{
delete::DeletePrivateMessage,
undo_delete::UndoDeletePrivateMessage,
},
removal::{
remove::RemovePostCommentCommunityOrMod,
undo_remove::UndoRemovePostCommentOrCommunity,
},
removal::{remove::RemoveMod, undo_remove::UndoRemovePostCommentOrCommunity},
voting::{undo_vote::UndoVote, vote::Vote},
};
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler};
@ -45,14 +42,14 @@ pub enum GroupInboxActivities {
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
Vote(Vote),
UndoVote(UndoVote),
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod),
DeletePostCommentOrCommunity(Delete),
UndoDeletePostCommentOrCommunity(UndoDelete),
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
UpdateCommunity(Box<UpdateCommunity>),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
}
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
@ -65,14 +62,14 @@ pub enum SharedInboxActivities {
CreateOrUpdatePost(Box<CreateOrUpdatePost>),
Vote(Vote),
UndoVote(UndoVote),
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod),
Delete(Delete),
UndoDelete(UndoDelete),
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
UpdateCommunity(Box<UpdateCommunity>),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
// received by person
AcceptFollowCommunity(AcceptFollowCommunity),
// Note, pm activities need to be at the end, otherwise comments will end up here. We can probably

View file

@ -102,25 +102,6 @@ pub(crate) fn check_is_apub_id_valid(
Ok(())
}
/// Common functions for ActivityPub objects, which are implemented by most (but not all) objects
/// and actors in Lemmy.
#[async_trait::async_trait(?Send)]
pub trait ApubObjectType {
async fn send_delete(&self, creator: &DbPerson, context: &LemmyContext)
-> Result<(), LemmyError>;
async fn send_undo_delete(
&self,
creator: &DbPerson,
context: &LemmyContext,
) -> Result<(), LemmyError>;
async fn send_remove(&self, mod_: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_undo_remove(
&self,
mod_: &DbPerson,
context: &LemmyContext,
) -> Result<(), LemmyError>;
}
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
/// implemented by all actors.
trait ActorType {
@ -160,11 +141,6 @@ pub trait CommunityType {
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
async fn send_update(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_undo_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_announce(
&self,

View file

@ -15,3 +15,15 @@ pub enum CommentInReplyToMigration {
Old(Vec<Url>),
New(Url),
}
// Another migration we are doing is to handle all deletions and removals using Delete activity.
// This is because Remove is for removing an object from a collection, so using it that way doesn't
// really make sense. It is also a problem because we have a RemoveMod activity, which was awkward
// to handle together with removing posts etc.
//
// v0.11: send and receive mod removals as Remove
// v0.12: receive removals as Remove, send as Delete (compatible with v0.11)
// v0.13: send and receive mod removals as Delete (compatible with v0.12)
//
// For v0.13, delete [`UndoRemovePostCommentOrCommunity`], and don't handle object deletion in
// [`RemoveMod`] handler.