Read remote nodeinfo before doing anything

This commit is contained in:
Felix Ableitner 2020-03-18 16:08:08 +01:00
parent 0cfb0da9cd
commit c95165b01a
3 changed files with 49 additions and 31 deletions

View file

@ -37,6 +37,6 @@ fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
.unwrap() .unwrap()
} }
fn get_apub_protocol_string() -> &'static str { pub fn get_apub_protocol_string() -> &'static str {
"http" "http"
} }

View file

@ -5,6 +5,7 @@ use crate::api::post::GetPostsResponse;
use crate::db::community_view::CommunityView; use crate::db::community_view::CommunityView;
use crate::db::post_view::PostView; use crate::db::post_view::PostView;
use crate::naive_now; use crate::naive_now;
use crate::routes::nodeinfo::{NodeInfo, NodeInfoWellKnown};
use crate::settings::Settings; use crate::settings::Settings;
use activitystreams::actor::apub::Group; use activitystreams::actor::apub::Group;
use activitystreams::collection::apub::{OrderedCollection, UnorderedCollection}; use activitystreams::collection::apub::{OrderedCollection, UnorderedCollection};
@ -14,9 +15,20 @@ use failure::Error;
use log::warn; use log::warn;
use serde::Deserialize; use serde::Deserialize;
fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
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<Vec<CommunityView>, Error> { fn fetch_communities_from_instance(domain: &str) -> Result<Vec<CommunityView>, Error> {
// TODO: check nodeinfo to make sure we are dealing with a lemmy instance let node_info = fetch_node_info(domain)?;
// -> means we need proper nodeinfo json classes instead of inline generation 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: 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 // TODO: see if there is any standard for discovering remote actors, so we dont have to rely on lemmy apis
let communities_uri = format!( let communities_uri = format!(

View file

@ -1,4 +1,5 @@
extern crate lazy_static; extern crate lazy_static;
use crate::apub::get_apub_protocol_string;
use crate::db::site_view::SiteView; use crate::db::site_view::SiteView;
use crate::version; use crate::version;
use crate::Settings; use crate::Settings;
@ -7,7 +8,8 @@ use actix_web::web;
use actix_web::HttpResponse; use actix_web::HttpResponse;
use diesel::r2d2::{ConnectionManager, Pool}; use diesel::r2d2::{ConnectionManager, Pool};
use diesel::PgConnection; use diesel::PgConnection;
use serde::Serialize; use serde::{Deserialize, Serialize};
use std::fmt::Debug;
pub fn config(cfg: &mut web::ServiceConfig) { pub fn config(cfg: &mut web::ServiceConfig) {
cfg cfg
@ -19,7 +21,11 @@ async fn node_info_well_known() -> HttpResponse<Body> {
let node_info = NodeInfoWellKnown { let node_info = NodeInfoWellKnown {
links: NodeInfoWellKnownLinks { links: NodeInfoWellKnownLinks {
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(), 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) HttpResponse::Ok().json(node_info)
@ -62,41 +68,41 @@ async fn node_info(
Ok(res) Ok(res)
} }
#[derive(Serialize)] #[derive(Serialize, Deserialize, Debug)]
struct NodeInfoWellKnown { pub struct NodeInfoWellKnown {
links: NodeInfoWellKnownLinks, pub links: NodeInfoWellKnownLinks,
} }
#[derive(Serialize)] #[derive(Serialize, Deserialize, Debug)]
struct NodeInfoWellKnownLinks { pub struct NodeInfoWellKnownLinks {
rel: String, pub rel: String,
href: String, pub href: String,
} }
#[derive(Serialize)] #[derive(Serialize, Deserialize, Debug)]
struct NodeInfo { pub struct NodeInfo {
version: String, pub version: String,
software: NodeInfoSoftware, pub software: NodeInfoSoftware,
protocols: Vec<String>, pub protocols: Vec<String>,
usage: NodeInfoUsage, pub usage: NodeInfoUsage,
} }
#[derive(Serialize)] #[derive(Serialize, Deserialize, Debug)]
struct NodeInfoSoftware { pub struct NodeInfoSoftware {
name: String, pub name: String,
version: String, pub version: String,
} }
#[derive(Serialize)] #[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct NodeInfoUsage { pub struct NodeInfoUsage {
users: NodeInfoUsers, pub users: NodeInfoUsers,
local_posts: i64, pub local_posts: i64,
local_comments: i64, pub local_comments: i64,
open_registrations: bool, pub open_registrations: bool,
} }
#[derive(Serialize)] #[derive(Serialize, Deserialize, Debug)]
struct NodeInfoUsers { pub struct NodeInfoUsers {
total: i64, pub total: i64,
} }