mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-01-11 20:45:53 +00:00
Rewrite delete activities
This commit is contained in:
parent
e65897a350
commit
bc6294a834
16 changed files with 501 additions and 721 deletions
|
@ -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)
|
||||
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?;
|
||||
} else {
|
||||
updated_comment
|
||||
.send_undo_delete(&local_user_view.person, 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)
|
||||
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?;
|
||||
} else {
|
||||
updated_comment
|
||||
.send_undo_remove(&local_user_view.person, context)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Refetch it
|
||||
let comment_id = data.comment_id;
|
||||
|
|
|
@ -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)
|
||||
send_apub_delete(
|
||||
&local_user_view.person,
|
||||
&updated_community,
|
||||
updated_community.actor_id.clone().into(),
|
||||
deleted,
|
||||
context,
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
updated_community
|
||||
.send_undo_delete(local_user_view.person.to_owned(), 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)
|
||||
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?;
|
||||
} else {
|
||||
updated_community.send_undo_remove(context).await?;
|
||||
}
|
||||
|
||||
let community_id = data.community_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
|
|
|
@ -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)
|
||||
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?;
|
||||
} else {
|
||||
updated_post
|
||||
.send_undo_delete(&local_user_view.person, 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)
|
||||
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?;
|
||||
} else {
|
||||
updated_post
|
||||
.send_undo_remove(&local_user_view.person, context)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Refetch the post
|
||||
let post_id = data.post_id;
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,33 +83,17 @@ 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,
|
||||
} else {
|
||||
receive_remove_action(
|
||||
&self.common.actor,
|
||||
&self.object,
|
||||
None,
|
||||
context,
|
||||
request_counter,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
|
|
|
@ -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,
|
||||
use crate::activities::{
|
||||
deletion::{undo_delete::UndoDelete, verify_delete_activity},
|
||||
removal::remove::RemoveMod,
|
||||
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 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 {
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
pub(crate) mod comment;
|
||||
pub(crate) mod community;
|
||||
pub(crate) mod person;
|
||||
pub(crate) mod post;
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue