rewrite, test and fix add/remove mod, update community handlers

This commit is contained in:
Felix Ableitner 2021-07-14 07:33:31 +02:00
parent 186c0b93d1
commit 64c5ba3bd6
10 changed files with 106 additions and 114 deletions

View file

@ -1,12 +1,16 @@
use crate::activities::{community::verify_add_remove_moderator_target, verify_mod_action};
use crate::activities::{
verify_activity,
verify_add_remove_moderator_target,
verify_mod_action,
verify_person_in_community,
};
use activitystreams::{activity::kind::AddType, base::AnyBase};
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},
CommunityType,
};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler, PublicUrl};
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
use lemmy_db_queries::{source::community::CommunityModerator_, Joinable};
use lemmy_db_schema::source::community::{CommunityModerator, CommunityModeratorForm};
use lemmy_utils::LemmyError;
@ -28,12 +32,16 @@ pub struct AddMod {
#[async_trait::async_trait(?Send)]
impl ActivityHandler for AddMod {
async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.target, &self.cc[0])?;
check_is_apub_id_valid(&self.common.actor, false)?;
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?;
verify_add_remove_moderator_target(&self.target, self.cc[0].clone())
verify_add_remove_moderator_target(&self.target, self.cc[0].clone())?;
Ok(())
}
async fn receive(

View file

@ -1,14 +1,18 @@
use crate::{
activities::{
comment::{create::CreateComment, update::UpdateComment},
community::{block_user::BlockUserFromCommunity, undo_block_user::UndoBlockUserFromCommunity},
community::{
add_mod::AddMod,
block_user::BlockUserFromCommunity,
undo_block_user::UndoBlockUserFromCommunity,
},
deletion::{
delete::DeletePostCommentOrCommunity,
undo_delete::UndoDeletePostCommentOrCommunity,
},
post::{create::CreatePost, update::UpdatePost},
removal::{
remove::RemovePostCommentOrCommunity,
remove::RemovePostCommentCommunityOrMod,
undo_remove::UndoRemovePostCommentOrCommunity,
},
verify_activity,
@ -43,10 +47,11 @@ pub enum AnnouncableActivities {
UndoDislikePostOrComment(UndoDislikePostOrComment),
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
RemovePostCommentOrCommunity(RemovePostCommentOrCommunity),
RemovePostCommentCommunityOrMod(RemovePostCommentCommunityOrMod),
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]

View file

@ -1,16 +1,12 @@
use anyhow::anyhow;
use lemmy_api_common::{blocking, community::CommunityResponse};
use lemmy_apub::generate_moderators_url;
use lemmy_db_schema::CommunityId;
use lemmy_db_views_actor::community_view::CommunityView;
use lemmy_utils::LemmyError;
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext};
use url::Url;
pub mod add_mod;
pub mod announce;
pub mod block_user;
pub mod remove_mod;
pub mod undo_block_user;
pub mod update;
@ -37,12 +33,3 @@ pub(crate) async fn send_websocket_message<
Ok(())
}
/// For Add/Remove community moderator activities, check that the target field actually contains
/// /c/community/moderators. Any different values are unsupported.
fn verify_add_remove_moderator_target(target: &Url, community: Url) -> Result<(), LemmyError> {
if target != &generate_moderators_url(&community.into())?.into_inner() {
return Err(anyhow!("Unkown target url").into());
}
Ok(())
}

View file

@ -1,67 +0,0 @@
use crate::activities::{community::verify_add_remove_moderator_target, verify_mod_action};
use activitystreams::{activity::kind::RemoveType, base::AnyBase};
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},
CommunityType,
};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler, PublicUrl};
use lemmy_db_queries::Joinable;
use lemmy_db_schema::source::community::{CommunityModerator, CommunityModeratorForm};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RemoveMod {
to: PublicUrl,
object: Url,
target: Url,
cc: [Url; 1],
#[serde(rename = "type")]
kind: RemoveType,
#[serde(flatten)]
common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for RemoveMod {
async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.target, &self.cc[0])?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
verify_add_remove_moderator_target(&self.target, self.cc[0].clone())
}
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let community =
get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
let add_mod = get_or_fetch_and_upsert_person(&self.object, context, request_counter).await?;
let form = CommunityModeratorForm {
community_id: community.id,
person_id: add_mod.id,
};
blocking(context.pool(), move |conn| {
CommunityModerator::leave(conn, &form)
})
.await??;
let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(self)?)?;
community
.send_announce(anybase, Some(self.object.clone()), context)
.await?;
// TODO: send websocket notification about removed mod
Ok(())
}
fn common(&self) -> &ActivityCommonFields {
&self.common
}
}

View file

@ -1,8 +1,13 @@
use crate::activities::{community::send_websocket_message, verify_mod_action};
use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use crate::activities::{
community::send_websocket_message,
verify_activity,
verify_mod_action,
verify_person_in_community,
};
use activitystreams::activity::kind::UpdateType;
use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, objects::FromApubToForm, GroupExt};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandler, PublicUrl};
use lemmy_apub::{objects::FromApubToForm, GroupExt};
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
use lemmy_db_queries::{ApubObject, Crud};
use lemmy_db_schema::source::community::{Community, CommunityForm};
use lemmy_utils::LemmyError;
@ -25,11 +30,15 @@ pub struct UpdateCommunity {
#[async_trait::async_trait(?Send)]
impl ActivityHandler for UpdateCommunity {
async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
self.object.id(self.cc[0].as_str())?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await
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(

View file

@ -4,6 +4,7 @@ use lemmy_apub::{
check_community_or_site_ban,
check_is_apub_id_valid,
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
generate_moderators_url,
};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields};
use lemmy_db_queries::ApubObject;
@ -109,3 +110,12 @@ async fn verify_mod_action(
}
Ok(())
}
/// For Add/Remove community moderator activities, check that the target field actually contains
/// /c/community/moderators. Any different values are unsupported.
fn verify_add_remove_moderator_target(target: &Url, community: Url) -> Result<(), LemmyError> {
if target != &generate_moderators_url(&community.into())?.into_inner() {
return Err(anyhow!("Unkown target url").into());
}
Ok(())
}

View file

@ -3,22 +3,32 @@ use crate::activities::{
community::send_websocket_message as send_community_message,
post::send_websocket_message as send_post_message,
verify_activity,
verify_add_remove_moderator_target,
verify_mod_action,
verify_person_in_community,
};
use activitystreams::activity::kind::RemoveType;
use activitystreams::{activity::kind::RemoveType, base::AnyBase};
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,
person::get_or_fetch_and_upsert_person,
},
CommunityType,
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_db_queries::{
source::{comment::Comment_, community::Community_, post::Post_},
Joinable,
};
use lemmy_db_schema::source::{
comment::Comment,
community::{Community, CommunityModerator, CommunityModeratorForm},
post::Post,
};
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
@ -26,18 +36,20 @@ 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 {
pub struct RemovePostCommentCommunityOrMod {
to: PublicUrl,
pub(in crate::activities::removal) object: Url,
cc: [Url; 1],
#[serde(rename = "type")]
kind: RemoveType,
// if target is set, this is means remove mod from community
target: Option<Url>,
#[serde(flatten)]
common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for RemovePostCommentOrCommunity {
impl ActivityHandler for RemovePostCommentCommunityOrMod {
async fn verify(
&self,
context: &LemmyContext,
@ -50,6 +62,12 @@ impl ActivityHandler for RemovePostCommentOrCommunity {
if object_community.is_ok() {
verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
}
// removing community mod
else if let Some(target) = &self.target {
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?;
verify_add_remove_moderator_target(target, self.cc[0].clone())?;
}
// removing a post or comment
else {
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
@ -82,6 +100,28 @@ impl ActivityHandler for RemovePostCommentOrCommunity {
)
.await
}
// removing community mod
else if self.target.is_some() {
let community =
get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
let remove_mod =
get_or_fetch_and_upsert_person(&self.object, context, request_counter).await?;
let form = CommunityModeratorForm {
community_id: community.id,
person_id: remove_mod.id,
};
blocking(context.pool(), move |conn| {
CommunityModerator::leave(conn, &form)
})
.await??;
let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(self)?)?;
community
.send_announce(anybase, Some(self.object.clone()), context)
.await?;
// TODO: send websocket notification about removed mod
Ok(())
}
// removing a post or comment
else {
match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {

View file

@ -2,7 +2,7 @@ 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,
removal::remove::RemovePostCommentCommunityOrMod,
verify_activity,
verify_mod_action,
verify_person_in_community,
@ -28,7 +28,7 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoRemovePostCommentOrCommunity {
to: PublicUrl,
object: RemovePostCommentOrCommunity,
object: RemovePostCommentCommunityOrMod,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,

View file

@ -4,7 +4,6 @@ use crate::activities::{
add_mod::AddMod,
announce::AnnounceActivity,
block_user::BlockUserFromCommunity,
remove_mod::RemoveMod,
undo_block_user::UndoBlockUserFromCommunity,
update::UpdateCommunity,
},
@ -17,7 +16,10 @@ use crate::activities::{
undo_delete::UndoDeletePrivateMessage,
update::UpdatePrivateMessage,
},
removal::{remove::RemovePostCommentOrCommunity, undo_remove::UndoRemovePostCommentOrCommunity},
removal::{
remove::RemovePostCommentCommunityOrMod,
undo_remove::UndoRemovePostCommentOrCommunity,
},
voting::{
dislike::DislikePostOrComment,
like::LikePostOrComment,
@ -56,13 +58,12 @@ pub enum GroupInboxActivities {
UndoDislikePostOrComment(UndoDislikePostOrComment),
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
RemovePostCommentOrCommunity(RemovePostCommentOrCommunity),
RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod),
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
UpdateCommunity(Box<UpdateCommunity>),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
}
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
@ -81,13 +82,12 @@ pub enum SharedInboxActivities {
UndoLikePostOrComment(UndoLikePostOrComment),
DeletePostCommentOrCommunity(DeletePostCommentOrCommunity),
UndoDeletePostCommentOrCommunity(UndoDeletePostCommentOrCommunity),
RemovePostCommentOrCommunity(RemovePostCommentOrCommunity),
RemovePostCommentOrCommunity(RemovePostCommentCommunityOrMod),
UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity),
UpdateCommunity(Box<UpdateCommunity>),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
// received by person
AcceptFollowCommunity(AcceptFollowCommunity),
// Note, pm activities need to be at the end, otherwise comments will end up here. We can probably

View file

@ -8,5 +8,5 @@ for Item in alpha beta gamma delta epsilon ; do
sudo chown -R 991:991 volumes/pictrs_$Item
done
sudo docker-compose pull --ignore-pull-failures || true
#sudo docker-compose pull --ignore-pull-failures || true
sudo docker-compose up