From b3edd303603db09c7d6640d339beb40004dfe5e7 Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Tue, 5 Nov 2024 17:34:35 +0100 Subject: [PATCH 01/12] feat(): init discover feature --- .../src/discover_feature/errors.rs | 25 ++++++++++ .../src/discover_feature/handler.rs | 50 +++++++++++++++++++ .../src/discover_feature/mod.rs | 3 ++ .../src/discover_feature/model.rs | 20 ++++++++ .../web-plugins/didcomm-messaging/src/lib.rs | 1 + 5 files changed, 99 insertions(+) create mode 100644 crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs create mode 100644 crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs create mode 100644 crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs create mode 100644 crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs new file mode 100644 index 00000000..582ed167 --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs @@ -0,0 +1,25 @@ +use axum::Json; +use serde_json::{json, Value}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum DiscoveryError { + #[error("message body is malformed")] + MalformedBody, + #[error("Repository not set")] + RepostitoryError +} +impl DiscoveryError { + /// Converts the error to an axum JSON representation. + pub fn json(&self) -> Json { + Json(json!({ + "error": self.to_string() + })) + } +} + +impl From for Json { + fn from(error: DiscoveryError) -> Self { + error.json() + } +} diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs new file mode 100644 index 00000000..04cd67bf --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs @@ -0,0 +1,50 @@ +use std::sync::Arc; + +use axum::response::{IntoResponse, Response}; +use didcomm::Message; +use hyper::StatusCode; + + +use crate::web::AppState; + +use super::errors::DiscoveryError; + +// handle discover feature request +// https://didcomm.org/discover-features/2.0/ +pub(crate) fn handle_query_request( + state: Arc, + message: Message, +) -> Result, Response> { + + let disclosed_protocols: Vec = Vec::new(); + let supported_protocols: Vec = Vec::new(); + + let body = message.body.get("queries"); + + if body.is_none() { + return Err(StatusCode::BAD_REQUEST.into_response()); + } + + let querie = body.unwrap().as_array(); + if querie.is_none() { + return Err(DiscoveryError::MalformedBody.json().into_response()); + } + let queries = querie.unwrap(); + + for sq in queries { + let val = sq.get("match"); + // only supports feature-type protocol + match val { + Some(val) => { + let protocol = val.to_string(); + if supported_protocols.contains(&protocol) { + disclosed_protocols.push(protocol); + }; + // build response message + + + }, + None => Err(DiscoveryError::MalformedBody.json().into_response()) + } + } +} diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs new file mode 100644 index 00000000..e53d9aac --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs @@ -0,0 +1,3 @@ +pub(super) mod model; +pub(crate) mod handler; +pub(crate) mod errors; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs new file mode 100644 index 00000000..226c6914 --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs @@ -0,0 +1,20 @@ +use serde::Deserialize; +use serde_json::Value; + +#[derive(Deserialize)] +pub struct Queries { + queries: Vec, +} + +#[derive(Deserialize)] +pub struct Disclosures { + disclosures: Vec, +} +#[derive(Deserialize)] +struct DisclosuresContent { + #[serde(rename = "feature-type")] + feature_type: String, + id: String, + #[serde(skip_serializing_if = "Option::is_none")] + roles: Option> +} \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/lib.rs b/crates/web-plugins/didcomm-messaging/src/lib.rs index fbd014a0..f2e0b588 100644 --- a/crates/web-plugins/didcomm-messaging/src/lib.rs +++ b/crates/web-plugins/didcomm-messaging/src/lib.rs @@ -2,6 +2,7 @@ pub mod client; pub mod web; pub mod plugin; pub(crate) mod did_rotation; +pub(crate) mod discover_feature; mod model; mod forward; From d252297f92ad8b26dffe9fde81b8dd854b090b7e Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Wed, 6 Nov 2024 15:47:57 +0100 Subject: [PATCH 02/12] feat(discover_feature): init discover feature protocol --- .../src/discover_feature/constant.rs | 1 + .../src/discover_feature/handler.rs | 104 +++++++++++++----- .../src/discover_feature/mod.rs | 3 +- .../src/discover_feature/model.rs | 23 ++-- 4 files changed, 96 insertions(+), 35 deletions(-) create mode 100644 crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs new file mode 100644 index 00000000..29620f75 --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs @@ -0,0 +1 @@ +pub(super) const DISCOVER_FEATURE: &str = "https://didcomm.org/discover-features/2.0/disclose"; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs index 04cd67bf..127e6b53 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs @@ -3,26 +3,27 @@ use std::sync::Arc; use axum::response::{IntoResponse, Response}; use didcomm::Message; use hyper::StatusCode; - +use serde_json::json; +use uuid::Uuid; use crate::web::AppState; -use super::errors::DiscoveryError; +use super::{ + constant::DISCOVER_FEATURE, + errors::DiscoveryError, + model::{Disclosures, DisclosuresContent}, +}; // handle discover feature request // https://didcomm.org/discover-features/2.0/ -pub(crate) fn handle_query_request( - state: Arc, - message: Message, -) -> Result, Response> { - - let disclosed_protocols: Vec = Vec::new(); +pub(crate) fn handle_query_request(message: Message) -> Result, Response> { + let mut disclosed_protocols: Vec = Vec::new(); let supported_protocols: Vec = Vec::new(); let body = message.body.get("queries"); if body.is_none() { - return Err(StatusCode::BAD_REQUEST.into_response()); + return Err(StatusCode::BAD_REQUEST.into_response()); } let querie = body.unwrap().as_array(); @@ -30,21 +31,74 @@ pub(crate) fn handle_query_request( return Err(DiscoveryError::MalformedBody.json().into_response()); } let queries = querie.unwrap(); + let _ = queries.iter().map(|value| { + Ok(match value.get("feature-type") { + Some(protocol) => { + if protocol.to_string() == "protocol" { + match value.get("match") { + Some(id) => { + if supported_protocols + .iter() + .find(|&id| id == &id.to_string()) + .is_some() + { + disclosed_protocols.push(id.to_owned().to_string()); + } + } + None => return Err(DiscoveryError::MalformedBody.json().into_response()), + } - for sq in queries { - let val = sq.get("match"); - // only supports feature-type protocol - match val { - Some(val) => { - let protocol = val.to_string(); - if supported_protocols.contains(&protocol) { - disclosed_protocols.push(protocol); - }; - // build response message - - - }, - None => Err(DiscoveryError::MalformedBody.json().into_response()) - } - } + // Only support features of type protocol + } else { + } + } + None => return Err(DiscoveryError::MalformedBody.json().into_response()), + }) + }); + // build response body + let _ = disclosed_protocols.iter().map(|id| { + let mut body = Disclosures::new(); + let content = DisclosuresContent { + feature_type: "feature_type".to_string(), + id: id.to_string(), + roles: None, + }; + body.disclosures.push(content); + }); + let id = Uuid::new_v4().urn().to_string(); + + Ok(Some( + Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(), + )) } +#[cfg(test)] +mod test { + use axum::body::HttpBody; + use didcomm::Message; + use serde_json::json; + use uuid::Uuid; + + use crate::discover_feature::model::Queries; + + use super::{handle_query_request, DISCOVER_FEATURE}; + + + #[tokio::test] + async fn test_get_queries() { + let queries = json!({"feature-type": "https://didcomm.org/discover-features/2.0/disclose"}); + let body = Queries { queries: vec![queries] }; + let id = Uuid::new_v4().urn().to_string(); + + let message = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); + match handle_query_request(message) { + Ok(result) => { + let msg = result.unwrap(); + println!("{:#?}", msg); + }, + Err(e) => { + + println!("{:?}", e); + } + } + } +} \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs index e53d9aac..adda26ca 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs @@ -1,3 +1,4 @@ pub(super) mod model; pub(crate) mod handler; -pub(crate) mod errors; \ No newline at end of file +pub(crate) mod errors; +pub(super) mod constant; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs index 226c6914..32162e14 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs @@ -1,20 +1,25 @@ -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use serde_json::Value; -#[derive(Deserialize)] +#[derive(Deserialize, Serialize)] pub struct Queries { - queries: Vec, + pub queries: Vec, } #[derive(Deserialize)] pub struct Disclosures { - disclosures: Vec, + pub disclosures: Vec, +} +impl Disclosures { + pub fn new() -> Self { + Disclosures { disclosures: vec![] } + } } #[derive(Deserialize)] -struct DisclosuresContent { +pub struct DisclosuresContent { #[serde(rename = "feature-type")] - feature_type: String, - id: String, + pub feature_type: String, + pub id: String, #[serde(skip_serializing_if = "Option::is_none")] - roles: Option> -} \ No newline at end of file + pub roles: Option>, +} From 74253f2c9bcaee923de99a804a6d65093ba35d9e Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Fri, 8 Nov 2024 08:55:34 +0100 Subject: [PATCH 03/12] feat(): discover feature protocol impl --- .../src/discover_feature/constant.rs | 3 +- .../src/discover_feature/errors.rs | 4 +- .../src/discover_feature/handler.rs | 146 ++++++++++++------ .../src/discover_feature/model.rs | 6 +- 4 files changed, 104 insertions(+), 55 deletions(-) diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs index 29620f75..a27925a3 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs @@ -1 +1,2 @@ -pub(super) const DISCOVER_FEATURE: &str = "https://didcomm.org/discover-features/2.0/disclose"; \ No newline at end of file +pub(super) const DISCOVER_FEATURE: &str = "https://didcomm.org/discover-features/2.0/disclose"; +pub(super) const QUERY_FEATURE: &str = "https://didcomm.org/discover-features/2.0/queries"; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs index 582ed167..a587e8ea 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs @@ -7,7 +7,9 @@ pub enum DiscoveryError { #[error("message body is malformed")] MalformedBody, #[error("Repository not set")] - RepostitoryError + RepostitoryError, + #[error("No query field in body")] + QueryNotFound } impl DiscoveryError { /// Converts the error to an axum JSON representation. diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs index 127e6b53..b343f155 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs @@ -1,13 +1,8 @@ -use std::sync::Arc; - use axum::response::{IntoResponse, Response}; use didcomm::Message; -use hyper::StatusCode; use serde_json::json; use uuid::Uuid; -use crate::web::AppState; - use super::{ constant::DISCOVER_FEATURE, errors::DiscoveryError, @@ -15,26 +10,27 @@ use super::{ }; // handle discover feature request +// takes a message and a vector of supported messaging protocols as PIURI // https://didcomm.org/discover-features/2.0/ -pub(crate) fn handle_query_request(message: Message) -> Result, Response> { +pub(crate) fn handle_query_request( + message: Message, + supported_protocols: Vec, +) -> Result { let mut disclosed_protocols: Vec = Vec::new(); - let supported_protocols: Vec = Vec::new(); - let body = message.body.get("queries"); + let body = message.body.get("queries").and_then(|val| val.as_array()); if body.is_none() { - return Err(StatusCode::BAD_REQUEST.into_response()); + return Err(DiscoveryError::QueryNotFound.json().into_response()); } - let querie = body.unwrap().as_array(); - if querie.is_none() { - return Err(DiscoveryError::MalformedBody.json().into_response()); - } - let queries = querie.unwrap(); - let _ = queries.iter().map(|value| { - Ok(match value.get("feature-type") { - Some(protocol) => { - if protocol.to_string() == "protocol" { + let queries = body.unwrap(); + + for value in queries.iter() { + match value.get("feature-type") { + Some(val) => { + let val = val.as_str().unwrap(); + if val == "protocol" { match value.get("match") { Some(id) => { if supported_protocols @@ -50,55 +46,105 @@ pub(crate) fn handle_query_request(message: Message) -> Result, // Only support features of type protocol } else { + // do nothing } } None => return Err(DiscoveryError::MalformedBody.json().into_response()), - }) - }); + }; + } // build response body - let _ = disclosed_protocols.iter().map(|id| { - let mut body = Disclosures::new(); + let mut body = Disclosures::new(); + for id in disclosed_protocols.iter() { let content = DisclosuresContent { - feature_type: "feature_type".to_string(), - id: id.to_string(), + feature_type: "protocol".to_string(), + id: id.to_owned(), roles: None, }; + let content = json!(content); + body.disclosures.push(content); - }); + } + let id = Uuid::new_v4().urn().to_string(); + let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); - Ok(Some( - Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(), - )) + Ok(msg) } #[cfg(test)] mod test { - use axum::body::HttpBody; + use didcomm::Message; use serde_json::json; use uuid::Uuid; - use crate::discover_feature::model::Queries; + use crate::discover_feature::{constant::QUERY_FEATURE, model::Queries}; - use super::{handle_query_request, DISCOVER_FEATURE}; + use super::handle_query_request; + const TRUST: &str = "https://didcomm.org/trust-ping/2.0/ping"; + #[tokio::test] + async fn test_get_supported_protocols() { + let queries = json!({"feature-type": "protocol", "match": TRUST}); - - #[tokio::test] - async fn test_get_queries() { - let queries = json!({"feature-type": "https://didcomm.org/discover-features/2.0/disclose"}); - let body = Queries { queries: vec![queries] }; - let id = Uuid::new_v4().urn().to_string(); + let supported_protocols = vec![TRUST.to_string()]; + let body = Queries { + queries: vec![queries], + }; + let id = Uuid::new_v4().urn().to_string(); + + let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); + match handle_query_request(message, supported_protocols) { + Ok(result) => { + assert!(result.body.get("disclosures").is_some()); + assert!(result.body.get("disclosures").unwrap().is_array()); + assert!( + result + .body + .get("disclosures") + .unwrap() + .as_array() + .unwrap() + .len() + == 1 + ); + let content = result.body.get("disclosures").unwrap().as_array().unwrap()[0] + .as_object() + .unwrap() + .get("id") + .unwrap() + .as_str() + .unwrap(); + let content: String = serde_json::from_str(content).unwrap(); + assert_eq!(content, TRUST.to_string()); + } + Err(e) => { + panic!("This should not occur {:?}", e) + } + } + } + #[tokio::test] + async fn test_unsupported_feature_type() { + let queries = json!({"feature-type": "goal-code", "match": "org.didcomm"}); - let message = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); - match handle_query_request(message) { - Ok(result) => { - let msg = result.unwrap(); - println!("{:#?}", msg); - }, - Err(e) => { - - println!("{:?}", e); - } - } - } -} \ No newline at end of file + let supported_protocols = vec![TRUST.to_string()]; + let body = Queries { + queries: vec![queries], + }; + let id = Uuid::new_v4().urn().to_string(); + + let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); + match handle_query_request(message, supported_protocols) { + Ok(result) => { + assert!(result + .body + .get("disclosures") + .unwrap() + .as_array() + .unwrap() + .is_empty()) + } + Err(e) => { + panic!("This should not occur: {:#?}", e) + } + } + } +} diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs index 32162e14..ab4ee416 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs @@ -6,16 +6,16 @@ pub struct Queries { pub queries: Vec, } -#[derive(Deserialize)] +#[derive(Deserialize, Serialize, Debug)] pub struct Disclosures { - pub disclosures: Vec, + pub disclosures: Vec, } impl Disclosures { pub fn new() -> Self { Disclosures { disclosures: vec![] } } } -#[derive(Deserialize)] +#[derive(Deserialize, Serialize)] pub struct DisclosuresContent { #[serde(rename = "feature-type")] pub feature_type: String, From 5e69107a66620b82b2dc5bd1fc1b457da871914c Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Wed, 13 Nov 2024 14:45:47 +0100 Subject: [PATCH 04/12] feat(discover_feature): changed function signature --- .vscode/launch.json | 16 ++ .../src/did_rotation/did_rotation.rs | 2 + .../src/discover_feature/errors.rs | 2 +- .../src/discover_feature/handler.rs | 187 ++++++++++++------ .../didcomm-messaging/src/forward/routing.rs | 1 + .../didcomm-messaging/src/plugin.rs | 1 + .../didcomm-messaging/src/web/handler.rs | 1 + .../didcomm-messaging/src/web/mod.rs | 14 +- 8 files changed, 158 insertions(+), 66 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..10efcb2f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug", + "program": "${workspaceFolder}/", + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs b/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs index 1f345d52..1cd16b0a 100644 --- a/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs +++ b/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs @@ -129,7 +129,9 @@ mod test { public_domain, diddoc, keystore, + None, Some(repository), + )); state diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs index a587e8ea..a54ffe61 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs @@ -8,7 +8,7 @@ pub enum DiscoveryError { MalformedBody, #[error("Repository not set")] RepostitoryError, - #[error("No query field in body")] + #[error("No queries field in body")] QueryNotFound } impl DiscoveryError { diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs index b343f155..403ac868 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs +++ b/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs @@ -1,8 +1,12 @@ +use std::sync::Arc; + use axum::response::{IntoResponse, Response}; use didcomm::Message; use serde_json::json; use uuid::Uuid; +use crate::web::AppState; + use super::{ constant::DISCOVER_FEATURE, errors::DiscoveryError, @@ -10,94 +14,144 @@ use super::{ }; // handle discover feature request -// takes a message and a vector of supported messaging protocols as PIURI // https://didcomm.org/discover-features/2.0/ pub(crate) fn handle_query_request( message: Message, - supported_protocols: Vec, -) -> Result { + state: Arc, +) -> Result, Response> { let mut disclosed_protocols: Vec = Vec::new(); let body = message.body.get("queries").and_then(|val| val.as_array()); - if body.is_none() { - return Err(DiscoveryError::QueryNotFound.json().into_response()); - } - - let queries = body.unwrap(); - - for value in queries.iter() { - match value.get("feature-type") { - Some(val) => { - let val = val.as_str().unwrap(); - if val == "protocol" { - match value.get("match") { - Some(id) => { - if supported_protocols - .iter() - .find(|&id| id == &id.to_string()) - .is_some() - { - disclosed_protocols.push(id.to_owned().to_string()); + if let Some(queries) = body { + for value in queries { + match value.get("feature-type") { + Some(val) => { + let val = val.as_str().unwrap(); + if val.to_string() == "protocol" { + match value.get("match") { + Some(id) => { + let id = id.to_string(); + let parts: Vec<&str> = id.split("/").collect(); + let (name, version) = (parts[3], parts[4]); + let query_protocol = format!("{}/{}", name, version); + + if let Some(supported_protocols) = + &state.clone().supported_protocols + { + if supported_protocols + .iter() + .find(|&disclose_protocol| { + disclose_protocol == &query_protocol + }) + .is_some() + { + disclosed_protocols.push(id); + } + } + } + None => { + return Err(DiscoveryError::MalformedBody.json().into_response()) } } - None => return Err(DiscoveryError::MalformedBody.json().into_response()), } - - // Only support features of type protocol - } else { - // do nothing } + None => return Err(DiscoveryError::MalformedBody.json().into_response()), } - None => return Err(DiscoveryError::MalformedBody.json().into_response()), - }; - } - // build response body - let mut body = Disclosures::new(); - for id in disclosed_protocols.iter() { - let content = DisclosuresContent { - feature_type: "protocol".to_string(), - id: id.to_owned(), - roles: None, - }; - let content = json!(content); + } - body.disclosures.push(content); - } + // build response body + let mut body = Disclosures::new(); + for id in disclosed_protocols.iter() { + let content = DisclosuresContent { + feature_type: "protocol".to_string(), + id: id.to_owned(), + roles: None, + }; + let content = json!(content); + + body.disclosures.push(content); + } - let id = Uuid::new_v4().urn().to_string(); - let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); + let id = Uuid::new_v4().urn().to_string(); + let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); - Ok(msg) + Ok(Some(msg)) + } else { + return Err(DiscoveryError::QueryNotFound.json().into_response()); + } } #[cfg(test)] mod test { + use std::{sync::Arc, vec}; + use didcomm::Message; use serde_json::json; use uuid::Uuid; - use crate::discover_feature::{constant::QUERY_FEATURE, model::Queries}; + use crate::{ + discover_feature::{constant::QUERY_FEATURE, model::Queries}, + repository::stateful::tests::{ + MockConnectionRepository, MockMessagesRepository, MockSecretsRepository, + }, + util::{self, MockFileSystem}, + web::{AppState, AppStateRepository}, + }; use super::handle_query_request; const TRUST: &str = "https://didcomm.org/trust-ping/2.0/ping"; + pub fn setup() -> Arc { + let public_domain = String::from("http://alice-mediator.com"); + + let mut mock_fs = MockFileSystem; + let storage_dirpath = std::env::var("STORAGE_DIRPATH").unwrap_or_else(|_| "/".to_owned()); + let diddoc: did_utils::didcore::Document = + util::read_diddoc(&mock_fs, &storage_dirpath).unwrap(); + let keystore = util::read_keystore(&mut mock_fs, "").unwrap(); + + let repository = AppStateRepository { + connection_repository: Arc::new(MockConnectionRepository::from(vec![])), + secret_repository: Arc::new(MockSecretsRepository::from(vec![])), + message_repository: Arc::new(MockMessagesRepository::from(vec![])), + }; + + let state = Arc::new(AppState::from( + public_domain, + diddoc, + keystore, + Some(vec!["trust-ping/2.0".to_string()]), + Some(repository), + )); + + state + } + #[tokio::test] async fn test_get_supported_protocols() { let queries = json!({"feature-type": "protocol", "match": TRUST}); - let supported_protocols = vec![TRUST.to_string()]; let body = Queries { queries: vec![queries], }; let id = Uuid::new_v4().urn().to_string(); let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); - match handle_query_request(message, supported_protocols) { + let state = setup(); + match handle_query_request(message, state) { Ok(result) => { - assert!(result.body.get("disclosures").is_some()); - assert!(result.body.get("disclosures").unwrap().is_array()); + assert!(result.clone().unwrap().body.get("disclosures").is_some()); + assert!(result + .clone() + .unwrap() + .body + .get("disclosures") + .unwrap() + .is_array()); assert!( result + .clone() + .unwrap() .body .get("disclosures") .unwrap() @@ -106,15 +160,26 @@ mod test { .len() == 1 ); - let content = result.body.get("disclosures").unwrap().as_array().unwrap()[0] - .as_object() - .unwrap() - .get("id") - .unwrap() - .as_str() - .unwrap(); - let content: String = serde_json::from_str(content).unwrap(); - assert_eq!(content, TRUST.to_string()); + + assert_eq!( + serde_json::from_str::( + result + .unwrap() + .body + .get("disclosures") + .unwrap() + .as_array() + .unwrap()[0] + .as_object() + .unwrap() + .get("id") + .unwrap() + .as_str() + .unwrap() + ) + .unwrap(), + TRUST.to_string() + ); } Err(e) => { panic!("This should not occur {:?}", e) @@ -124,17 +189,17 @@ mod test { #[tokio::test] async fn test_unsupported_feature_type() { let queries = json!({"feature-type": "goal-code", "match": "org.didcomm"}); - - let supported_protocols = vec![TRUST.to_string()]; + let state = setup(); let body = Queries { queries: vec![queries], }; let id = Uuid::new_v4().urn().to_string(); let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); - match handle_query_request(message, supported_protocols) { + match handle_query_request(message, state) { Ok(result) => { assert!(result + .unwrap() .body .get("disclosures") .unwrap() diff --git a/crates/web-plugins/didcomm-messaging/src/forward/routing.rs b/crates/web-plugins/didcomm-messaging/src/forward/routing.rs index 497ec18e..5a9fc9bb 100644 --- a/crates/web-plugins/didcomm-messaging/src/forward/routing.rs +++ b/crates/web-plugins/didcomm-messaging/src/forward/routing.rs @@ -135,6 +135,7 @@ mod test { public_domain, diddoc, keystore, + None, Some(repository), )); diff --git a/crates/web-plugins/didcomm-messaging/src/plugin.rs b/crates/web-plugins/didcomm-messaging/src/plugin.rs index 55585c1a..0c05b2d6 100644 --- a/crates/web-plugins/didcomm-messaging/src/plugin.rs +++ b/crates/web-plugins/didcomm-messaging/src/plugin.rs @@ -106,6 +106,7 @@ impl Plugin for MediatorCoordinationPlugin { env.public_domain.clone(), diddoc, keystore, + None, Some(repository), ); diff --git a/crates/web-plugins/didcomm-messaging/src/web/handler.rs b/crates/web-plugins/didcomm-messaging/src/web/handler.rs index eccd2790..f1dd75f2 100644 --- a/crates/web-plugins/didcomm-messaging/src/web/handler.rs +++ b/crates/web-plugins/didcomm-messaging/src/web/handler.rs @@ -129,6 +129,7 @@ pub mod tests { public_domain, diddoc, keystore, + None, Some(repository), )); let app = web::routes(Arc::clone(&state)); diff --git a/crates/web-plugins/didcomm-messaging/src/web/mod.rs b/crates/web-plugins/didcomm-messaging/src/web/mod.rs index 1c06889d..09301f43 100644 --- a/crates/web-plugins/didcomm-messaging/src/web/mod.rs +++ b/crates/web-plugins/didcomm-messaging/src/web/mod.rs @@ -3,16 +3,18 @@ pub mod error; pub(crate) mod handler; pub(crate) mod midlw; -pub use self::midlw::{unpack_didcomm_message, pack_response_message}; +pub use self::midlw::{pack_response_message, unpack_didcomm_message}; use axum::{middleware, routing::post, Router}; use database::Repository; use did_utils::{didcore::Document, jwk::Jwk}; use keystore::KeyStore; -use std::sync::Arc; +use std::{string, sync::Arc}; use crate::{ - didcomm::bridge::{LocalDIDResolver, LocalSecretsResolver}, model::stateful::entity::{Connection, RoutedMessage, Secrets}, util + didcomm::bridge::{LocalDIDResolver, LocalSecretsResolver}, + model::stateful::entity::{Connection, RoutedMessage, Secrets}, + util, }; pub fn routes(state: Arc) -> Router { @@ -27,7 +29,6 @@ pub fn routes(state: Arc) -> Router { } #[derive(Clone)] -#[allow(unused)] pub struct AppState { // Metadata pub public_domain: String, @@ -42,6 +43,9 @@ pub struct AppState { // Persistence layer pub(crate) repository: Option, + + // Disclosed protocols as strings e.g `coordinate-mediation/2.0` + pub(crate) supported_protocols: Option>, } #[derive(Clone)] @@ -56,6 +60,7 @@ impl AppState { public_domain: String, diddoc: Document, keystore: KeyStore, + disclosed_protocols: Option>, repository: Option, ) -> Self { let (did_url, assertion_pubkey) = util::extract_assertion_key(&diddoc) @@ -84,6 +89,7 @@ impl AppState { did_resolver, secrets_resolver, repository, + supported_protocols: disclosed_protocols, } } } From b6e3105f18eb46d52a25495395d1782180bbc048 Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Wed, 13 Nov 2024 15:54:37 +0100 Subject: [PATCH 05/12] feat(): moved discover-features into protocol section --- .../protocols/discover-features/Cargo.toml | 20 ++++ .../discover-features/src}/constant.rs | 0 .../discover-features/src}/errors.rs | 0 .../discover-features/src}/handler.rs | 29 +++--- .../protocols/discover-features/src/lib.rs | 4 + .../discover-features/src}/model.rs | 0 .../didcomm-messaging/shared/src/state.rs | 5 + .../shared/src/utils/tests_utils.rs | 7 +- .../src/discover_feature/mod.rs | 4 - .../didcomm-messaging/src/plugin.rs | 2 +- .../didcomm-messaging/src/web/mod.rs | 95 ------------------- 11 files changed, 47 insertions(+), 119 deletions(-) create mode 100644 crates/web-plugins/didcomm-messaging/protocols/discover-features/Cargo.toml rename crates/web-plugins/didcomm-messaging/{src/discover_feature => protocols/discover-features/src}/constant.rs (100%) rename crates/web-plugins/didcomm-messaging/{src/discover_feature => protocols/discover-features/src}/errors.rs (100%) rename crates/web-plugins/didcomm-messaging/{src/discover_feature => protocols/discover-features/src}/handler.rs (89%) create mode 100644 crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs rename crates/web-plugins/didcomm-messaging/{src/discover_feature => protocols/discover-features/src}/model.rs (100%) delete mode 100644 crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs delete mode 100644 crates/web-plugins/didcomm-messaging/src/web/mod.rs diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/Cargo.toml b/crates/web-plugins/didcomm-messaging/protocols/discover-features/Cargo.toml new file mode 100644 index 00000000..6de5de47 --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "discover-features" +version = "0.1.0" +edition = "2021" + +[dependencies] +shared.workspace = true +axum.workspace = true +didcomm.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = ["full", "rt"] } +uuid.workspace = true +keystore.workspace = true + +[dev-dependencies] +shared = { workspace = true, features = ["test-utils"] } +keystore = { workspace = true, features = ["test-utils"] } +did-utils.workspace = true \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs similarity index 100% rename from crates/web-plugins/didcomm-messaging/src/discover_feature/constant.rs rename to crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs similarity index 100% rename from crates/web-plugins/didcomm-messaging/src/discover_feature/errors.rs rename to crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs similarity index 89% rename from crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs rename to crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs index 403ac868..103dd62d 100644 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs @@ -3,10 +3,9 @@ use std::sync::Arc; use axum::response::{IntoResponse, Response}; use didcomm::Message; use serde_json::json; +use shared::state::AppState; use uuid::Uuid; -use crate::web::AppState; - use super::{ constant::DISCOVER_FEATURE, errors::DiscoveryError, @@ -15,7 +14,7 @@ use super::{ // handle discover feature request // https://didcomm.org/discover-features/2.0/ -pub(crate) fn handle_query_request( +pub fn handle_query_request( message: Message, state: Arc, ) -> Result, Response> { @@ -86,40 +85,34 @@ mod test { use std::{sync::Arc, vec}; + use did_utils::didcore::Document; use didcomm::Message; + use keystore::tests::MockKeyStore; use serde_json::json; + use shared::{ + repository::tests::{MockConnectionRepository, MockMessagesRepository}, + state::{AppState, AppStateRepository}, + }; use uuid::Uuid; - use crate::{ - discover_feature::{constant::QUERY_FEATURE, model::Queries}, - repository::stateful::tests::{ - MockConnectionRepository, MockMessagesRepository, MockSecretsRepository, - }, - util::{self, MockFileSystem}, - web::{AppState, AppStateRepository}, - }; + use crate::{constant::QUERY_FEATURE, model::Queries}; use super::handle_query_request; const TRUST: &str = "https://didcomm.org/trust-ping/2.0/ping"; pub fn setup() -> Arc { let public_domain = String::from("http://alice-mediator.com"); - let mut mock_fs = MockFileSystem; - let storage_dirpath = std::env::var("STORAGE_DIRPATH").unwrap_or_else(|_| "/".to_owned()); - let diddoc: did_utils::didcore::Document = - util::read_diddoc(&mock_fs, &storage_dirpath).unwrap(); - let keystore = util::read_keystore(&mut mock_fs, "").unwrap(); + let diddoc = Document::default(); let repository = AppStateRepository { connection_repository: Arc::new(MockConnectionRepository::from(vec![])), - secret_repository: Arc::new(MockSecretsRepository::from(vec![])), message_repository: Arc::new(MockMessagesRepository::from(vec![])), + keystore: Arc::new(MockKeyStore::new(vec![])), }; let state = Arc::new(AppState::from( public_domain, diddoc, - keystore, Some(vec!["trust-ping/2.0".to_string()]), Some(repository), )); diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs new file mode 100644 index 00000000..f626e0c3 --- /dev/null +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs @@ -0,0 +1,4 @@ +mod errors; +mod constant; +mod handler; +mod model; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/model.rs similarity index 100% rename from crates/web-plugins/didcomm-messaging/src/discover_feature/model.rs rename to crates/web-plugins/didcomm-messaging/protocols/discover-features/src/model.rs diff --git a/crates/web-plugins/didcomm-messaging/shared/src/state.rs b/crates/web-plugins/didcomm-messaging/shared/src/state.rs index 95d2541f..581bc80e 100644 --- a/crates/web-plugins/didcomm-messaging/shared/src/state.rs +++ b/crates/web-plugins/didcomm-messaging/shared/src/state.rs @@ -22,6 +22,9 @@ pub struct AppState { // Persistence layer pub repository: Option, + + // disclosed protocols name/version e.g 'trust-ping/2.0' + pub supported_protocols: Option> } #[derive(Clone)] @@ -35,6 +38,7 @@ impl AppState { pub fn from( public_domain: String, diddoc: Document, + disclose_protocols: Option>, repository: Option, ) -> Self { let did_resolver = LocalDIDResolver::new(&diddoc); @@ -51,6 +55,7 @@ impl AppState { did_resolver, secrets_resolver, repository, + supported_protocols: disclose_protocols, } } } diff --git a/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs b/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs index 2ad2041d..5a406359 100644 --- a/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs +++ b/crates/web-plugins/didcomm-messaging/shared/src/utils/tests_utils.rs @@ -93,7 +93,12 @@ pub mod tests { keystore: Arc::new(MockKeyStore::new(vec![mediator_secret])), }; - let state = Arc::new(AppState::from(public_domain, diddoc, Some(repository))); + let state = Arc::new(AppState::from( + public_domain, + diddoc, + None, + Some(repository), + )); state } diff --git a/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs b/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs deleted file mode 100644 index adda26ca..00000000 --- a/crates/web-plugins/didcomm-messaging/src/discover_feature/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub(super) mod model; -pub(crate) mod handler; -pub(crate) mod errors; -pub(super) mod constant; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/src/plugin.rs b/crates/web-plugins/didcomm-messaging/src/plugin.rs index f6293a18..f27462cc 100644 --- a/crates/web-plugins/didcomm-messaging/src/plugin.rs +++ b/crates/web-plugins/didcomm-messaging/src/plugin.rs @@ -98,7 +98,7 @@ impl Plugin for MediatorCoordination { }; // Compile state - let state = AppState::from(env.public_domain.clone(), diddoc, Some(repository)); + let state = AppState::from(env.public_domain.clone(), diddoc,None, Some(repository)); // Build router web::routes(Arc::new(state)) diff --git a/crates/web-plugins/didcomm-messaging/src/web/mod.rs b/crates/web-plugins/didcomm-messaging/src/web/mod.rs deleted file mode 100644 index 09301f43..00000000 --- a/crates/web-plugins/didcomm-messaging/src/web/mod.rs +++ /dev/null @@ -1,95 +0,0 @@ -pub(crate) mod coord; -pub mod error; -pub(crate) mod handler; -pub(crate) mod midlw; - -pub use self::midlw::{pack_response_message, unpack_didcomm_message}; - -use axum::{middleware, routing::post, Router}; -use database::Repository; -use did_utils::{didcore::Document, jwk::Jwk}; -use keystore::KeyStore; -use std::{string, sync::Arc}; - -use crate::{ - didcomm::bridge::{LocalDIDResolver, LocalSecretsResolver}, - model::stateful::entity::{Connection, RoutedMessage, Secrets}, - util, -}; - -pub fn routes(state: Arc) -> Router { - Router::new() - // Unified route for all DIDComm messages - .route("/", post(handler::process_didcomm_message)) - .route_layer(middleware::from_fn_with_state( - state.clone(), - midlw::unpack_didcomm_message, - )) - .with_state(state) -} - -#[derive(Clone)] -pub struct AppState { - // Metadata - pub public_domain: String, - - // Crypto identity - pub diddoc: Document, - pub assertion_jwk: (String, Jwk), - - // DIDComm Resolvers - pub(crate) did_resolver: LocalDIDResolver, - pub(crate) secrets_resolver: LocalSecretsResolver, - - // Persistence layer - pub(crate) repository: Option, - - // Disclosed protocols as strings e.g `coordinate-mediation/2.0` - pub(crate) supported_protocols: Option>, -} - -#[derive(Clone)] -pub struct AppStateRepository { - pub connection_repository: Arc>, - pub secret_repository: Arc>, - pub message_repository: Arc>, -} - -impl AppState { - pub fn from( - public_domain: String, - diddoc: Document, - keystore: KeyStore, - disclosed_protocols: Option>, - repository: Option, - ) -> Self { - let (did_url, assertion_pubkey) = util::extract_assertion_key(&diddoc) - .expect("Failed to retrieve assertion key details from server DID document"); - let assertion_jwk = ( - did_url, - keystore - .find_keypair(&assertion_pubkey) - .expect("Unsuccessful keystore search"), - ); - - let did_resolver = LocalDIDResolver::new(&diddoc); - let secrets_resolver = { - let (vm_id, jwk) = util::extract_agreement_key(&diddoc) - .expect("Failed to retrieve agreement key details from server DID document"); - let secret = keystore - .find_keypair(&jwk) - .expect("Unsuccessful keystore search"); - LocalSecretsResolver::new(&vm_id, &secret) - }; - - Self { - public_domain, - diddoc, - assertion_jwk, - did_resolver, - secrets_resolver, - repository, - supported_protocols: disclosed_protocols, - } - } -} From 1d52acba26739fb2d7a0994965f88bcf1ff3419e Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Wed, 13 Nov 2024 16:15:26 +0100 Subject: [PATCH 06/12] fix(discover-features): removed unused values --- .vscode/launch.json | 16 ---------------- .../protocols/discover-features/src/constant.rs | 4 ++-- .../protocols/discover-features/src/handler.rs | 11 ++++++----- .../src/did_rotation/did_rotation.rs | 2 +- 4 files changed, 9 insertions(+), 24 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 10efcb2f..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "lldb", - "request": "launch", - "name": "Debug", - "program": "${workspaceFolder}/", - "args": [], - "cwd": "${workspaceFolder}" - } - ] -} \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs index a27925a3..9a44ebae 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs @@ -1,2 +1,2 @@ -pub(super) const DISCOVER_FEATURE: &str = "https://didcomm.org/discover-features/2.0/disclose"; -pub(super) const QUERY_FEATURE: &str = "https://didcomm.org/discover-features/2.0/queries"; \ No newline at end of file +pub(super) const _DISCOVER_FEATURE: &str = "https://didcomm.org/discover-features/2.0/disclose"; +pub(super) const _QUERY_FEATURE: &str = "https://didcomm.org/discover-features/2.0/queries"; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs index 103dd62d..9421b009 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs @@ -6,8 +6,9 @@ use serde_json::json; use shared::state::AppState; use uuid::Uuid; +use crate::constant::_DISCOVER_FEATURE; + use super::{ - constant::DISCOVER_FEATURE, errors::DiscoveryError, model::{Disclosures, DisclosuresContent}, }; @@ -73,7 +74,7 @@ pub fn handle_query_request( } let id = Uuid::new_v4().urn().to_string(); - let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); + let msg = Message::build(id, _DISCOVER_FEATURE.to_string(), json!(body)).finalize(); Ok(Some(msg)) } else { @@ -95,7 +96,7 @@ mod test { }; use uuid::Uuid; - use crate::{constant::QUERY_FEATURE, model::Queries}; + use crate::{constant::_QUERY_FEATURE, model::Queries}; use super::handle_query_request; const TRUST: &str = "https://didcomm.org/trust-ping/2.0/ping"; @@ -129,7 +130,7 @@ mod test { }; let id = Uuid::new_v4().urn().to_string(); - let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); + let message = Message::build(id, _QUERY_FEATURE.to_string(), json!(body)).finalize(); let state = setup(); match handle_query_request(message, state) { Ok(result) => { @@ -188,7 +189,7 @@ mod test { }; let id = Uuid::new_v4().urn().to_string(); - let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); + let message = Message::build(id, _QUERY_FEATURE.to_string(), json!(body)).finalize(); match handle_query_request(message, state) { Ok(result) => { assert!(result diff --git a/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs b/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs index 04331aa2..cf0a65e2 100644 --- a/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs +++ b/crates/web-plugins/didcomm-messaging/src/did_rotation/did_rotation.rs @@ -162,7 +162,7 @@ mod test { message_repository: Arc::new(MockMessagesRepository::from(vec![])), }; - let state = Arc::new(AppState::from(public_domain, diddoc, Some(repository))); + let state = Arc::new(AppState::from(public_domain, diddoc, None, Some(repository))); state } From b50dac7355ee76f93d76881e978d2a1b0404994f Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Thu, 14 Nov 2024 12:50:38 +0100 Subject: [PATCH 07/12] fix(): change handler visibility --- .../protocols/discover-features/src/errors.rs | 6 ------ .../protocols/discover-features/src/lib.rs | 6 +++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs index a54ffe61..f35d5303 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs @@ -19,9 +19,3 @@ impl DiscoveryError { })) } } - -impl From for Json { - fn from(error: DiscoveryError) -> Self { - error.json() - } -} diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs index f626e0c3..36888dda 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs @@ -1,4 +1,4 @@ -mod errors; mod constant; -mod handler; -mod model; \ No newline at end of file +mod errors; +pub mod handler; +mod model; From 353ccb85f1b8abcfaad16ee22b992830b4c1f7b9 Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Thu, 14 Nov 2024 12:55:12 +0100 Subject: [PATCH 08/12] fix(): remove unused error --- .../didcomm-messaging/protocols/discover-features/src/errors.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs index f35d5303..61c8dcde 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs @@ -6,8 +6,6 @@ use thiserror::Error; pub enum DiscoveryError { #[error("message body is malformed")] MalformedBody, - #[error("Repository not set")] - RepostitoryError, #[error("No queries field in body")] QueryNotFound } From 934c51d8be950c66381217db7bb63cd561ef1405 Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Fri, 15 Nov 2024 16:39:00 +0100 Subject: [PATCH 09/12] feat(): adding wildcard support --- .../discover-features/src/constant.rs | 2 - .../discover-features/src/handler.rs | 144 ++++++++++++++---- .../protocols/discover-features/src/lib.rs | 1 - .../didcomm-messaging/shared/src/constants.rs | 2 + .../didcomm-messaging/shared/src/state.rs | 2 +- 5 files changed, 120 insertions(+), 31 deletions(-) delete mode 100644 crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs deleted file mode 100644 index 9a44ebae..00000000 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/constant.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub(super) const _DISCOVER_FEATURE: &str = "https://didcomm.org/discover-features/2.0/disclose"; -pub(super) const _QUERY_FEATURE: &str = "https://didcomm.org/discover-features/2.0/queries"; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs index 9421b009..c5ca2e27 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs @@ -1,13 +1,19 @@ -use std::sync::Arc; +use std::{ + collections::{HashMap, HashSet}, + fmt::format, + sync::Arc, +}; -use axum::response::{IntoResponse, Response}; +use axum::{ + http::version, + response::{IntoResponse, Response}, +}; use didcomm::Message; +use serde::de::value; use serde_json::json; -use shared::state::AppState; +use shared::{constants::DISCOVER_FEATURE, state::AppState}; use uuid::Uuid; -use crate::constant::_DISCOVER_FEATURE; - use super::{ errors::DiscoveryError, model::{Disclosures, DisclosuresContent}, @@ -21,9 +27,26 @@ pub fn handle_query_request( ) -> Result, Response> { let mut disclosed_protocols: Vec = Vec::new(); - let body = message.body.get("queries").and_then(|val| val.as_array()); + let queries = message.body.get("queries").and_then(|val| val.as_array()); - if let Some(queries) = body { + let mut extracted_protocol = HashSet::new(); + let mut wildcard_protocol: HashSet = HashSet::new(); + + if let Some(supported_protocol) = &state.supported_protocols { + for protocol in supported_protocol { + let parts: Vec<&str> = protocol.split("/").collect(); + let (name, version) = (parts[3], parts[4]); + let protocol = format!("{}/{}", name, version); + extracted_protocol.insert(protocol); + } + // wildcard scenario + for protocol in extracted_protocol.clone() { + let value: Vec<&str> = protocol.split(".").collect(); + wildcard_protocol.insert(value[0].to_string()); + } + }; + + if let Some(queries) = queries { for value in queries { match value.get("feature-type") { Some(val) => { @@ -34,18 +57,22 @@ pub fn handle_query_request( let id = id.to_string(); let parts: Vec<&str> = id.split("/").collect(); let (name, version) = (parts[3], parts[4]); - let query_protocol = format!("{}/{}", name, version); - - if let Some(supported_protocols) = - &state.clone().supported_protocols - { - if supported_protocols - .iter() - .find(|&disclose_protocol| { - disclose_protocol == &query_protocol - }) - .is_some() - { + let version: Vec<&str> = version.split("\"").collect(); + let version = version[0]; + + let semver: Vec<&str> = version.split(".").collect(); + let minor: &str = semver[1]; + if minor != "*" { + let protocol = format!("{}/{}", name, version); + + if let Some(_) = extracted_protocol.get(&protocol) { + disclosed_protocols.push(id.clone()); + } + } + if minor == "*" { + let major = semver[0]; + let protocol = format!("{}/{}", name, major); + if let Some(_) = wildcard_protocol.get(&protocol) { disclosed_protocols.push(id); } } @@ -74,8 +101,9 @@ pub fn handle_query_request( } let id = Uuid::new_v4().urn().to_string(); - let msg = Message::build(id, _DISCOVER_FEATURE.to_string(), json!(body)).finalize(); + let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); + println!("{:#?}", msg); Ok(Some(msg)) } else { return Err(DiscoveryError::QueryNotFound.json().into_response()); @@ -91,15 +119,16 @@ mod test { use keystore::tests::MockKeyStore; use serde_json::json; use shared::{ + constants::QUERY_FEATURE, repository::tests::{MockConnectionRepository, MockMessagesRepository}, state::{AppState, AppStateRepository}, }; use uuid::Uuid; - use crate::{constant::_QUERY_FEATURE, model::Queries}; + use crate::model::Queries; use super::handle_query_request; - const TRUST: &str = "https://didcomm.org/trust-ping/2.0/ping"; + const MEDIATION: &str = "https://didcomm.org/coordinate-mediation/2.*"; pub fn setup() -> Arc { let public_domain = String::from("http://alice-mediator.com"); @@ -114,7 +143,9 @@ mod test { let state = Arc::new(AppState::from( public_domain, diddoc, - Some(vec!["trust-ping/2.0".to_string()]), + Some(vec![ + "https://didcomm.org/coordinate-mediation/2.0/mediate-request".to_string(), + ]), Some(repository), )); @@ -123,14 +154,73 @@ mod test { #[tokio::test] async fn test_get_supported_protocols() { - let queries = json!({"feature-type": "protocol", "match": TRUST}); + let queries = json!({"feature-type": "protocol", "match": MEDIATION}); + + let body = Queries { + queries: vec![queries], + }; + let id = Uuid::new_v4().urn().to_string(); + + let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); + let state = setup(); + match handle_query_request(message, state) { + Ok(result) => { + assert!(result.clone().unwrap().body.get("disclosures").is_some()); + assert!(result + .clone() + .unwrap() + .body + .get("disclosures") + .unwrap() + .is_array()); + assert!( + result + .clone() + .unwrap() + .body + .get("disclosures") + .unwrap() + .as_array() + .unwrap() + .len() + == 1 + ); + + assert_eq!( + serde_json::from_str::( + result + .unwrap() + .body + .get("disclosures") + .unwrap() + .as_array() + .unwrap()[0] + .as_object() + .unwrap() + .get("id") + .unwrap() + .as_str() + .unwrap() + ) + .unwrap(), + MEDIATION.to_string() + ); + } + Err(e) => { + panic!("This should not occur {:?}", e) + } + } + } + #[tokio::test] + async fn test_get_wildcard_supported_protocols() { + let queries = json!({"feature-type": "protocol", "match": "https://didcomm.org/coordinate-mediation/2.*"}); let body = Queries { queries: vec![queries], }; let id = Uuid::new_v4().urn().to_string(); - let message = Message::build(id, _QUERY_FEATURE.to_string(), json!(body)).finalize(); + let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); let state = setup(); match handle_query_request(message, state) { Ok(result) => { @@ -172,7 +262,7 @@ mod test { .unwrap() ) .unwrap(), - TRUST.to_string() + MEDIATION.to_string() ); } Err(e) => { @@ -189,7 +279,7 @@ mod test { }; let id = Uuid::new_v4().urn().to_string(); - let message = Message::build(id, _QUERY_FEATURE.to_string(), json!(body)).finalize(); + let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); match handle_query_request(message, state) { Ok(result) => { assert!(result diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs index 36888dda..10f2947e 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/lib.rs @@ -1,4 +1,3 @@ -mod constant; mod errors; pub mod handler; mod model; diff --git a/crates/web-plugins/didcomm-messaging/shared/src/constants.rs b/crates/web-plugins/didcomm-messaging/shared/src/constants.rs index 2dfc81ac..fe6df2ee 100644 --- a/crates/web-plugins/didcomm-messaging/shared/src/constants.rs +++ b/crates/web-plugins/didcomm-messaging/shared/src/constants.rs @@ -26,3 +26,5 @@ pub const TRUST_PING_RESPONSE_2_0: &str = "https://didcomm.org/trust-ping/2.0/pi pub const DIDCOMM_ENCRYPTED_MIME_TYPE: &str = "application/didcomm-encrypted+json"; pub const DIDCOMM_ENCRYPTED_SHORT_MIME_TYPE: &str = "didcomm-encrypted+json"; +pub const DISCOVER_FEATURE: &str = "https://didcomm.org/discover-features/2.0/disclose"; +pub const QUERY_FEATURE: &str = "https://didcomm.org/discover-features/2.0/queries"; \ No newline at end of file diff --git a/crates/web-plugins/didcomm-messaging/shared/src/state.rs b/crates/web-plugins/didcomm-messaging/shared/src/state.rs index 581bc80e..a3edf1c7 100644 --- a/crates/web-plugins/didcomm-messaging/shared/src/state.rs +++ b/crates/web-plugins/didcomm-messaging/shared/src/state.rs @@ -23,7 +23,7 @@ pub struct AppState { // Persistence layer pub repository: Option, - // disclosed protocols name/version e.g 'trust-ping/2.0' + // disclosed protocols `https://org.didcomm.com/{protocol-name}/{version}/{request-type}`` pub supported_protocols: Option> } From 99dacd276fcab11d8f9656c7426294d81d5641c1 Mon Sep 17 00:00:00 2001 From: Christiantyemele Date: Mon, 18 Nov 2024 00:49:59 +0100 Subject: [PATCH 10/12] update(): code refactoring --- .../protocols/discover-features/src/errors.rs | 4 +- .../discover-features/src/handler.rs | 265 +++++++++--------- 2 files changed, 137 insertions(+), 132 deletions(-) diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs index 61c8dcde..32d78ac5 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs @@ -7,7 +7,9 @@ pub enum DiscoveryError { #[error("message body is malformed")] MalformedBody, #[error("No queries field in body")] - QueryNotFound + QueryNotFound, + #[error("query feature-type not supported try using `protocol`")] + FeatureNOTSupported } impl DiscoveryError { /// Converts the error to an axum JSON representation. diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs index c5ca2e27..00558fe8 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs @@ -1,15 +1,7 @@ -use std::{ - collections::{HashMap, HashSet}, - fmt::format, - sync::Arc, -}; +use std::{collections::HashSet, sync::Arc}; -use axum::{ - http::version, - response::{IntoResponse, Response}, -}; +use axum::response::{IntoResponse, Response}; use didcomm::Message; -use serde::de::value; use serde_json::json; use shared::{constants::DISCOVER_FEATURE, state::AppState}; use uuid::Uuid; @@ -25,89 +17,111 @@ pub fn handle_query_request( message: Message, state: Arc, ) -> Result, Response> { - let mut disclosed_protocols: Vec = Vec::new(); + let mut disclosed_protocols: HashSet = HashSet::new(); let queries = message.body.get("queries").and_then(|val| val.as_array()); - let mut extracted_protocol = HashSet::new(); - let mut wildcard_protocol: HashSet = HashSet::new(); - - if let Some(supported_protocol) = &state.supported_protocols { - for protocol in supported_protocol { - let parts: Vec<&str> = protocol.split("/").collect(); - let (name, version) = (parts[3], parts[4]); - let protocol = format!("{}/{}", name, version); - extracted_protocol.insert(protocol); - } - // wildcard scenario - for protocol in extracted_protocol.clone() { - let value: Vec<&str> = protocol.split(".").collect(); - wildcard_protocol.insert(value[0].to_string()); - } - }; - - if let Some(queries) = queries { - for value in queries { - match value.get("feature-type") { - Some(val) => { - let val = val.as_str().unwrap(); - if val.to_string() == "protocol" { - match value.get("match") { - Some(id) => { - let id = id.to_string(); - let parts: Vec<&str> = id.split("/").collect(); - let (name, version) = (parts[3], parts[4]); - let version: Vec<&str> = version.split("\"").collect(); - let version = version[0]; + if let Some(_) = &state.supported_protocols { + if let Some(queries) = queries { + for value in queries { + match value.get("feature-type") { + Some(val) => { + let val = val.as_str().unwrap(); + if val.to_string() == "protocol" { + match value.get("match") { + Some(id) => { + let id = id.as_str().unwrap_or_default(); - let semver: Vec<&str> = version.split(".").collect(); - let minor: &str = semver[1]; - if minor != "*" { - let protocol = format!("{}/{}", name, version); + if !id.ends_with(".*") { + if state.as_ref().clone().supported_protocols.is_some_and( + |a| { + a.into_iter() + .find(|protocol| { + protocol.contains(&id.to_string()) + }) + .is_some() + }, + ) { + disclosed_protocols.insert(id.to_owned()); + } + } + // wildcard scenario + if id.ends_with(".*") { + let parts: Vec<&str> = id.split(".*").collect(); + // container + let mut container: String = Default::default(); - if let Some(_) = extracted_protocol.get(&protocol) { - disclosed_protocols.push(id.clone()); + if let Some(id) = parts.get(0) { + if state + .as_ref() + .clone() + .supported_protocols + .is_some_and(|a| { + a.into_iter() + .find(|protocol| { + protocol.contains(&id.to_string()) + }) + .is_some_and(|protocol| { + container = protocol; + return true; + }) + }) + { + let parts: Vec<&str> = + container.split(id).collect(); + let minor = parts[1] + .to_string() + .chars() + .nth(1) + .unwrap_or_default(); + let id = format!("{id}.{minor}"); + disclosed_protocols.insert(id.to_string()); + } + } } } - if minor == "*" { - let major = semver[0]; - let protocol = format!("{}/{}", name, major); - if let Some(_) = wildcard_protocol.get(&protocol) { - disclosed_protocols.push(id); - } + None => { + return Err(DiscoveryError::MalformedBody + .json() + .into_response()) } } - None => { - return Err(DiscoveryError::MalformedBody.json().into_response()) - } + } else { + return Err(DiscoveryError::FeatureNOTSupported.json().into_response()); } } + None => return Err(DiscoveryError::MalformedBody.json().into_response()), } - None => return Err(DiscoveryError::MalformedBody.json().into_response()), } - } - // build response body - let mut body = Disclosures::new(); - for id in disclosed_protocols.iter() { - let content = DisclosuresContent { - feature_type: "protocol".to_string(), - id: id.to_owned(), - roles: None, - }; - let content = json!(content); - - body.disclosures.push(content); + // build response body + let msg = build_response(disclosed_protocols); + Ok(Some(msg)) + } else { + return Err(DiscoveryError::QueryNotFound.json().into_response()); } - - let id = Uuid::new_v4().urn().to_string(); - let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); - - println!("{:#?}", msg); - Ok(Some(msg)) } else { - return Err(DiscoveryError::QueryNotFound.json().into_response()); + let msg = build_response(disclosed_protocols); + Ok(Some(msg)) + } +} +fn build_response(disclosed_protocols: HashSet) -> Message { + let mut body = Disclosures::new(); + for id in disclosed_protocols.iter() { + let content = DisclosuresContent { + feature_type: "protocol".to_string(), + id: id.to_owned(), + roles: None, + }; + let content = json!(content); + + body.disclosures.push(content); } + + let id = Uuid::new_v4().urn().to_string(); + let msg = Message::build(id, DISCOVER_FEATURE.to_string(), json!(body)).finalize(); + + msg } #[cfg(test)] mod test { @@ -128,7 +142,8 @@ mod test { use crate::model::Queries; use super::handle_query_request; - const MEDIATION: &str = "https://didcomm.org/coordinate-mediation/2.*"; + const MEDIATION: &str = "https://didcomm.org/coordinate-mediation/2.0"; + pub fn setup() -> Arc { let public_domain = String::from("http://alice-mediator.com"); @@ -165,6 +180,7 @@ mod test { let state = setup(); match handle_query_request(message, state) { Ok(result) => { + println!("{:#?}", &result.clone().unwrap()); assert!(result.clone().unwrap().body.get("disclosures").is_some()); assert!(result .clone() @@ -173,7 +189,7 @@ mod test { .get("disclosures") .unwrap() .is_array()); - assert!( + assert_eq!( result .clone() .unwrap() @@ -182,29 +198,26 @@ mod test { .unwrap() .as_array() .unwrap() - .len() - == 1 + .len(), + 1 ); + let id = serde_json::from_str::( + &result + .unwrap() + .body + .get("disclosures") + .unwrap() + .as_array() + .unwrap()[0] + .as_object() + .unwrap() + .get("id") + .unwrap() + .to_string(), + ) + .unwrap(); - assert_eq!( - serde_json::from_str::( - result - .unwrap() - .body - .get("disclosures") - .unwrap() - .as_array() - .unwrap()[0] - .as_object() - .unwrap() - .get("id") - .unwrap() - .as_str() - .unwrap() - ) - .unwrap(), - MEDIATION.to_string() - ); + assert_eq!(id, MEDIATION.to_string()); } Err(e) => { panic!("This should not occur {:?}", e) @@ -212,7 +225,7 @@ mod test { } } #[tokio::test] - async fn test_get_wildcard_supported_protocols() { + async fn test_get_supported_protocols_with_wildcard() { let queries = json!({"feature-type": "protocol", "match": "https://didcomm.org/coordinate-mediation/2.*"}); let body = Queries { @@ -224,6 +237,7 @@ mod test { let state = setup(); match handle_query_request(message, state) { Ok(result) => { + println!("{:#?}", &result.clone().unwrap()); assert!(result.clone().unwrap().body.get("disclosures").is_some()); assert!(result .clone() @@ -244,26 +258,23 @@ mod test { .len() == 1 ); + let id = serde_json::from_str::( + &result + .unwrap() + .body + .get("disclosures") + .unwrap() + .as_array() + .unwrap()[0] + .as_object() + .unwrap() + .get("id") + .unwrap() + .to_string(), + ) + .unwrap(); - assert_eq!( - serde_json::from_str::( - result - .unwrap() - .body - .get("disclosures") - .unwrap() - .as_array() - .unwrap()[0] - .as_object() - .unwrap() - .get("id") - .unwrap() - .as_str() - .unwrap() - ) - .unwrap(), - MEDIATION.to_string() - ); + assert_eq!(id, MEDIATION.to_string()); } Err(e) => { panic!("This should not occur {:?}", e) @@ -280,20 +291,12 @@ mod test { let id = Uuid::new_v4().urn().to_string(); let message = Message::build(id, QUERY_FEATURE.to_string(), json!(body)).finalize(); + match handle_query_request(message, state) { - Ok(result) => { - assert!(result - .unwrap() - .body - .get("disclosures") - .unwrap() - .as_array() - .unwrap() - .is_empty()) - } - Err(e) => { - panic!("This should not occur: {:#?}", e) + Ok(_) => { + panic!("This should'nt occur"); } + Err(_) => {} } } } From 118cc7778d082f4fca4c1bc6132c3b27ffa28e71 Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Tue, 19 Nov 2024 15:11:58 +0100 Subject: [PATCH 11/12] fix(): code review --- .../protocols/discover-features/src/errors.rs | 23 +++++++++++------ .../discover-features/src/handler.rs | 25 ++++++++----------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs index 32d78ac5..7ed11107 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/errors.rs @@ -1,5 +1,4 @@ -use axum::Json; -use serde_json::{json, Value}; +use axum::{http::StatusCode, response::IntoResponse, Json}; use thiserror::Error; #[derive(Debug, Error)] @@ -11,11 +10,19 @@ pub enum DiscoveryError { #[error("query feature-type not supported try using `protocol`")] FeatureNOTSupported } -impl DiscoveryError { - /// Converts the error to an axum JSON representation. - pub fn json(&self) -> Json { - Json(json!({ - "error": self.to_string() - })) + +impl IntoResponse for DiscoveryError { + fn into_response(self) -> axum::response::Response { + let status_code = match self { + DiscoveryError::MalformedBody => StatusCode::BAD_REQUEST, + DiscoveryError::QueryNotFound => StatusCode::EXPECTATION_FAILED, + DiscoveryError::FeatureNOTSupported => StatusCode::NOT_ACCEPTABLE, + }; + + let body = Json(serde_json::json!({ + "error": self.to_string(), + })); + + (status_code, body).into_response() } } diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs index 00558fe8..932a45f0 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs @@ -26,8 +26,8 @@ pub fn handle_query_request( for value in queries { match value.get("feature-type") { Some(val) => { - let val = val.as_str().unwrap(); - if val.to_string() == "protocol" { + let val = val.as_str().unwrap_or_default(); + if val == "protocol" { match value.get("match") { Some(id) => { let id = id.as_str().unwrap_or_default(); @@ -46,7 +46,7 @@ pub fn handle_query_request( } } // wildcard scenario - if id.ends_with(".*") { + else { let parts: Vec<&str> = id.split(".*").collect(); // container let mut container: String = Default::default(); @@ -69,6 +69,7 @@ pub fn handle_query_request( { let parts: Vec<&str> = container.split(id).collect(); + // getting the minor version supported by the mediator when we have a request with a wilcard as minor let minor = parts[1] .to_string() .chars() @@ -80,17 +81,13 @@ pub fn handle_query_request( } } } - None => { - return Err(DiscoveryError::MalformedBody - .json() - .into_response()) - } + None => return Err(DiscoveryError::MalformedBody.into_response()), } } else { - return Err(DiscoveryError::FeatureNOTSupported.json().into_response()); + return Err(DiscoveryError::FeatureNOTSupported.into_response()); } } - None => return Err(DiscoveryError::MalformedBody.json().into_response()), + None => return Err(DiscoveryError::MalformedBody.into_response()), } } @@ -98,7 +95,7 @@ pub fn handle_query_request( let msg = build_response(disclosed_protocols); Ok(Some(msg)) } else { - return Err(DiscoveryError::QueryNotFound.json().into_response()); + return Err(DiscoveryError::QueryNotFound.into_response()); } } else { let msg = build_response(disclosed_protocols); @@ -180,7 +177,6 @@ mod test { let state = setup(); match handle_query_request(message, state) { Ok(result) => { - println!("{:#?}", &result.clone().unwrap()); assert!(result.clone().unwrap().body.get("disclosures").is_some()); assert!(result .clone() @@ -228,8 +224,9 @@ mod test { async fn test_get_supported_protocols_with_wildcard() { let queries = json!({"feature-type": "protocol", "match": "https://didcomm.org/coordinate-mediation/2.*"}); + // test duplicates in queries let body = Queries { - queries: vec![queries], + queries: vec![queries.clone(), queries], }; let id = Uuid::new_v4().urn().to_string(); @@ -237,7 +234,7 @@ mod test { let state = setup(); match handle_query_request(message, state) { Ok(result) => { - println!("{:#?}", &result.clone().unwrap()); + println!("{:#?}", result.clone().unwrap()); assert!(result.clone().unwrap().body.get("disclosures").is_some()); assert!(result .clone() From 6b64fd475aff845bbb3ae0bdf4d7f60a5be67df4 Mon Sep 17 00:00:00 2001 From: Christian_Yemele Date: Fri, 22 Nov 2024 09:57:51 +0100 Subject: [PATCH 12/12] fix(): code refactoring --- .../discover-features/src/handler.rs | 73 +++++++++---------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs index 932a45f0..f8c6f885 100644 --- a/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs +++ b/crates/web-plugins/didcomm-messaging/protocols/discover-features/src/handler.rs @@ -18,10 +18,12 @@ pub fn handle_query_request( state: Arc, ) -> Result, Response> { let mut disclosed_protocols: HashSet = HashSet::new(); + let supported: &Vec; let queries = message.body.get("queries").and_then(|val| val.as_array()); - if let Some(_) = &state.supported_protocols { + if let Some(protocols) = &state.supported_protocols { + supported = protocols; if let Some(queries) = queries { for value in queries { match value.get("feature-type") { @@ -32,55 +34,48 @@ pub fn handle_query_request( Some(id) => { let id = id.as_str().unwrap_or_default(); - if !id.ends_with(".*") { - if state.as_ref().clone().supported_protocols.is_some_and( - |a| { - a.into_iter() - .find(|protocol| { - protocol.contains(&id.to_string()) - }) - .is_some() - }, - ) { - disclosed_protocols.insert(id.to_owned()); - } + if !id + .ends_with(".*") + .then(|| { + supported + .into_iter() + .find(|protocol| protocol.contains(&id.to_string())) + .is_some() + }) + .is_some() + { + disclosed_protocols.insert(id.to_owned()); } // wildcard scenario else { let parts: Vec<&str> = id.split(".*").collect(); - // container + // stores the full protocol obtained when we have a match with wildcard let mut container: String = Default::default(); if let Some(id) = parts.get(0) { - if state - .as_ref() - .clone() - .supported_protocols - .is_some_and(|a| { - a.into_iter() - .find(|protocol| { - protocol.contains(&id.to_string()) - }) - .is_some_and(|protocol| { - container = protocol; - return true; - }) + supported + .into_iter() + .find(|protocol| protocol.contains(&id.to_string())) + .is_some_and(|protocol| { + container = protocol.to_string(); + return true; }) - { - let parts: Vec<&str> = - container.split(id).collect(); - // getting the minor version supported by the mediator when we have a request with a wilcard as minor - let minor = parts[1] - .to_string() - .chars() - .nth(1) - .unwrap_or_default(); - let id = format!("{id}.{minor}"); - disclosed_protocols.insert(id.to_string()); - } + .then(|| { + let parts: Vec<&str> = + container.split(id).collect(); + // getting the minor version supported by the mediator when we have a request with a wildcard as minor + let minor = parts[1] + .to_string() + .chars() + .nth(1) + .unwrap_or_default(); + let id = format!("{id}.{minor}"); + disclosed_protocols.insert(id.to_string()); + }); } } } + None => return Err(DiscoveryError::MalformedBody.into_response()), } } else {