63 lines
2.1 KiB
Rust
63 lines
2.1 KiB
Rust
|
|
//! Node identity endpoint — exposes this node's Ed25519 public key.
|
||
|
|
//!
|
||
|
|
//! `GET /identity` returns the node's ID and public key as JSON. No
|
||
|
|
//! authentication is required; only the public half of the keypair is
|
||
|
|
//! disclosed.
|
||
|
|
|
||
|
|
use poem::handler;
|
||
|
|
use poem::web::Json;
|
||
|
|
use serde::Serialize;
|
||
|
|
|
||
|
|
/// JSON response body for `GET /identity`.
|
||
|
|
#[derive(Serialize)]
|
||
|
|
pub struct IdentityResponse {
|
||
|
|
/// Node ID: lowercase hex-encoding of the 32-byte Ed25519 public key.
|
||
|
|
pub node_id: String,
|
||
|
|
/// Lowercase hex-encoding of the 32-byte Ed25519 public key.
|
||
|
|
pub pubkey: String,
|
||
|
|
}
|
||
|
|
|
||
|
|
/// `GET /identity` — return this node's Ed25519 public key.
|
||
|
|
///
|
||
|
|
/// Returns `{"node_id": "<64-hex>", "pubkey": "<64-hex>"}`.
|
||
|
|
/// No authentication required; the private key is never exposed.
|
||
|
|
#[handler]
|
||
|
|
pub fn identity_handler() -> Json<IdentityResponse> {
|
||
|
|
match crate::node_identity::get_identity() {
|
||
|
|
Some(id) => Json(IdentityResponse {
|
||
|
|
node_id: id.node_id.clone(),
|
||
|
|
pubkey: id.pubkey_hex.clone(),
|
||
|
|
}),
|
||
|
|
None => Json(IdentityResponse {
|
||
|
|
node_id: "uninitialized".to_string(),
|
||
|
|
pubkey: "uninitialized".to_string(),
|
||
|
|
}),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
use poem::{Route, get, test::TestClient};
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn identity_endpoint_returns_json() {
|
||
|
|
// Initialise a temporary key file so get_identity() returns Some.
|
||
|
|
let tmp = tempfile::tempdir().unwrap();
|
||
|
|
let key_path = tmp.path().join("node_identity.key");
|
||
|
|
crate::node_identity::init_identity(&key_path).unwrap();
|
||
|
|
|
||
|
|
let app = Route::new().at("/identity", get(identity_handler));
|
||
|
|
let cli = TestClient::new(app);
|
||
|
|
let resp = cli.get("/identity").send().await;
|
||
|
|
resp.assert_status_is_ok();
|
||
|
|
|
||
|
|
let body: serde_json::Value = resp.json().await.value().deserialize();
|
||
|
|
let node_id = body["node_id"].as_str().unwrap();
|
||
|
|
let pubkey = body["pubkey"].as_str().unwrap();
|
||
|
|
assert_eq!(node_id.len(), 64);
|
||
|
|
assert!(node_id.chars().all(|c| c.is_ascii_hexdigit()));
|
||
|
|
assert_eq!(node_id, pubkey);
|
||
|
|
}
|
||
|
|
}
|