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 inbox; | ||||
| mod label; | ||||
| mod nodeinfo; | ||||
| mod notify; | ||||
| mod requests; | ||||
| mod state; | ||||
|  | @ -126,7 +127,12 @@ async fn main() -> Result<(), anyhow::Error> { | |||
|                     .route(web::post().to(inbox::inbox)), | ||||
|             ) | ||||
|             .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")? | ||||
|     .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, | ||||
|     actor_cache: ActorCache, | ||||
|     config: Config, | ||||
|     user_agent: String, | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
|             client: Client::default(), | ||||
|             key_id, | ||||
|             private_key, | ||||
|             actor_cache, | ||||
|             config: Config::default().dont_use_created_field(), | ||||
|             user_agent, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -48,6 +55,7 @@ impl Requests { | |||
|             .client | ||||
|             .get(url) | ||||
|             .header("Accept", "application/activity+json") | ||||
|             .header("User-Agent", self.user_agent.as_str()) | ||||
|             .signature(&self.config, &self.key_id, |signing_string| { | ||||
|                 self.sign(signing_string) | ||||
|             })? | ||||
|  | @ -105,7 +113,7 @@ impl Requests { | |||
|             .post(inbox.as_str()) | ||||
|             .header("Accept", "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( | ||||
|                 &self.config, | ||||
|                 &self.key_id, | ||||
|  |  | |||
							
								
								
									
										19
									
								
								src/state.rs
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								src/state.rs
									
										
									
									
									
								
							|  | @ -40,6 +40,7 @@ pub enum UrlKind { | |||
|     Following, | ||||
|     Inbox, | ||||
|     MainKey, | ||||
|     NodeInfo, | ||||
|     Outbox, | ||||
| } | ||||
| 
 | ||||
|  | @ -92,6 +93,7 @@ impl Settings { | |||
|             UrlKind::Following => format!("{}://{}/following", scheme, self.hostname), | ||||
|             UrlKind::Inbox => format!("{}://{}/inbox", 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), | ||||
|         } | ||||
|     } | ||||
|  | @ -99,14 +101,31 @@ impl Settings { | |||
|     fn generate_resource(&self) -> String { | ||||
|         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 { | ||||
|     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 { | ||||
|         Requests::new( | ||||
|             self.generate_url(UrlKind::MainKey), | ||||
|             self.settings.private_key.clone(), | ||||
|             self.actor_cache.clone(), | ||||
|             format!("{} {}", self.software_name(), self.software_version()), | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue