Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/msg builders #972

Merged
merged 31 commits into from
Sep 13, 2023
Merged
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
99b41de
Added builders for decorators and ack messages
bobozaur Sep 5, 2023
96577c0
Added remaining message builders
bobozaur Sep 6, 2023
ca08b33
Modified Connection Invitation to use uniform decorators
bobozaur Sep 6, 2023
f01142d
Added MsgPartsBuilder
bobozaur Sep 6, 2023
c62c51a
Used builders within aries-vcx
bobozaur Sep 7, 2023
62917e1
Replaced constructor methods with builders in aries-vcx and libvcx-core
bobozaur Sep 8, 2023
938831d
Fixed napi-rs msg building
bobozaur Sep 8, 2023
39f71a2
Formatting fix
bobozaur Sep 8, 2023
84a1c00
Messages tests fixes
bobozaur Sep 8, 2023
bfe1e97
Used did_parser::Did in PwDidInvitation
bobozaur Sep 8, 2023
2421c0e
Fixed InvitationContent serde impl
bobozaur Sep 11, 2023
692f264
Removed some awkward inner structs builders
bobozaur Sep 12, 2023
be0366f
Adjusted attachment decorator tests
bobozaur Sep 12, 2023
d12cd25
Adjusted localization decorators tests
bobozaur Sep 12, 2023
144f996
Adjusted thread decorator tests
bobozaur Sep 12, 2023
4f735fb
Adjusted timing decorator tests
bobozaur Sep 12, 2023
07d0405
Adjusted connection protocol messages tests
bobozaur Sep 12, 2023
ae763b2
Adjusted credential issuance protocol messages tests
bobozaur Sep 12, 2023
33fdefe
Adjusted discover features protocol messages tests
bobozaur Sep 12, 2023
092d44f
Adjusted notification protocol messages tests
bobozaur Sep 12, 2023
513b09f
Adjusted OOB protocol messages tests
bobozaur Sep 12, 2023
f081d4a
Adjusted present proof protocol messages tests
bobozaur Sep 12, 2023
aaaa1a2
Adjusted revocation protocol messages tests
bobozaur Sep 12, 2023
06e4cc1
Adjusted trust ping protocol messages tests
bobozaur Sep 12, 2023
63ffb4f
Adjusted basic message protocol messages tests
bobozaur Sep 12, 2023
2bab9f4
Adjusted report problem protocol messages tests
bobozaur Sep 12, 2023
30228e0
Ran cargo fmt
bobozaur Sep 12, 2023
529f4f7
Post rebase fixes
bobozaur Sep 12, 2023
b3ddc87
Fix msg_type regressions
bobozaur Sep 12, 2023
5b1637c
Fix credential thread building
bobozaur Sep 12, 2023
66eaf07
Added extraction of thread_id from Thread
bobozaur Sep 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added MsgPartsBuilder
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
bobozaur committed Sep 12, 2023
commit f01142d2375d09c4d5616ed2f6afdfd65e3e7b52
40 changes: 25 additions & 15 deletions aries_vcx/src/common/ledger/transactions.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bs58;
use diddoc_legacy::aries::diddoc::AriesDidDoc;
use diddoc_legacy::aries::service::AriesService;
use messages::msg_fields::protocols::connection::invitation::Invitation;
use messages::msg_fields::protocols::connection::invitation::{Invitation, InvitationContent};
use messages::msg_fields::protocols::out_of_band::invitation::OobService;
use std::{collections::HashMap, sync::Arc};

@@ -93,25 +93,35 @@ pub async fn add_new_did(
pub async fn into_did_doc(indy_ledger: &Arc<dyn IndyLedgerRead>, invitation: &AnyInvitation) -> VcxResult<AriesDidDoc> {
let mut did_doc: AriesDidDoc = AriesDidDoc::default();
let (service_endpoint, recipient_keys, routing_keys) = match invitation {
AnyInvitation::Con(Invitation::Public(invitation)) => {
did_doc.set_id(invitation.content.did.to_string());
let service = get_service(indy_ledger, &invitation.content.did)
.await
.unwrap_or_else(|err| {
error!("Failed to obtain service definition from the ledger: {}", err);
AriesService::default()
});
AnyInvitation::Con(Invitation {
id,
content: InvitationContent::Public(content),
decorators,
}) => {
did_doc.set_id(content.did.to_string());
let service = get_service(indy_ledger, &content.did).await.unwrap_or_else(|err| {
error!("Failed to obtain service definition from the ledger: {}", err);
AriesService::default()
});
(service.service_endpoint, service.recipient_keys, service.routing_keys)
}
AnyInvitation::Con(Invitation::Pairwise(invitation)) => {
did_doc.set_id(invitation.id.clone());
AnyInvitation::Con(Invitation {
id,
content: InvitationContent::Pairwise(content),
decorators,
}) => {
did_doc.set_id(id.clone());
(
invitation.content.service_endpoint.clone(),
invitation.content.recipient_keys.clone(),
invitation.content.routing_keys.clone(),
content.service_endpoint.clone(),
content.recipient_keys.clone(),
content.routing_keys.clone(),
)
}
AnyInvitation::Con(Invitation::PairwiseDID(_)) => {
AnyInvitation::Con(Invitation {
id,
content: InvitationContent::PairwiseDID(content),
decorators,
}) => {
return Err(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidDid,
format!("PairwiseDID invitation not supported yet!"),
33 changes: 18 additions & 15 deletions aries_vcx/src/handlers/connection/mediated_connection.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ use futures::future::BoxFuture;
use futures::stream::StreamExt;
use messages::decorators::timing::Timing;
use messages::msg_fields::protocols::basic_message::{BasicMessage, BasicMessageContent, BasicMessageDecorators};
use messages::msg_fields::protocols::connection::invitation::Invitation;
use messages::msg_fields::protocols::connection::invitation::InvitationContent;
use messages::msg_fields::protocols::connection::request::Request;
use messages::msg_fields::protocols::connection::Connection;
use messages::msg_fields::protocols::discover_features::disclose::Disclose;
@@ -614,14 +614,16 @@ impl MediatedConnection {
SmConnection::Invitee(sm_invitee) => {
let (sm_invitee, can_autohop) = match message {
Some(message) => match message {
AriesMessage::Connection(Connection::Invitation(Invitation::Public(invitation))) => (
sm_invitee.handle_invitation(AnyInvitation::Con(Invitation::Public(invitation)))?,
false,
),
AriesMessage::Connection(Connection::Invitation(Invitation::Pairwise(invitation))) => (
sm_invitee.handle_invitation(AnyInvitation::Con(Invitation::Pairwise(invitation)))?,
false,
),
AriesMessage::Connection(Connection::Invitation(invitation))
if matches!(invitation.content, InvitationContent::Public(_)) =>
{
(sm_invitee.handle_invitation(AnyInvitation::Con(invitation))?, false)
}
AriesMessage::Connection(Connection::Invitation(invitation))
if matches!(invitation.content, InvitationContent::Pairwise(_)) =>
{
(sm_invitee.handle_invitation(AnyInvitation::Con(invitation))?, false)
}
AriesMessage::Connection(Connection::Response(response)) => {
let send_message = self.send_message_closure_connection(Arc::clone(wallet));
(
@@ -807,13 +809,14 @@ impl MediatedConnection {
Err(_) => {
let now = Utc::now();

let content = BasicMessageContent::new(message.to_owned(), now);

let mut decorators = BasicMessageDecorators::default();
let mut timing = Timing::default();
timing.out_time = Some(now);
let content = BasicMessageContent::builder()
.content(message.to_owned())
.sent_time(now)
.build();

decorators.timing = Some(timing);
let decorators = BasicMessageDecorators::builder()
.timing(Timing::builder().out_time(now).build())
.build();

BasicMessage::with_decorators(Uuid::new_v4().to_string(), content, decorators).into()
}
11 changes: 5 additions & 6 deletions aries_vcx/src/handlers/discovery/mod.rs
Original file line number Diff line number Diff line change
@@ -21,8 +21,7 @@ pub async fn send_discovery_query(
pw_vk: &str,
) -> VcxResult<()> {
let query = query.unwrap_or("*".to_owned());
let mut content = QueryContent::new(query);
content.comment = comment;
let content = QueryContent::builder().query(query).comment(comment).build();

let mut decorators = QueryDecorators::default();
let mut timing = Timing::default();
@@ -43,10 +42,10 @@ pub async fn respond_discovery_query(
) -> VcxResult<()> {
let content = DiscloseContent::default();

let mut decorators = DiscloseDecorators::new(Thread::builder().thid(query.id).build());
let mut timing = Timing::default();
timing.out_time = Some(Utc::now());
decorators.timing = Some(timing);
let decorators = DiscloseDecorators::builder()
.thread(Thread::builder().thid(query.id).build())
.timing(Timing::builder().out_time(Utc::now()).build())
.build();

let disclose = Disclose::with_decorators(Uuid::new_v4().to_string(), content, decorators);

14 changes: 8 additions & 6 deletions aries_vcx/src/handlers/issuance/holder.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ use messages::msg_fields::protocols::cred_issuance::offer_credential::OfferCrede
use messages::msg_fields::protocols::cred_issuance::propose_credential::ProposeCredential;
use messages::msg_fields::protocols::cred_issuance::request_credential::RequestCredential;
use messages::msg_fields::protocols::cred_issuance::CredentialIssuance;
use messages::msg_fields::protocols::notification::ack::{AckDecorators, AckStatus};
use messages::msg_fields::protocols::notification::ack::{AckContent, AckDecorators, AckStatus};
use messages::msg_fields::protocols::report_problem::ProblemReport;
use messages::msg_fields::protocols::revocation::revoke::Revoke;
use messages::AriesMessage;
@@ -25,11 +25,13 @@ use crate::handlers::revocation_notification::receiver::RevocationNotificationRe
use crate::protocols::issuance::holder::state_machine::{HolderFullState, HolderSM, HolderState};

fn build_credential_ack(thread_id: &str) -> AckCredential {
let content = AckCredentialContent::new(AckStatus::Ok);
let mut decorators = AckDecorators::new(Thread::builder().thid(thread_id.to_owned()).build());
let mut timing = Timing::default();
timing.out_time = Some(Utc::now());
decorators.timing = Some(timing);
let content = AckCredentialContent::builder()
.inner(AckContent::builder().status(AckStatus::Ok).build())
.build();
let decorators = AckDecorators::builder()
.thread(Thread::builder().thid(thread_id.to_owned()).build())
.timing(Timing::builder().out_time(Utc::now()).build())
.build();

AckCredential::with_decorators(Uuid::new_v4().to_string(), content, decorators)
}
78 changes: 42 additions & 36 deletions aries_vcx/src/handlers/issuance/issuer.rs
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ fn _build_credential_preview(credential_json: &str) -> VcxResult<CredentialPrevi
})?;

// todo: should throw err if cred_values is not serde_json::Value::Array or serde_json::Value::Object
let mut credential_preview = CredentialPreview::new(Vec::new());
let mut attributes = Vec::new();

match cred_values {
serde_json::Value::Array(cred_values) => {
@@ -60,48 +60,54 @@ fn _build_credential_preview(credential_json: &str) -> VcxResult<CredentialPrevi
format!("No 'value' field in cred_value: {:?}", cred_value),
))?;

let mut attr = CredentialAttr::new(
key.as_str()
.ok_or(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidOption,
"Credential value names are currently only allowed to be strings",
))?
.to_owned(),
value
.as_str()
.ok_or(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidOption,
"Credential values are currently only allowed to be strings",
))?
.to_owned(),
);

attr.mime_type = Some(MimeType::Plain);
credential_preview.attributes.push(attr);
let name = key
.as_str()
.ok_or(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidOption,
"Credential value names are currently only allowed to be strings",
))?
.to_owned();

let value = value
.as_str()
.ok_or(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidOption,
"Credential values are currently only allowed to be strings",
))?
.to_owned();

let attr = CredentialAttr::builder()
.name(name)
.value(value)
.mime_type(MimeType::Plain)
.build();

attributes.push(attr);
}
}
serde_json::Value::Object(values_map) => {
for item in values_map.iter() {
let (key, value) = item;

let mut attr = CredentialAttr::new(
key.to_owned(),
value
.as_str()
.ok_or(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidOption,
"Credential values are currently only allowed to be strings",
))?
.to_owned(),
);

attr.mime_type = Some(MimeType::Plain);
credential_preview.attributes.push(attr);
let value = value
.as_str()
.ok_or(AriesVcxError::from_msg(
AriesVcxErrorKind::InvalidOption,
"Credential values are currently only allowed to be strings",
))?
.to_owned();
let attr = CredentialAttr::builder()
.name(key.to_owned())
.value(value)
.mime_type(MimeType::Plain)
.build();

attributes.push(attr);
}
}
_ => {}
};
Ok(credential_preview)

Ok(CredentialPreview::builder().attributes(attributes).build())
}

impl Issuer {
@@ -284,7 +290,7 @@ impl Issuer {
content,
decorators,
} = report;
let report = ProblemReport::with_decorators(id, content.0, decorators);
let report = ProblemReport::with_decorators(id, content.inner, decorators);
self.issuer_sm.clone().receive_problem_report(report)?
}
AriesMessage::CredentialIssuance(CredentialIssuance::ProblemReport(report)) => {
@@ -293,7 +299,7 @@ impl Issuer {
content,
decorators,
} = report;
let report = ProblemReport::with_decorators(id, content.0, decorators);
let report = ProblemReport::with_decorators(id, content.inner, decorators);
self.issuer_sm.clone().receive_problem_report(report)?
}
_ => self.issuer_sm.clone(),
2 changes: 1 addition & 1 deletion aries_vcx/src/handlers/out_of_band/sender.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ pub struct OutOfBandSender {
impl OutOfBandSender {
pub fn create() -> Self {
let id = Uuid::new_v4().to_string();
let content = InvitationContent::new(Vec::new());
let content = InvitationContent::builder().services(Vec::new()).build();
let decorators = InvitationDecorators::default();

Self {
8 changes: 5 additions & 3 deletions aries_vcx/src/handlers/proof_presentation/prover.rs
Original file line number Diff line number Diff line change
@@ -179,7 +179,7 @@ impl Prover {
content,
decorators,
} = report;
let report = ProblemReport::with_decorators(id, content.0, decorators);
let report = ProblemReport::with_decorators(id, content.inner, decorators);
self.prover_sm.clone().receive_presentation_reject(report)?
}
AriesMessage::PresentProof(PresentProof::ProblemReport(report)) => {
@@ -188,7 +188,7 @@ impl Prover {
content,
decorators,
} = report;
let report = ProblemReport::with_decorators(id, content.0, decorators);
let report = ProblemReport::with_decorators(id, content.inner, decorators);
self.prover_sm.clone().receive_presentation_reject(report)?
}
_ => self.prover_sm.clone(),
@@ -229,7 +229,9 @@ impl Prover {
})?;
let thread_id = self.prover_sm.get_thread_id()?;
let id = Uuid::new_v4().to_string();
let content = ProposePresentationContent::new(presentation_preview);
let content = ProposePresentationContent::builder()
.presentation_proposal(presentation_preview)
.build();
let mut decorators = ProposePresentationDecorators::default();
let thread = Thread::builder().thid(thread_id.to_owned()).build();
let mut timing = Timing::default();
6 changes: 5 additions & 1 deletion messages/src/misc/mod.rs
Original file line number Diff line number Diff line change
@@ -84,7 +84,11 @@ pub mod test_utils {
obj.insert("@id".to_owned(), json!(id));
obj.insert("@type".to_owned(), json!(msg_type));

let msg = MsgParts::with_decorators(id, content, decorators);
let msg = MsgParts::<T, U>::builder()
.id(id)
.content(content)
.decorators(decorators)
.build();
let msg = AriesMessage::from(msg);

test_serde(msg, expected);
2 changes: 1 addition & 1 deletion messages/src/msg_fields/protocols/connection/mod.rs
Original file line number Diff line number Diff line change
@@ -88,4 +88,4 @@ transit_to_aries_msg!(ProblemReportContent: ProblemReportDecorators, Connection)
into_msg_with_type!(Invitation, ConnectionTypeV1_0, Invitation);
into_msg_with_type!(Request, ConnectionTypeV1_0, Request);
into_msg_with_type!(Response, ConnectionTypeV1_0, Response);
into_msg_with_type!(ProblemReport, ConnectionTypeV1_0, ProblemReport);
into_msg_with_type!(ProblemReport, ConnectionTypeV1_0, ProblemReport);
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ pub type Query = MsgParts<QueryContent, QueryDecorators>;
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, TypedBuilder)]
pub struct QueryContent {
pub query: String,
#[builder(default, setter(strip_option))]
#[builder(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
}
141 changes: 136 additions & 5 deletions messages/src/msg_parts.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::marker::PhantomData;

use serde::{Deserialize, Serialize};

// Bind `shared_vcx::misc::serde_ignored::SerdeIgnored` type as `NoDecorators`.
@@ -27,19 +29,148 @@ pub struct MsgParts<C, D = NoDecorators> {
pub decorators: D,
}

impl<C> MsgParts<C> {
pub fn new(id: String, content: C) -> Self {
impl<C, D> MsgParts<C, D> {
/// Create a builder for building `MsgParts`.
/// On the builder, call `.id(...)`, `.content(...)`, `.decorators(...)` to set the values of the fields.
/// Finally, call `.build()` to create the instance of `MsgParts`.
pub fn builder() -> MsgPartsBuilder<C, D, ((), (), ())> {
MsgPartsBuilder {
fields: ((), (), ()),
phantom: PhantomData,
}
}
}

#[must_use]
#[doc(hidden)]
/// A builder not unlike the ones derived through [`typed_builder::TypedBuilder`], with the caveat
/// that this one supports the decorators not being set, in which case it resorts to [`NoDecorators`].
pub struct MsgPartsBuilder<C, D = NoDecorators, TypedBuilderFields = ((), (), ())> {
fields: TypedBuilderFields,
phantom: PhantomData<(C, D)>,
}

impl<C, D, TypedBuilderFields> Clone for MsgPartsBuilder<C, D, TypedBuilderFields>
where
TypedBuilderFields: Clone,
{
fn clone(&self) -> Self {
Self {
fields: self.fields.clone(),
phantom: PhantomData,
}
}
}

#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C, D, __content, __decorators> MsgPartsBuilder<C, D, ((), __content, __decorators)> {
pub fn id(self, id: String) -> MsgPartsBuilder<C, D, ((String,), __content, __decorators)> {
let id = (id,);
let ((), content, decorators) = self.fields;
MsgPartsBuilder {
fields: (id, content, decorators),
phantom: self.phantom,
}
}
}

#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C, D, __id, __decorators> MsgPartsBuilder<C, D, (__id, (), __decorators)> {
pub fn content(self, content: C) -> MsgPartsBuilder<C, D, (__id, (C,), __decorators)> {
let content = (content,);
let (id, (), decorators) = self.fields;

MsgPartsBuilder {
fields: (id, content, decorators),
phantom: self.phantom,
}
}
}

#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C, D, __id, __content> MsgPartsBuilder<C, D, (__id, __content, ())> {
pub fn decorators<D2>(self, decorators: D2) -> MsgPartsBuilder<C, D2, (__id, __content, (D2,))> {
let decorators = (decorators,);
let (id, content, _) = self.fields;
MsgPartsBuilder {
fields: (id, content, decorators),
phantom: PhantomData,
}
}
}

#[doc(hidden)]
#[allow(dead_code, non_camel_case_types, non_snake_case)]
pub enum MsgPartsBuilderInvalid {}

#[doc(hidden)]
#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C, D, __content, __decorators> MsgPartsBuilder<C, D, ((String,), __content, __decorators)> {
#[deprecated(note = "Repeated field id")]
pub fn id(self, _: MsgPartsBuilderInvalid) -> MsgPartsBuilder<C, D, ((String,), __content, __decorators)> {
self
}
}

#[doc(hidden)]
#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C, D, __id, __decorators> MsgPartsBuilder<C, D, (__id, (C,), __decorators)> {
#[deprecated(note = "Repeated field content")]
pub fn content(self, _: MsgPartsBuilderInvalid) -> MsgPartsBuilder<C, D, (__id, (C,), __decorators)> {
self
}
}

#[doc(hidden)]
#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C, D, __id, __content> MsgPartsBuilder<C, D, (__id, __content, (D,))> {
#[deprecated(note = "Repeated field decorators")]
pub fn decorators(self, _: MsgPartsBuilderInvalid) -> MsgPartsBuilder<C, D, (__id, __content, (D,))> {
self
}
}

#[doc(hidden)]
#[allow(dead_code, non_camel_case_types, missing_docs, clippy::panic)]
impl<C, D, __content, __decorators> MsgPartsBuilder<C, D, ((), __content, __decorators)> {
#[deprecated(note = "Missing required field id")]
pub fn build(self, _: MsgPartsBuilderInvalid) -> ! {
panic!()
}
}

#[doc(hidden)]
#[allow(dead_code, non_camel_case_types, missing_docs, clippy::panic)]
impl<C, D, __decorators> MsgPartsBuilder<C, D, ((String,), (), __decorators)> {
#[deprecated(note = "Missing required field content")]
pub fn build(self, _: MsgPartsBuilderInvalid) -> ! {
panic!()
}
}

#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C> MsgPartsBuilder<C, NoDecorators, ((String,), (C,), ())> {
pub fn build(self) -> MsgParts<C> {
let (id, content, _) = self.fields;
let id = id.0;
let content = content.0;

MsgParts {
id,
content,
decorators: NoDecorators,
}
}
}
#[allow(dead_code, non_camel_case_types, missing_docs)]
impl<C, D> MsgPartsBuilder<C, D, ((String,), (C,), (D,))> {
pub fn build(self) -> MsgParts<C, D> {
let (id, content, decorators) = self.fields;
let id = id.0;
let content = content.0;
let decorators = decorators.0;

impl<C, D> MsgParts<C, D> {
pub fn with_decorators(id: String, content: C, decorators: D) -> Self {
Self {
MsgParts {
id,
content,
decorators,