Implement NodeInfo 2.1
This commit is contained in:
parent
0817177282
commit
94a5f3a3cd
4 changed files with 117 additions and 31 deletions
|
@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Added `emojis` field to Mastodon API Account entity.
|
- Added `emojis` field to Mastodon API Account entity.
|
||||||
- Support audio attachments.
|
- Support audio attachments.
|
||||||
- Added CLI command for viewing unreachable actors.
|
- Added CLI command for viewing unreachable actors.
|
||||||
|
- Implemented NodeInfo 2.1.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -169,8 +169,9 @@ async fn main() -> std::io::Result<()> {
|
||||||
.service(activitypub::emoji_view)
|
.service(activitypub::emoji_view)
|
||||||
.service(activitypub::tag_view)
|
.service(activitypub::tag_view)
|
||||||
.service(atom_scope())
|
.service(atom_scope())
|
||||||
.service(nodeinfo::get_nodeinfo)
|
.service(nodeinfo::get_nodeinfo_jrd)
|
||||||
.service(nodeinfo::get_nodeinfo_2_0)
|
.service(nodeinfo::get_nodeinfo_2_0)
|
||||||
|
.service(nodeinfo::get_nodeinfo_2_1)
|
||||||
.service(web_client::profile_page_redirect())
|
.service(web_client::profile_page_redirect())
|
||||||
.service(web_client::post_page_redirect())
|
.service(web_client::post_page_redirect())
|
||||||
.service(
|
.service(
|
||||||
|
|
|
@ -4,16 +4,56 @@ use serde::Serialize;
|
||||||
|
|
||||||
use mitra_config::{Config, RegistrationType, MITRA_VERSION};
|
use mitra_config::{Config, RegistrationType, MITRA_VERSION};
|
||||||
|
|
||||||
|
const MITRA_NAME: &str = "mitra";
|
||||||
|
const MITRA_REPOSITORY: &str = "https://codeberg.org/silverpill/mitra";
|
||||||
|
const ATOM_SERVICE: &str = "atom1.0";
|
||||||
|
const ACTIVITYPUB_PROTOCOL: &str = "activitypub";
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Software {
|
struct Software20 {
|
||||||
name: String,
|
name: String,
|
||||||
version: String,
|
version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Software20 {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: MITRA_NAME.to_string(),
|
||||||
|
version: MITRA_VERSION.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct Software21 {
|
||||||
|
name: String,
|
||||||
|
version: String,
|
||||||
|
repository: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Software21 {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: MITRA_NAME.to_string(),
|
||||||
|
version: MITRA_VERSION.to_string(),
|
||||||
|
repository: MITRA_REPOSITORY.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Services {
|
struct Services {
|
||||||
inbound: Vec<String>,
|
inbound: Vec<&'static str>,
|
||||||
outbound: Vec<String>,
|
outbound: Vec<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Services {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
inbound: vec![],
|
||||||
|
outbound: vec![ATOM_SERVICE],
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -35,12 +75,25 @@ struct Metadata {
|
||||||
node_description: String,
|
node_description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Metadata {
|
||||||
|
fn new(config: &Config) -> Self {
|
||||||
|
Self {
|
||||||
|
node_name: config.instance_title.clone(),
|
||||||
|
node_description: config.instance_short_description.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_open_registrations(config: &Config) -> bool {
|
||||||
|
config.registration.registration_type != RegistrationType::Invite
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct NodeInfo20 {
|
pub struct NodeInfo20 {
|
||||||
version: String,
|
version: &'static str,
|
||||||
software: Software,
|
software: Software20,
|
||||||
protocols: Vec<String>,
|
protocols: Vec<&'static str>,
|
||||||
services: Services,
|
services: Services,
|
||||||
open_registrations: bool,
|
open_registrations: bool,
|
||||||
usage: Usage,
|
usage: Usage,
|
||||||
|
@ -49,28 +102,40 @@ pub struct NodeInfo20 {
|
||||||
|
|
||||||
impl NodeInfo20 {
|
impl NodeInfo20 {
|
||||||
pub fn new(config: &Config, usage: Usage) -> Self {
|
pub fn new(config: &Config, usage: Usage) -> Self {
|
||||||
let software = Software {
|
|
||||||
name: "mitra".to_string(),
|
|
||||||
version: MITRA_VERSION.to_string(),
|
|
||||||
};
|
|
||||||
let services = Services {
|
|
||||||
inbound: vec![],
|
|
||||||
outbound: vec!["atom1.0".to_string()],
|
|
||||||
};
|
|
||||||
let metadata = Metadata {
|
|
||||||
node_name: config.instance_title.clone(),
|
|
||||||
node_description: config.instance_short_description.clone(),
|
|
||||||
};
|
|
||||||
Self {
|
Self {
|
||||||
version: "2.0".to_string(),
|
version: "2.0",
|
||||||
software,
|
software: Software20::default(),
|
||||||
protocols: vec!["activitypub".to_string()],
|
protocols: vec![ACTIVITYPUB_PROTOCOL],
|
||||||
services,
|
services: Services::default(),
|
||||||
open_registrations:
|
open_registrations: has_open_registrations(config),
|
||||||
config.registration.registration_type !=
|
|
||||||
RegistrationType::Invite,
|
|
||||||
usage,
|
usage,
|
||||||
metadata,
|
metadata: Metadata::new(config),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct NodeInfo21 {
|
||||||
|
version: &'static str,
|
||||||
|
software: Software21,
|
||||||
|
protocols: Vec<&'static str>,
|
||||||
|
services: Services,
|
||||||
|
open_registrations: bool,
|
||||||
|
usage: Usage,
|
||||||
|
metadata: Metadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeInfo21 {
|
||||||
|
pub fn new(config: &Config, usage: Usage) -> Self {
|
||||||
|
Self {
|
||||||
|
version: "2.1",
|
||||||
|
software: Software21::default(),
|
||||||
|
protocols: vec![ACTIVITYPUB_PROTOCOL],
|
||||||
|
services: Services::default(),
|
||||||
|
open_registrations: has_open_registrations(config),
|
||||||
|
usage,
|
||||||
|
metadata: Metadata::new(config),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,22 +11,29 @@ use crate::webfinger::types::{
|
||||||
JsonResourceDescriptor,
|
JsonResourceDescriptor,
|
||||||
};
|
};
|
||||||
use super::helpers::get_usage;
|
use super::helpers::get_usage;
|
||||||
use super::types::NodeInfo20;
|
use super::types::{NodeInfo20, NodeInfo21};
|
||||||
|
|
||||||
#[get("/.well-known/nodeinfo")]
|
#[get("/.well-known/nodeinfo")]
|
||||||
pub async fn get_nodeinfo(
|
pub async fn get_nodeinfo_jrd(
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
) -> Result<HttpResponse, HttpError> {
|
) -> Result<HttpResponse, HttpError> {
|
||||||
let nodeinfo_2_0_url = format!("{}/nodeinfo/2.0", config.instance_url());
|
let nodeinfo_2_0_url = format!("{}/nodeinfo/2.0", config.instance_url());
|
||||||
let link = Link {
|
let nodeinfo_2_0_link = Link {
|
||||||
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(),
|
rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(),
|
||||||
media_type: None,
|
media_type: None,
|
||||||
href: Some(nodeinfo_2_0_url),
|
href: Some(nodeinfo_2_0_url),
|
||||||
properties: Default::default(),
|
properties: Default::default(),
|
||||||
};
|
};
|
||||||
|
let nodeinfo_2_1_url = format!("{}/nodeinfo/2.1", config.instance_url());
|
||||||
|
let nodeinfo_2_1_link = Link {
|
||||||
|
rel: "http://nodeinfo.diaspora.software/ns/schema/2.1".to_string(),
|
||||||
|
media_type: None,
|
||||||
|
href: Some(nodeinfo_2_1_url),
|
||||||
|
properties: Default::default(),
|
||||||
|
};
|
||||||
let jrd = JsonResourceDescriptor {
|
let jrd = JsonResourceDescriptor {
|
||||||
subject: config.instance_url(),
|
subject: config.instance_url(),
|
||||||
links: vec![link],
|
links: vec![nodeinfo_2_0_link, nodeinfo_2_1_link],
|
||||||
};
|
};
|
||||||
let response = HttpResponse::Ok().json(jrd);
|
let response = HttpResponse::Ok().json(jrd);
|
||||||
Ok(response)
|
Ok(response)
|
||||||
|
@ -43,3 +50,15 @@ pub async fn get_nodeinfo_2_0(
|
||||||
let response = HttpResponse::Ok().json(nodeinfo);
|
let response = HttpResponse::Ok().json(nodeinfo);
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/nodeinfo/2.1")]
|
||||||
|
pub async fn get_nodeinfo_2_1(
|
||||||
|
config: web::Data<Config>,
|
||||||
|
db_pool: web::Data<DbPool>,
|
||||||
|
) -> Result<HttpResponse, HttpError> {
|
||||||
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
|
let usage = get_usage(db_client).await?;
|
||||||
|
let nodeinfo = NodeInfo21::new(&config, usage);
|
||||||
|
let response = HttpResponse::Ok().json(nodeinfo);
|
||||||
|
Ok(response)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue