Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into 231-discover-feature-…
Browse files Browse the repository at this point in the history
…protocol
  • Loading branch information
Christiantyemele committed Nov 19, 2024
2 parents 99dacd2 + 6d512f6 commit 7f9512e
Show file tree
Hide file tree
Showing 26 changed files with 533 additions and 555 deletions.
16 changes: 12 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
[package]
name = "didcomm-mediator"
version = "0.1.0"
name = "didcomm-mediator"
version = "0.1.0"
authors = ["adorsys GmbH Co. KG"]
license = "Apache-2.0"
description = "A Rust Mediator for DIDComm messaging, supporting secure and decentralized communication."
repository = "https://github.com/adorsys/didcomm-mediator-rs"
homepage = "https://github.com/adorsys/didcomm-mediator-rs/blob/main/README.md"
documentation = "https://github.com/adorsys/didcomm-mediator-rs/tree/main/docs"
keywords = ["DIDComm", "Mediator", "DIDComm Mediator", "DIDComm Mediation", "DIDCOMM Messaging", "Decentralized Identity", "Rust Mediator"]
categories = ["cryptography", "decentralized-systems"]
edition = "2021"
description = "A mediator for DIDComm messages"
authors = ["adorsys GmbH Co. KG"]
readme = "README.md"



[workspace]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ For further understanding checkout the [docs](docs/mediator-doc.md)<br>
|[Pickup Protocol](https://didcomm.org/messagepickup/3.0/)| ADOPTED ||
|[DID Rotation](https://didcomm.org/book/v2/didrotation) | ACCEPTED ||
|[Cross-Domain Messaging/ Routing Protocol](https://identity.foundation/didcomm-messaging/spec/#routing-protocol-20) | ADOPTED ||
|[Trust Ping Ptotocol](https://identity.foundation/didcomm-messaging/spec/#trust-ping-protocol-20) | ADOPTED||
|[Trust Ping Ptotocol](https://identity.foundation/didcomm-messaging/spec/#trust-ping-protocol-20) | ADOPTED||
|[Discover Features Protocol](https://didcomm.org/discover-features/2.0/) | ADOPTED ||
|[Out of band Messaging](https://identity.foundation/didcomm-messaging/spec/#out-of-band-messages) | ADOPTED | ⚪
|[Basic Message Protocol](https://didcomm.org/basicmessage/2.0/#:~:text=The%20BasicMessage%20protocol%20describes%20a,message%20type%20used%20to%20communicate.) | ADOPTED||
|[Acks](https://github.com/hyperledger/aries-rfcs/tree/main/features/0015-acks)| ADOPTED ||
|[Present Proof Protocol](https://didcomm.org/present-proof/3.0/)| ADOPTED ||
|[Basic Message Protocol](https://didcomm.org/basicmessage/2.0/#:~:text=The%20BasicMessage%20protocol%20describes%20a,message%20type%20used%20to%20communicate.) | ADOPTED||

## Building and testing

Expand Down
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;
Loading

0 comments on commit 7f9512e

Please sign in to comment.