Add pending status for federated follows

This commit is contained in:
Felix Ableitner 2020-11-10 16:45:10 +01:00
parent 94dd335fac
commit 06e82fe761
10 changed files with 48 additions and 13 deletions

View file

@ -188,6 +188,7 @@ impl Perform for CreateCommunity {
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: inserted_community.id, community_id: inserted_community.id,
user_id: user.id, user_id: user.id,
pending: false,
}; };
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form); let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
@ -479,6 +480,7 @@ impl Perform for FollowCommunity {
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: data.community_id, community_id: data.community_id,
user_id: user.id, user_id: user.id,
pending: false,
}; };
if community.local { if community.local {

View file

@ -251,6 +251,7 @@ impl Perform for Register {
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: main_community.id, community_id: main_community.id,
user_id: inserted_user.id, user_id: inserted_user.id,
pending: false,
}; };
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form); let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);

View file

@ -12,7 +12,12 @@ use activitystreams::{
base::{AnyBase, BaseExt, ExtendsExt}, base::{AnyBase, BaseExt, ExtendsExt},
object::ObjectExt, object::ObjectExt,
}; };
use lemmy_db::{community::Community, user::User_, DbPool}; use lemmy_db::{
community::{Community, CommunityFollower, CommunityFollowerForm},
user::User_,
DbPool,
Followable,
};
use lemmy_structs::blocking; use lemmy_structs::blocking;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -44,6 +49,16 @@ impl ActorType for User_ {
}) })
.await??; .await??;
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
user_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.to_owned(), community.actor_id()?); let mut follow = Follow::new(self.actor_id.to_owned(), community.actor_id()?);
follow follow
.set_context(activitystreams::context()) .set_context(activitystreams::context())

View file

@ -191,6 +191,7 @@ async fn handle_follow(
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: community.id, community_id: community.id,
user_id: user.id, user_id: user.id,
pending: false,
}; };
// This will fail if they're already a follower, but ignore the error. // This will fail if they're already a follower, but ignore the error.
@ -245,6 +246,7 @@ async fn handle_undo_follow(
let community_follower_form = CommunityFollowerForm { let community_follower_form = CommunityFollowerForm {
community_id: community.id, community_id: community.id,
user_id: user.id, user_id: user.id,
pending: false,
}; };
// This will fail if they aren't a follower, but ignore the error. // This will fail if they aren't a follower, but ignore the error.

View file

@ -46,7 +46,7 @@ use actix_web::{web, HttpRequest, HttpResponse};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use diesel::NotFound; use diesel::NotFound;
use lemmy_db::{ use lemmy_db::{
community::{Community, CommunityFollower, CommunityFollowerForm}, community::{Community, CommunityFollower},
private_message::PrivateMessage, private_message::PrivateMessage,
user::User_, user::User_,
Followable, Followable,
@ -173,8 +173,6 @@ async fn receive_accept(
let accept = Accept::from_any_base(activity)?.context(location_info!())?; let accept = Accept::from_any_base(activity)?.context(location_info!())?;
verify_activity_domains_valid(&accept, &actor.actor_id()?, false)?; verify_activity_domains_valid(&accept, &actor.actor_id()?, false)?;
// TODO: we should check that we actually sent this activity, because the remote instance
// could just put a fake Follow
let object = accept.object().to_owned().one().context(location_info!())?; let object = accept.object().to_owned().one().context(location_info!())?;
let follow = Follow::from_any_base(object)?.context(location_info!())?; let follow = Follow::from_any_base(object)?.context(location_info!())?;
verify_activity_domains_valid(&follow, &user.actor_id()?, false)?; verify_activity_domains_valid(&follow, &user.actor_id()?, false)?;
@ -188,17 +186,13 @@ async fn receive_accept(
let community = let community =
get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?; get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?;
// Now you need to add this to the community follower let community_id = community.id;
let community_follower_form = CommunityFollowerForm { let user_id = user.id;
community_id: community.id, // This will throw an error if no follow was requested
user_id: user.id,
};
// This will fail if they're already a follower
blocking(&context.pool(), move |conn| { blocking(&context.pool(), move |conn| {
CommunityFollower::follow(conn, &community_follower_form).ok() CommunityFollower::follow_accepted(conn, community_id, user_id)
}) })
.await?; .await??;
Ok(()) Ok(())
} }

View file

@ -275,6 +275,7 @@ pub struct CommunityFollower {
pub id: i32, pub id: i32,
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub user_id: i32,
pub pending: bool,
pub published: chrono::NaiveDateTime, pub published: chrono::NaiveDateTime,
} }
@ -283,6 +284,7 @@ pub struct CommunityFollower {
pub struct CommunityFollowerForm { pub struct CommunityFollowerForm {
pub community_id: i32, pub community_id: i32,
pub user_id: i32, pub user_id: i32,
pub pending: bool,
} }
impl Followable<CommunityFollowerForm> for CommunityFollower { impl Followable<CommunityFollowerForm> for CommunityFollower {
@ -295,6 +297,19 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
.values(community_follower_form) .values(community_follower_form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
} }
fn follow_accepted(conn: &PgConnection, community_id_: i32, user_id_: i32) -> Result<Self, Error>
where
Self: Sized,
{
use crate::schema::community_follower::dsl::*;
diesel::update(
community_follower
.filter(community_id.eq(community_id_))
.filter(user_id.eq(user_id_)),
)
.set(pending.eq(true))
.get_result::<Self>(conn)
}
fn unfollow( fn unfollow(
conn: &PgConnection, conn: &PgConnection,
community_follower_form: &CommunityFollowerForm, community_follower_form: &CommunityFollowerForm,

View file

@ -54,6 +54,9 @@ pub trait Crud<T> {
pub trait Followable<T> { pub trait Followable<T> {
fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error> fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error>
where
Self: Sized;
fn follow_accepted(conn: &PgConnection, community_id: i32, user_id: i32) -> Result<Self, Error>
where where
Self: Sized; Self: Sized;
fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error> fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error>

View file

@ -149,6 +149,7 @@ table! {
id -> Int4, id -> Int4,
community_id -> Int4, community_id -> Int4,
user_id -> Int4, user_id -> Int4,
pending -> Bool,
published -> Timestamp, published -> Timestamp,
} }
} }

View file

@ -0,0 +1 @@
ALTER TABLE community_follower DROP COLUMN pending;

View file

@ -0,0 +1 @@
ALTER TABLE community_follower ADD COLUMN pending BOOLEAN DEFAULT FALSE;