From ba7b96fe99e32884f39afe7b5bf8232adc535349 Mon Sep 17 00:00:00 2001 From: nain-F49FF806 <126972030+nain-F49FF806@users.noreply.github.com> Date: Thu, 14 Sep 2023 01:44:18 +0200 Subject: [PATCH] Add simple client implementation Has majorly common code with mediator agent. It's in essence one hybrid, with organized code. Then again, aries agents are meant to be horizontal. Signed-off-by: nain-F49FF806 <126972030+nain-F49FF806@users.noreply.github.com> --- mediator/Cargo.lock | 1 + mediator/Cargo.toml | 4 ++ mediator/src/agent/client.rs | 88 +++++++++++++++++++++++ mediator/src/agent/mod.rs | 3 + mediator/src/routes/client.rs | 32 +++++++++ mediator/src/{routes.rs => routes/mod.rs} | 12 ++-- 6 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 mediator/src/agent/client.rs create mode 100644 mediator/src/routes/client.rs rename mediator/src/{routes.rs => routes/mod.rs} (79%) diff --git a/mediator/Cargo.lock b/mediator/Cargo.lock index 49c25e0824..ae3a26a9cd 100644 --- a/mediator/Cargo.lock +++ b/mediator/Cargo.lock @@ -2361,6 +2361,7 @@ dependencies = [ "fast_qr", "log", "messages", + "reqwest", "serde_json", "tokio", "tower-http", diff --git a/mediator/Cargo.toml b/mediator/Cargo.toml index 605cb712b4..3d4cdc26f5 100644 --- a/mediator/Cargo.toml +++ b/mediator/Cargo.toml @@ -18,8 +18,12 @@ env_logger = "0.10.0" fast_qr = { version = "0.10.2", features = ["svg"] } log = "0.4.20" messages = { version = "0.58.0", path = "../messages" } +reqwest = { version = "0.11.20", features = ["json"] } serde_json = "1.0.106" tokio = { version = "1", features = ["rt-multi-thread", "macros"] } tower-http = { version = "0.4.4", features = ["catch-panic"] } url = "2.4.1" uuid = "1.4.1" + +[dev-dependencies] +reqwest = "0.11.20" diff --git a/mediator/src/agent/client.rs b/mediator/src/agent/client.rs new file mode 100644 index 0000000000..be3f1c607e --- /dev/null +++ b/mediator/src/agent/client.rs @@ -0,0 +1,88 @@ +use std::sync::Arc; + +use aries_vcx::handlers::util::AnyInvitation; +// use aries_vcx::protocols::connection::initiation_type::Invitee; +use aries_vcx::protocols::connection::invitee::states::initial::Initial as ClientInit; +// use aries_vcx::protocols::connection::invitee::states::invited::Invited; +use aries_vcx::protocols::connection::invitee::states::requested::Requested as ClientRequestSent; +use aries_vcx::protocols::connection::invitee::InviteeConnection; + +use aries_vcx::protocols::connection::Connection; +use aries_vcx::protocols::mediated_connection::pairwise_info::PairwiseInfo; +// use aries_vcx::protocols::oob; +use aries_vcx::utils::mockdata::profile::mock_ledger::MockLedger; +use aries_vcx_core::ledger::base_ledger::IndyLedgerRead; +use aries_vcx_core::wallet::base_wallet::BaseWallet; +use aries_vcx_core::wallet::indy::IndySdkWallet; +use diddoc_legacy::aries::diddoc::AriesDidDoc; +// use diddoc_legacy::aries::service::AriesService; +use messages::msg_fields::protocols::out_of_band::invitation::Invitation as OOBInvitation; +use messages::msg_fields::protocols::out_of_band::invitation::OobService; + +use super::Agent; +use crate::utils::prelude::*; + +pub fn oob2did(oob: OOBInvitation) -> AriesDidDoc { + let mut did_doc: AriesDidDoc = AriesDidDoc::default(); + did_doc.set_id(oob.id.clone()); + let oob_service = oob.content.services.first().expect("OOB needs a service").clone(); + + match oob_service { + OobService::AriesService(service) => { + did_doc.set_service_endpoint(service.service_endpoint); + did_doc.set_recipient_keys(service.recipient_keys); + did_doc.set_routing_keys(service.routing_keys); + } + _ => panic!("Assuming fully clean AriesService variant only"), + } + did_doc +} + +// client role utilities +impl Agent { + /// Starts a new connection and tries to create request to the specified OOB invite endpoint + pub async fn client_connect_req(&self, oob_invite: OOBInvitation) -> InviteeConnection { + // let (did, vk) = self.wallet.create_and_store_my_did(None, None).await.unwrap(); + // let client_conn = + // InviteeConnection::::new_invitee("foo".into(), PairwiseInfo { pw_did: did, pw_vk: vk }); + + // fn accept_invitation( + // client_conn: InviteeConnection, + // oob_invite: OOBInvitation, + // ) -> InviteeConnection { + // let did_doc = oob2did(oob_invite.clone()); + // let state = Invited::new(did_doc, AnyInvitation::Oob(oob_invite)); + // // Convert to `InvitedState` + // Connection { + // state, + // source_id: "foo".into(), + // pairwise_info: client_conn.pairwise_info().clone(), + // initiation_type: Invitee, + // } + // } + // let client_conn = accept_invitation(client_conn, oob_invite); + // todo!() + + let (pw_did, pw_vk) = self.wallet.create_and_store_my_did(None, None).await.unwrap(); + + let mock_ledger: Arc = Arc::new(MockLedger {}); // cause we know we want call ledger *eew...* + let mut client_conn = + InviteeConnection::::new_invitee("foo".into(), PairwiseInfo { pw_did, pw_vk }) + .accept_invitation(&mock_ledger, AnyInvitation::Oob(oob_invite)) + .await + .unwrap(); + + let client_conn = client_conn + .prepare_request("http://response.http.alt".parse().unwrap(), vec![]) + .await + .unwrap(); + + let msg_connection_request = client_conn.get_request().clone(); + info!("Client Connection Request: {:#?}", msg_connection_request); + // invitee_requested + // .send_message(&self.wallet, &msg_connection_request.into(), &HttpClient) + // .await + // .unwrap(); + client_conn + } +} diff --git a/mediator/src/agent/mod.rs b/mediator/src/agent/mod.rs index 8cbd74ae83..f976b47693 100644 --- a/mediator/src/agent/mod.rs +++ b/mediator/src/agent/mod.rs @@ -10,6 +10,8 @@ use diddoc_legacy::aries::service::AriesService; use messages::msg_fields::protocols::out_of_band::invitation::Invitation as OOBInvitation; use crate::utils::Result_; +// #[cfg(test)] +pub mod client; #[derive(Debug, Clone)] pub struct Agent @@ -41,6 +43,7 @@ impl Agent { Self::new_from_wallet_config(config).await } } + // Utils impl Agent where diff --git a/mediator/src/routes/client.rs b/mediator/src/routes/client.rs new file mode 100644 index 0000000000..468a7461c0 --- /dev/null +++ b/mediator/src/routes/client.rs @@ -0,0 +1,32 @@ +use super::*; +use crate::agent::client::oob2did; +use log::info; +use messages::msg_fields::protocols::out_of_band::invitation::Invitation as OOBInvitation; + +#[debug_handler] +pub async fn connection_request( + State(agent): State>, + Json(oob_invite): Json, +) -> Json { + let state = agent.client_connect_req(oob_invite.clone()).await; + let req_msg = serde_json::to_value(state.get_request()).unwrap(); + info!( + "Sending Connection Request: {},", + serde_json::to_string_pretty(&req_msg).unwrap() + ); + let service_endpoint = oob2did(oob_invite).get_endpoint().expect("Service needs an endpoint"); + let http_client = reqwest::Client::new(); + let res = http_client + .post(service_endpoint) + .json(&req_msg) + .send() + .await + .expect("Something went wrong") + .error_for_status() + .expect("Unexpected response") + .json::() + .await + .expect("Decoding should mostly succeed"); + info!("Received response: {},", serde_json::to_string_pretty(&res).unwrap()); + Json(res) +} diff --git a/mediator/src/routes.rs b/mediator/src/routes/mod.rs similarity index 79% rename from mediator/src/routes.rs rename to mediator/src/routes/mod.rs index 5c644b7853..60845b9229 100644 --- a/mediator/src/routes.rs +++ b/mediator/src/routes/mod.rs @@ -3,14 +3,18 @@ use std::sync::Arc; use aries_vcx_core::wallet::indy::IndySdkWallet; use axum::extract::State; use axum::response::Html; -use axum::routing::get; -use axum::Router; +use axum::routing::{get, post}; +use axum::{Json, Router}; use axum_macros::debug_handler; +use serde_json::Value; use crate::agent::Agent; +type ArcAgent = Arc>; + +pub mod client; #[debug_handler] -pub async fn oob_invite_qr(State(agent): State>>) -> Html { +pub async fn oob_invite_qr(State(agent): State>) -> Html { let oob = agent.get_oob_invite().unwrap(); let oob_string = serde_json::to_string_pretty(&oob).unwrap(); let qr = fast_qr::QRBuilder::new(oob_string.clone()).build().unwrap(); @@ -34,7 +38,7 @@ pub async fn readme() -> Html { pub async fn build_router(endpoint_root: &str) -> Router { let mut agent = Agent::new_demo_agent().await.unwrap(); agent - .init_service(vec![], format!("http://{endpoint_root}").parse().unwrap()) + .init_service(vec![], format!("http://{endpoint_root}/aries").parse().unwrap()) .await .unwrap(); Router::default()