Rewrite following activities

This commit is contained in:
Felix Ableitner 2021-08-03 00:08:12 +02:00
parent 9d936a3d85
commit fe95fbe9f2
25 changed files with 176 additions and 193 deletions

View file

@ -8,7 +8,13 @@ use lemmy_api_common::{
get_local_user_view_from_jwt,
is_mod_or_admin,
};
use lemmy_apub::{ActorType, CommunityType, UserType};
use lemmy_apub::{
activities::following::{
follow::FollowCommunity as FollowCommunityApub,
undo::UndoFollowCommunity,
},
CommunityType,
};
use lemmy_db_queries::{
source::{comment::Comment_, community::CommunityModerator_, post::Post_},
Bannable,
@ -74,15 +80,9 @@ impl Perform for FollowCommunity {
} else if data.follow {
// Dont actually add to the community followers here, because you need
// to wait for the accept
local_user_view
.person
.send_follow(&community.actor_id(), context)
.await?;
FollowCommunityApub::send(&local_user_view.person, &community, context).await?;
} else {
local_user_view
.person
.send_unfollow(&community.actor_id(), context)
.await?;
UndoFollowCommunity::send(&local_user_view.person, &community, context).await?;
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
if blocking(context.pool(), unfollow).await?.is_err() {
return Err(ApiError::err("community_follower_already_exists").into());

View file

@ -104,7 +104,7 @@ impl ActivityHandler for CreateOrUpdateComment {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -45,7 +45,7 @@ impl ActivityHandler for AddMod {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
@ -71,7 +71,7 @@ impl ActivityHandler for AddMod {
.await??;
}
if community.local {
let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(self)?)?;
let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(&self)?)?;
community
.send_announce(anybase, Some(self.object.clone()), context)
.await?;

View file

@ -110,7 +110,7 @@ impl ActivityHandler for AnnounceActivity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -42,7 +42,7 @@ impl ActivityHandler for BlockUserFromCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -43,7 +43,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -45,7 +45,7 @@ impl ActivityHandler for UpdateCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -74,7 +74,7 @@ impl ActivityHandler for DeletePostCommentOrCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -62,7 +62,7 @@ impl ActivityHandler for UndoDeletePostCommentOrCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -1,12 +1,23 @@
use crate::{
activities::{following::follow::FollowCommunity, verify_activity, verify_community},
activities::{
following::follow::FollowCommunity,
generate_activity_id,
verify_activity,
verify_community,
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
ActorType,
};
use activitystreams::activity::kind::AcceptType;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler};
use lemmy_db_queries::Followable;
use lemmy_db_schema::source::community::CommunityFollower;
use lemmy_db_queries::{ApubObject, Followable};
use lemmy_db_schema::source::{
community::{Community, CommunityFollower},
person::Person,
};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
@ -22,6 +33,35 @@ pub struct AcceptFollowCommunity {
common: ActivityCommonFields,
}
impl AcceptFollowCommunity {
pub async fn send(follow: FollowCommunity, context: &LemmyContext) -> Result<(), LemmyError> {
let community_id = follow.object.clone();
let community = blocking(context.pool(), move |conn| {
Community::read_from_apub_id(conn, &community_id.into())
})
.await??;
let person_id = follow.common.actor.clone();
let person = blocking(context.pool(), move |conn| {
Person::read_from_apub_id(conn, &person_id.into())
})
.await??;
let id = generate_activity_id(AcceptType::Accept)?;
let accept = AcceptFollowCommunity {
to: person.actor_id(),
object: follow,
kind: AcceptType::Accept,
common: ActivityCommonFields {
context: lemmy_context(),
id: id.clone(),
actor: community.actor_id(),
unparsed: Default::default(),
},
};
let inbox = vec![person.inbox_url.into()];
send_activity_new(context, &accept, &id, &community, inbox, true).await
}
}
/// Handle accepted follows
#[async_trait::async_trait(?Send)]
impl ActivityHandler for AcceptFollowCommunity {
@ -39,7 +79,7 @@ impl ActivityHandler for AcceptFollowCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -1,18 +1,24 @@
use crate::{
activities::{verify_activity, verify_person},
activities::{
following::accept::AcceptFollowCommunity,
generate_activity_id,
verify_activity,
verify_person,
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
CommunityType,
ActorType,
};
use activitystreams::{
activity::{kind::FollowType, Follow},
base::{AnyBase, ExtendsExt},
};
use anyhow::Context;
use activitystreams::activity::kind::FollowType;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler};
use lemmy_db_queries::Followable;
use lemmy_db_schema::source::community::{CommunityFollower, CommunityFollowerForm};
use lemmy_utils::{location_info, LemmyError};
use lemmy_db_schema::source::{
community::{Community, CommunityFollower, CommunityFollowerForm},
person::Person,
};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
@ -22,11 +28,44 @@ pub struct FollowCommunity {
pub(in crate::activities::following) to: Url,
pub(in crate::activities::following) object: Url,
#[serde(rename = "type")]
kind: FollowType,
pub(in crate::activities::following) kind: FollowType,
#[serde(flatten)]
pub(in crate::activities::following) common: ActivityCommonFields,
}
impl FollowCommunity {
pub async fn send(
actor: &Person,
community: &Community,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
person_id: actor.id,
pending: true,
};
blocking(context.pool(), move |conn| {
CommunityFollower::follow(conn, &community_follower_form).ok()
})
.await?;
let id = generate_activity_id(FollowType::Follow)?;
let follow = FollowCommunity {
to: community.actor_id(),
object: community.actor_id(),
kind: FollowType::Follow,
common: ActivityCommonFields {
context: lemmy_context(),
id: id.clone(),
actor: actor.actor_id(),
unparsed: Default::default(),
},
};
let inbox = vec![community.inbox_url.clone().into()];
send_activity_new(context, &follow, &id, actor, inbox, true).await
}
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for FollowCommunity {
async fn verify(
@ -41,7 +80,7 @@ impl ActivityHandler for FollowCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
@ -61,10 +100,7 @@ impl ActivityHandler for FollowCommunity {
})
.await?;
// TODO: avoid the conversion and pass our own follow struct directly
let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(self)?)?;
let anybase = Follow::from_any_base(anybase)?.context(location_info!())?;
community.send_accept_follow(anybase, context).await
AcceptFollowCommunity::send(self, context).await
}
fn common(&self) -> &ActivityCommonFields {

View file

@ -1,12 +1,23 @@
use crate::{
activities::{following::follow::FollowCommunity, verify_activity, verify_person},
activities::{
following::follow::FollowCommunity,
generate_activity_id,
verify_activity,
verify_person,
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
ActorType,
};
use activitystreams::activity::kind::UndoType;
use activitystreams::activity::kind::{FollowType, UndoType};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler};
use lemmy_db_queries::Followable;
use lemmy_db_schema::source::community::{CommunityFollower, CommunityFollowerForm};
use lemmy_db_schema::source::{
community::{Community, CommunityFollower, CommunityFollowerForm},
person::Person,
};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
@ -22,6 +33,39 @@ pub struct UndoFollowCommunity {
common: ActivityCommonFields,
}
impl UndoFollowCommunity {
pub async fn send(
actor: &Person,
community: &Community,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let id = generate_activity_id(UndoType::Undo)?;
let undo = UndoFollowCommunity {
to: community.actor_id(),
object: FollowCommunity {
to: community.actor_id(),
object: community.actor_id(),
kind: FollowType::Follow,
common: ActivityCommonFields {
context: lemmy_context(),
id: generate_activity_id(FollowType::Follow)?,
actor: actor.actor_id(),
unparsed: Default::default(),
},
},
kind: UndoType::Undo,
common: ActivityCommonFields {
context: lemmy_context(),
id: id.clone(),
actor: actor.actor_id(),
unparsed: Default::default(),
},
};
let inbox = vec![community.get_shared_inbox_or_inbox_url()];
send_activity_new(context, &undo, &id, actor, inbox, true).await
}
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for UndoFollowCommunity {
async fn verify(
@ -38,7 +82,7 @@ impl ActivityHandler for UndoFollowCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -114,7 +114,7 @@ impl ActivityHandler for CreateOrUpdatePost {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -79,7 +79,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -33,7 +33,7 @@ impl ActivityHandler for DeletePrivateMessage {
}
async fn receive(
&self,
self,
context: &LemmyContext,
_request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -44,7 +44,7 @@ impl ActivityHandler for UndoDeletePrivateMessage {
}
async fn receive(
&self,
self,
context: &LemmyContext,
_request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -77,7 +77,7 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
@ -115,7 +115,7 @@ impl ActivityHandler for RemovePostCommentCommunityOrMod {
CommunityModerator::leave(conn, &form)
})
.await??;
let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(self)?)?;
let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(&self)?)?;
community
.send_announce(anybase, Some(self.object.clone()), context)
.await?;

View file

@ -62,7 +62,7 @@ impl ActivityHandler for UndoRemovePostCommentOrCommunity {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -1,9 +1,9 @@
use crate::{
activities::generate_activity_id,
activity_queue::{send_activity_single_dest, send_to_community, send_to_community_followers},
activity_queue::{send_to_community, send_to_community_followers},
check_is_apub_id_valid,
extensions::context::lemmy_context,
fetcher::{get_or_fetch_and_upsert_actor, person::get_or_fetch_and_upsert_person},
fetcher::get_or_fetch_and_upsert_actor,
generate_moderators_url,
insert_activity,
objects::ToApub,
@ -13,7 +13,6 @@ use crate::{
use activitystreams::{
activity::{
kind::{
AcceptType,
AddType,
AnnounceType,
BlockType,
@ -23,13 +22,10 @@ use activitystreams::{
UndoType,
UpdateType,
},
Accept,
ActorAndObjectRefExt,
Add,
Announce,
Block,
Delete,
Follow,
OptTargetRefExt,
Remove,
Undo,
@ -81,31 +77,6 @@ impl CommunityType for Community {
self.followers_url.clone().into()
}
/// As a local community, accept the follow request from a remote person.
async fn send_accept_follow(
&self,
follow: Follow,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let actor_uri = follow
.actor()?
.as_single_xsd_any_uri()
.context(location_info!())?;
let person = get_or_fetch_and_upsert_person(actor_uri, context, &mut 0).await?;
let mut accept = Accept::new(
self.actor_id.to_owned().into_inner(),
follow.into_any_base()?,
);
accept
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(AcceptType::Accept)?)
.set_to(person.actor_id());
send_activity_single_dest(accept, self, person.inbox_url.into(), context).await?;
Ok(())
}
/// If a remote community is updated by a local mod, send the updated info to the community's
/// instance.
async fn send_update(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,27 +1,5 @@
use crate::{
activities::generate_activity_id,
activity_queue::send_activity_single_dest,
extensions::context::lemmy_context,
ActorType,
UserType,
};
use activitystreams::{
activity::{
kind::{FollowType, UndoType},
Follow,
Undo,
},
base::{BaseExt, ExtendsExt},
object::ObjectExt,
};
use lemmy_api_common::blocking;
use lemmy_db_queries::{ApubObject, Followable};
use lemmy_db_schema::source::{
community::{Community, CommunityFollower, CommunityFollowerForm},
person::Person,
};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use crate::ActorType;
use lemmy_db_schema::source::person::Person;
use url::Url;
impl ActorType for Person {
@ -51,69 +29,3 @@ impl ActorType for Person {
.into()
}
}
#[async_trait::async_trait(?Send)]
impl UserType for Person {
/// As a given local person, send out a follow request to a remote community.
async fn send_follow(
&self,
follow_actor_id: &Url,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let follow_actor_id = follow_actor_id.to_owned();
let community = blocking(context.pool(), move |conn| {
Community::read_from_apub_id(conn, &follow_actor_id.into())
})
.await??;
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
person_id: self.id,
pending: true,
};
blocking(context.pool(), move |conn| {
CommunityFollower::follow(conn, &community_follower_form).ok()
})
.await?;
let mut follow = Follow::new(self.actor_id(), community.actor_id());
follow
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(FollowType::Follow)?)
.set_to(community.actor_id());
send_activity_single_dest(follow, self, community.inbox_url.into(), context).await?;
Ok(())
}
async fn send_unfollow(
&self,
follow_actor_id: &Url,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let follow_actor_id = follow_actor_id.to_owned();
let community = blocking(context.pool(), move |conn| {
Community::read_from_apub_id(conn, &follow_actor_id.into())
})
.await??;
let mut follow = Follow::new(self.actor_id(), community.actor_id());
follow
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(FollowType::Follow)?)
.set_to(community.actor_id());
// Undo that fake activity
let mut undo = Undo::new(
self.actor_id.to_owned().into_inner(),
follow.into_any_base()?,
);
undo
.set_many_contexts(lemmy_context())
.set_id(generate_activity_id(UndoType::Undo)?)
.set_to(community.actor_id());
send_activity_single_dest(undo, self, community.inbox_url.into(), context).await?;
Ok(())
}
}

View file

@ -101,7 +101,7 @@ impl ActivityHandler for UndoVote {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -113,7 +113,7 @@ impl ActivityHandler for Vote {
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {

View file

@ -18,7 +18,6 @@ use crate::{
fetcher::community::get_or_fetch_and_upsert_community,
};
use activitystreams::{
activity::Follow,
actor,
base::AnyBase,
object::{ApObject, AsObject, ObjectExt},
@ -185,11 +184,6 @@ pub trait ActorType {
pub trait CommunityType {
fn followers_url(&self) -> Url;
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_update(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
async fn send_delete(&self, mod_: Person, context: &LemmyContext) -> Result<(), LemmyError>;
@ -232,20 +226,6 @@ pub trait CommunityType {
) -> 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,
Person,

View file

@ -39,7 +39,7 @@ pub trait ActivityHandler {
) -> Result<(), LemmyError>;
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError>;

View file

@ -92,7 +92,7 @@ pub fn derive_activity_handler(input: proc_macro::TokenStream) -> proc_macro::To
}
}
async fn receive(
&self,
self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {