Send activities to correct inbox, seperate community/user inboxes
This commit is contained in:
parent
7ba6ee8714
commit
9a85f1b25f
7 changed files with 135 additions and 122 deletions
3
docker/federation/run-federation-test.bash
vendored
3
docker/federation/run-federation-test.bash
vendored
|
@ -3,6 +3,7 @@ set -e
|
||||||
|
|
||||||
if [ "$1" = "-yarn" ]; then
|
if [ "$1" = "-yarn" ]; then
|
||||||
pushd ../../ui/ || exit
|
pushd ../../ui/ || exit
|
||||||
|
yarn
|
||||||
yarn build
|
yarn build
|
||||||
popd || exit
|
popd || exit
|
||||||
fi
|
fi
|
||||||
|
@ -13,4 +14,4 @@ popd || exit
|
||||||
|
|
||||||
sudo docker build ../../ -f Dockerfile -t lemmy-federation:latest
|
sudo docker build ../../ -f Dockerfile -t lemmy-federation:latest
|
||||||
|
|
||||||
sudo docker-compose up
|
sudo docker-compose up
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::apub::{get_apub_protocol_string, get_following_instances};
|
|
||||||
use crate::db::community::Community;
|
use crate::db::community::Community;
|
||||||
|
use crate::db::community_view::CommunityFollowerView;
|
||||||
use crate::db::post::Post;
|
use crate::db::post::Post;
|
||||||
use crate::db::user::User_;
|
use crate::db::user::User_;
|
||||||
use crate::db::Crud;
|
use crate::db::Crud;
|
||||||
|
@ -46,18 +46,14 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_followers(_community: &Community) -> Vec<String> {
|
fn get_followers(conn: &PgConnection, community: &Community) -> Result<Vec<String>, Error> {
|
||||||
// TODO: this is wrong, needs to go to the (non-local) followers of the community
|
Ok(
|
||||||
get_following_instances()
|
CommunityFollowerView::for_community(conn, community.id)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| {
|
.filter(|c| !c.user_local)
|
||||||
format!(
|
.map(|c| format!("{}/inbox", c.user_actor_id.to_owned()))
|
||||||
"{}://{}/federation/inbox",
|
.collect(),
|
||||||
get_apub_protocol_string(),
|
)
|
||||||
i.domain
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_create(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
|
pub fn post_create(post: &Post, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
|
||||||
|
@ -73,7 +69,7 @@ pub fn post_create(post: &Post, creator: &User_, conn: &PgConnection) -> Result<
|
||||||
.create_props
|
.create_props
|
||||||
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
||||||
.set_object_base_box(page)?;
|
.set_object_base_box(page)?;
|
||||||
send_activity(&create, get_followers(&community))?;
|
send_activity(&create, get_followers(conn, &community)?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +86,7 @@ pub fn post_update(post: &Post, creator: &User_, conn: &PgConnection) -> Result<
|
||||||
.update_props
|
.update_props
|
||||||
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
|
||||||
.set_object_base_box(page)?;
|
.set_object_base_box(page)?;
|
||||||
send_activity(&update, get_followers(&community))?;
|
send_activity(&update, get_followers(conn, &community)?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
53
server/src/apub/community_inbox.rs
Normal file
53
server/src/apub/community_inbox.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use crate::apub::activities::accept_follow;
|
||||||
|
use crate::apub::fetcher::fetch_remote_user;
|
||||||
|
use crate::db::community::{Community, CommunityFollower, CommunityFollowerForm};
|
||||||
|
use crate::db::Followable;
|
||||||
|
use activitystreams::activity::Follow;
|
||||||
|
use actix_web::{web, HttpResponse};
|
||||||
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
|
use diesel::PgConnection;
|
||||||
|
use failure::Error;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[serde(untagged)]
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub enum CommunityAcceptedObjects {
|
||||||
|
Follow(Follow),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn community_inbox(
|
||||||
|
input: web::Json<CommunityAcceptedObjects>,
|
||||||
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let input = input.into_inner();
|
||||||
|
let conn = &db.get().unwrap();
|
||||||
|
match input {
|
||||||
|
CommunityAcceptedObjects::Follow(f) => handle_follow(&f, conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_follow(follow: &Follow, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
|
println!("received follow: {:?}", &follow);
|
||||||
|
|
||||||
|
// TODO: make sure this is a local community
|
||||||
|
let community_uri = follow
|
||||||
|
.follow_props
|
||||||
|
.get_object_xsd_any_uri()
|
||||||
|
.unwrap()
|
||||||
|
.to_string();
|
||||||
|
let community = Community::read_from_actor_id(conn, &community_uri)?;
|
||||||
|
let user_uri = follow
|
||||||
|
.follow_props
|
||||||
|
.get_actor_xsd_any_uri()
|
||||||
|
.unwrap()
|
||||||
|
.to_string();
|
||||||
|
let user = fetch_remote_user(&Url::parse(&user_uri)?, conn)?;
|
||||||
|
// TODO: insert ID of the user into follows of the community
|
||||||
|
let community_follower_form = CommunityFollowerForm {
|
||||||
|
community_id: community.id,
|
||||||
|
user_id: user.id,
|
||||||
|
};
|
||||||
|
CommunityFollower::follow(&conn, &community_follower_form)?;
|
||||||
|
accept_follow(&follow)?;
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
|
@ -1,101 +0,0 @@
|
||||||
use crate::apub::activities::accept_follow;
|
|
||||||
use crate::apub::fetcher::fetch_remote_user;
|
|
||||||
use crate::db::community::{Community, CommunityFollower, CommunityFollowerForm};
|
|
||||||
use crate::db::post::{Post, PostForm};
|
|
||||||
use crate::db::Crud;
|
|
||||||
use crate::db::Followable;
|
|
||||||
use activitystreams::activity::{Accept, Create, Follow, Update};
|
|
||||||
use activitystreams::object::Page;
|
|
||||||
use actix_web::{web, HttpResponse};
|
|
||||||
use diesel::r2d2::{ConnectionManager, Pool};
|
|
||||||
use diesel::PgConnection;
|
|
||||||
use failure::Error;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
// TODO: need a proper actor that has this inbox
|
|
||||||
|
|
||||||
pub async fn inbox(
|
|
||||||
input: web::Json<AcceptedObjects>,
|
|
||||||
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
|
||||||
) -> Result<HttpResponse, Error> {
|
|
||||||
// TODO: make sure that things are received in the correct inbox
|
|
||||||
// (by using seperate handler functions and checking the user/community name in the path)
|
|
||||||
let input = input.into_inner();
|
|
||||||
let conn = &db.get().unwrap();
|
|
||||||
match input {
|
|
||||||
AcceptedObjects::Create(c) => handle_create(&c, conn),
|
|
||||||
AcceptedObjects::Update(u) => handle_update(&u, conn),
|
|
||||||
AcceptedObjects::Follow(f) => handle_follow(&f, conn),
|
|
||||||
AcceptedObjects::Accept(a) => handle_accept(&a, conn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_create(create: &Create, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
|
||||||
let page = create
|
|
||||||
.create_props
|
|
||||||
.get_object_base_box()
|
|
||||||
.to_owned()
|
|
||||||
.unwrap()
|
|
||||||
.to_owned()
|
|
||||||
.to_concrete::<Page>()?;
|
|
||||||
let post = PostForm::from_page(&page, conn)?;
|
|
||||||
Post::create(conn, &post)?;
|
|
||||||
// TODO: send the new post out via websocket
|
|
||||||
Ok(HttpResponse::Ok().finish())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_update(update: &Update, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
|
||||||
let page = update
|
|
||||||
.update_props
|
|
||||||
.get_object_base_box()
|
|
||||||
.to_owned()
|
|
||||||
.unwrap()
|
|
||||||
.to_owned()
|
|
||||||
.to_concrete::<Page>()?;
|
|
||||||
let post = PostForm::from_page(&page, conn)?;
|
|
||||||
let id = Post::read_from_apub_id(conn, &post.ap_id)?.id;
|
|
||||||
Post::update(conn, id, &post)?;
|
|
||||||
// TODO: send the new post out via websocket
|
|
||||||
Ok(HttpResponse::Ok().finish())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_follow(follow: &Follow, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
|
||||||
println!("received follow: {:?}", &follow);
|
|
||||||
|
|
||||||
// TODO: make sure this is a local community
|
|
||||||
let community_uri = follow
|
|
||||||
.follow_props
|
|
||||||
.get_object_xsd_any_uri()
|
|
||||||
.unwrap()
|
|
||||||
.to_string();
|
|
||||||
let community = Community::read_from_actor_id(conn, &community_uri)?;
|
|
||||||
let user_uri = follow
|
|
||||||
.follow_props
|
|
||||||
.get_actor_xsd_any_uri()
|
|
||||||
.unwrap()
|
|
||||||
.to_string();
|
|
||||||
let user = fetch_remote_user(&Url::parse(&user_uri)?, conn)?;
|
|
||||||
// TODO: insert ID of the user into follows of the community
|
|
||||||
let community_follower_form = CommunityFollowerForm {
|
|
||||||
community_id: community.id,
|
|
||||||
user_id: user.id,
|
|
||||||
};
|
|
||||||
CommunityFollower::follow(&conn, &community_follower_form)?;
|
|
||||||
accept_follow(&follow)?;
|
|
||||||
Ok(HttpResponse::Ok().finish())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_accept(accept: &Accept, _conn: &PgConnection) -> Result<HttpResponse, Error> {
|
|
||||||
println!("received accept: {:?}", &accept);
|
|
||||||
// TODO: at this point, indicate to the user that they are following the community
|
|
||||||
Ok(HttpResponse::Ok().finish())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[serde(untagged)]
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
pub enum AcceptedObjects {
|
|
||||||
Create(Create),
|
|
||||||
Update(Update),
|
|
||||||
Follow(Follow),
|
|
||||||
Accept(Accept),
|
|
||||||
}
|
|
|
@ -1,10 +1,11 @@
|
||||||
pub mod activities;
|
pub mod activities;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
pub mod community_inbox;
|
||||||
pub mod fetcher;
|
pub mod fetcher;
|
||||||
pub mod inbox;
|
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod signatures;
|
pub mod signatures;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
pub mod user_inbox;
|
||||||
use crate::apub::signatures::PublicKeyExtension;
|
use crate::apub::signatures::PublicKeyExtension;
|
||||||
use crate::Settings;
|
use crate::Settings;
|
||||||
use activitystreams::actor::{properties::ApActorProperties, Group, Person};
|
use activitystreams::actor::{properties::ApActorProperties, Group, Person};
|
||||||
|
|
64
server/src/apub/user_inbox.rs
Normal file
64
server/src/apub/user_inbox.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
use crate::db::post::{Post, PostForm};
|
||||||
|
use crate::db::Crud;
|
||||||
|
use activitystreams::activity::{Accept, Create, Update};
|
||||||
|
use activitystreams::object::Page;
|
||||||
|
use actix_web::{web, HttpResponse};
|
||||||
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
|
use diesel::PgConnection;
|
||||||
|
use failure::Error;
|
||||||
|
|
||||||
|
#[serde(untagged)]
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub enum UserAcceptedObjects {
|
||||||
|
Create(Create),
|
||||||
|
Update(Update),
|
||||||
|
Accept(Accept),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn user_inbox(
|
||||||
|
input: web::Json<UserAcceptedObjects>,
|
||||||
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let input = input.into_inner();
|
||||||
|
let conn = &db.get().unwrap();
|
||||||
|
match input {
|
||||||
|
UserAcceptedObjects::Create(c) => handle_create(&c, conn),
|
||||||
|
UserAcceptedObjects::Update(u) => handle_update(&u, conn),
|
||||||
|
UserAcceptedObjects::Accept(a) => handle_accept(&a, conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_create(create: &Create, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
|
let page = create
|
||||||
|
.create_props
|
||||||
|
.get_object_base_box()
|
||||||
|
.to_owned()
|
||||||
|
.unwrap()
|
||||||
|
.to_owned()
|
||||||
|
.to_concrete::<Page>()?;
|
||||||
|
let post = PostForm::from_page(&page, conn)?;
|
||||||
|
Post::create(conn, &post)?;
|
||||||
|
// TODO: send the new post out via websocket
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_update(update: &Update, conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
|
let page = update
|
||||||
|
.update_props
|
||||||
|
.get_object_base_box()
|
||||||
|
.to_owned()
|
||||||
|
.unwrap()
|
||||||
|
.to_owned()
|
||||||
|
.to_concrete::<Page>()?;
|
||||||
|
let post = PostForm::from_page(&page, conn)?;
|
||||||
|
let id = Post::read_from_apub_id(conn, &post.ap_id)?.id;
|
||||||
|
Post::update(conn, id, &post)?;
|
||||||
|
// TODO: send the new post out via websocket
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_accept(accept: &Accept, _conn: &PgConnection) -> Result<HttpResponse, Error> {
|
||||||
|
println!("received accept: {:?}", &accept);
|
||||||
|
// TODO: at this point, indicate to the user that they are following the community
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
|
@ -10,15 +10,14 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
"/federation/communities",
|
"/federation/communities",
|
||||||
web::get().to(apub::community::get_apub_community_list),
|
web::get().to(apub::community::get_apub_community_list),
|
||||||
)
|
)
|
||||||
// TODO: this needs to be moved to the actors (eg /federation/u/{}/inbox)
|
// TODO: check the user/community params for these
|
||||||
.route("/federation/inbox", web::post().to(apub::inbox::inbox))
|
|
||||||
.route(
|
.route(
|
||||||
"/federation/c/{_}/inbox",
|
"/federation/c/{_}/inbox",
|
||||||
web::post().to(apub::inbox::inbox),
|
web::post().to(apub::community_inbox::community_inbox),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/federation/u/{_}/inbox",
|
"/federation/u/{_}/inbox",
|
||||||
web::post().to(apub::inbox::inbox),
|
web::post().to(apub::user_inbox::user_inbox),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/federation/c/{community_name}",
|
"/federation/c/{community_name}",
|
||||||
|
|
Loading…
Reference in a new issue