mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-23 04:41:19 +00:00
Implement federated bans (fixes #1298)
This commit is contained in:
parent
df7fe705eb
commit
45b39699a5
7 changed files with 212 additions and 14 deletions
|
@ -134,6 +134,15 @@ impl Perform for BanFromCommunity {
|
|||
person_id: data.person_id,
|
||||
};
|
||||
|
||||
let community = blocking(context.pool(), move |conn: &'_ _| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
let banned_person = blocking(context.pool(), move |conn: &'_ _| {
|
||||
Person::read(conn, banned_person_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
if data.ban {
|
||||
let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
|
||||
if blocking(context.pool(), ban).await?.is_err() {
|
||||
|
@ -151,11 +160,17 @@ impl Perform for BanFromCommunity {
|
|||
})
|
||||
.await?
|
||||
.ok();
|
||||
community
|
||||
.send_block_user(&local_user_view.person, banned_person, context)
|
||||
.await?;
|
||||
} else {
|
||||
let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
|
||||
if blocking(context.pool(), unban).await?.is_err() {
|
||||
return Err(ApiError::err("community_user_already_banned").into());
|
||||
}
|
||||
community
|
||||
.send_undo_block_user(&local_user_view.person, banned_person, context)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Remove/Restore their data if that's desired
|
||||
|
|
|
@ -11,11 +11,21 @@ use crate::{
|
|||
};
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
kind::{AcceptType, AddType, AnnounceType, DeleteType, LikeType, RemoveType, UndoType},
|
||||
kind::{
|
||||
AcceptType,
|
||||
AddType,
|
||||
AnnounceType,
|
||||
BlockType,
|
||||
DeleteType,
|
||||
LikeType,
|
||||
RemoveType,
|
||||
UndoType,
|
||||
},
|
||||
Accept,
|
||||
ActorAndObjectRefExt,
|
||||
Add,
|
||||
Announce,
|
||||
Block,
|
||||
Delete,
|
||||
Follow,
|
||||
OptTargetRefExt,
|
||||
|
@ -170,7 +180,7 @@ impl CommunityType for Community {
|
|||
insert_activity(inner_id, activity.clone(), true, false, context.pool()).await?;
|
||||
}
|
||||
|
||||
let mut announce = Announce::new(self.actor_id.to_owned().into_inner(), activity);
|
||||
let mut announce = Announce::new(self.actor_id(), activity);
|
||||
announce
|
||||
.set_many_contexts(lemmy_context()?)
|
||||
.set_id(generate_activity_id(AnnounceType::Announce)?)
|
||||
|
@ -209,10 +219,7 @@ impl CommunityType for Community {
|
|||
added_mod: Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let mut add = Add::new(
|
||||
actor.actor_id.clone().into_inner(),
|
||||
added_mod.actor_id.into_inner(),
|
||||
);
|
||||
let mut add = Add::new(actor.actor_id(), added_mod.actor_id());
|
||||
add
|
||||
.set_many_contexts(lemmy_context()?)
|
||||
.set_id(generate_activity_id(AddType::Add)?)
|
||||
|
@ -230,10 +237,7 @@ impl CommunityType for Community {
|
|||
removed_mod: Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let mut remove = Remove::new(
|
||||
actor.actor_id.clone().into_inner(),
|
||||
removed_mod.actor_id.into_inner(),
|
||||
);
|
||||
let mut remove = Remove::new(actor.actor_id(), removed_mod.actor_id());
|
||||
remove
|
||||
.set_many_contexts(lemmy_context()?)
|
||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||
|
@ -244,4 +248,46 @@ impl CommunityType for Community {
|
|||
send_to_community(remove, &actor, self, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// / TODO: also need to implement the Undo for this
|
||||
async fn send_block_user(
|
||||
&self,
|
||||
actor: &Person,
|
||||
blocked_user: Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let mut block = Block::new(actor.actor_id(), blocked_user.actor_id());
|
||||
block
|
||||
.set_many_contexts(lemmy_context()?)
|
||||
.set_id(generate_activity_id(BlockType::Block)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![self.actor_id()]);
|
||||
|
||||
send_to_community(block, &actor, self, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_undo_block_user(
|
||||
&self,
|
||||
actor: &Person,
|
||||
blocked_user: Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let mut block = Block::new(actor.actor_id(), blocked_user.actor_id());
|
||||
block
|
||||
.set_many_contexts(lemmy_context()?)
|
||||
.set_id(generate_activity_id(BlockType::Block)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![self.actor_id()]);
|
||||
|
||||
// Undo that fake activity
|
||||
let mut undo = Undo::new(actor.actor_id(), block.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.clone().into_inner()]);
|
||||
send_to_community(undo, &actor, self, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ impl UserType for Person {
|
|||
})
|
||||
.await?;
|
||||
|
||||
let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id());
|
||||
let mut follow = Follow::new(self.actor_id(), community.actor_id());
|
||||
follow
|
||||
.set_many_contexts(lemmy_context()?)
|
||||
.set_id(generate_activity_id(FollowType::Follow)?)
|
||||
|
@ -95,7 +95,7 @@ impl UserType for Person {
|
|||
})
|
||||
.await??;
|
||||
|
||||
let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id());
|
||||
let mut follow = Follow::new(self.actor_id(), community.actor_id());
|
||||
follow
|
||||
.set_many_contexts(lemmy_context()?)
|
||||
.set_id(generate_activity_id(FollowType::Follow)?)
|
||||
|
|
|
@ -222,6 +222,19 @@ pub trait CommunityType {
|
|||
removed_mod: Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError>;
|
||||
|
||||
async fn send_block_user(
|
||||
&self,
|
||||
actor: &Person,
|
||||
blocked_user: Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError>;
|
||||
async fn send_undo_block_user(
|
||||
&self,
|
||||
actor: &Person,
|
||||
blocked_user: Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
|||
is_activity_already_known,
|
||||
receive_for_community::{
|
||||
receive_add_for_community,
|
||||
receive_block_user_for_community,
|
||||
receive_create_for_community,
|
||||
receive_delete_for_community,
|
||||
receive_dislike_for_community,
|
||||
|
@ -58,6 +59,7 @@ pub enum CommunityValidTypes {
|
|||
Delete, // post or comment deleted by creator
|
||||
Remove, // post or comment removed by mod or admin, or mod removed from community
|
||||
Add, // mod added to community
|
||||
Block, // user blocked by community
|
||||
}
|
||||
|
||||
pub type CommunityAcceptedActivities = ActorAndObject<CommunityValidTypes>;
|
||||
|
@ -224,6 +226,16 @@ pub(crate) async fn community_receive_message(
|
|||
.await?;
|
||||
true
|
||||
}
|
||||
CommunityValidTypes::Block => {
|
||||
Box::pin(receive_block_user_for_community(
|
||||
context,
|
||||
any_base.clone(),
|
||||
None,
|
||||
request_counter,
|
||||
))
|
||||
.await?;
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
if do_announce {
|
||||
|
|
|
@ -25,6 +25,7 @@ use crate::{
|
|||
is_addressed_to_local_person,
|
||||
receive_for_community::{
|
||||
receive_add_for_community,
|
||||
receive_block_user_for_community,
|
||||
receive_create_for_community,
|
||||
receive_delete_for_community,
|
||||
receive_dislike_for_community,
|
||||
|
@ -276,6 +277,7 @@ enum AnnouncableActivities {
|
|||
Remove,
|
||||
Undo,
|
||||
Add,
|
||||
Block,
|
||||
}
|
||||
|
||||
/// Takes an announce and passes the inner activity to the appropriate handler.
|
||||
|
@ -352,6 +354,10 @@ pub async fn receive_announce(
|
|||
Some(Add) => {
|
||||
receive_add_for_community(context, inner_activity, Some(announce), request_counter).await
|
||||
}
|
||||
Some(Block) => {
|
||||
receive_block_user_for_community(context, inner_activity, Some(announce), request_counter)
|
||||
.await
|
||||
}
|
||||
_ => receive_unhandled_activity(inner_activity),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ use activitystreams::{
|
|||
ActorAndObjectRef,
|
||||
Add,
|
||||
Announce,
|
||||
Block,
|
||||
Create,
|
||||
Delete,
|
||||
Dislike,
|
||||
|
@ -64,10 +65,25 @@ use lemmy_apub::{
|
|||
CommunityType,
|
||||
PostOrComment,
|
||||
};
|
||||
use lemmy_db_queries::{source::community::CommunityModerator_, ApubObject, Crud, Joinable};
|
||||
use lemmy_db_queries::{
|
||||
source::community::CommunityModerator_,
|
||||
ApubObject,
|
||||
Bannable,
|
||||
Crud,
|
||||
Followable,
|
||||
Joinable,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityFollowerForm,
|
||||
CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
},
|
||||
person::Person,
|
||||
site::Site,
|
||||
},
|
||||
|
@ -271,6 +287,7 @@ enum UndoableActivities {
|
|||
Remove,
|
||||
Like,
|
||||
Dislike,
|
||||
Block,
|
||||
}
|
||||
|
||||
/// A post/comment action being reverted (either a delete, remove, upvote or downvote)
|
||||
|
@ -301,6 +318,16 @@ pub(in crate::inbox) async fn receive_undo_for_community(
|
|||
Some(Dislike) => {
|
||||
receive_undo_dislike_for_community(context, undo, expected_domain, request_counter).await
|
||||
}
|
||||
Some(Block) => {
|
||||
receive_undo_block_user_for_community(
|
||||
context,
|
||||
undo,
|
||||
announce,
|
||||
expected_domain,
|
||||
request_counter,
|
||||
)
|
||||
.await
|
||||
}
|
||||
_ => receive_unhandled_activity(undo),
|
||||
}
|
||||
}
|
||||
|
@ -451,6 +478,85 @@ pub(in crate::inbox) async fn receive_undo_dislike_for_community(
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn receive_block_user_for_community(
|
||||
context: &LemmyContext,
|
||||
block_any_base: AnyBase,
|
||||
announce: Option<Announce>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let block = Block::from_any_base(block_any_base.to_owned())?.context(location_info!())?;
|
||||
let community = extract_community_from_cc(&block, context).await?;
|
||||
|
||||
verify_mod_activity(&block, announce, &community, context).await?;
|
||||
verify_is_addressed_to_public(&block)?;
|
||||
|
||||
let blocked_user = block
|
||||
.object()
|
||||
.as_single_xsd_any_uri()
|
||||
.context(location_info!())?;
|
||||
let blocked_user =
|
||||
get_or_fetch_and_upsert_person(&blocked_user, context, request_counter).await?;
|
||||
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
community_id: community.id,
|
||||
person_id: blocked_user.id,
|
||||
};
|
||||
|
||||
blocking(context.pool(), move |conn: &'_ _| {
|
||||
CommunityPersonBan::ban(conn, &community_user_ban_form)
|
||||
})
|
||||
.await??;
|
||||
|
||||
// Also unsubscribe them from the community, if they are subscribed
|
||||
let community_follower_form = CommunityFollowerForm {
|
||||
community_id: community.id,
|
||||
person_id: blocked_user.id,
|
||||
pending: false,
|
||||
};
|
||||
blocking(context.pool(), move |conn: &'_ _| {
|
||||
CommunityFollower::unfollow(conn, &community_follower_form)
|
||||
})
|
||||
.await?
|
||||
.ok();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn receive_undo_block_user_for_community(
|
||||
context: &LemmyContext,
|
||||
undo: Undo,
|
||||
announce: Option<Announce>,
|
||||
expected_domain: &Url,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object = undo.object().clone().one().context(location_info!())?;
|
||||
let block = Block::from_any_base(object)?.context(location_info!())?;
|
||||
let community = extract_community_from_cc(&block, context).await?;
|
||||
|
||||
verify_activity_domains_valid(&block, &expected_domain, false)?;
|
||||
verify_is_addressed_to_public(&block)?;
|
||||
verify_undo_remove_actor_instance(&undo, &block, &announce, context).await?;
|
||||
|
||||
let blocked_user = block
|
||||
.object()
|
||||
.as_single_xsd_any_uri()
|
||||
.context(location_info!())?;
|
||||
let blocked_user =
|
||||
get_or_fetch_and_upsert_person(&blocked_user, context, request_counter).await?;
|
||||
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
community_id: community.id,
|
||||
person_id: blocked_user.id,
|
||||
};
|
||||
|
||||
blocking(context.pool(), move |conn: &'_ _| {
|
||||
CommunityPersonBan::unban(conn, &community_user_ban_form)
|
||||
})
|
||||
.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn fetch_post_or_comment_by_id(
|
||||
apub_id: &Url,
|
||||
context: &LemmyContext,
|
||||
|
|
Loading…
Reference in a new issue