Skip to content

Commit

Permalink
Merge pull request #244 from adorsys/240-change-the-signature-of-the-…
Browse files Browse the repository at this point in the history
…request-handlers-functions-in-the-didcomm-messaging-plugin

240 change the signature of the request handlers functions in the didcomm messaging plugin
  • Loading branch information
Hermann-Core authored Nov 14, 2024
2 parents deb4208 + f7ce91f commit c7d7ea9
Show file tree
Hide file tree
Showing 22 changed files with 448 additions and 549 deletions.
1 change: 1 addition & 0 deletions crates/web-plugins/didcomm-messaging/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ plugin-api.workspace = true
filesystem.workspace = true
forward.workspace = true
pickup.workspace = true
trust-ping.workspace = true
mediator-coordination.workspace = true

mongodb.workspace = true
Expand Down
36 changes: 20 additions & 16 deletions crates/web-plugins/didcomm-messaging/protocols/forward/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
use axum::Json;
use serde_json::{json, Value};
use axum::{response::IntoResponse, Json};
use hyper::StatusCode;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum RoutingError {
pub enum ForwardError {
#[error("message body is malformed")]
MalformedBody,
#[error("Repository not set")]
RepostitoryError
}
impl RoutingError {
/// Converts the error to an axum JSON representation.
pub fn json(&self) -> Json<Value> {
Json(json!({
"error": self.to_string()
}))
}
#[error("Uncoordinated sender")]
UncoordinatedSender,
#[error("Internal server error")]
InternalServerError,
}

impl From<RoutingError> for Json<Value> {
fn from(error: RoutingError) -> Self {
error.json()
impl IntoResponse for ForwardError {
fn into_response(self) -> axum::response::Response {
let status_code = match self {
ForwardError::MalformedBody => StatusCode::BAD_REQUEST,
ForwardError::UncoordinatedSender => StatusCode::UNAUTHORIZED,
ForwardError::InternalServerError => StatusCode::INTERNAL_SERVER_ERROR,
};

let body = Json(serde_json::json!({
"error": self.to_string(),
}));

(status_code, body).into_response()
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod error;

pub mod web;

// Re-exports
pub use error::ForwardError;
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use super::routing::handler;
use axum::response::Response;
use crate::{web::routing::handler, ForwardError};
use didcomm::Message;
use shared::state::AppState;
use std::sync::Arc;

/// Mediator receives forwarded messages, extract the next field in the message body, and the attachments in the message
/// then stores the attachment with the next field as key for pickup
pub async fn mediator_forward_process(
state: &AppState,
state: Arc<AppState>,
payload: Message,
) -> Result<Message, Response> {
let result = handler(state, payload).await.unwrap();
) -> Result<Option<Message>, ForwardError> {
let result = handler(state.clone(), payload).await.unwrap();
Ok(result)
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use crate::error::RoutingError;
use axum::response::{IntoResponse, Response};
use crate::error::ForwardError;
use database::Repository;
use didcomm::{AttachmentData, Message};
use hyper::StatusCode;
use mongodb::bson::doc;
use serde_json::{json, Value};
use shared::{
errors::MediationError,
repository::entity::{Connection, RoutedMessage},
state::{AppState, AppStateRepository},
};
Expand All @@ -15,47 +12,39 @@ use std::sync::Arc;
async fn checks(
message: &Message,
connection_repository: &Arc<dyn Repository<Connection>>,
) -> Result<String, Response> {
) -> Result<String, ForwardError> {
let next = message.body.get("next").and_then(Value::as_str);
match next {
Some(next) => next,
None => {
let response = (StatusCode::BAD_REQUEST, RoutingError::MalformedBody.json());
return Err(response.into_response());
}
None => return Err(ForwardError::MalformedBody),
};

// Check if the client's did in mediator's keylist
let _connection = match connection_repository
.find_one_by(doc! {"keylist": doc!{ "$elemMatch": { "$eq": &next}}})
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR.into_response())?
.map_err(|_| ForwardError::InternalServerError)?
{
Some(connection) => connection,
None => {
let response = (
StatusCode::UNAUTHORIZED,
MediationError::UncoordinatedSender.json(),
);
return Err(response.into_response());
}
None => return Err(ForwardError::UncoordinatedSender),
};

Ok(next.unwrap().to_string())
}

pub(crate) async fn handler(state: &AppState, message: Message) -> Result<Message, MediationError> {
pub(crate) async fn handler(state: Arc<AppState>, message: Message) -> Result<Option<Message>, ForwardError> {
let AppStateRepository {
message_repository,
connection_repository,
..
} = state
.repository
.as_ref()
.ok_or_else(|| MediationError::RepostitoryError)?;
.ok_or_else(|| ForwardError::InternalServerError)?;

let next = match checks(&message, connection_repository).await.ok() {
Some(next) => Ok(next),
None => Err(MediationError::RepostitoryError),
None => Err(ForwardError::InternalServerError),
};

let attachments = message.attachments.unwrap_or_default();
Expand All @@ -72,9 +61,9 @@ pub(crate) async fn handler(state: &AppState, message: Message) -> Result<Messag
recipient_did: next.as_ref().unwrap().to_owned(),
})
.await
.map_err(|_| MediationError::PersisenceError)?;
.map_err(|_| ForwardError::InternalServerError)?;
}
Ok(Message::build("".to_string(), "".to_string(), json!("")).finalize())
Ok(None)
}

#[cfg(test)]
Expand All @@ -87,6 +76,7 @@ mod test {
algorithms::AnonCryptAlg, protocols::routing::wrap_in_forward, secrets::SecretsResolver,
Message, PackEncryptedOptions, UnpackOptions,
};
use keystore::tests::MockKeyStore;
use keystore::Secrets;
use serde_json::json;
use shared::{
Expand All @@ -99,7 +89,6 @@ mod test {
};
use std::sync::Arc;
use uuid::Uuid;
use keystore::tests::MockKeyStore;

fn _initial_connections() -> Vec<Connection> {
let _recipient_did = _recipient_did();
Expand All @@ -125,14 +114,14 @@ mod test {
// simulate sender forwarding process
let mut state = tests::setup().clone();
let state = Arc::make_mut(&mut state);

let mock_connections = MockConnectionRepository::from(_initial_connections());
state.repository = Some(AppStateRepository {
connection_repository: Arc::new(mock_connections),
message_repository: Arc::new(MockMessagesRepository::from(vec![])),
keystore: Arc::new(MockKeyStore::new(vec![])),
});

let msg = Message::build(
Uuid::new_v4().to_string(),
"example/v1".to_owned(),
Expand All @@ -153,10 +142,6 @@ mod test {
)
.await
.expect("Unable pack_encrypted");
println!("Encryption metadata is\n{:?}\n", _metadata);

// --- Sending message by Alice ---
println!("Alice is sending message \n{}\n", packed_forward_msg);

let msg = wrap_in_forward(
&packed_forward_msg,
Expand All @@ -169,7 +154,6 @@ mod test {
.await
.expect("Unable wrap_in_forward");

println!(" wraped in forward\n{}\n", msg);
let (msg, _metadata) = Message::unpack(
&msg,
&state.did_resolver,
Expand All @@ -179,14 +163,7 @@ mod test {
.await
.expect("Unable unpack");

println!("Mediator1 received message is \n{:?}\n", msg);

println!(
"Mediator1 received message unpack metadata is \n{:?}\n",
_metadata
);

let msg = mediator_forward_process(state, msg).await.unwrap();
let msg = mediator_forward_process(Arc::new(state.clone()), msg).await.unwrap();

println!("Mediator1 is forwarding message \n{:?}\n", msg);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use axum::{response::IntoResponse, Json};
use hyper::StatusCode;
use thiserror::Error;

/// Represents errors that can occur during mediation.
#[derive(Debug, Error, PartialEq, Eq)]
pub enum MediationError {
#[error("No return route all decoration")]
NoReturnRouteAllDecoration,
#[error("invalid message type")]
InvalidMessageType,
#[error("uncoordinated sender")]
UncoordinatedSender,
#[error("could not parse into expected message format")]
UnexpectedMessageFormat,
}

impl IntoResponse for MediationError {
fn into_response(self) -> axum::response::Response {
let status_code = match self {
MediationError::NoReturnRouteAllDecoration | MediationError::InvalidMessageType => {
StatusCode::BAD_REQUEST
}
MediationError::UncoordinatedSender => StatusCode::UNAUTHORIZED,
MediationError::UnexpectedMessageFormat => StatusCode::BAD_REQUEST,
};

let body = Json(serde_json::json!({
"error": self.to_string(),
}));

(status_code, body).into_response()
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
mod errors;
mod jose;
mod model;

pub mod client;
pub mod web;

mod jose;
mod model;
// Re-exports
pub use errors::MediationError;
Original file line number Diff line number Diff line change
@@ -1,36 +1,13 @@
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use crate::errors::MediationError;
use didcomm::Message;
use serde_json::{json, Value};

use shared::{
constants::{MEDIATE_REQUEST_2_0, MEDIATE_REQUEST_DIC_1_0},
errors::MediationError,
};

macro_rules! run {
($expression:expr) => {
match $expression {
Ok(res) => res,

Err(err) => return Err(err),
}
};
}

pub(crate) use run;

use shared::constants::{MEDIATE_REQUEST_2_0, MEDIATE_REQUEST_DIC_1_0};
/// Validate that JWM's indicative body type is a mediation request
pub(crate) fn ensure_jwm_type_is_mediation_request(message: &Message) -> Result<(), Response> {
pub(crate) fn ensure_jwm_type_is_mediation_request(
message: &Message,
) -> Result<(), MediationError> {
if ![MEDIATE_REQUEST_2_0, MEDIATE_REQUEST_DIC_1_0].contains(&message.type_.as_str()) {
let response = (
StatusCode::BAD_REQUEST,
MediationError::InvalidMessageType.json(),
);

return Err(response.into_response());
return Err(MediationError::InvalidMessageType);
}

Ok(())
Expand All @@ -41,14 +18,9 @@ pub(crate) fn ensure_jwm_type_is_mediation_request(message: &Message) -> Result<
pub fn ensure_mediation_request_type(
mediation_request: &Value,
message_type: &str,
) -> Result<(), Response> {
) -> Result<(), MediationError> {
if mediation_request.get("type") != Some(&json!(message_type)) {
let response = (
StatusCode::BAD_REQUEST,
MediationError::InvalidMessageType.json(),
);

return Err(response.into_response());
return Err(MediationError::InvalidMessageType);
}

Ok(())
Expand All @@ -57,7 +29,7 @@ pub fn ensure_mediation_request_type(
#[cfg(test)]
mod tests {
use super::*;
use shared::{utils::tests_utils::tests::*, midlw::tests::assert_error};
use shared::utils::tests_utils::tests::*;

#[cfg(feature = "stateless")]
use crate::model::stateless::coord::{
Expand All @@ -75,8 +47,6 @@ mod tests {
"urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(),
MEDIATE_REQUEST_2_0.to_string(),
json!({
"id": "id_alice_mediation_request",
"type": MEDIATE_REQUEST_2_0,
"did": "did:key:alice_identity_pub@alice_mediator",
"services": ["inbox", "outbox"]
}),
Expand All @@ -91,8 +61,6 @@ mod tests {
"urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(),
MEDIATE_REQUEST_DIC_1_0.to_string(),
json!({
"id": "id_alice_mediation_request",
"type": MEDIATE_REQUEST_DIC_1_0,
"did": "did:key:alice_identity_pub@alice_mediator",
"services": ["inbox", "outbox"]
}),
Expand All @@ -109,8 +77,6 @@ mod tests {
"urn:uuid:8f8208ae-6e16-4275-bde8-7b7cb81ffa59".to_owned(),
"invalid-type".to_string(),
json!({
"id": "id_alice_mediation_request",
"type": MEDIATE_REQUEST_2_0,
"did": "did:key:alice_identity_pub@alice_mediator",
"services": ["inbox", "outbox"]
}),
Expand All @@ -119,12 +85,10 @@ mod tests {
.from(_edge_did())
.finalize();

assert_error(
assert_eq!(
ensure_jwm_type_is_mediation_request(&msg).unwrap_err(),
StatusCode::BAD_REQUEST,
&MediationError::InvalidMessageType.json().0,
)
.await;
MediationError::InvalidMessageType,
);
}

#[cfg(feature = "stateless")]
Expand Down
Loading

0 comments on commit c7d7ea9

Please sign in to comment.