mirror of
https://git.asonix.dog/asonix/relay.git
synced 2024-11-28 20:41:33 +00:00
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…
Reference in a new issue