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()
}
fn get_apub_protocol_string() -> &'static str {
pub fn get_apub_protocol_string() -> &'static str {
"http"
}

View file

@ -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<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> {
// 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!(

View file

@ -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<Body> {
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<String>,
usage: NodeInfoUsage,
#[derive(Serialize, Deserialize, Debug)]
pub struct NodeInfo {
pub version: String,
pub software: NodeInfoSoftware,
pub protocols: Vec<String>,
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,
}