Use Url instead of String
This commit is contained in:
parent
edd0ef5991
commit
6962b9c433
6 changed files with 42 additions and 37 deletions
1
server/Cargo.lock
generated
vendored
1
server/Cargo.lock
generated
vendored
|
@ -2743,6 +2743,7 @@ dependencies = [
|
||||||
"idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
2
server/Cargo.toml
vendored
2
server/Cargo.toml
vendored
|
@ -34,7 +34,7 @@ rss = "1.9.0"
|
||||||
htmlescape = "0.3.1"
|
htmlescape = "0.3.1"
|
||||||
config = "0.10.1"
|
config = "0.10.1"
|
||||||
hjson = "0.8.2"
|
hjson = "0.8.2"
|
||||||
url = "2.1.1"
|
url = { version = "2.1.1", features = ["serde"] }
|
||||||
percent-encoding = "2.1.0"
|
percent-encoding = "2.1.0"
|
||||||
isahc = "0.9"
|
isahc = "0.9"
|
||||||
comrak = "0.7"
|
comrak = "0.7"
|
||||||
|
|
|
@ -22,6 +22,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CommunityQuery {
|
pub struct CommunityQuery {
|
||||||
|
@ -87,16 +88,14 @@ impl Community {
|
||||||
|
|
||||||
impl CommunityForm {
|
impl CommunityForm {
|
||||||
pub fn from_group(group: &GroupExt, conn: &PgConnection) -> Result<Self, Error> {
|
pub fn from_group(group: &GroupExt, conn: &PgConnection) -> Result<Self, Error> {
|
||||||
let followers_uri = &group.extension.get_followers().unwrap().to_string();
|
let followers_uri = Url::parse(&group.extension.get_followers().unwrap().to_string())?;
|
||||||
let outbox_uri = &group.extension.get_outbox().to_string();
|
let outbox_uri = Url::parse(&group.extension.get_outbox().to_string())?;
|
||||||
let _outbox = fetch_remote_object::<OrderedCollection>(outbox_uri)?;
|
let _outbox = fetch_remote_object::<OrderedCollection>(&outbox_uri)?;
|
||||||
let _followers = fetch_remote_object::<UnorderedCollection>(followers_uri)?;
|
let _followers = fetch_remote_object::<UnorderedCollection>(&followers_uri)?;
|
||||||
let oprops = &group.base.object_props;
|
let oprops = &group.base.object_props;
|
||||||
let aprops = &group.extension;
|
let aprops = &group.extension;
|
||||||
let creator = fetch_remote_user(
|
let apub_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
|
||||||
&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string(),
|
let creator = fetch_remote_user(&apub_id, conn)?;
|
||||||
conn,
|
|
||||||
)?;
|
|
||||||
Ok(CommunityForm {
|
Ok(CommunityForm {
|
||||||
name: oprops.get_name_xsd_string().unwrap().to_string(),
|
name: oprops.get_name_xsd_string().unwrap().to_string(),
|
||||||
title: aprops.get_preferred_username().unwrap().to_string(),
|
title: aprops.get_preferred_username().unwrap().to_string(),
|
||||||
|
|
|
@ -12,6 +12,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct PostQuery {
|
pub struct PostQuery {
|
||||||
|
@ -64,10 +65,8 @@ impl Post {
|
||||||
impl PostForm {
|
impl PostForm {
|
||||||
pub fn from_page(page: &Page, conn: &PgConnection) -> Result<PostForm, Error> {
|
pub fn from_page(page: &Page, conn: &PgConnection) -> Result<PostForm, Error> {
|
||||||
let oprops = &page.object_props;
|
let oprops = &page.object_props;
|
||||||
let creator = fetch_remote_user(
|
let apub_id = Url::parse(&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string())?;
|
||||||
&oprops.get_attributed_to_xsd_any_uri().unwrap().to_string(),
|
let creator = fetch_remote_user(&apub_id, conn)?;
|
||||||
conn,
|
|
||||||
)?;
|
|
||||||
Ok(PostForm {
|
Ok(PostForm {
|
||||||
name: oprops.get_name_xsd_string().unwrap().to_string(),
|
name: oprops.get_name_xsd_string().unwrap().to_string(),
|
||||||
url: oprops.get_url_xsd_any_uri().map(|u| u.to_string()),
|
url: oprops.get_url_xsd_any_uri().map(|u| u.to_string()),
|
||||||
|
|
|
@ -15,22 +15,23 @@ use isahc::prelude::*;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
|
fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
|
||||||
let well_known_uri = format!(
|
let well_known_uri = Url::parse(&format!(
|
||||||
"{}://{}/.well-known/nodeinfo",
|
"{}://{}/.well-known/nodeinfo",
|
||||||
get_apub_protocol_string(),
|
get_apub_protocol_string(),
|
||||||
domain
|
domain
|
||||||
);
|
))?;
|
||||||
let well_known = fetch_remote_object::<NodeInfoWellKnown>(&well_known_uri)?;
|
let well_known = fetch_remote_object::<NodeInfoWellKnown>(&well_known_uri)?;
|
||||||
Ok(fetch_remote_object::<NodeInfo>(&well_known.links.href)?)
|
Ok(fetch_remote_object::<NodeInfo>(&well_known.links.href)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_communities_from_instance(
|
fn fetch_communities_from_instance(
|
||||||
community_list_url: &str,
|
community_list: &Url,
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
) -> Result<Vec<Community>, Error> {
|
) -> Result<Vec<Community>, Error> {
|
||||||
fetch_remote_object::<UnorderedCollection>(community_list_url)?
|
fetch_remote_object::<UnorderedCollection>(community_list)?
|
||||||
.collection_props
|
.collection_props
|
||||||
.get_many_items_base_boxes()
|
.get_many_items_base_boxes()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -53,16 +54,16 @@ fn fetch_communities_from_instance(
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add an optional param last_updated and only fetch if its too old
|
// TODO: add an optional param last_updated and only fetch if its too old
|
||||||
pub fn fetch_remote_object<Response>(uri: &str) -> Result<Response, Error>
|
pub fn fetch_remote_object<Response>(url: &Url) -> Result<Response, Error>
|
||||||
where
|
where
|
||||||
Response: for<'de> Deserialize<'de>,
|
Response: for<'de> Deserialize<'de>,
|
||||||
{
|
{
|
||||||
if Settings::get().federation.tls_enabled && !uri.starts_with("https://") {
|
if Settings::get().federation.tls_enabled && url.scheme() != "https" {
|
||||||
return Err(format_err!("Activitypub uri is insecure: {}", uri));
|
return Err(format_err!("Activitypub uri is insecure: {}", url));
|
||||||
}
|
}
|
||||||
// TODO: this function should return a future
|
// TODO: this function should return a future
|
||||||
let timeout = Duration::from_secs(60);
|
let timeout = Duration::from_secs(60);
|
||||||
let text = Request::get(uri)
|
let text = Request::get(url.as_str())
|
||||||
.header("Accept", APUB_JSON_CONTENT_TYPE)
|
.header("Accept", APUB_JSON_CONTENT_TYPE)
|
||||||
.connect_timeout(timeout)
|
.connect_timeout(timeout)
|
||||||
.timeout(timeout)
|
.timeout(timeout)
|
||||||
|
@ -78,11 +79,14 @@ fn fetch_remote_community_posts(
|
||||||
community: &Community,
|
community: &Community,
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
) -> Result<Vec<Post>, Error> {
|
) -> Result<Vec<Post>, Error> {
|
||||||
let endpoint = format!("http://{}/federation/c/{}", instance, community.name);
|
let endpoint = Url::parse(&format!(
|
||||||
|
"http://{}/federation/c/{}",
|
||||||
|
instance, community.name
|
||||||
|
))?;
|
||||||
let group = fetch_remote_object::<GroupExt>(&endpoint)?;
|
let group = fetch_remote_object::<GroupExt>(&endpoint)?;
|
||||||
let outbox_uri = &group.extension.get_outbox().to_string();
|
let outbox_uri = Url::parse(&group.extension.get_outbox().to_string())?;
|
||||||
// TODO: outbox url etc should be stored in local db
|
// TODO: outbox url etc should be stored in local db
|
||||||
let outbox = fetch_remote_object::<OrderedCollection>(outbox_uri)?;
|
let outbox = fetch_remote_object::<OrderedCollection>(&outbox_uri)?;
|
||||||
let items = outbox.collection_props.get_many_items_base_boxes();
|
let items = outbox.collection_props.get_many_items_base_boxes();
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
|
@ -106,7 +110,7 @@ fn fetch_remote_community_posts(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch_remote_user(apub_id: &str, conn: &PgConnection) -> Result<User_, Error> {
|
pub fn fetch_remote_user(apub_id: &Url, conn: &PgConnection) -> Result<User_, Error> {
|
||||||
let person = fetch_remote_object::<PersonExt>(apub_id)?;
|
let person = fetch_remote_object::<PersonExt>(apub_id)?;
|
||||||
let uf = UserForm::from_person(&person)?;
|
let uf = UserForm::from_person(&person)?;
|
||||||
let existing = User_::read_from_apub_id(conn, &uf.actor_id);
|
let existing = User_::read_from_apub_id(conn, &uf.actor_id);
|
||||||
|
@ -122,8 +126,8 @@ pub fn fetch_remote_user(apub_id: &str, conn: &PgConnection) -> Result<User_, Er
|
||||||
pub fn fetch_all(conn: &PgConnection) -> Result<(), Error> {
|
pub fn fetch_all(conn: &PgConnection) -> Result<(), Error> {
|
||||||
for instance in &get_following_instances() {
|
for instance in &get_following_instances() {
|
||||||
let node_info = fetch_node_info(instance)?;
|
let node_info = fetch_node_info(instance)?;
|
||||||
if let Some(community_list_url) = node_info.metadata.community_list_url {
|
if let Some(community_list) = node_info.metadata.community_list_url {
|
||||||
let communities = fetch_communities_from_instance(&community_list_url, conn)?;
|
let communities = fetch_communities_from_instance(&community_list, conn)?;
|
||||||
for c in communities {
|
for c in communities {
|
||||||
fetch_remote_community_posts(instance, &c, conn)?;
|
fetch_remote_community_posts(instance, &c, conn)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,10 @@ 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 failure::Error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg
|
cfg
|
||||||
|
@ -16,18 +18,18 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
.route("/.well-known/nodeinfo", web::get().to(node_info_well_known));
|
.route("/.well-known/nodeinfo", web::get().to(node_info_well_known));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn node_info_well_known() -> HttpResponse<Body> {
|
async fn node_info_well_known() -> Result<HttpResponse<Body>, Error> {
|
||||||
let node_info = NodeInfoWellKnown {
|
let node_info = NodeInfoWellKnown {
|
||||||
links: NodeInfoWellKnownLinks {
|
links: NodeInfoWellKnownLinks {
|
||||||
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(),
|
rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0")?,
|
||||||
href: format!(
|
href: Url::parse(&format!(
|
||||||
"{}://{}/nodeinfo/2.0.json",
|
"{}://{}/nodeinfo/2.0.json",
|
||||||
get_apub_protocol_string(),
|
get_apub_protocol_string(),
|
||||||
Settings::get().hostname
|
Settings::get().hostname
|
||||||
),
|
))?,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
HttpResponse::Ok().json(node_info)
|
Ok(HttpResponse::Ok().json(node_info))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn node_info(
|
async fn node_info(
|
||||||
|
@ -60,11 +62,11 @@ async fn node_info(
|
||||||
open_registrations: site_view.open_registration,
|
open_registrations: site_view.open_registration,
|
||||||
},
|
},
|
||||||
metadata: NodeInfoMetadata {
|
metadata: NodeInfoMetadata {
|
||||||
community_list_url: Some(format!(
|
community_list_url: Some(Url::parse(&format!(
|
||||||
"{}://{}/federation/communities",
|
"{}://{}/federation/communities",
|
||||||
get_apub_protocol_string(),
|
get_apub_protocol_string(),
|
||||||
Settings::get().hostname
|
Settings::get().hostname
|
||||||
)),
|
))?),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -81,8 +83,8 @@ pub struct NodeInfoWellKnown {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct NodeInfoWellKnownLinks {
|
pub struct NodeInfoWellKnownLinks {
|
||||||
pub rel: String,
|
pub rel: Url,
|
||||||
pub href: String,
|
pub href: Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
@ -116,5 +118,5 @@ pub struct NodeInfoUsers {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct NodeInfoMetadata {
|
pub struct NodeInfoMetadata {
|
||||||
pub community_list_url: Option<String>,
|
pub community_list_url: Option<Url>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue