mirror of
https://github.com/LemmyNet/lemmy
synced 2024-11-14 16:57:24 +00:00
rework delete/remove activity receivers (still quite messy)
This commit is contained in:
parent
28e960bd9c
commit
186c0b93d1
24 changed files with 573 additions and 727 deletions
|
@ -2,19 +2,23 @@ use crate::{
|
|||
activities::{
|
||||
comment::{create::CreateComment, update::UpdateComment},
|
||||
community::{block_user::BlockUserFromCommunity, undo_block_user::UndoBlockUserFromCommunity},
|
||||
deletion::{
|
||||
delete::DeletePostCommentOrCommunity,
|
||||
undo_delete::UndoDeletePostCommentOrCommunity,
|
||||
},
|
||||
post::{create::CreatePost, update::UpdatePost},
|
||||
post_or_comment::{
|
||||
delete::DeletePostOrComment,
|
||||
dislike::DislikePostOrComment,
|
||||
like::LikePostOrComment,
|
||||
remove::RemovePostOrComment,
|
||||
undo_delete::UndoDeletePostOrComment,
|
||||
undo_dislike::UndoDislikePostOrComment,
|
||||
undo_like::UndoLikePostOrComment,
|
||||
undo_remove::UndoRemovePostOrComment,
|
||||
removal::{
|
||||
remove::RemovePostCommentOrCommunity,
|
||||
undo_remove::UndoRemovePostCommentOrCommunity,
|
||||
},
|
||||
verify_activity,
|
||||
verify_community,
|
||||
voting::{
|
||||
dislike::DislikePostOrComment,
|
||||
like::LikePostOrComment,
|
||||
undo_dislike::UndoDislikePostOrComment,
|
||||
undo_like::UndoLikePostOrComment,
|
||||
},
|
||||
},
|
||||
http::is_activity_already_known,
|
||||
};
|
||||
|
@ -37,10 +41,10 @@ pub enum AnnouncableActivities {
|
|||
DislikePostOrComment(DislikePostOrComment),
|
||||
UndoLikePostOrComment(UndoLikePostOrComment),
|
||||
UndoDislikePostOrComment(UndoDislikePostOrComment),
|
||||
DeletePostOrComment(DeletePostOrComment),
|
||||
RemovePostOrComment(RemovePostOrComment),
|
||||
UndoRemovePostOrComment(UndoRemovePostOrComment),
|
||||
UndoDeletePostOrComment(UndoDeletePostOrComment),
|
||||
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
|
||||
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
|
||||
RemovePostCommentOrCommunity(RemovePostCommentOrCommunity),
|
||||
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
||||
BlockUserFromCommunity(BlockUserFromCommunity),
|
||||
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
||||
}
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
use crate::activities::{community::send_websocket_message, verify_mod_action};
|
||||
use activitystreams::activity::kind::DeleteType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{
|
||||
check_is_apub_id_valid,
|
||||
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
|
||||
ActorType,
|
||||
CommunityType,
|
||||
};
|
||||
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::{source::community::Community_, ApubObject};
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
||||
use url::Url;
|
||||
|
||||
// We have two possibilities which need to be handled:
|
||||
// 1. actor is remote mod, community id in object
|
||||
// 2. actor is community, cc is followers collection
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DeleteCommunity {
|
||||
to: PublicUrl,
|
||||
pub(in crate::activities::community) object: Url,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: DeleteType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for DeleteCommunity {
|
||||
async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
|
||||
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
|
||||
let object = self.object.clone();
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_apub_id(conn, &object.into())
|
||||
})
|
||||
.await?;
|
||||
// remote mod action on local community
|
||||
if let Ok(c) = community {
|
||||
verify_domains_match(&self.object, &self.cc[0])?;
|
||||
check_is_apub_id_valid(&self.common.actor, false)?;
|
||||
verify_mod_action(&self.common.actor, c.actor_id(), context).await
|
||||
}
|
||||
// community action sent to followers
|
||||
else {
|
||||
verify_domains_match(&self.common.actor, &self.object)?;
|
||||
verify_domains_match(&self.common.actor, &self.cc[0])
|
||||
}
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
// TODO: match on actor to decide what to do
|
||||
let actor = self.object.clone();
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_apub_id(conn, &actor.into())
|
||||
})
|
||||
.await?;
|
||||
let community_id = match community {
|
||||
Ok(c) => {
|
||||
// remote mod sent delete to local community, forward it to followers
|
||||
let actor =
|
||||
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
|
||||
c.send_delete(actor, context).await?;
|
||||
c.id
|
||||
}
|
||||
Err(_) => {
|
||||
// refetch the remote community
|
||||
let community =
|
||||
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await?;
|
||||
community.id
|
||||
}
|
||||
};
|
||||
let deleted_community = blocking(context.pool(), move |conn| {
|
||||
Community::update_deleted(conn, community_id, true)
|
||||
})
|
||||
.await??;
|
||||
|
||||
send_websocket_message(
|
||||
deleted_community.id,
|
||||
UserOperationCrud::DeleteCommunity,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
|
@ -10,15 +10,13 @@ use url::Url;
|
|||
pub mod add_mod;
|
||||
pub mod announce;
|
||||
pub mod block_user;
|
||||
pub mod delete;
|
||||
pub mod remove;
|
||||
pub mod remove_mod;
|
||||
pub mod undo_block_user;
|
||||
pub mod undo_delete;
|
||||
pub mod undo_remove;
|
||||
pub mod update;
|
||||
|
||||
async fn send_websocket_message<OP: ToString + Send + lemmy_websocket::OperationType + 'static>(
|
||||
pub(crate) async fn send_websocket_message<
|
||||
OP: ToString + Send + lemmy_websocket::OperationType + 'static,
|
||||
>(
|
||||
community_id: CommunityId,
|
||||
op: OP,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
use crate::activities::community::send_websocket_message;
|
||||
use activitystreams::activity::kind::RemoveType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::check_is_apub_id_valid;
|
||||
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::{source::community::Community_, ApubObject};
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
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 RemoveCommunity {
|
||||
to: PublicUrl,
|
||||
pub(in crate::activities::community) object: Url,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: RemoveType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for RemoveCommunity {
|
||||
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
|
||||
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
|
||||
check_is_apub_id_valid(&self.common.actor, false)?;
|
||||
verify_domains_match(&self.common.actor, &self.object)?;
|
||||
verify_domains_match(&self.common.actor, &self.cc[0])
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
_request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object = self.object.clone();
|
||||
// only search in local database, there is no reason to fetch something thats deleted
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_apub_id(conn, &object.into())
|
||||
})
|
||||
.await??;
|
||||
let removed_community = blocking(context.pool(), move |conn| {
|
||||
Community::update_removed(conn, community.id, true)
|
||||
})
|
||||
.await??;
|
||||
|
||||
send_websocket_message(
|
||||
removed_community.id,
|
||||
UserOperationCrud::RemoveCommunity,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
use crate::activities::{
|
||||
community::{delete::DeleteCommunity, send_websocket_message},
|
||||
verify_mod_action,
|
||||
};
|
||||
use activitystreams::activity::kind::DeleteType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{
|
||||
check_is_apub_id_valid,
|
||||
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
|
||||
ActorType,
|
||||
CommunityType,
|
||||
};
|
||||
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::{source::community::Community_, ApubObject};
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{LemmyContext, UserOperationCrud};
|
||||
use url::Url;
|
||||
|
||||
// We have two possibilities which need to be handled:
|
||||
// 1. actor is remote mod, community id in object
|
||||
// 2. actor is community, cc is followers collection
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoDeleteCommunity {
|
||||
to: PublicUrl,
|
||||
object: DeleteCommunity,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: DeleteType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoDeleteCommunity {
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
|
||||
let object = self.object.object.clone();
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_apub_id(conn, &object.into())
|
||||
})
|
||||
.await?;
|
||||
// remote mod action on local community
|
||||
if let Ok(c) = community {
|
||||
verify_domains_match(&self.object.object, &self.cc[0])?;
|
||||
check_is_apub_id_valid(&self.common.actor, false)?;
|
||||
verify_mod_action(&self.common.actor, c.actor_id(), context).await?;
|
||||
}
|
||||
// community action sent to followers
|
||||
else {
|
||||
verify_domains_match(&self.common.actor, &self.object.object)?;
|
||||
verify_domains_match(&self.common.actor, &self.cc[0])?;
|
||||
}
|
||||
self.object.verify(context, request_counter).await
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object = self.object.object.clone();
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_apub_id(conn, &object.into())
|
||||
})
|
||||
.await?;
|
||||
let community_id = match community {
|
||||
Ok(c) => {
|
||||
// remote mod sent undo to local community, forward it to followers
|
||||
let actor =
|
||||
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
|
||||
c.send_delete(actor, context).await?;
|
||||
c.id
|
||||
}
|
||||
Err(_) => {
|
||||
// refetch the remote community
|
||||
let community =
|
||||
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await?;
|
||||
community.id
|
||||
}
|
||||
};
|
||||
let restored_community = blocking(context.pool(), move |conn| {
|
||||
Community::update_deleted(conn, community_id, false)
|
||||
})
|
||||
.await??;
|
||||
|
||||
send_websocket_message(
|
||||
restored_community.id,
|
||||
UserOperationCrud::EditCommunity,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
use crate::activities::community::{remove::RemoveCommunity, send_websocket_message};
|
||||
use activitystreams::activity::kind::RemoveType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{check_is_apub_id_valid, fetcher::community::get_or_fetch_and_upsert_community};
|
||||
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::source::community::Community_;
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
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 UndoRemoveCommunity {
|
||||
to: PublicUrl,
|
||||
object: RemoveCommunity,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: RemoveType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoRemoveCommunity {
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
|
||||
check_is_apub_id_valid(&self.common.actor, false)?;
|
||||
verify_domains_match(&self.common.actor, &self.object.object)?;
|
||||
verify_domains_match(&self.common.actor, &self.cc[0])?;
|
||||
self.object.verify(context, request_counter).await
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community_id = self.object.object.clone();
|
||||
let community =
|
||||
get_or_fetch_and_upsert_community(&community_id, context, request_counter).await?;
|
||||
|
||||
let restored_community = blocking(context.pool(), move |conn| {
|
||||
Community::update_removed(conn, community.id, false)
|
||||
})
|
||||
.await??;
|
||||
|
||||
send_websocket_message(
|
||||
restored_community.id,
|
||||
UserOperationCrud::EditCommunity,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
158
crates/apub_receive/src/activities/deletion/delete.rs
Normal file
158
crates/apub_receive/src/activities/deletion/delete.rs
Normal file
|
@ -0,0 +1,158 @@
|
|||
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,
|
||||
verify_activity,
|
||||
verify_mod_action,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::DeleteType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{
|
||||
fetcher::{
|
||||
community::get_or_fetch_and_upsert_community,
|
||||
objects::get_or_fetch_and_insert_post_or_comment,
|
||||
person::get_or_fetch_and_upsert_person,
|
||||
},
|
||||
ActorType,
|
||||
CommunityType,
|
||||
PostOrComment,
|
||||
};
|
||||
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::{
|
||||
source::{comment::Comment_, community::Community_, post::Post_},
|
||||
Crud,
|
||||
};
|
||||
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;
|
||||
|
||||
/// This is very confusing, because there are four distinct cases to handle:
|
||||
/// - user deletes their post
|
||||
/// - user deletes their comment
|
||||
/// - remote community mod deletes local community
|
||||
/// - remote community deletes itself (triggered by a mod)
|
||||
///
|
||||
/// TODO: we should probably change how community deletions work to simplify this. Probably by
|
||||
/// 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(in crate::activities::deletion) object: Url,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: DeleteType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for DeletePostCommentOrCommunity {
|
||||
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;
|
||||
// deleting a community (set counter 0 to only fetch from local db)
|
||||
if object_community.is_ok() {
|
||||
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
|
||||
}
|
||||
// deleting a post or comment
|
||||
else {
|
||||
verify_person_in_community(&self.common().actor, &self.cc, context, request_counter).await?;
|
||||
let object_creator =
|
||||
get_post_or_comment_actor_id(&self.object, context, request_counter).await?;
|
||||
verify_urls_match(&self.common.actor, &object_creator)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object_community =
|
||||
get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
|
||||
// deleting a community
|
||||
if let Ok(community) = object_community {
|
||||
if community.local {
|
||||
// repeat these checks just to be sure
|
||||
verify_person_in_community(&self.common().actor, &self.cc, context, request_counter)
|
||||
.await?;
|
||||
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
|
||||
let mod_ =
|
||||
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
|
||||
community.send_delete(mod_, context).await?;
|
||||
}
|
||||
let deleted_community = blocking(context.pool(), move |conn| {
|
||||
Community::update_deleted(conn, community.id, true)
|
||||
})
|
||||
.await??;
|
||||
|
||||
send_community_message(
|
||||
deleted_community.id,
|
||||
UserOperationCrud::DeleteCommunity,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
// deleting a post or comment
|
||||
else {
|
||||
match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {
|
||||
PostOrComment::Post(post) => {
|
||||
let deleted_post = blocking(context.pool(), move |conn| {
|
||||
Post::update_deleted(conn, post.id, true)
|
||||
})
|
||||
.await??;
|
||||
send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
|
||||
}
|
||||
PostOrComment::Comment(comment) => {
|
||||
let deleted_comment = blocking(context.pool(), move |conn| {
|
||||
Comment::update_deleted(conn, comment.id, true)
|
||||
})
|
||||
.await??;
|
||||
send_comment_message(
|
||||
deleted_comment.id,
|
||||
vec![],
|
||||
UserOperationCrud::EditComment,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_post_or_comment_actor_id(
|
||||
object: &Url,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Url, LemmyError> {
|
||||
let actor_id =
|
||||
match get_or_fetch_and_insert_post_or_comment(object, context, request_counter).await? {
|
||||
PostOrComment::Post(post) => {
|
||||
let creator_id = post.creator_id;
|
||||
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
|
||||
.await??
|
||||
.actor_id()
|
||||
}
|
||||
PostOrComment::Comment(comment) => {
|
||||
let creator_id = comment.creator_id;
|
||||
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
|
||||
.await??
|
||||
.actor_id()
|
||||
}
|
||||
};
|
||||
Ok(actor_id)
|
||||
}
|
2
crates/apub_receive/src/activities/deletion/mod.rs
Normal file
2
crates/apub_receive/src/activities/deletion/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod delete;
|
||||
pub mod undo_delete;
|
125
crates/apub_receive/src/activities/deletion/undo_delete.rs
Normal file
125
crates/apub_receive/src/activities/deletion/undo_delete.rs
Normal file
|
@ -0,0 +1,125 @@
|
|||
use crate::activities::{
|
||||
comment::send_websocket_message as send_comment_message,
|
||||
community::send_websocket_message as send_community_message,
|
||||
deletion::delete::DeletePostCommentOrCommunity,
|
||||
post::send_websocket_message as send_post_message,
|
||||
verify_activity,
|
||||
verify_mod_action,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::UndoType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{
|
||||
fetcher::{
|
||||
community::get_or_fetch_and_upsert_community,
|
||||
objects::get_or_fetch_and_insert_post_or_comment,
|
||||
person::get_or_fetch_and_upsert_person,
|
||||
},
|
||||
CommunityType,
|
||||
PostOrComment,
|
||||
};
|
||||
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
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 url::Url;
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoDeletePostCommentOrCommunity {
|
||||
to: PublicUrl,
|
||||
object: DeletePostCommentOrCommunity,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: UndoType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoDeletePostCommentOrCommunity {
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self.common())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
let object_community =
|
||||
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
|
||||
// restoring a community
|
||||
if object_community.is_ok() {
|
||||
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
|
||||
}
|
||||
// restoring a post or comment
|
||||
else {
|
||||
verify_person_in_community(&self.common().actor, &self.cc, context, request_counter).await?;
|
||||
verify_urls_match(&self.common.actor, &self.object.common().actor)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object_community =
|
||||
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
|
||||
// restoring a community
|
||||
if let Ok(community) = object_community {
|
||||
if community.local {
|
||||
// repeat these checks just to be sure
|
||||
verify_person_in_community(&self.common().actor, &self.cc, context, request_counter)
|
||||
.await?;
|
||||
verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
|
||||
let mod_ =
|
||||
get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
|
||||
community.send_undo_delete(mod_, context).await?;
|
||||
}
|
||||
let deleted_community = blocking(context.pool(), move |conn| {
|
||||
Community::update_deleted(conn, community.id, false)
|
||||
})
|
||||
.await??;
|
||||
|
||||
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 deleted_post = blocking(context.pool(), move |conn| {
|
||||
Post::update_deleted(conn, post.id, false)
|
||||
})
|
||||
.await??;
|
||||
send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
|
||||
}
|
||||
PostOrComment::Comment(comment) => {
|
||||
let deleted_comment = blocking(context.pool(), move |conn| {
|
||||
Comment::update_deleted(conn, comment.id, false)
|
||||
})
|
||||
.await??;
|
||||
send_comment_message(
|
||||
deleted_comment.id,
|
||||
vec![],
|
||||
UserOperationCrud::EditComment,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
|
@ -18,10 +18,12 @@ use url::Url;
|
|||
|
||||
pub mod comment;
|
||||
pub mod community;
|
||||
pub mod deletion;
|
||||
pub mod following;
|
||||
pub mod post;
|
||||
pub mod post_or_comment;
|
||||
pub mod private_message;
|
||||
pub mod removal;
|
||||
pub mod voting;
|
||||
|
||||
/// Checks that the specified Url actually identifies a Person (by fetching it), and that the person
|
||||
/// doesn't have a site ban.
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
use crate::activities::{
|
||||
comment::send_websocket_message as send_comment_message,
|
||||
post::send_websocket_message as send_post_message,
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::DeleteType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{
|
||||
fetcher::objects::get_or_fetch_and_insert_post_or_comment,
|
||||
ActorType,
|
||||
PostOrComment,
|
||||
};
|
||||
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::{
|
||||
source::{comment::Comment_, post::Post_},
|
||||
Crud,
|
||||
};
|
||||
use lemmy_db_schema::source::{comment::Comment, 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 DeletePostOrComment {
|
||||
to: PublicUrl,
|
||||
pub(in crate::activities::post_or_comment) object: Url,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: DeleteType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for DeletePostOrComment {
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self.common())?;
|
||||
verify_person_in_community(&self.common().actor, &self.cc, context, request_counter).await?;
|
||||
let object_creator =
|
||||
get_post_or_comment_actor_id(&self.object, context, request_counter).await?;
|
||||
verify_urls_match(&self.common.actor, &object_creator)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {
|
||||
PostOrComment::Post(post) => {
|
||||
let deleted_post = blocking(context.pool(), move |conn| {
|
||||
Post::update_deleted(conn, post.id, true)
|
||||
})
|
||||
.await??;
|
||||
send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
|
||||
}
|
||||
PostOrComment::Comment(comment) => {
|
||||
let deleted_comment = blocking(context.pool(), move |conn| {
|
||||
Comment::update_deleted(conn, comment.id, true)
|
||||
})
|
||||
.await??;
|
||||
send_comment_message(
|
||||
deleted_comment.id,
|
||||
vec![],
|
||||
UserOperationCrud::EditComment,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_post_or_comment_actor_id(
|
||||
object: &Url,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Url, LemmyError> {
|
||||
let actor_id =
|
||||
match get_or_fetch_and_insert_post_or_comment(object, context, request_counter).await? {
|
||||
PostOrComment::Post(post) => {
|
||||
let creator_id = post.creator_id;
|
||||
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
|
||||
.await??
|
||||
.actor_id()
|
||||
}
|
||||
PostOrComment::Comment(comment) => {
|
||||
let creator_id = comment.creator_id;
|
||||
blocking(context.pool(), move |conn| Person::read(conn, creator_id))
|
||||
.await??
|
||||
.actor_id()
|
||||
}
|
||||
};
|
||||
Ok(actor_id)
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
pub mod delete;
|
||||
pub mod dislike;
|
||||
pub mod like;
|
||||
pub mod remove;
|
||||
pub mod undo_delete;
|
||||
pub mod undo_dislike;
|
||||
pub mod undo_like;
|
||||
pub mod undo_remove;
|
||||
mod voting;
|
|
@ -1,75 +0,0 @@
|
|||
use crate::activities::{
|
||||
comment::send_websocket_message as send_comment_message,
|
||||
post::send_websocket_message as send_post_message,
|
||||
verify_activity,
|
||||
verify_mod_action,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::RemoveType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{fetcher::objects::get_or_fetch_and_insert_post_or_comment, PostOrComment};
|
||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::source::{comment::Comment_, post::Post_};
|
||||
use lemmy_db_schema::source::{comment::Comment, 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 RemovePostOrComment {
|
||||
to: PublicUrl,
|
||||
pub(in crate::activities::post_or_comment) object: Url,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: RemoveType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for RemovePostOrComment {
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self.common())?;
|
||||
verify_person_in_community(&self.common().actor, &self.cc, context, request_counter).await?;
|
||||
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
use crate::activities::{
|
||||
comment::send_websocket_message as send_comment_message,
|
||||
post::send_websocket_message as send_post_message,
|
||||
post_or_comment::delete::DeletePostOrComment,
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::UndoType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{fetcher::objects::get_or_fetch_and_insert_post_or_comment, PostOrComment};
|
||||
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::source::{comment::Comment_, post::Post_};
|
||||
use lemmy_db_schema::source::{comment::Comment, 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 UndoDeletePostOrComment {
|
||||
to: PublicUrl,
|
||||
object: DeletePostOrComment,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: UndoType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoDeletePostOrComment {
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self.common())?;
|
||||
verify_person_in_community(&self.common().actor, &self.cc, context, request_counter).await?;
|
||||
verify_urls_match(&self.common.actor, &self.object.common().actor)?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
match get_or_fetch_and_insert_post_or_comment(&self.object.object, context, request_counter)
|
||||
.await?
|
||||
{
|
||||
PostOrComment::Post(post) => {
|
||||
let deleted_post = blocking(context.pool(), move |conn| {
|
||||
Post::update_deleted(conn, post.id, false)
|
||||
})
|
||||
.await??;
|
||||
send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
|
||||
}
|
||||
PostOrComment::Comment(comment) => {
|
||||
let deleted_comment = blocking(context.pool(), move |conn| {
|
||||
Comment::update_deleted(conn, comment.id, false)
|
||||
})
|
||||
.await??;
|
||||
send_comment_message(
|
||||
deleted_comment.id,
|
||||
vec![],
|
||||
UserOperationCrud::EditComment,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
use crate::activities::{
|
||||
comment::send_websocket_message as send_comment_message,
|
||||
post::send_websocket_message as send_post_message,
|
||||
post_or_comment::remove::RemovePostOrComment,
|
||||
verify_activity,
|
||||
verify_mod_action,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::UndoType;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{fetcher::objects::get_or_fetch_and_insert_post_or_comment, PostOrComment};
|
||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
use lemmy_db_queries::source::{comment::Comment_, post::Post_};
|
||||
use lemmy_db_schema::source::{comment::Comment, 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 UndoRemovePostOrComment {
|
||||
to: PublicUrl,
|
||||
object: RemovePostOrComment,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: UndoType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoRemovePostOrComment {
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self.common())?;
|
||||
verify_person_in_community(&self.common().actor, &self.cc, 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
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
2
crates/apub_receive/src/activities/removal/mod.rs
Normal file
2
crates/apub_receive/src/activities/removal/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod remove;
|
||||
pub mod undo_remove;
|
115
crates/apub_receive/src/activities/removal/remove.rs
Normal file
115
crates/apub_receive/src/activities/removal/remove.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
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,
|
||||
verify_activity,
|
||||
verify_mod_action,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::RemoveType;
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{
|
||||
fetcher::{
|
||||
community::get_or_fetch_and_upsert_community,
|
||||
objects::get_or_fetch_and_insert_post_or_comment,
|
||||
},
|
||||
PostOrComment,
|
||||
};
|
||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
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 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 RemovePostCommentOrCommunity {
|
||||
to: PublicUrl,
|
||||
pub(in crate::activities::removal) object: Url,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: RemoveType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for RemovePostCommentOrCommunity {
|
||||
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 a post or comment
|
||||
else {
|
||||
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
|
||||
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
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 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
120
crates/apub_receive/src/activities/removal/undo_remove.rs
Normal file
120
crates/apub_receive/src/activities/removal/undo_remove.rs
Normal file
|
@ -0,0 +1,120 @@
|
|||
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::RemovePostCommentOrCommunity,
|
||||
verify_activity,
|
||||
verify_mod_action,
|
||||
verify_person_in_community,
|
||||
};
|
||||
use activitystreams::activity::kind::UndoType;
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub::{
|
||||
fetcher::{
|
||||
community::get_or_fetch_and_upsert_community,
|
||||
objects::get_or_fetch_and_insert_post_or_comment,
|
||||
},
|
||||
PostOrComment,
|
||||
};
|
||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
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 url::Url;
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoRemovePostCommentOrCommunity {
|
||||
to: PublicUrl,
|
||||
object: RemovePostCommentOrCommunity,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: UndoType,
|
||||
#[serde(flatten)]
|
||||
common: ActivityCommonFields,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoRemovePostCommentOrCommunity {
|
||||
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.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, 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
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn receive(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object_community =
|
||||
get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
|
||||
// restoring a community
|
||||
if let Ok(community) = object_community {
|
||||
if community.local {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn common(&self) -> &ActivityCommonFields {
|
||||
&self.common
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use crate::activities::{
|
||||
post_or_comment::voting::receive_like_or_dislike,
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
voting::receive_like_or_dislike,
|
||||
};
|
||||
use activitystreams::activity::kind::DislikeType;
|
||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
|
|
@ -1,7 +1,7 @@
|
|||
use crate::activities::{
|
||||
post_or_comment::voting::receive_like_or_dislike,
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
voting::receive_like_or_dislike,
|
||||
};
|
||||
use activitystreams::activity::kind::LikeType;
|
||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
|
||||
|
@ -13,7 +13,7 @@ use url::Url;
|
|||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LikePostOrComment {
|
||||
to: PublicUrl,
|
||||
pub(in crate::activities::post_or_comment) object: Url,
|
||||
pub(in crate::activities::voting) object: Url,
|
||||
cc: [Url; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: LikeType,
|
|
@ -20,7 +20,12 @@ use lemmy_websocket::{LemmyContext, UserOperation};
|
|||
use std::ops::Deref;
|
||||
use url::Url;
|
||||
|
||||
pub(in crate::activities::post_or_comment) async fn receive_like_or_dislike(
|
||||
pub mod dislike;
|
||||
pub mod like;
|
||||
pub mod undo_dislike;
|
||||
pub mod undo_like;
|
||||
|
||||
pub(in crate::activities::voting) async fn receive_like_or_dislike(
|
||||
score: i16,
|
||||
actor: &Url,
|
||||
object: &Url,
|
||||
|
@ -94,7 +99,7 @@ async fn like_or_dislike_post(
|
|||
send_post_message(post.id, UserOperation::CreatePostLike, context).await
|
||||
}
|
||||
|
||||
pub(in crate::activities::post_or_comment) async fn receive_undo_like_or_dislike(
|
||||
pub(in crate::activities::voting) async fn receive_undo_like_or_dislike(
|
||||
actor: &Url,
|
||||
object: &Url,
|
||||
context: &LemmyContext,
|
|
@ -1,7 +1,7 @@
|
|||
use crate::activities::{
|
||||
post_or_comment::{dislike::DislikePostOrComment, voting::receive_undo_like_or_dislike},
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
voting::{dislike::DislikePostOrComment, receive_undo_like_or_dislike},
|
||||
};
|
||||
use activitystreams::activity::kind::UndoType;
|
||||
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
|
@ -1,7 +1,7 @@
|
|||
use crate::activities::{
|
||||
post_or_comment::{like::LikePostOrComment, voting::receive_undo_like_or_dislike},
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
voting::{like::LikePostOrComment, receive_undo_like_or_dislike},
|
||||
};
|
||||
use activitystreams::activity::kind::UndoType;
|
||||
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler, PublicUrl};
|
|
@ -4,32 +4,26 @@ use crate::activities::{
|
|||
add_mod::AddMod,
|
||||
announce::AnnounceActivity,
|
||||
block_user::BlockUserFromCommunity,
|
||||
delete::DeleteCommunity,
|
||||
remove::RemoveCommunity,
|
||||
remove_mod::RemoveMod,
|
||||
undo_block_user::UndoBlockUserFromCommunity,
|
||||
undo_delete::UndoDeleteCommunity,
|
||||
undo_remove::UndoRemoveCommunity,
|
||||
update::UpdateCommunity,
|
||||
},
|
||||
deletion::{delete::DeletePostCommentOrCommunity, undo_delete::UndoDeletePostCommentOrCommunity},
|
||||
following::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity},
|
||||
post::{create::CreatePost, update::UpdatePost},
|
||||
post_or_comment::{
|
||||
delete::DeletePostOrComment,
|
||||
dislike::DislikePostOrComment,
|
||||
like::LikePostOrComment,
|
||||
remove::RemovePostOrComment,
|
||||
undo_delete::UndoDeletePostOrComment,
|
||||
undo_dislike::UndoDislikePostOrComment,
|
||||
undo_like::UndoLikePostOrComment,
|
||||
undo_remove::UndoRemovePostOrComment,
|
||||
},
|
||||
private_message::{
|
||||
create::CreatePrivateMessage,
|
||||
delete::DeletePrivateMessage,
|
||||
undo_delete::UndoDeletePrivateMessage,
|
||||
update::UpdatePrivateMessage,
|
||||
},
|
||||
removal::{remove::RemovePostCommentOrCommunity, undo_remove::UndoRemovePostCommentOrCommunity},
|
||||
voting::{
|
||||
dislike::DislikePostOrComment,
|
||||
like::LikePostOrComment,
|
||||
undo_dislike::UndoDislikePostOrComment,
|
||||
undo_like::UndoLikePostOrComment,
|
||||
},
|
||||
};
|
||||
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler};
|
||||
use lemmy_utils::LemmyError;
|
||||
|
@ -60,15 +54,11 @@ pub enum GroupInboxActivities {
|
|||
DislikePostOrComment(DislikePostOrComment),
|
||||
UndoLikePostOrComment(UndoLikePostOrComment),
|
||||
UndoDislikePostOrComment(UndoDislikePostOrComment),
|
||||
DeletePostOrComment(DeletePostOrComment),
|
||||
UndoDeletePostOrComment(UndoDeletePostOrComment),
|
||||
RemovePostOrComment(RemovePostOrComment),
|
||||
UndoRemovePostOrComment(UndoRemovePostOrComment),
|
||||
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
|
||||
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
|
||||
RemovePostCommentOrCommunity(RemovePostCommentOrCommunity),
|
||||
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
||||
UpdateCommunity(Box<UpdateCommunity>),
|
||||
DeleteCommunity(DeleteCommunity),
|
||||
RemoveCommunity(RemoveCommunity),
|
||||
UndoDeleteCommunity(UndoDeleteCommunity),
|
||||
UndoRemoveCommunity(UndoRemoveCommunity),
|
||||
BlockUserFromCommunity(BlockUserFromCommunity),
|
||||
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
||||
AddMod(AddMod),
|
||||
|
@ -89,15 +79,11 @@ pub enum SharedInboxActivities {
|
|||
DislikePostOrComment(DislikePostOrComment),
|
||||
UndoDislikePostOrComment(UndoDislikePostOrComment),
|
||||
UndoLikePostOrComment(UndoLikePostOrComment),
|
||||
DeletePostOrComment(DeletePostOrComment),
|
||||
UndoDeletePostOrComment(UndoDeletePostOrComment),
|
||||
RemovePostOrComment(RemovePostOrComment),
|
||||
UndoRemovePostOrComment(UndoRemovePostOrComment),
|
||||
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
|
||||
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
|
||||
RemovePostCommentOrCommunity(RemovePostCommentOrCommunity),
|
||||
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
|
||||
UpdateCommunity(Box<UpdateCommunity>),
|
||||
DeleteCommunity(DeleteCommunity),
|
||||
RemoveCommunity(RemoveCommunity),
|
||||
UndoDeleteCommunity(UndoDeleteCommunity),
|
||||
UndoRemoveCommunity(UndoRemoveCommunity),
|
||||
BlockUserFromCommunity(BlockUserFromCommunity),
|
||||
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
|
||||
AddMod(AddMod),
|
||||
|
|
Loading…
Reference in a new issue