use anyhow::Context;
use lemmy_api_structs::{blocking, community::*};
use lemmy_apub::{
- activities::send::community::{send_add_mod, send_remove_mod},
generate_apub_endpoint,
generate_followers_url,
generate_inbox_url,
generate_shared_inbox_url,
ActorType,
+ CommunityType,
EndpointType,
+ UserType,
};
use lemmy_db_queries::{
diesel_option_overwrite_to_url,
})
.await??;
if data.added {
- send_add_mod(user, updated_mod, community, context).await?;
+ community.send_add_mod(&user, updated_mod, context).await?;
} else {
- send_remove_mod(user, updated_mod, community, context).await?;
+ community
+ .send_remove_mod(&user, updated_mod, context)
+ .await?;
}
// Note: in case a remote mod is added, this returns the old moderators list, it will only get
use crate::{activities::receive::get_actor_as_user, objects::FromApub, ActorType, NoteExt};
use activitystreams::{
- activity::{ActorAndObjectRefExt, Create, Dislike, Like, Remove, Update},
+ activity::{ActorAndObjectRefExt, Create, Dislike, Like, Update},
base::ExtendsExt,
};
use anyhow::Context;
pub(crate) async fn receive_remove_comment(
context: &LemmyContext,
- _remove: Remove,
comment: Comment,
) -> Result<(), LemmyError> {
let removed_comment = blocking(context.pool(), move |conn| {
-use crate::{
- activities::receive::verify_activity_domains_valid,
- inbox::verify_is_addressed_to_public,
-};
-use activitystreams::{
- activity::{ActorAndObjectRefExt, Delete, Remove, Undo},
- base::{AnyBase, ExtendsExt},
-};
-use anyhow::Context;
use lemmy_api_structs::{blocking, community::CommunityResponse};
-use lemmy_db_queries::{source::community::Community_, ApubObject};
+use lemmy_db_queries::source::community::Community_;
use lemmy_db_schema::source::community::Community;
use lemmy_db_views_actor::community_view::CommunityView;
-use lemmy_utils::{location_info, LemmyError};
+use lemmy_utils::LemmyError;
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation};
-use url::Url;
pub(crate) async fn receive_delete_community(
context: &LemmyContext,
pub(crate) async fn receive_remove_community(
context: &LemmyContext,
- activity: AnyBase,
- expected_domain: &Url,
+ community: Community,
) -> Result<(), LemmyError> {
- let remove = Remove::from_any_base(activity)?.context(location_info!())?;
- verify_activity_domains_valid(&remove, expected_domain, true)?;
- verify_is_addressed_to_public(&remove)?;
-
- let community_uri = remove
- .object()
- .to_owned()
- .single_xsd_any_uri()
- .context(location_info!())?;
- let community = blocking(context.pool(), move |conn| {
- Community::read_from_apub_id(conn, &community_uri.into())
- })
- .await??;
-
let removed_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, true)
})
pub(crate) async fn receive_undo_delete_community(
context: &LemmyContext,
- undo: Undo,
community: Community,
- expected_domain: &Url,
) -> Result<(), LemmyError> {
- verify_is_addressed_to_public(&undo)?;
- let inner = undo.object().to_owned().one().context(location_info!())?;
- let delete = Delete::from_any_base(inner)?.context(location_info!())?;
- verify_activity_domains_valid(&delete, expected_domain, true)?;
- verify_is_addressed_to_public(&delete)?;
-
let deleted_community = blocking(context.pool(), move |conn| {
Community::update_deleted(conn, community.id, false)
})
pub(crate) async fn receive_undo_remove_community(
context: &LemmyContext,
- undo: Undo,
- expected_domain: &Url,
+ community: Community,
) -> Result<(), LemmyError> {
- verify_is_addressed_to_public(&undo)?;
-
- let inner = undo.object().to_owned().one().context(location_info!())?;
- let remove = Remove::from_any_base(inner)?.context(location_info!())?;
- verify_activity_domains_valid(&remove, &expected_domain, true)?;
- verify_is_addressed_to_public(&remove)?;
-
- let community_uri = remove
- .object()
- .to_owned()
- .single_xsd_any_uri()
- .context(location_info!())?;
- let community = blocking(context.pool(), move |conn| {
- Community::read_from_apub_id(conn, &community_uri.into())
- })
- .await??;
-
let removed_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community.id, false)
})
PageExt,
};
use activitystreams::{
- activity::{Announce, Create, Dislike, Like, Remove, Update},
+ activity::{Announce, Create, Dislike, Like, Update},
prelude::*,
};
use anyhow::Context;
pub(crate) async fn receive_remove_post(
context: &LemmyContext,
- _remove: Remove,
post: Post,
) -> Result<(), LemmyError> {
let removed_post = blocking(context.pool(), move |conn| {
fetcher::user::get_or_fetch_and_upsert_user,
generate_moderators_url,
ActorType,
+ CommunityType,
};
use activitystreams::{
activity::{
.unwrap_or_else(|| self.inbox_url.to_owned())
.into()
}
+}
- async fn send_follow(
- &self,
- _follow_actor_id: &Url,
- _context: &LemmyContext,
- ) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
- async fn send_unfollow(
- &self,
- _follow_actor_id: &Url,
- _context: &LemmyContext,
- ) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
+#[async_trait::async_trait(?Send)]
+impl CommunityType for Community {
/// As a local community, accept the follow request from a remote user.
async fn send_accept_follow(
&self,
.set_many_contexts(lemmy_context()?)
.set_id(generate_activity_id(AnnounceType::Announce)?)
.set_to(public())
- .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
+ .set_many_ccs(vec![self.actor_id()]);
send_to_community_followers(announce, self, context).await?;
Ok(inboxes)
}
-}
-pub async fn send_add_mod(
- actor: User_,
- added_mod: User_,
- community: Community,
- context: &LemmyContext,
-) -> Result<(), LemmyError> {
- let mut add = Add::new(
- actor.actor_id.clone().into_inner(),
- added_mod.actor_id.into_inner(),
- );
- add
- .set_many_contexts(lemmy_context()?)
- .set_id(generate_activity_id(AddType::Add)?)
- .set_to(public())
- .set_many_ccs(vec![community.actor_id()])
- .set_target(generate_moderators_url(&community.actor_id)?.into_inner());
+ async fn send_add_mod(
+ &self,
+ actor: &User_,
+ added_mod: User_,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError> {
+ let mut add = Add::new(
+ actor.actor_id.clone().into_inner(),
+ added_mod.actor_id.into_inner(),
+ );
+ add
+ .set_many_contexts(lemmy_context()?)
+ .set_id(generate_activity_id(AddType::Add)?)
+ .set_to(public())
+ .set_many_ccs(vec![self.actor_id()])
+ .set_target(generate_moderators_url(&self.actor_id)?.into_inner());
- if community.local {
- community
- .send_announce(add.into_any_base()?, context)
- .await?;
- } else {
- send_to_community(add, &actor, &community, context).await?;
+ send_to_community(add, actor, self, context).await?;
+ Ok(())
}
- Ok(())
-}
-pub async fn send_remove_mod(
- actor: User_,
- removed_mod: User_,
- community: Community,
- context: &LemmyContext,
-) -> Result<(), LemmyError> {
- let mut remove = Remove::new(
- actor.actor_id.clone().into_inner(),
- removed_mod.actor_id.into_inner(),
- );
- remove
- .set_many_contexts(lemmy_context()?)
- .set_id(generate_activity_id(RemoveType::Remove)?)
- .set_to(public())
- .set_many_ccs(vec![community.actor_id()])
- .set_target(generate_moderators_url(&community.actor_id)?.into_inner());
+ async fn send_remove_mod(
+ &self,
+ actor: &User_,
+ removed_mod: User_,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError> {
+ let mut remove = Remove::new(
+ actor.actor_id.clone().into_inner(),
+ removed_mod.actor_id.into_inner(),
+ );
+ remove
+ .set_many_contexts(lemmy_context()?)
+ .set_id(generate_activity_id(RemoveType::Remove)?)
+ .set_to(public())
+ .set_many_ccs(vec![self.actor_id()])
+ .set_target(generate_moderators_url(&self.actor_id)?.into_inner());
- if community.local {
- community
- .send_announce(remove.into_any_base()?, context)
- .await?;
- } else {
- send_to_community(remove, &actor, &community, context).await?;
+ send_to_community(remove, &actor, self, context).await?;
+ Ok(())
}
- Ok(())
}
activity_queue::send_activity_single_dest,
extensions::context::lemmy_context,
ActorType,
+ UserType,
};
use activitystreams::{
activity::{
Follow,
Undo,
},
- base::{AnyBase, BaseExt, ExtendsExt},
+ base::{BaseExt, ExtendsExt},
object::ObjectExt,
};
use lemmy_api_structs::blocking;
-use lemmy_db_queries::{ApubObject, DbPool, Followable};
+use lemmy_db_queries::{ApubObject, Followable};
use lemmy_db_schema::source::{
community::{Community, CommunityFollower, CommunityFollowerForm},
user::User_,
.unwrap_or_else(|| self.inbox_url.to_owned())
.into()
}
+}
+#[async_trait::async_trait(?Send)]
+impl UserType for User_ {
/// As a given local user, send out a follow request to a remote community.
async fn send_follow(
&self,
send_activity_single_dest(undo, self, community.inbox_url.into(), context).await?;
Ok(())
}
-
- async fn send_accept_follow(
- &self,
- _follow: Follow,
- _context: &LemmyContext,
- ) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
- async fn send_delete(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
- async fn send_undo_delete(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
- async fn send_remove(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
- async fn send_undo_remove(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
- async fn send_announce(
- &self,
- _activity: AnyBase,
- _context: &LemmyContext,
- ) -> Result<(), LemmyError> {
- unimplemented!()
- }
-
- async fn get_follower_inboxes(&self, _pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
- unimplemented!()
- }
}
extensions::signatures::sign_and_send,
insert_activity,
ActorType,
+ CommunityType,
APUB_JSON_CONTENT_TYPE,
};
use activitystreams::{
},
insert_activity,
ActorType,
+ CommunityType,
};
use activitystreams::{
activity::{kind::FollowType, ActorAndObject, Follow, Undo},
objects::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
user::get_or_fetch_and_upsert_user,
},
+ find_object_by_id,
find_post_or_comment_by_id,
generate_moderators_url,
inbox::verify_is_addressed_to_public,
ActorType,
+ CommunityType,
+ Object,
PostOrComment,
};
use activitystreams::{
.context(location_info!())?;
match find_post_or_comment_by_id(context, object).await {
- Ok(PostOrComment::Post(p)) => receive_remove_post(context, remove, *p).await,
- Ok(PostOrComment::Comment(c)) => receive_remove_comment(context, remove, *c).await,
+ Ok(PostOrComment::Post(p)) => receive_remove_post(context, *p).await,
+ Ok(PostOrComment::Comment(c)) => receive_remove_comment(context, *c).await,
// if we dont have the object, no need to do anything
Err(_) => Ok(()),
}
.map(|o| o.id())
.flatten()
.context(location_info!())?;
- let original_id = match find_post_or_comment_by_id(context, object_id.to_owned()).await? {
- PostOrComment::Post(p) => p.ap_id.into_inner(),
- PostOrComment::Comment(c) => c.ap_id.into_inner(),
+ let original_id = match find_object_by_id(context, object_id.to_owned()).await? {
+ Object::Post(p) => p.ap_id.into_inner(),
+ Object::Comment(c) => c.ap_id.into_inner(),
+ Object::Community(c) => c.actor_id(),
+ Object::User(u) => u.actor_id(),
+ Object::PrivateMessage(p) => p.ap_id.into_inner(),
};
if actor_id.domain() != original_id.domain() {
let community = extract_community_from_cc(activity, context).await?;
ActorType,
};
use activitystreams::{
- activity::{Accept, ActorAndObject, Announce, Create, Delete, Follow, Undo, Update},
+ activity::{Accept, ActorAndObject, Announce, Create, Delete, Follow, Remove, Undo, Update},
base::AnyBase,
prelude::*,
};
receive_delete(context, any_base, &actor_url, request_counter).await?
}
UserValidTypes::Undo => receive_undo(context, any_base, &actor_url, request_counter).await?,
- UserValidTypes::Remove => receive_remove_community(&context, any_base, &actor_url).await?,
+ UserValidTypes::Remove => receive_remove(context, any_base, &actor_url).await?,
};
// TODO: would be logical to move websocket notification code here
}
}
+async fn receive_remove(
+ context: &LemmyContext,
+ any_base: AnyBase,
+ expected_domain: &Url,
+) -> Result<(), LemmyError> {
+ let remove = Remove::from_any_base(any_base.clone())?.context(location_info!())?;
+ verify_activity_domains_valid(&remove, expected_domain, true)?;
+ let object_uri = remove
+ .object()
+ .to_owned()
+ .single_xsd_any_uri()
+ .context(location_info!())?;
+ let community = blocking(context.pool(), move |conn| {
+ Community::read_from_apub_id(conn, &object_uri.into())
+ })
+ .await??;
+ receive_remove_community(&context, community).await
+}
+
async fn receive_undo(
context: &LemmyContext,
any_base: AnyBase,
expected_domain: &Url,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- use CommunityOrPrivateMessage::*;
let undo = Undo::from_any_base(any_base)?.context(location_info!())?;
verify_activity_domains_valid(&undo, expected_domain, true)?;
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
+ use CommunityOrPrivateMessage::*;
match find_community_or_private_message_by_id(context, object_uri).await? {
- Community(c) => receive_undo_delete_community(context, undo, c, expected_domain).await,
+ Community(c) => receive_undo_delete_community(context, c).await,
PrivateMessage(p) => {
receive_undo_delete_private_message(context, undo, expected_domain, p, request_counter)
.await
}
}
}
- Some("Remove") => receive_undo_remove_community(context, undo, expected_domain).await,
+ Some("Remove") => {
+ let remove = Remove::from_any_base(inner_activity)?.context(location_info!())?;
+ let object_uri = remove
+ .object()
+ .to_owned()
+ .single_xsd_any_uri()
+ .context(location_info!())?;
+ let community = blocking(context.pool(), move |conn| {
+ Community::read_from_apub_id(conn, &object_uri.into())
+ })
+ .await??;
+ receive_undo_remove_community(context, community).await
+ }
_ => receive_unhandled_activity(undo),
}
}
fn public_key(&self) -> Option<String>;
fn private_key(&self) -> Option<String>;
- async fn send_follow(
- &self,
- follow_actor_id: &Url,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
- async fn send_unfollow(
- &self,
- follow_actor_id: &Url,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
-
- async fn send_accept_follow(
- &self,
- follow: Follow,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
-
- async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError>;
- async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError>;
-
- async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
- async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
-
- async fn send_announce(
- &self,
- activity: AnyBase,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
-
- /// For a given community, returns the inboxes of all followers.
- async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
-
fn get_shared_inbox_or_inbox_url(&self) -> Url;
/// Outbox URL is not generally used by Lemmy, so it can be generated on the fly (but only for
}
}
+#[async_trait::async_trait(?Send)]
+pub trait CommunityType {
+ async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
+ async fn send_accept_follow(
+ &self,
+ follow: Follow,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError>;
+
+ async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError>;
+ async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError>;
+
+ async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
+ async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
+
+ async fn send_announce(
+ &self,
+ activity: AnyBase,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError>;
+
+ async fn send_add_mod(
+ &self,
+ actor: &User_,
+ added_mod: User_,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError>;
+ async fn send_remove_mod(
+ &self,
+ actor: &User_,
+ removed_mod: User_,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError>;
+}
+
+#[async_trait::async_trait(?Send)]
+pub trait UserType {
+ async fn send_follow(
+ &self,
+ follow_actor_id: &Url,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError>;
+ async fn send_unfollow(
+ &self,
+ follow_actor_id: &Url,
+ context: &LemmyContext,
+ ) -> Result<(), LemmyError>;
+}
+
pub enum EndpointType {
Community,
User,
Err(NotFound.into())
}
+#[derive(Debug)]
pub(crate) enum Object {
Comment(Comment),
Post(Post),