create '/api/v1/auxiliary-details' that exposes nodes location

This commit is contained in:
Jędrzej Stuczyński
2024-05-20 10:57:37 +01:00
parent be6c63723c
commit 3077c2ea8d
10 changed files with 97 additions and 3 deletions
Generated
+1
View File
@@ -5153,6 +5153,7 @@ version = "0.1.0"
dependencies = [
"async-trait",
"base64 0.21.7",
"celes",
"humantime 2.1.0",
"humantime-serde",
"nym-bin-common",
@@ -0,0 +1,31 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::api::{FormattedResponse, OutputParams};
use crate::router::types::RequestError;
use axum::extract::Query;
use nym_node_requests::api::v1::node::models::AuxiliaryDetails;
/// Returns auxiliary details of this node.
#[utoipa::path(
get,
path = "/auxiliary-details",
context_path = "/api/v1",
tag = "Node",
responses(
(status = 200, content(
("application/json" = AuxiliaryDetails),
("application/yaml" = AuxiliaryDetails)
)),
),
params(OutputParams)
)]
pub(crate) async fn auxiliary(
description: AuxiliaryDetails,
Query(output): Query<OutputParams>,
) -> Result<AuxiliaryDetailsResponse, RequestError> {
let output = output.output.unwrap_or_default();
Ok(output.to_response(description))
}
pub type AuxiliaryDetailsResponse = FormattedResponse<AuxiliaryDetails>;
@@ -1,6 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::api::v1::node::auxiliary::auxiliary;
use crate::api::v1::node::build_information::build_information;
use crate::api::v1::node::description::description;
use crate::api::v1::node::hardware::host_system;
@@ -11,6 +12,7 @@ use axum::Router;
use nym_node_requests::api::v1::node::models;
use nym_node_requests::routes::api::v1;
pub mod auxiliary;
pub mod build_information;
pub mod description;
pub mod hardware;
@@ -24,6 +26,7 @@ pub struct Config {
pub system_info: Option<models::HostSystem>,
pub roles: models::NodeRoles,
pub description: models::NodeDescription,
pub auxiliary_details: models::AuxiliaryDetails,
}
pub(super) fn routes<S: Send + Sync + 'static + Clone>(config: Config) -> Router<S> {
@@ -63,4 +66,11 @@ pub(super) fn routes<S: Send + Sync + 'static + Clone>(config: Config) -> Router
move |query| description(node_description, query)
}),
)
.route(
v1::AUXILIARY,
get({
let auxiliary_details = config.auxiliary_details;
move |query| auxiliary(auxiliary_details, query)
}),
)
}
@@ -19,6 +19,7 @@ use utoipa_swagger_ui::SwaggerUi;
api::v1::node::roles::roles,
api::v1::node::hardware::host_system,
api::v1::node::description::description,
api::v1::node::auxiliary::auxiliary,
api::v1::metrics::mixing::mixing_stats,
api::v1::metrics::verloc::verloc_stats,
api::v1::metrics::prometheus::prometheus_metrics,
@@ -52,6 +53,7 @@ use utoipa_swagger_ui::SwaggerUi;
api_requests::v1::node::models::Cpu,
api_requests::v1::node::models::CryptoHardware,
api_requests::v1::node::models::NodeDescription,
api_requests::v1::node::models::AuxiliaryDetails,
api_requests::v1::metrics::models::MixingStats,
api_requests::v1::metrics::models::VerlocStats,
api_requests::v1::metrics::models::VerlocResult,
+8 -1
View File
@@ -15,7 +15,7 @@ use nym_node_requests::api::v1::mixnode::models::Mixnode;
use nym_node_requests::api::v1::network_requester::exit_policy::models::UsedExitPolicy;
use nym_node_requests::api::v1::network_requester::models::NetworkRequester;
use nym_node_requests::api::v1::node::models;
use nym_node_requests::api::v1::node::models::{HostSystem, NodeDescription};
use nym_node_requests::api::v1::node::models::{AuxiliaryDetails, HostSystem, NodeDescription};
use nym_node_requests::api::SignedHostInformation;
use nym_node_requests::routes;
use std::net::SocketAddr;
@@ -47,6 +47,7 @@ impl Config {
system_info: None,
roles: Default::default(),
description: Default::default(),
auxiliary_details: Default::default(),
},
metrics: Default::default(),
gateway: Default::default(),
@@ -88,6 +89,12 @@ impl Config {
self
}
#[must_use]
pub fn with_auxiliary_details(mut self, auxiliary_details: AuxiliaryDetails) -> Self {
self.api.v1_config.node.auxiliary_details = auxiliary_details;
self
}
#[must_use]
pub fn with_gateway(mut self, gateway: Gateway) -> Self {
self.api.v1_config.node.roles.gateway_enabled = true;
+1
View File
@@ -12,6 +12,7 @@ license.workspace = true
[dependencies]
base64 = { workspace = true }
celes = { workspace = true } # country codes
humantime = { workspace = true }
humantime-serde = { workspace = true }
schemars = { workspace = true, features = ["preserve_order"] }
@@ -1,6 +1,8 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::helpers::de_maybe_stringified;
use celes::Country;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
@@ -163,3 +165,15 @@ pub struct NodeDescription {
/// details define other optional details.
pub details: String,
}
/// Auxiliary details of the associated Nym Node.
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct AuxiliaryDetails {
/// Optional ISO 3166 alpha-2 two-letter country code of the node's **physical** location
#[serde(deserialize_with = "de_maybe_stringified")]
#[cfg_attr(feature = "openapi", schema(example = "PL", value_type = Option<String>))]
#[schemars(with = "Option<String>")]
#[schemars(length(equal = 2))]
pub location: Option<Country>,
}
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Deserializer};
use std::fmt::Display;
use std::str::FromStr;
pub fn de_maybe_stringified<'de, D, T, E>(deserializer: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
T: FromStr<Err = E>,
E: Display,
{
let raw = String::deserialize(deserializer)?;
if raw.is_empty() {
Ok(None)
} else {
Ok(Some(raw.parse().map_err(serde::de::Error::custom)?))
}
}
+3
View File
@@ -6,6 +6,7 @@
pub mod api;
pub mod error;
pub(crate) mod helpers;
macro_rules! absolute_route {
( $name:ident, $parent:expr, $suffix:expr ) => {
@@ -34,6 +35,7 @@ pub mod routes {
pub const HOST_INFO: &str = "/host-information";
pub const SYSTEM_INFO: &str = "/system-info";
pub const NODE_DESCRIPTION: &str = "/description";
pub const AUXILIARY: &str = "/auxiliary-details";
pub const HEALTH: &str = "/health";
pub const SWAGGER: &str = "/swagger";
@@ -50,6 +52,7 @@ pub mod routes {
absolute_route!(host_info_absolute, v1_absolute(), HOST_INFO);
absolute_route!(system_info_absolute, v1_absolute(), SYSTEM_INFO);
absolute_route!(description_absolute, v1_absolute(), NODE_DESCRIPTION);
absolute_route!(auxiliary_absolute, v1_absolute(), AUXILIARY);
absolute_route!(gateway_absolute, v1_absolute(), GATEWAY);
absolute_route!(mixnode_absolute, v1_absolute(), MIXNODE);
+6 -1
View File
@@ -463,6 +463,10 @@ impl NymNode {
&self.ed25519_identity_keys,
)?;
let auxiliary_details = api_requests::v1::node::models::AuxiliaryDetails {
location: self.config.host.location.clone(),
};
// mixnode info
let mixnode_details = api_requests::v1::mixnode::models::Mixnode {};
@@ -535,7 +539,8 @@ impl NymNode {
.with_network_requester_details(nr_details)
.with_ip_packet_router_details(ipr_details)
.with_used_exit_policy(exit_policy_details)
.with_description(self.description.clone());
.with_description(self.description.clone())
.with_auxiliary_details(auxiliary_details);
if self.config.http.expose_system_info {
config = config.with_system_info(get_system_info(