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)", | ||||
|  "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)", | ||||
|  "webfinger 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| @ -1913,6 +1914,17 @@ name = "void" | ||||
| version = "1.0.2" | ||||
| 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]] | ||||
| name = "winapi" | ||||
| 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 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 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.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" | ||||
|  | ||||
| @ -24,6 +24,7 @@ serde_derive = "1.0" | ||||
| serde_json = "1.0" | ||||
| tera = "0.11" | ||||
| url = "1.7" | ||||
| webfinger = "0.1" | ||||
| 
 | ||||
| [dependencies.chrono] | ||||
| features = ["serde"] | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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)) | ||||
|  | ||||
| @ -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)) | ||||
|  | ||||
| @ -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" | ||||
|         })) | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user