Use the webfinger crate
This commit is contained in:
parent
0dfc303c83
commit
5415b70854
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -1020,6 +1020,7 @@ dependencies = [
|
|||||||
"serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"webfinger 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1913,6 +1914,17 @@ name = "void"
|
|||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webfinger"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"reqwest 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -2176,6 +2188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||||
"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
|
"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
|
"checksum webfinger 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27a4e6d1de7050af8beb026c02bcef5340ec1f3af6d4a02248b7990908baa3ff"
|
||||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
|
@ -24,6 +24,7 @@ serde_derive = "1.0"
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tera = "0.11"
|
tera = "0.11"
|
||||||
url = "1.7"
|
url = "1.7"
|
||||||
|
webfinger = "0.1"
|
||||||
|
|
||||||
[dependencies.chrono]
|
[dependencies.chrono]
|
||||||
features = ["serde"]
|
features = ["serde"]
|
||||||
|
@ -33,6 +33,7 @@ extern crate serde_derive;
|
|||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate tera;
|
extern crate tera;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
|
extern crate webfinger;
|
||||||
|
|
||||||
use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}};
|
use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
@ -14,13 +14,13 @@ use openssl::{
|
|||||||
rsa::Rsa,
|
rsa::Rsa,
|
||||||
sign::Signer
|
sign::Signer
|
||||||
};
|
};
|
||||||
|
use webfinger::*;
|
||||||
|
|
||||||
use activity_pub::{
|
use activity_pub::{
|
||||||
ActivityStream, Id, IntoId,
|
ActivityStream, Id, IntoId,
|
||||||
actor::{Actor as APActor, ActorType},
|
actor::{Actor as APActor, ActorType},
|
||||||
inbox::WithInbox,
|
inbox::WithInbox,
|
||||||
sign,
|
sign
|
||||||
webfinger::*
|
|
||||||
};
|
};
|
||||||
use models::instance::*;
|
use models::instance::*;
|
||||||
use schema::blogs;
|
use schema::blogs;
|
||||||
@ -91,9 +91,9 @@ impl Blog {
|
|||||||
|
|
||||||
fn fetch_from_webfinger(conn: &PgConnection, acct: String) -> Option<Blog> {
|
fn fetch_from_webfinger(conn: &PgConnection, acct: String) -> Option<Blog> {
|
||||||
match resolve(acct.clone()) {
|
match resolve(acct.clone()) {
|
||||||
Ok(url) => Blog::fetch_from_url(conn, url),
|
Ok(wf) => wf.links.into_iter().find(|l| l.mime_type == Some(String::from("application/activity+json"))).and_then(|l| Blog::fetch_from_url(conn, l.href)),
|
||||||
Err(details) => {
|
Err(details) => {
|
||||||
println!("{}", details);
|
println!("{:?}", details);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,6 +171,30 @@ impl Blog {
|
|||||||
pub fn get_keypair(&self) -> PKey<Private> {
|
pub fn get_keypair(&self) -> PKey<Private> {
|
||||||
PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.clone().unwrap().as_ref()).unwrap()).unwrap()
|
PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.clone().unwrap().as_ref()).unwrap()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn webfinger(&self, conn: &PgConnection) -> Webfinger {
|
||||||
|
Webfinger {
|
||||||
|
subject: format!("acct:{}@{}", self.actor_id, self.get_instance(conn).public_domain),
|
||||||
|
aliases: vec![self.compute_id(conn)],
|
||||||
|
links: vec![
|
||||||
|
Link {
|
||||||
|
rel: String::from("http://webfinger.net/rel/profile-page"),
|
||||||
|
mime_type: None,
|
||||||
|
href: self.compute_id(conn)
|
||||||
|
},
|
||||||
|
Link {
|
||||||
|
rel: String::from("http://schemas.google.com/g/2010#updates-from"),
|
||||||
|
mime_type: Some(String::from("application/atom+xml")),
|
||||||
|
href: self.compute_box(conn, "feed.atom")
|
||||||
|
},
|
||||||
|
Link {
|
||||||
|
rel: String::from("self"),
|
||||||
|
mime_type: Some(String::from("application/activity+json")),
|
||||||
|
href: self.compute_id(conn)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoId for Blog {
|
impl IntoId for Blog {
|
||||||
@ -234,33 +258,6 @@ impl APActor for Blog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Webfinger for Blog {
|
|
||||||
fn webfinger_subject(&self, conn: &PgConnection) -> String {
|
|
||||||
format!("acct:{}@{}", self.actor_id, self.get_instance(conn).public_domain)
|
|
||||||
}
|
|
||||||
fn webfinger_aliases(&self, conn: &PgConnection) -> Vec<String> {
|
|
||||||
vec![self.compute_id(conn)]
|
|
||||||
}
|
|
||||||
fn webfinger_links(&self, conn: &PgConnection) -> Vec<Vec<(String, String)>> {
|
|
||||||
vec![
|
|
||||||
vec![
|
|
||||||
(String::from("rel"), String::from("http://webfinger.net/rel/profile-page")),
|
|
||||||
(String::from("href"), self.compute_id(conn))
|
|
||||||
],
|
|
||||||
vec![
|
|
||||||
(String::from("rel"), String::from("http://schemas.google.com/g/2010#updates-from")),
|
|
||||||
(String::from("type"), String::from("application/atom+xml")),
|
|
||||||
(String::from("href"), self.compute_box(conn, "feed.atom"))
|
|
||||||
],
|
|
||||||
vec![
|
|
||||||
(String::from("rel"), String::from("self")),
|
|
||||||
(String::from("type"), String::from("application/activity+json")),
|
|
||||||
(String::from("href"), self.compute_id(conn))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl sign::Signer for Blog {
|
impl sign::Signer for Blog {
|
||||||
fn get_key_id(&self, conn: &PgConnection) -> String {
|
fn get_key_id(&self, conn: &PgConnection) -> String {
|
||||||
format!("{}#main-key", self.compute_id(conn))
|
format!("{}#main-key", self.compute_id(conn))
|
||||||
|
@ -24,6 +24,7 @@ use rocket::{
|
|||||||
};
|
};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
use webfinger::*;
|
||||||
|
|
||||||
use BASE_URL;
|
use BASE_URL;
|
||||||
use activity_pub::{
|
use activity_pub::{
|
||||||
@ -31,7 +32,7 @@ use activity_pub::{
|
|||||||
actor::{ActorType, Actor as APActor},
|
actor::{ActorType, Actor as APActor},
|
||||||
inbox::{Inbox, WithInbox},
|
inbox::{Inbox, WithInbox},
|
||||||
sign::{Signer, gen_keypair},
|
sign::{Signer, gen_keypair},
|
||||||
webfinger::{Webfinger, resolve}
|
webfinger::{resolve}
|
||||||
};
|
};
|
||||||
use db_conn::DbConn;
|
use db_conn::DbConn;
|
||||||
use models::{
|
use models::{
|
||||||
@ -336,6 +337,30 @@ impl User {
|
|||||||
json["fqn"] = serde_json::Value::String(self.get_fqn(conn));
|
json["fqn"] = serde_json::Value::String(self.get_fqn(conn));
|
||||||
json
|
json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn webfinger(&self, conn: &PgConnection) -> Webfinger {
|
||||||
|
Webfinger {
|
||||||
|
subject: format!("acct:{}@{}", self.username, self.get_instance(conn).public_domain),
|
||||||
|
aliases: vec![self.compute_id(conn)],
|
||||||
|
links: vec![
|
||||||
|
Link {
|
||||||
|
rel: String::from("http://webfinger.net/rel/profile-page"),
|
||||||
|
mime_type: None,
|
||||||
|
href: self.compute_id(conn)
|
||||||
|
},
|
||||||
|
Link {
|
||||||
|
rel: String::from("http://schemas.google.com/g/2010#updates-from"),
|
||||||
|
mime_type: Some(String::from("application/atom+xml")),
|
||||||
|
href: self.compute_box(conn, "feed.atom")
|
||||||
|
},
|
||||||
|
Link {
|
||||||
|
rel: String::from("self"),
|
||||||
|
mime_type: Some(String::from("application/activity+json")),
|
||||||
|
href: self.compute_id(conn)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'r> FromRequest<'a, 'r> for User {
|
impl<'a, 'r> FromRequest<'a, 'r> for User {
|
||||||
@ -445,33 +470,6 @@ impl Inbox for User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Webfinger for User {
|
|
||||||
fn webfinger_subject(&self, conn: &PgConnection) -> String {
|
|
||||||
format!("acct:{}@{}", self.username, self.get_instance(conn).public_domain)
|
|
||||||
}
|
|
||||||
fn webfinger_aliases(&self, conn: &PgConnection) -> Vec<String> {
|
|
||||||
vec![self.compute_id(conn)]
|
|
||||||
}
|
|
||||||
fn webfinger_links(&self, conn: &PgConnection) -> Vec<Vec<(String, String)>> {
|
|
||||||
vec![
|
|
||||||
vec![
|
|
||||||
(String::from("rel"), String::from("http://webfinger.net/rel/profile-page")),
|
|
||||||
(String::from("href"), self.compute_id(conn))
|
|
||||||
],
|
|
||||||
vec![
|
|
||||||
(String::from("rel"), String::from("http://schemas.google.com/g/2010#updates-from")),
|
|
||||||
(String::from("type"), String::from("application/atom+xml")),
|
|
||||||
(String::from("href"), self.compute_box(conn, "feed.atom"))
|
|
||||||
],
|
|
||||||
vec![
|
|
||||||
(String::from("rel"), String::from("self")),
|
|
||||||
(String::from("type"), String::from("application/activity+json")),
|
|
||||||
(String::from("href"), self.compute_id(conn))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Signer for User {
|
impl Signer for User {
|
||||||
fn get_key_id(&self, conn: &PgConnection) -> String {
|
fn get_key_id(&self, conn: &PgConnection) -> String {
|
||||||
format!("{}#main-key", self.compute_id(conn))
|
format!("{}#main-key", self.compute_id(conn))
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use rocket::http::ContentType;
|
use rocket::http::ContentType;
|
||||||
use rocket::response::Content;
|
use rocket::response::Content;
|
||||||
|
use serde_json;
|
||||||
|
use webfinger::*;
|
||||||
|
|
||||||
use BASE_URL;
|
use BASE_URL;
|
||||||
use activity_pub::{ap_url, webfinger::Webfinger};
|
use activity_pub::ap_url;
|
||||||
use db_conn::DbConn;
|
use db_conn::DbConn;
|
||||||
use models::{blogs::Blog, users::User};
|
use models::{blogs::Blog, users::User};
|
||||||
|
|
||||||
@ -33,29 +35,32 @@ struct WebfingerQuery {
|
|||||||
resource: String
|
resource: String
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/.well-known/webfinger?<query>")]
|
struct WebfingerResolver;
|
||||||
fn webfinger(query: WebfingerQuery, conn: DbConn) -> Content<Result<String, &'static str>> {
|
|
||||||
let mut parsed_query = query.resource.splitn(2, ":");
|
|
||||||
let res_type = parsed_query.next().unwrap();
|
|
||||||
let res = parsed_query.next().unwrap();
|
|
||||||
if res_type == "acct" {
|
|
||||||
let mut parsed_res = res.split("@");
|
|
||||||
let user = parsed_res.next().unwrap();
|
|
||||||
let res_dom = parsed_res.next().unwrap();
|
|
||||||
|
|
||||||
if res_dom == BASE_URL.as_str() {
|
impl Resolver<DbConn> for WebfingerResolver {
|
||||||
let res = match User::find_local(&*conn, String::from(user)) {
|
fn instance_domain<'a>() -> &'a str {
|
||||||
Some(usr) => Ok(usr.webfinger(&*conn)),
|
BASE_URL.as_str()
|
||||||
None => match Blog::find_local(&*conn, String::from(user)) {
|
}
|
||||||
Some(blog) => Ok(blog.webfinger(&*conn)),
|
|
||||||
None => Err("Requested actor not found")
|
fn find(acct: String, conn: DbConn) -> Result<Webfinger, ResolverError> {
|
||||||
}
|
match User::find_local(&*conn, acct.clone()) {
|
||||||
};
|
Some(usr) => Ok(usr.webfinger(&*conn)),
|
||||||
Content(ContentType::new("application", "jrd+json"), res)
|
None => match Blog::find_local(&*conn, acct) {
|
||||||
} else {
|
Some(blog) => Ok(blog.webfinger(&*conn)),
|
||||||
Content(ContentType::new("text", "plain"), Err("Invalid instance"))
|
None => Err(ResolverError::NotFound)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
Content(ContentType::new("text", "plain"), Err("Invalid resource type. Only acct is supported"))
|
}
|
||||||
|
|
||||||
|
#[get("/.well-known/webfinger?<query>")]
|
||||||
|
fn webfinger(query: WebfingerQuery, conn: DbConn) -> Content<String> {
|
||||||
|
match WebfingerResolver::endpoint(query.resource, conn).and_then(|wf| serde_json::to_string(&wf).map_err(|_| ResolverError::NotFound)) {
|
||||||
|
Ok(wf) => Content(ContentType::new("application", "jrd+json"), wf),
|
||||||
|
Err(err) => Content(ContentType::new("text", "plain"), String::from(match err {
|
||||||
|
ResolverError::InvalidResource => "Invalid resource. Make sure to request an acct: URI",
|
||||||
|
ResolverError::NotFound => "Requested resource was not found",
|
||||||
|
ResolverError::WrongInstance => "This is not the instance of the requested resource"
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user