Add nodeinfo support
This commit is contained in:
		
							parent
							
								
									19e23fbfa5
								
							
						
					
					
						commit
						790d0965fb
					
				
					 4 changed files with 117 additions and 3 deletions
				
			
		|  | @ -14,6 +14,7 @@ mod db_actor; | ||||||
| mod error; | mod error; | ||||||
| mod inbox; | mod inbox; | ||||||
| mod label; | mod label; | ||||||
|  | mod nodeinfo; | ||||||
| mod notify; | mod notify; | ||||||
| mod requests; | mod requests; | ||||||
| mod state; | mod state; | ||||||
|  | @ -126,7 +127,12 @@ async fn main() -> Result<(), anyhow::Error> { | ||||||
|                     .route(web::post().to(inbox::inbox)), |                     .route(web::post().to(inbox::inbox)), | ||||||
|             ) |             ) | ||||||
|             .service(web::resource("/actor").route(web::get().to(actor_route))) |             .service(web::resource("/actor").route(web::get().to(actor_route))) | ||||||
|             .service(actix_webfinger::resource::<_, RelayResolver>()) |             .service(web::resource("/nodeinfo/2.0").route(web::get().to(nodeinfo::route))) | ||||||
|  |             .service( | ||||||
|  |                 web::scope("/.well-known") | ||||||
|  |                     .service(actix_webfinger::scoped::<_, RelayResolver>()) | ||||||
|  |                     .service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))), | ||||||
|  |             ) | ||||||
|     }) |     }) | ||||||
|     .bind("0.0.0.0:8080")? |     .bind("0.0.0.0:8080")? | ||||||
|     .run() |     .run() | ||||||
|  |  | ||||||
							
								
								
									
										81
									
								
								src/nodeinfo.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/nodeinfo.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | ||||||
|  | use crate::state::{State, UrlKind}; | ||||||
|  | use actix_web::{web, Responder}; | ||||||
|  | use actix_webfinger::Link; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | pub async fn well_known(state: web::Data<State>) -> impl Responder { | ||||||
|  |     web::Json(Link { | ||||||
|  |         rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_owned(), | ||||||
|  |         href: Some(state.generate_url(UrlKind::NodeInfo)), | ||||||
|  |         template: None, | ||||||
|  |         kind: None, | ||||||
|  |     }) | ||||||
|  |     .with_header("Content-Type", "application/jrd+json") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub async fn route(state: web::Data<State>) -> web::Json<NodeInfo> { | ||||||
|  |     web::Json(NodeInfo { | ||||||
|  |         version: NodeInfoVersion, | ||||||
|  |         software: Software { | ||||||
|  |             name: state.software_name(), | ||||||
|  |             version: state.software_version(), | ||||||
|  |         }, | ||||||
|  |         protocols: vec![Protocol::ActivityPub], | ||||||
|  |         services: vec![], | ||||||
|  |         open_registrations: false, | ||||||
|  |         usage: Usage { | ||||||
|  |             local_posts: 0, | ||||||
|  |             local_comments: 0, | ||||||
|  |         }, | ||||||
|  |         metadata: Metadata::default(), | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, serde::Serialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct NodeInfo { | ||||||
|  |     version: NodeInfoVersion, | ||||||
|  |     software: Software, | ||||||
|  |     protocols: Vec<Protocol>, | ||||||
|  |     services: Vec<Service>, | ||||||
|  |     open_registrations: bool, | ||||||
|  |     usage: Usage, | ||||||
|  |     metadata: Metadata, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, Default)] | ||||||
|  | pub struct NodeInfoVersion; | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, Default, serde::Serialize)] | ||||||
|  | pub struct Software { | ||||||
|  |     name: String, | ||||||
|  |     version: String, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, serde::Serialize)] | ||||||
|  | pub enum Protocol { | ||||||
|  |     ActivityPub, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, serde::Serialize)] | ||||||
|  | pub enum Service {} | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, Default, serde::Serialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct Usage { | ||||||
|  |     local_posts: u64, | ||||||
|  |     local_comments: u64, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, Default, serde::Serialize)] | ||||||
|  | #[serde(transparent)] | ||||||
|  | pub struct Metadata(pub HashMap<String, serde_json::Value>); | ||||||
|  | 
 | ||||||
|  | impl serde::ser::Serialize for NodeInfoVersion { | ||||||
|  |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||||||
|  |     where | ||||||
|  |         S: serde::ser::Serializer, | ||||||
|  |     { | ||||||
|  |         serializer.serialize_str("2.0") | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -15,16 +15,23 @@ pub struct Requests { | ||||||
|     private_key: RSAPrivateKey, |     private_key: RSAPrivateKey, | ||||||
|     actor_cache: ActorCache, |     actor_cache: ActorCache, | ||||||
|     config: Config, |     config: Config, | ||||||
|  |     user_agent: String, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Requests { | impl Requests { | ||||||
|     pub fn new(key_id: String, private_key: RSAPrivateKey, actor_cache: ActorCache) -> Self { |     pub fn new( | ||||||
|  |         key_id: String, | ||||||
|  |         private_key: RSAPrivateKey, | ||||||
|  |         actor_cache: ActorCache, | ||||||
|  |         user_agent: String, | ||||||
|  |     ) -> Self { | ||||||
|         Requests { |         Requests { | ||||||
|             client: Client::default(), |             client: Client::default(), | ||||||
|             key_id, |             key_id, | ||||||
|             private_key, |             private_key, | ||||||
|             actor_cache, |             actor_cache, | ||||||
|             config: Config::default().dont_use_created_field(), |             config: Config::default().dont_use_created_field(), | ||||||
|  |             user_agent, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -48,6 +55,7 @@ impl Requests { | ||||||
|             .client |             .client | ||||||
|             .get(url) |             .get(url) | ||||||
|             .header("Accept", "application/activity+json") |             .header("Accept", "application/activity+json") | ||||||
|  |             .header("User-Agent", self.user_agent.as_str()) | ||||||
|             .signature(&self.config, &self.key_id, |signing_string| { |             .signature(&self.config, &self.key_id, |signing_string| { | ||||||
|                 self.sign(signing_string) |                 self.sign(signing_string) | ||||||
|             })? |             })? | ||||||
|  | @ -105,7 +113,7 @@ impl Requests { | ||||||
|             .post(inbox.as_str()) |             .post(inbox.as_str()) | ||||||
|             .header("Accept", "application/activity+json") |             .header("Accept", "application/activity+json") | ||||||
|             .header("Content-Type", "application/activity+json") |             .header("Content-Type", "application/activity+json") | ||||||
|             .header("User-Agent", "Aode Relay v0.1.0") |             .header("User-Agent", self.user_agent.as_str()) | ||||||
|             .signature_with_digest( |             .signature_with_digest( | ||||||
|                 &self.config, |                 &self.config, | ||||||
|                 &self.key_id, |                 &self.key_id, | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								src/state.rs
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								src/state.rs
									
										
									
									
									
								
							|  | @ -40,6 +40,7 @@ pub enum UrlKind { | ||||||
|     Following, |     Following, | ||||||
|     Inbox, |     Inbox, | ||||||
|     MainKey, |     MainKey, | ||||||
|  |     NodeInfo, | ||||||
|     Outbox, |     Outbox, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -92,6 +93,7 @@ impl Settings { | ||||||
|             UrlKind::Following => format!("{}://{}/following", scheme, self.hostname), |             UrlKind::Following => format!("{}://{}/following", scheme, self.hostname), | ||||||
|             UrlKind::Inbox => format!("{}://{}/inbox", scheme, self.hostname), |             UrlKind::Inbox => format!("{}://{}/inbox", scheme, self.hostname), | ||||||
|             UrlKind::MainKey => format!("{}://{}/actor#main-key", scheme, self.hostname), |             UrlKind::MainKey => format!("{}://{}/actor#main-key", scheme, self.hostname), | ||||||
|  |             UrlKind::NodeInfo => format!("{}://{}/nodeinfo/2.0", scheme, self.hostname), | ||||||
|             UrlKind::Outbox => format!("{}://{}/outbox", scheme, self.hostname), |             UrlKind::Outbox => format!("{}://{}/outbox", scheme, self.hostname), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -99,14 +101,31 @@ impl Settings { | ||||||
|     fn generate_resource(&self) -> String { |     fn generate_resource(&self) -> String { | ||||||
|         format!("relay@{}", self.hostname) |         format!("relay@{}", self.hostname) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn software_name(&self) -> String { | ||||||
|  |         "AodeRelay".to_owned() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn software_version(&self) -> String { | ||||||
|  |         "v0.1.0-master".to_owned() | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl State { | impl State { | ||||||
|  |     pub fn software_name(&self) -> String { | ||||||
|  |         self.settings.software_name() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn software_version(&self) -> String { | ||||||
|  |         self.settings.software_version() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn requests(&self) -> Requests { |     pub fn requests(&self) -> Requests { | ||||||
|         Requests::new( |         Requests::new( | ||||||
|             self.generate_url(UrlKind::MainKey), |             self.generate_url(UrlKind::MainKey), | ||||||
|             self.settings.private_key.clone(), |             self.settings.private_key.clone(), | ||||||
|             self.actor_cache.clone(), |             self.actor_cache.clone(), | ||||||
|  |             format!("{} {}", self.software_name(), self.software_version()), | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue