From bd030470b1f488f40b739bbbcbd281c5234ec62c Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Wed, 18 Mar 2020 16:08:08 +0100 Subject: [PATCH] Read remote nodeinfo before doing anything --- server/src/apub/mod.rs | 2 +- server/src/apub/puller.rs | 16 +++++++-- server/src/routes/nodeinfo.rs | 62 +++++++++++++++++++---------------- 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index c0e881af4..b7202d57f 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -37,6 +37,6 @@ fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url { .unwrap() } -fn get_apub_protocol_string() -> &'static str { +pub fn get_apub_protocol_string() -> &'static str { "http" } diff --git a/server/src/apub/puller.rs b/server/src/apub/puller.rs index 7ae0696ec..e7b5d6d7d 100644 --- a/server/src/apub/puller.rs +++ b/server/src/apub/puller.rs @@ -5,6 +5,7 @@ use crate::api::post::GetPostsResponse; use crate::db::community_view::CommunityView; use crate::db::post_view::PostView; use crate::naive_now; +use crate::routes::nodeinfo::{NodeInfo, NodeInfoWellKnown}; use crate::settings::Settings; use activitystreams::actor::apub::Group; use activitystreams::collection::apub::{OrderedCollection, UnorderedCollection}; @@ -14,9 +15,20 @@ use failure::Error; use log::warn; use serde::Deserialize; +fn fetch_node_info(domain: &str) -> Result { + let well_known: NodeInfoWellKnown = + reqwest::get(&format!("http://{}/.well-known/nodeinfo", domain))?.json()?; + Ok(reqwest::get(&well_known.links.href)?.json()?) +} fn fetch_communities_from_instance(domain: &str) -> Result, Error> { - // TODO: check nodeinfo to make sure we are dealing with a lemmy instance - // -> means we need proper nodeinfo json classes instead of inline generation + let node_info = fetch_node_info(domain)?; + if node_info.software.name != "lemmy" { + return Err(format_err!( + "{} is not a Lemmy instance, federation is not supported", + domain + )); + } + // TODO: follow pagination (seems like page count is missing?) // TODO: see if there is any standard for discovering remote actors, so we dont have to rely on lemmy apis let communities_uri = format!( diff --git a/server/src/routes/nodeinfo.rs b/server/src/routes/nodeinfo.rs index 75568608e..901db9d31 100644 --- a/server/src/routes/nodeinfo.rs +++ b/server/src/routes/nodeinfo.rs @@ -1,4 +1,5 @@ extern crate lazy_static; +use crate::apub::get_apub_protocol_string; use crate::db::site_view::SiteView; use crate::version; use crate::Settings; @@ -7,7 +8,8 @@ use actix_web::web; use actix_web::HttpResponse; use diesel::r2d2::{ConnectionManager, Pool}; use diesel::PgConnection; -use serde::Serialize; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; pub fn config(cfg: &mut web::ServiceConfig) { cfg @@ -19,7 +21,11 @@ async fn node_info_well_known() -> HttpResponse { let node_info = NodeInfoWellKnown { links: NodeInfoWellKnownLinks { rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(), - href: format!("https://{}/nodeinfo/2.0.json", Settings::get().hostname), + href: format!( + "{}://{}/nodeinfo/2.0.json", + get_apub_protocol_string(), + Settings::get().hostname + ), }, }; HttpResponse::Ok().json(node_info) @@ -62,41 +68,41 @@ async fn node_info( Ok(res) } -#[derive(Serialize)] -struct NodeInfoWellKnown { - links: NodeInfoWellKnownLinks, +#[derive(Serialize, Deserialize, Debug)] +pub struct NodeInfoWellKnown { + pub links: NodeInfoWellKnownLinks, } -#[derive(Serialize)] -struct NodeInfoWellKnownLinks { - rel: String, - href: String, +#[derive(Serialize, Deserialize, Debug)] +pub struct NodeInfoWellKnownLinks { + pub rel: String, + pub href: String, } -#[derive(Serialize)] -struct NodeInfo { - version: String, - software: NodeInfoSoftware, - protocols: Vec, - usage: NodeInfoUsage, +#[derive(Serialize, Deserialize, Debug)] +pub struct NodeInfo { + pub version: String, + pub software: NodeInfoSoftware, + pub protocols: Vec, + pub usage: NodeInfoUsage, } -#[derive(Serialize)] -struct NodeInfoSoftware { - name: String, - version: String, +#[derive(Serialize, Deserialize, Debug)] +pub struct NodeInfoSoftware { + pub name: String, + pub version: String, } -#[derive(Serialize)] +#[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] -struct NodeInfoUsage { - users: NodeInfoUsers, - local_posts: i64, - local_comments: i64, - open_registrations: bool, +pub struct NodeInfoUsage { + pub users: NodeInfoUsers, + pub local_posts: i64, + pub local_comments: i64, + pub open_registrations: bool, } -#[derive(Serialize)] -struct NodeInfoUsers { - total: i64, +#[derive(Serialize, Deserialize, Debug)] +pub struct NodeInfoUsers { + pub total: i64, }