Add pending status for federated follows #130
|
@ -1852,8 +1852,10 @@ dependencies = [
|
||||||
name = "lemmy_server"
|
name = "lemmy_server"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"activitystreams",
|
||||||
"actix",
|
"actix",
|
||||||
"actix-files",
|
"actix-files",
|
||||||
|
"actix-rt",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"actix-web-actors",
|
"actix-web-actors",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
@ -1877,6 +1879,7 @@ dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rss",
|
"rss",
|
||||||
"serde 1.0.117",
|
"serde 1.0.117",
|
||||||
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"strum",
|
"strum",
|
||||||
"tokio 0.3.1",
|
"tokio 0.3.1",
|
||||||
|
|
|
@ -46,6 +46,9 @@ tokio = "0.3"
|
||||||
sha2 = "0.9"
|
sha2 = "0.9"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
reqwest = { version = "0.10", features = ["json"] }
|
reqwest = { version = "0.10", features = ["json"] }
|
||||||
|
activitystreams = "0.7.0-alpha.4"
|
||||||
|
actix-rt = { version = "1.1", default-features = false }
|
||||||
|
serde_json = { version = "1.0", features = ["preserve_order"]}
|
||||||
|
|
||||||
[dev-dependencies.cargo-husky]
|
[dev-dependencies.cargo-husky]
|
||||||
version = "1"
|
version = "1"
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -54,7 +54,8 @@ pub async fn get_activity(
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
if !activity.local || activity.sensitive {
|
let sensitive = activity.sensitive.unwrap_or(true);
|
||||||
|
if !activity.local || sensitive {
|
||||||
Ok(HttpResponse::NotFound().finish())
|
Ok(HttpResponse::NotFound().finish())
|
||||||
} else {
|
} else {
|
||||||
Ok(create_apub_response(&activity.data))
|
Ok(create_apub_response(&activity.data))
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,22 +12,22 @@ use std::{
|
||||||
#[table_name = "activity"]
|
#[table_name = "activity"]
|
||||||
pub struct Activity {
|
pub struct Activity {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub ap_id: String,
|
|
||||||
pub data: Value,
|
pub data: Value,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub sensitive: bool,
|
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub ap_id: Option<String>,
|
||||||
|
pub sensitive: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "activity"]
|
#[table_name = "activity"]
|
||||||
pub struct ActivityForm {
|
pub struct ActivityForm {
|
||||||
pub ap_id: String,
|
|
||||||
pub data: Value,
|
pub data: Value,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub sensitive: bool,
|
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub ap_id: String,
|
||||||
|
pub sensitive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ActivityForm> for Activity {
|
impl Crud<ActivityForm> for Activity {
|
||||||
|
@ -53,6 +53,10 @@ impl Crud<ActivityForm> for Activity {
|
||||||
.set(new_activity)
|
.set(new_activity)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
fn delete(conn: &PgConnection, activity_id: i32) -> Result<usize, Error> {
|
||||||
|
use crate::schema::activity::dsl::*;
|
||||||
|
diesel::delete(activity.find(activity_id)).execute(conn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Activity {
|
impl Activity {
|
||||||
|
@ -115,7 +119,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
@ -162,11 +166,11 @@ mod tests {
|
||||||
let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
|
let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
|
||||||
|
|
||||||
let expected_activity = Activity {
|
let expected_activity = Activity {
|
||||||
ap_id: ap_id.to_string(),
|
ap_id: Some(ap_id.to_string()),
|
||||||
id: inserted_activity.id,
|
id: inserted_activity.id,
|
||||||
data: test_json,
|
data: test_json,
|
||||||
local: true,
|
local: true,
|
||||||
sensitive: false,
|
sensitive: Some(false),
|
||||||
published: inserted_activity.published,
|
published: inserted_activity.published,
|
||||||
updated: None,
|
updated: None,
|
||||||
};
|
};
|
||||||
|
@ -174,6 +178,7 @@ mod tests {
|
||||||
let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
|
let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
|
||||||
let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, ap_id).unwrap();
|
let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, ap_id).unwrap();
|
||||||
User_::delete(&conn, inserted_creator.id).unwrap();
|
User_::delete(&conn, inserted_creator.id).unwrap();
|
||||||
|
Activity::delete(&conn, inserted_activity.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_activity, read_activity);
|
assert_eq!(expected_activity, read_activity);
|
||||||
assert_eq!(expected_activity, read_activity_by_apub_id);
|
assert_eq!(expected_activity, read_activity_by_apub_id);
|
||||||
|
|
|
@ -280,7 +280,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -519,7 +519,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -276,6 +276,7 @@ pub struct CommunityFollower {
|
||||||
pub community_id: i32,
|
pub community_id: i32,
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub pending: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
|
@ -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,
|
||||||
|
@ -326,7 +341,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
@ -392,6 +407,7 @@ mod tests {
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
user_id: inserted_user.id,
|
||||||
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_community_follower =
|
let inserted_community_follower =
|
||||||
|
@ -401,6 +417,7 @@ mod tests {
|
||||||
id: inserted_community_follower.id,
|
id: inserted_community_follower.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
user_id: inserted_user.id,
|
||||||
|
pending: Some(false),
|
||||||
published: inserted_community_follower.published,
|
published: inserted_community_follower.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -416,7 +416,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
@ -445,7 +445,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -100,7 +100,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -349,7 +349,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -416,7 +416,7 @@ mod tests {
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
theme: "browser".into(),
|
theme: "browser".into(),
|
||||||
default_sort_type: SortType::Hot as i16,
|
default_sort_type: SortType::Hot as i16,
|
||||||
|
|
|
@ -157,7 +157,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
@ -186,7 +186,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
table! {
|
table! {
|
||||||
activity (id) {
|
activity (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
ap_id -> Text,
|
|
||||||
data -> Jsonb,
|
data -> Jsonb,
|
||||||
local -> Bool,
|
local -> Bool,
|
||||||
sensitive -> Bool,
|
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
updated -> Nullable<Timestamp>,
|
updated -> Nullable<Timestamp>,
|
||||||
|
ap_id -> Nullable<Text>,
|
||||||
|
sensitive -> Nullable<Bool>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +150,7 @@ table! {
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
user_id -> Int4,
|
user_id -> Int4,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
|
pending -> Nullable<Bool>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -96,7 +96,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
@ -125,7 +125,7 @@ mod tests {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE community_follower DROP COLUMN pending;
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE community_follower ADD COLUMN pending BOOLEAN DEFAULT FALSE;
|
5
test.sh
5
test.sh
|
@ -2,4 +2,7 @@
|
||||||
export DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
export DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
||||||
diesel migration run
|
diesel migration run
|
||||||
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
|
||||||
RUST_TEST_THREADS=1 cargo test --workspace --no-fail-fast
|
# Integration tests only work on stable due to a bug in config-rs
|
||||||
|
# https://github.com/mehcode/config-rs/issues/158
|
||||||
|
RUST_BACKTRACE=1 RUST_TEST_THREADS=1 \
|
||||||
|
cargo +stable test --workspace --no-fail-fast
|
||||||
|
|
|
@ -16,6 +16,18 @@ use diesel::{
|
||||||
PgConnection,
|
PgConnection,
|
||||||
};
|
};
|
||||||
use http_signature_normalization_actix::PrepareVerifyError;
|
use http_signature_normalization_actix::PrepareVerifyError;
|
||||||
|
use lemmy_api::match_websocket_operation;
|
||||||
|
use lemmy_apub::{
|
||||||
|
activity_queue::create_activity_queue,
|
||||||
|
inbox::{
|
||||||
|
community_inbox,
|
||||||
|
community_inbox::community_inbox,
|
||||||
|
shared_inbox,
|
||||||
|
shared_inbox::shared_inbox,
|
||||||
|
user_inbox,
|
||||||
|
user_inbox::user_inbox,
|
||||||
|
},
|
||||||
|
};
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
user::{User_, *},
|
user::{User_, *},
|
||||||
|
@ -24,22 +36,8 @@ use lemmy_db::{
|
||||||
SortType,
|
SortType,
|
||||||
};
|
};
|
||||||
use lemmy_rate_limit::{rate_limiter::RateLimiter, RateLimit};
|
use lemmy_rate_limit::{rate_limiter::RateLimiter, RateLimit};
|
||||||
use lemmy_server::{
|
|
||||||
apub::{
|
|
||||||
activity_queue::create_activity_queue,
|
|
||||||
inbox::{
|
|
||||||
community_inbox,
|
|
||||||
community_inbox::community_inbox,
|
|
||||||
shared_inbox,
|
|
||||||
shared_inbox::shared_inbox,
|
|
||||||
user_inbox,
|
|
||||||
user_inbox::user_inbox,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
websocket::chat_server::ChatServer,
|
|
||||||
LemmyContext,
|
|
||||||
};
|
|
||||||
use lemmy_utils::{apub::generate_actor_keypair, settings::Settings};
|
use lemmy_utils::{apub::generate_actor_keypair, settings::Settings};
|
||||||
|
use lemmy_websocket::{chat_server::ChatServer, LemmyContext};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -61,11 +59,12 @@ fn create_context() -> LemmyContext {
|
||||||
let chat_server = ChatServer::startup(
|
let chat_server = ChatServer::startup(
|
||||||
pool.clone(),
|
pool.clone(),
|
||||||
rate_limiter.clone(),
|
rate_limiter.clone(),
|
||||||
|
|c, i, o, d| Box::pin(match_websocket_operation(c, i, o, d)),
|
||||||
Client::default(),
|
Client::default(),
|
||||||
activity_queue.clone(),
|
activity_queue.clone(),
|
||||||
)
|
)
|
||||||
.start();
|
.start();
|
||||||
LemmyContext::new(
|
LemmyContext::create(
|
||||||
pool,
|
pool,
|
||||||
chat_server,
|
chat_server,
|
||||||
Client::default(),
|
Client::default(),
|
||||||
|
@ -84,7 +83,7 @@ fn create_user(conn: &PgConnection, name: &str) -> User_ {
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: false,
|
banned: Some(false),
|
||||||
updated: None,
|
updated: None,
|
||||||
published: None,
|
published: None,
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
@ -177,7 +176,7 @@ async fn test_user_inbox_expired_signature() {
|
||||||
let connection = &context.pool().get().unwrap();
|
let connection = &context.pool().get().unwrap();
|
||||||
let user = create_user(connection, "user_inbox_cgsax");
|
let user = create_user(connection, "user_inbox_cgsax");
|
||||||
let activity =
|
let activity =
|
||||||
create_activity::<CreateType, ActorAndObject<user_inbox::ValidTypes>>(user.actor_id);
|
create_activity::<CreateType, ActorAndObject<user_inbox::UserValidTypes>>(user.actor_id);
|
||||||
let path = Path::<String> {
|
let path = Path::<String> {
|
||||||
0: "username".to_string(),
|
0: "username".to_string(),
|
||||||
};
|
};
|
||||||
|
@ -196,8 +195,9 @@ async fn test_community_inbox_expired_signature() {
|
||||||
let user = create_user(connection, "community_inbox_hrxa");
|
let user = create_user(connection, "community_inbox_hrxa");
|
||||||
let community = create_community(connection, user.id);
|
let community = create_community(connection, user.id);
|
||||||
let request = create_http_request();
|
let request = create_http_request();
|
||||||
let activity =
|
let activity = create_activity::<FollowType, ActorAndObject<community_inbox::CommunityValidTypes>>(
|
||||||
create_activity::<FollowType, ActorAndObject<community_inbox::ValidTypes>>(user.actor_id);
|
user.actor_id,
|
||||||
|
);
|
||||||
let path = Path::<String> { 0: community.name };
|
let path = Path::<String> { 0: community.name };
|
||||||
let response = community_inbox(request, activity, path, web::Data::new(context)).await;
|
let response = community_inbox(request, activity, path, web::Data::new(context)).await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in New Issue
Not sure if this is correct, it should throw an error if no such row was found.
Not totally sure, but it follows the convention of the others. I think since its Result<Self, Error>, that it will either be the single row, or an error if nothing got updated.