Use the webfinger crate
This commit is contained in:
@@ -33,6 +33,7 @@ extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
extern crate tera;
|
||||
extern crate url;
|
||||
extern crate webfinger;
|
||||
|
||||
use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}};
|
||||
use dotenv::dotenv;
|
||||
|
||||
+28
-31
@@ -14,13 +14,13 @@ use openssl::{
|
||||
rsa::Rsa,
|
||||
sign::Signer
|
||||
};
|
||||
use webfinger::*;
|
||||
|
||||
use activity_pub::{
|
||||
ActivityStream, Id, IntoId,
|
||||
actor::{Actor as APActor, ActorType},
|
||||
inbox::WithInbox,
|
||||
sign,
|
||||
webfinger::*
|
||||
sign
|
||||
};
|
||||
use models::instance::*;
|
||||
use schema::blogs;
|
||||
@@ -91,9 +91,9 @@ impl Blog {
|
||||
|
||||
fn fetch_from_webfinger(conn: &PgConnection, acct: String) -> Option<Blog> {
|
||||
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) => {
|
||||
println!("{}", details);
|
||||
println!("{:?}", details);
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -171,6 +171,30 @@ impl Blog {
|
||||
pub fn get_keypair(&self) -> PKey<Private> {
|
||||
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 {
|
||||
@@ -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 {
|
||||
fn get_key_id(&self, conn: &PgConnection) -> String {
|
||||
format!("{}#main-key", self.compute_id(conn))
|
||||
|
||||
+26
-28
@@ -24,6 +24,7 @@ use rocket::{
|
||||
};
|
||||
use serde_json;
|
||||
use url::Url;
|
||||
use webfinger::*;
|
||||
|
||||
use BASE_URL;
|
||||
use activity_pub::{
|
||||
@@ -31,7 +32,7 @@ use activity_pub::{
|
||||
actor::{ActorType, Actor as APActor},
|
||||
inbox::{Inbox, WithInbox},
|
||||
sign::{Signer, gen_keypair},
|
||||
webfinger::{Webfinger, resolve}
|
||||
webfinger::{resolve}
|
||||
};
|
||||
use db_conn::DbConn;
|
||||
use models::{
|
||||
@@ -336,6 +337,30 @@ impl User {
|
||||
json["fqn"] = serde_json::Value::String(self.get_fqn(conn));
|
||||
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 {
|
||||
@@ -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 {
|
||||
fn get_key_id(&self, conn: &PgConnection) -> String {
|
||||
format!("{}#main-key", self.compute_id(conn))
|
||||
|
||||
+28
-23
@@ -1,8 +1,10 @@
|
||||
use rocket::http::ContentType;
|
||||
use rocket::response::Content;
|
||||
use serde_json;
|
||||
use webfinger::*;
|
||||
|
||||
use BASE_URL;
|
||||
use activity_pub::{ap_url, webfinger::Webfinger};
|
||||
use activity_pub::ap_url;
|
||||
use db_conn::DbConn;
|
||||
use models::{blogs::Blog, users::User};
|
||||
|
||||
@@ -33,29 +35,32 @@ struct WebfingerQuery {
|
||||
resource: String
|
||||
}
|
||||
|
||||
#[get("/.well-known/webfinger?<query>")]
|
||||
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();
|
||||
struct WebfingerResolver;
|
||||
|
||||
if res_dom == BASE_URL.as_str() {
|
||||
let res = match User::find_local(&*conn, String::from(user)) {
|
||||
Some(usr) => Ok(usr.webfinger(&*conn)),
|
||||
None => match Blog::find_local(&*conn, String::from(user)) {
|
||||
Some(blog) => Ok(blog.webfinger(&*conn)),
|
||||
None => Err("Requested actor not found")
|
||||
}
|
||||
};
|
||||
Content(ContentType::new("application", "jrd+json"), res)
|
||||
} else {
|
||||
Content(ContentType::new("text", "plain"), Err("Invalid instance"))
|
||||
impl Resolver<DbConn> for WebfingerResolver {
|
||||
fn instance_domain<'a>() -> &'a str {
|
||||
BASE_URL.as_str()
|
||||
}
|
||||
|
||||
fn find(acct: String, conn: DbConn) -> Result<Webfinger, ResolverError> {
|
||||
match User::find_local(&*conn, acct.clone()) {
|
||||
Some(usr) => Ok(usr.webfinger(&*conn)),
|
||||
None => match Blog::find_local(&*conn, acct) {
|
||||
Some(blog) => Ok(blog.webfinger(&*conn)),
|
||||
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"
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user