* Implement federated bans (fixes #1298) * mod actions should always be federated to affected user, in addition to followers * Make Undo/Block work for remote mods * clippy fix * fix federation test * vscodium doesnt auto-save changes...
This commit is contained in:
parent
89dd0f2925
commit
aa79c5131f
12 changed files with 335 additions and 113 deletions
|
@ -340,17 +340,9 @@ test('Enforce community ban for federated user', async () => {
|
||||||
let banAlpha = await banPersonFromCommunity(beta, alphaUser.person.id, 2, true);
|
let banAlpha = await banPersonFromCommunity(beta, alphaUser.person.id, 2, true);
|
||||||
expect(banAlpha.banned).toBe(true);
|
expect(banAlpha.banned).toBe(true);
|
||||||
|
|
||||||
// Alpha makes post on beta
|
// Alpha tries to make post on beta, but it fails because of ban
|
||||||
let postRes = await createPost(alpha, betaCommunity.community.id);
|
let postRes = await createPost(alpha, betaCommunity.community.id);
|
||||||
expect(postRes.post_view.post).toBeDefined();
|
expect(postRes.post_view).toBeUndefined();
|
||||||
expect(postRes.post_view.community.local).toBe(false);
|
|
||||||
expect(postRes.post_view.creator.local).toBe(true);
|
|
||||||
expect(postRes.post_view.counts.score).toBe(1);
|
|
||||||
|
|
||||||
// Make sure that post doesn't make it to beta community
|
|
||||||
let searchBeta = await searchPostLocal(beta, postRes.post_view.post);
|
|
||||||
let betaPost = searchBeta.posts[0];
|
|
||||||
expect(betaPost).toBeUndefined();
|
|
||||||
|
|
||||||
// Unban alpha
|
// Unban alpha
|
||||||
let unBanAlpha = await banPersonFromCommunity(
|
let unBanAlpha = await banPersonFromCommunity(
|
||||||
|
@ -360,4 +352,14 @@ test('Enforce community ban for federated user', async () => {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
expect(unBanAlpha.banned).toBe(false);
|
expect(unBanAlpha.banned).toBe(false);
|
||||||
|
let postRes2 = await createPost(alpha, betaCommunity.community.id);
|
||||||
|
expect(postRes2.post_view.post).toBeDefined();
|
||||||
|
expect(postRes2.post_view.community.local).toBe(false);
|
||||||
|
expect(postRes2.post_view.creator.local).toBe(true);
|
||||||
|
expect(postRes2.post_view.counts.score).toBe(1);
|
||||||
|
|
||||||
|
// Make sure that post makes it to beta community
|
||||||
|
let searchBeta = await searchPostLocal(beta, postRes2.post_view.post);
|
||||||
|
let betaPost = searchBeta.posts[0];
|
||||||
|
expect(betaPost).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
|
@ -130,6 +130,15 @@ impl Perform for BanFromCommunity {
|
||||||
person_id: data.person_id,
|
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 {
|
if data.ban {
|
||||||
let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
|
let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
|
||||||
if blocking(context.pool(), ban).await?.is_err() {
|
if blocking(context.pool(), ban).await?.is_err() {
|
||||||
|
@ -147,11 +156,18 @@ impl Perform for BanFromCommunity {
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
community
|
||||||
|
.send_block_user(&local_user_view.person, banned_person, context)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
|
let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
|
||||||
if blocking(context.pool(), unban).await?.is_err() {
|
if blocking(context.pool(), unban).await?.is_err() {
|
||||||
return Err(ApiError::err("community_user_already_banned").into());
|
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
|
// Remove/Restore their data if that's desired
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl ApubObjectType for Comment {
|
||||||
// Set the mention tags
|
// Set the mention tags
|
||||||
.set_many_tags(maa.get_tags()?);
|
.set_many_tags(maa.get_tags()?);
|
||||||
|
|
||||||
send_to_community(create.clone(), &creator, &community, context).await?;
|
send_to_community(create.clone(), &creator, &community, None, context).await?;
|
||||||
send_comment_mentions(&creator, maa.inboxes, create, context).await?;
|
send_comment_mentions(&creator, maa.inboxes, create, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ impl ApubObjectType for Comment {
|
||||||
// Set the mention tags
|
// Set the mention tags
|
||||||
.set_many_tags(maa.get_tags()?);
|
.set_many_tags(maa.get_tags()?);
|
||||||
|
|
||||||
send_to_community(update.clone(), &creator, &community, context).await?;
|
send_to_community(update.clone(), &creator, &community, None, context).await?;
|
||||||
send_comment_mentions(&creator, maa.inboxes, update, context).await?;
|
send_comment_mentions(&creator, maa.inboxes, update, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ impl ApubObjectType for Comment {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(delete, &creator, &community, context).await?;
|
send_to_community(delete, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ impl ApubObjectType for Comment {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(undo, &creator, &community, context).await?;
|
send_to_community(undo, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ impl ApubObjectType for Comment {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(remove, &mod_, &community, context).await?;
|
send_to_community(remove, &mod_, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ impl ApubObjectType for Comment {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(undo, &mod_, &community, context).await?;
|
send_to_community(undo, &mod_, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ impl ApubLikeableType for Comment {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(like, &creator, &community, context).await?;
|
send_to_community(like, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ impl ApubLikeableType for Comment {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(dislike, &creator, &community, context).await?;
|
send_to_community(dislike, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ impl ApubLikeableType for Comment {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(undo, &creator, &community, context).await?;
|
send_to_community(undo, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
activity_queue::{send_activity_single_dest, send_to_community, send_to_community_followers},
|
activity_queue::{send_activity_single_dest, send_to_community, send_to_community_followers},
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
extensions::context::lemmy_context,
|
extensions::context::lemmy_context,
|
||||||
fetcher::person::get_or_fetch_and_upsert_person,
|
fetcher::{get_or_fetch_and_upsert_actor, person::get_or_fetch_and_upsert_person},
|
||||||
generate_moderators_url,
|
generate_moderators_url,
|
||||||
insert_activity,
|
insert_activity,
|
||||||
ActorType,
|
ActorType,
|
||||||
|
@ -11,11 +11,21 @@ use crate::{
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::{
|
activity::{
|
||||||
kind::{AcceptType, AddType, AnnounceType, DeleteType, LikeType, RemoveType, UndoType},
|
kind::{
|
||||||
|
AcceptType,
|
||||||
|
AddType,
|
||||||
|
AnnounceType,
|
||||||
|
BlockType,
|
||||||
|
DeleteType,
|
||||||
|
LikeType,
|
||||||
|
RemoveType,
|
||||||
|
UndoType,
|
||||||
|
},
|
||||||
Accept,
|
Accept,
|
||||||
ActorAndObjectRefExt,
|
ActorAndObjectRefExt,
|
||||||
Add,
|
Add,
|
||||||
Announce,
|
Announce,
|
||||||
|
Block,
|
||||||
Delete,
|
Delete,
|
||||||
Follow,
|
Follow,
|
||||||
OptTargetRefExt,
|
OptTargetRefExt,
|
||||||
|
@ -62,6 +72,10 @@ impl ActorType for Community {
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl CommunityType for Community {
|
impl CommunityType for Community {
|
||||||
|
fn followers_url(&self) -> Url {
|
||||||
|
self.followers_url.clone().into_inner()
|
||||||
|
}
|
||||||
|
|
||||||
/// As a local community, accept the follow request from a remote person.
|
/// As a local community, accept the follow request from a remote person.
|
||||||
async fn send_accept_follow(
|
async fn send_accept_follow(
|
||||||
&self,
|
&self,
|
||||||
|
@ -94,9 +108,9 @@ impl CommunityType for Community {
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.followers_url.clone().into_inner()]);
|
.set_many_ccs(vec![self.followers_url()]);
|
||||||
|
|
||||||
send_to_community_followers(delete, self, context).await?;
|
send_to_community_followers(delete, self, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,16 +121,16 @@ impl CommunityType for Community {
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.followers_url.clone().into_inner()]);
|
.set_many_ccs(vec![self.followers_url()]);
|
||||||
|
|
||||||
let mut undo = Undo::new(self.actor_id(), delete.into_any_base()?);
|
let mut undo = Undo::new(self.actor_id(), delete.into_any_base()?);
|
||||||
undo
|
undo
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
.set_id(generate_activity_id(UndoType::Undo)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.followers_url.clone().into_inner()]);
|
.set_many_ccs(vec![self.followers_url()]);
|
||||||
|
|
||||||
send_to_community_followers(undo, self, context).await?;
|
send_to_community_followers(undo, self, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,9 +141,9 @@ impl CommunityType for Community {
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.followers_url.clone().into_inner()]);
|
.set_many_ccs(vec![self.followers_url()]);
|
||||||
|
|
||||||
send_to_community_followers(remove, self, context).await?;
|
send_to_community_followers(remove, self, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +154,7 @@ impl CommunityType for Community {
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.followers_url.clone().into_inner()]);
|
.set_many_ccs(vec![self.followers_url()]);
|
||||||
|
|
||||||
// Undo that fake activity
|
// Undo that fake activity
|
||||||
let mut undo = Undo::new(self.actor_id(), remove.into_any_base()?);
|
let mut undo = Undo::new(self.actor_id(), remove.into_any_base()?);
|
||||||
|
@ -148,9 +162,9 @@ impl CommunityType for Community {
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(LikeType::Like)?)
|
.set_id(generate_activity_id(LikeType::Like)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.followers_url.clone().into_inner()]);
|
.set_many_ccs(vec![self.followers_url()]);
|
||||||
|
|
||||||
send_to_community_followers(undo, self, context).await?;
|
send_to_community_followers(undo, self, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,9 +174,13 @@ impl CommunityType for Community {
|
||||||
/// If we are announcing a local activity, it hasn't been stored in the database yet, and we need
|
/// If we are announcing a local activity, it hasn't been stored in the database yet, and we need
|
||||||
/// to do it here, so that it can be fetched by ID. Remote activities are inserted into DB in the
|
/// to do it here, so that it can be fetched by ID. Remote activities are inserted into DB in the
|
||||||
/// inbox.
|
/// inbox.
|
||||||
|
///
|
||||||
|
/// If the `object` of the announced activity is an actor, the actor ID needs to be passed as
|
||||||
|
/// `object_actor`, so that the announce can be delivered to that user.
|
||||||
async fn send_announce(
|
async fn send_announce(
|
||||||
&self,
|
&self,
|
||||||
activity: AnyBase,
|
activity: AnyBase,
|
||||||
|
object_actor: Option<Url>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let inner_id = activity.id().context(location_info!())?;
|
let inner_id = activity.id().context(location_info!())?;
|
||||||
|
@ -170,14 +188,27 @@ impl CommunityType for Community {
|
||||||
insert_activity(inner_id, activity.clone(), true, false, context.pool()).await?;
|
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 ccs = vec![self.followers_url()];
|
||||||
|
let mut object_actor_inbox: Option<Url> = None;
|
||||||
|
if let Some(actor_id) = object_actor {
|
||||||
|
// Ignore errors, maybe its not actually an actor
|
||||||
|
// TODO: should pass the actual request counter in, but that seems complicated
|
||||||
|
let actor = get_or_fetch_and_upsert_actor(&actor_id, context, &mut 0)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
if let Some(actor) = actor {
|
||||||
|
ccs.push(actor_id);
|
||||||
|
object_actor_inbox = Some(actor.get_shared_inbox_or_inbox_url());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut announce = Announce::new(self.actor_id(), activity);
|
||||||
announce
|
announce
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(AnnounceType::Announce)?)
|
.set_id(generate_activity_id(AnnounceType::Announce)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.followers_url.clone().into_inner()]);
|
.set_many_ccs(ccs);
|
||||||
|
|
||||||
send_to_community_followers(announce, self, context).await?;
|
send_to_community_followers(announce, self, object_actor_inbox, context).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -209,10 +240,7 @@ impl CommunityType for Community {
|
||||||
added_mod: Person,
|
added_mod: Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let mut add = Add::new(
|
let mut add = Add::new(actor.actor_id(), added_mod.actor_id());
|
||||||
actor.actor_id.clone().into_inner(),
|
|
||||||
added_mod.actor_id.into_inner(),
|
|
||||||
);
|
|
||||||
add
|
add
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(AddType::Add)?)
|
.set_id(generate_activity_id(AddType::Add)?)
|
||||||
|
@ -220,7 +248,7 @@ impl CommunityType for Community {
|
||||||
.set_many_ccs(vec![self.actor_id()])
|
.set_many_ccs(vec![self.actor_id()])
|
||||||
.set_target(generate_moderators_url(&self.actor_id)?.into_inner());
|
.set_target(generate_moderators_url(&self.actor_id)?.into_inner());
|
||||||
|
|
||||||
send_to_community(add, actor, self, context).await?;
|
send_to_community(add, actor, self, Some(added_mod.actor_id()), context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,10 +258,7 @@ impl CommunityType for Community {
|
||||||
removed_mod: Person,
|
removed_mod: Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let mut remove = Remove::new(
|
let mut remove = Remove::new(actor.actor_id(), removed_mod.actor_id());
|
||||||
actor.actor_id.clone().into_inner(),
|
|
||||||
removed_mod.actor_id.into_inner(),
|
|
||||||
);
|
|
||||||
remove
|
remove
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||||
|
@ -241,7 +266,49 @@ impl CommunityType for Community {
|
||||||
.set_many_ccs(vec![self.actor_id()])
|
.set_many_ccs(vec![self.actor_id()])
|
||||||
.set_target(generate_moderators_url(&self.actor_id)?.into_inner());
|
.set_target(generate_moderators_url(&self.actor_id)?.into_inner());
|
||||||
|
|
||||||
send_to_community(remove, &actor, self, context).await?;
|
send_to_community(remove, &actor, self, Some(removed_mod.actor_id()), context).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
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, Some(blocked_user.actor_id()), context).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_undo_block_user(
|
||||||
|
&self,
|
||||||
|
actor: &Person,
|
||||||
|
unblocked_user: Person,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let mut block = Block::new(actor.actor_id(), unblocked_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.actor_id()]);
|
||||||
|
|
||||||
|
send_to_community(undo, &actor, self, Some(unblocked_user.actor_id()), context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl UserType for Person {
|
||||||
})
|
})
|
||||||
.await?;
|
.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
|
follow
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(FollowType::Follow)?)
|
.set_id(generate_activity_id(FollowType::Follow)?)
|
||||||
|
@ -95,7 +95,7 @@ impl UserType for Person {
|
||||||
})
|
})
|
||||||
.await??;
|
.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
|
follow
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(FollowType::Follow)?)
|
.set_id(generate_activity_id(FollowType::Follow)?)
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl ApubObjectType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(create, creator, &community, context).await?;
|
send_to_community(create, creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ impl ApubObjectType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(update, creator, &community, context).await?;
|
send_to_community(update, creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ impl ApubObjectType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(delete, creator, &community, context).await?;
|
send_to_community(delete, creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ impl ApubObjectType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(undo, creator, &community, context).await?;
|
send_to_community(undo, creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ impl ApubObjectType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(remove, mod_, &community, context).await?;
|
send_to_community(remove, mod_, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ impl ApubObjectType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(undo, mod_, &community, context).await?;
|
send_to_community(undo, mod_, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ impl ApubLikeableType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(like, &creator, &community, context).await?;
|
send_to_community(like, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ impl ApubLikeableType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(dislike, &creator, &community, context).await?;
|
send_to_community(dislike, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ impl ApubLikeableType for Post {
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![community.actor_id()]);
|
.set_many_ccs(vec![community.actor_id()]);
|
||||||
|
|
||||||
send_to_community(undo, &creator, &community, context).await?;
|
send_to_community(undo, &creator, &community, None, context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ use background_jobs::{
|
||||||
WorkerConfig,
|
WorkerConfig,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_db_queries::DbPool;
|
|
||||||
use lemmy_db_schema::source::{community::Community, person::Person};
|
use lemmy_db_schema::source::{community::Community, person::Person};
|
||||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -53,16 +52,7 @@ where
|
||||||
&activity.id_unchecked(),
|
&activity.id_unchecked(),
|
||||||
&inbox
|
&inbox
|
||||||
);
|
);
|
||||||
send_activity_internal(
|
send_activity_internal(context, activity, creator, vec![inbox], true, true).await?;
|
||||||
context.activity_queue(),
|
|
||||||
activity,
|
|
||||||
creator,
|
|
||||||
vec![inbox],
|
|
||||||
context.pool(),
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -72,11 +62,11 @@ where
|
||||||
///
|
///
|
||||||
/// * `activity` the apub activity to send
|
/// * `activity` the apub activity to send
|
||||||
/// * `community` the sending community
|
/// * `community` the sending community
|
||||||
/// * `sender_shared_inbox` in case of an announce, this should be the shared inbox of the inner
|
/// * `extra_inbox` actor inbox which should receive the activity, in addition to followers
|
||||||
/// activities creator, as receiving a known activity will cause an error
|
|
||||||
pub(crate) async fn send_to_community_followers<T, Kind>(
|
pub(crate) async fn send_to_community_followers<T, Kind>(
|
||||||
activity: T,
|
activity: T,
|
||||||
community: &Community,
|
community: &Community,
|
||||||
|
extra_inbox: Option<Url>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError>
|
) -> Result<(), LemmyError>
|
||||||
where
|
where
|
||||||
|
@ -84,31 +74,25 @@ where
|
||||||
Kind: Serialize,
|
Kind: Serialize,
|
||||||
<T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static,
|
<T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let follower_inboxes: Vec<Url> = community
|
let extra_inbox: Vec<Url> = extra_inbox.into_iter().collect();
|
||||||
.get_follower_inboxes(context.pool())
|
let follower_inboxes: Vec<Url> = vec![
|
||||||
.await?
|
community.get_follower_inboxes(context.pool()).await?,
|
||||||
.iter()
|
extra_inbox,
|
||||||
.unique()
|
]
|
||||||
.filter(|inbox| inbox.host_str() != Some(&Settings::get().hostname()))
|
.iter()
|
||||||
.filter(|inbox| check_is_apub_id_valid(inbox).is_ok())
|
.flatten()
|
||||||
.map(|inbox| inbox.to_owned())
|
.unique()
|
||||||
.collect();
|
.filter(|inbox| inbox.host_str() != Some(&Settings::get().hostname()))
|
||||||
|
.filter(|inbox| check_is_apub_id_valid(inbox).is_ok())
|
||||||
|
.map(|inbox| inbox.to_owned())
|
||||||
|
.collect();
|
||||||
debug!(
|
debug!(
|
||||||
"Sending activity {:?} to followers of {}",
|
"Sending activity {:?} to followers of {}",
|
||||||
&activity.id_unchecked().map(|i| i.to_string()),
|
&activity.id_unchecked().map(|i| i.to_string()),
|
||||||
&community.actor_id
|
&community.actor_id
|
||||||
);
|
);
|
||||||
|
|
||||||
send_activity_internal(
|
send_activity_internal(context, activity, community, follower_inboxes, true, false).await?;
|
||||||
context.activity_queue(),
|
|
||||||
activity,
|
|
||||||
community,
|
|
||||||
follower_inboxes,
|
|
||||||
context.pool(),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -118,11 +102,14 @@ where
|
||||||
/// * `activity` the activity to send
|
/// * `activity` the activity to send
|
||||||
/// * `creator` the creator of the activity
|
/// * `creator` the creator of the activity
|
||||||
/// * `community` the destination community
|
/// * `community` the destination community
|
||||||
|
/// * `object_actor` if the object of the activity is an actor, it should be passed here so it can
|
||||||
|
/// be sent directly to the actor
|
||||||
///
|
///
|
||||||
pub(crate) async fn send_to_community<T, Kind>(
|
pub(crate) async fn send_to_community<T, Kind>(
|
||||||
activity: T,
|
activity: T,
|
||||||
creator: &Person,
|
creator: &Person,
|
||||||
community: &Community,
|
community: &Community,
|
||||||
|
object_actor: Option<Url>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError>
|
) -> Result<(), LemmyError>
|
||||||
where
|
where
|
||||||
|
@ -133,7 +120,7 @@ where
|
||||||
// if this is a local community, we need to do an announce from the community instead
|
// if this is a local community, we need to do an announce from the community instead
|
||||||
if community.local {
|
if community.local {
|
||||||
community
|
community
|
||||||
.send_announce(activity.into_any_base()?, context)
|
.send_announce(activity.into_any_base()?, object_actor, context)
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
let inbox = community.get_shared_inbox_or_inbox_url();
|
let inbox = community.get_shared_inbox_or_inbox_url();
|
||||||
|
@ -143,16 +130,8 @@ where
|
||||||
&activity.id_unchecked(),
|
&activity.id_unchecked(),
|
||||||
&community.actor_id
|
&community.actor_id
|
||||||
);
|
);
|
||||||
send_activity_internal(
|
// dont send to object_actor here, as that is responsibility of the community itself
|
||||||
context.activity_queue(),
|
send_activity_internal(context, activity, creator, vec![inbox], true, false).await?;
|
||||||
activity,
|
|
||||||
creator,
|
|
||||||
vec![inbox],
|
|
||||||
context.pool(),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -185,12 +164,7 @@ where
|
||||||
.map(|i| i.to_owned())
|
.map(|i| i.to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
send_activity_internal(
|
send_activity_internal(
|
||||||
context.activity_queue(),
|
context, activity, creator, mentions, false, // Don't create a new DB row
|
||||||
activity,
|
|
||||||
creator,
|
|
||||||
mentions,
|
|
||||||
context.pool(),
|
|
||||||
false, // Don't create a new DB row
|
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -203,11 +177,10 @@ where
|
||||||
/// The caller of this function needs to remove any blocked domains from `to`,
|
/// The caller of this function needs to remove any blocked domains from `to`,
|
||||||
/// using `check_is_apub_id_valid()`.
|
/// using `check_is_apub_id_valid()`.
|
||||||
async fn send_activity_internal<T, Kind>(
|
async fn send_activity_internal<T, Kind>(
|
||||||
activity_sender: &QueueHandle,
|
context: &LemmyContext,
|
||||||
activity: T,
|
activity: T,
|
||||||
actor: &dyn ActorType,
|
actor: &dyn ActorType,
|
||||||
inboxes: Vec<Url>,
|
inboxes: Vec<Url>,
|
||||||
pool: &DbPool,
|
|
||||||
insert_into_db: bool,
|
insert_into_db: bool,
|
||||||
sensitive: bool,
|
sensitive: bool,
|
||||||
) -> Result<(), LemmyError>
|
) -> Result<(), LemmyError>
|
||||||
|
@ -234,7 +207,7 @@ where
|
||||||
// might send the same ap_id
|
// might send the same ap_id
|
||||||
if insert_into_db {
|
if insert_into_db {
|
||||||
let id = activity.id().context(location_info!())?;
|
let id = activity.id().context(location_info!())?;
|
||||||
insert_activity(id, activity.clone(), true, sensitive, pool).await?;
|
insert_activity(id, activity.clone(), true, sensitive, context.pool()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in inboxes {
|
for i in inboxes {
|
||||||
|
@ -247,7 +220,7 @@ where
|
||||||
if env::var("LEMMY_TEST_SEND_SYNC").is_ok() {
|
if env::var("LEMMY_TEST_SEND_SYNC").is_ok() {
|
||||||
do_send(message, &Client::default()).await?;
|
do_send(message, &Client::default()).await?;
|
||||||
} else {
|
} else {
|
||||||
activity_sender.queue::<SendActivityTask>(message)?;
|
context.activity_queue.queue::<SendActivityTask>(message)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,7 @@ pub trait ActorType {
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait CommunityType {
|
pub trait CommunityType {
|
||||||
|
fn followers_url(&self) -> Url;
|
||||||
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
|
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
|
||||||
async fn send_accept_follow(
|
async fn send_accept_follow(
|
||||||
&self,
|
&self,
|
||||||
|
@ -207,6 +208,7 @@ pub trait CommunityType {
|
||||||
async fn send_announce(
|
async fn send_announce(
|
||||||
&self,
|
&self,
|
||||||
activity: AnyBase,
|
activity: AnyBase,
|
||||||
|
object: Option<Url>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError>;
|
) -> Result<(), LemmyError>;
|
||||||
|
|
||||||
|
@ -222,6 +224,19 @@ pub trait CommunityType {
|
||||||
removed_mod: Person,
|
removed_mod: Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError>;
|
) -> 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)]
|
#[async_trait::async_trait(?Send)]
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
is_activity_already_known,
|
is_activity_already_known,
|
||||||
receive_for_community::{
|
receive_for_community::{
|
||||||
receive_add_for_community,
|
receive_add_for_community,
|
||||||
|
receive_block_user_for_community,
|
||||||
receive_create_for_community,
|
receive_create_for_community,
|
||||||
receive_delete_for_community,
|
receive_delete_for_community,
|
||||||
receive_dislike_for_community,
|
receive_dislike_for_community,
|
||||||
|
@ -58,6 +59,7 @@ pub enum CommunityValidTypes {
|
||||||
Delete, // post or comment deleted by creator
|
Delete, // post or comment deleted by creator
|
||||||
Remove, // post or comment removed by mod or admin, or mod removed from community
|
Remove, // post or comment removed by mod or admin, or mod removed from community
|
||||||
Add, // mod added to community
|
Add, // mod added to community
|
||||||
|
Block, // user blocked by community
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CommunityAcceptedActivities = ActorAndObject<CommunityValidTypes>;
|
pub type CommunityAcceptedActivities = ActorAndObject<CommunityValidTypes>;
|
||||||
|
@ -224,13 +226,35 @@ pub(crate) async fn community_receive_message(
|
||||||
.await?;
|
.await?;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
CommunityValidTypes::Block => {
|
||||||
|
Box::pin(receive_block_user_for_community(
|
||||||
|
context,
|
||||||
|
any_base.clone(),
|
||||||
|
None,
|
||||||
|
request_counter,
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
true
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if do_announce {
|
if do_announce {
|
||||||
// Check again that the activity is public, just to be sure
|
// Check again that the activity is public, just to be sure
|
||||||
verify_is_addressed_to_public(&activity)?;
|
verify_is_addressed_to_public(&activity)?;
|
||||||
|
let mut object_actor = activity.object().clone().single_xsd_any_uri();
|
||||||
|
// If activity is something like Undo/Block, we need to access activity.object.object
|
||||||
|
if object_actor.is_none() {
|
||||||
|
object_actor = activity
|
||||||
|
.object()
|
||||||
|
.as_one()
|
||||||
|
.map(|a| ActorAndObject::from_any_base(a.to_owned()).ok())
|
||||||
|
.flatten()
|
||||||
|
.flatten()
|
||||||
|
.map(|a: ActorAndObject<CommunityValidTypes>| a.object().to_owned().single_xsd_any_uri())
|
||||||
|
.flatten();
|
||||||
|
}
|
||||||
to_community
|
to_community
|
||||||
.send_announce(activity.into_any_base()?, context)
|
.send_announce(activity.into_any_base()?, object_actor, context)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ use crate::{
|
||||||
is_addressed_to_local_person,
|
is_addressed_to_local_person,
|
||||||
receive_for_community::{
|
receive_for_community::{
|
||||||
receive_add_for_community,
|
receive_add_for_community,
|
||||||
|
receive_block_user_for_community,
|
||||||
receive_create_for_community,
|
receive_create_for_community,
|
||||||
receive_delete_for_community,
|
receive_delete_for_community,
|
||||||
receive_dislike_for_community,
|
receive_dislike_for_community,
|
||||||
|
@ -276,6 +277,7 @@ enum AnnouncableActivities {
|
||||||
Remove,
|
Remove,
|
||||||
Undo,
|
Undo,
|
||||||
Add,
|
Add,
|
||||||
|
Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes an announce and passes the inner activity to the appropriate handler.
|
/// Takes an announce and passes the inner activity to the appropriate handler.
|
||||||
|
@ -352,6 +354,10 @@ pub async fn receive_announce(
|
||||||
Some(Add) => {
|
Some(Add) => {
|
||||||
receive_add_for_community(context, inner_activity, Some(announce), request_counter).await
|
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),
|
_ => receive_unhandled_activity(inner_activity),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ use activitystreams::{
|
||||||
ActorAndObjectRef,
|
ActorAndObjectRef,
|
||||||
Add,
|
Add,
|
||||||
Announce,
|
Announce,
|
||||||
|
Block,
|
||||||
Create,
|
Create,
|
||||||
Delete,
|
Delete,
|
||||||
Dislike,
|
Dislike,
|
||||||
|
@ -64,10 +65,25 @@ use lemmy_apub::{
|
||||||
CommunityType,
|
CommunityType,
|
||||||
PostOrComment,
|
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::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
community::{
|
||||||
|
Community,
|
||||||
|
CommunityFollower,
|
||||||
|
CommunityFollowerForm,
|
||||||
|
CommunityModerator,
|
||||||
|
CommunityModeratorForm,
|
||||||
|
CommunityPersonBan,
|
||||||
|
CommunityPersonBanForm,
|
||||||
|
},
|
||||||
person::Person,
|
person::Person,
|
||||||
site::Site,
|
site::Site,
|
||||||
},
|
},
|
||||||
|
@ -244,7 +260,13 @@ pub(in crate::inbox) async fn receive_remove_for_community(
|
||||||
CommunityModerator::leave(conn, &form)
|
CommunityModerator::leave(conn, &form)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
community.send_announce(remove_any_base, context).await?;
|
community
|
||||||
|
.send_announce(
|
||||||
|
remove_any_base,
|
||||||
|
remove.object().clone().single_xsd_any_uri(),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
// TODO: send websocket notification about removed mod
|
// TODO: send websocket notification about removed mod
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -271,6 +293,7 @@ enum UndoableActivities {
|
||||||
Remove,
|
Remove,
|
||||||
Like,
|
Like,
|
||||||
Dislike,
|
Dislike,
|
||||||
|
Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A post/comment action being reverted (either a delete, remove, upvote or downvote)
|
/// A post/comment action being reverted (either a delete, remove, upvote or downvote)
|
||||||
|
@ -301,6 +324,16 @@ pub(in crate::inbox) async fn receive_undo_for_community(
|
||||||
Some(Dislike) => {
|
Some(Dislike) => {
|
||||||
receive_undo_dislike_for_community(context, undo, expected_domain, request_counter).await
|
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),
|
_ => receive_unhandled_activity(undo),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,7 +452,13 @@ pub(in crate::inbox) async fn receive_add_for_community(
|
||||||
.await??;
|
.await??;
|
||||||
}
|
}
|
||||||
if community.local {
|
if community.local {
|
||||||
community.send_announce(add_any_base, context).await?;
|
community
|
||||||
|
.send_announce(
|
||||||
|
add_any_base,
|
||||||
|
add.object().clone().single_xsd_any_uri(),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
// TODO: send websocket notification about added mod
|
// TODO: send websocket notification about added mod
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -451,6 +490,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(
|
async fn fetch_post_or_comment_by_id(
|
||||||
apub_id: &Url,
|
apub_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub enum ValidTypes {
|
||||||
Remove,
|
Remove,
|
||||||
Announce,
|
Announce,
|
||||||
Add,
|
Add,
|
||||||
|
Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this isnt entirely correct, cause some of these receive are not ActorAndObject,
|
// TODO: this isnt entirely correct, cause some of these receive are not ActorAndObject,
|
||||||
|
|
Loading…
Reference in a new issue