From 74d19ecb13af605e17a8e6cc01eb0abf40fb0737 Mon Sep 17 00:00:00 2001 From: Ryan Tate Date: Thu, 19 Sep 2024 15:56:56 -0700 Subject: [PATCH] add top-level credential_types_hint to presentation definition Signed-off-by: Ryan Tate --- src/core/input_descriptor.rs | 89 ++++++----------------------- src/core/presentation_definition.rs | 70 ++++++++++++++++++++--- 2 files changed, 81 insertions(+), 78 deletions(-) diff --git a/src/core/input_descriptor.rs b/src/core/input_descriptor.rs index f68e557..e7c9670 100644 --- a/src/core/input_descriptor.rs +++ b/src/core/input_descriptor.rs @@ -272,6 +272,24 @@ impl InputDescriptor { Ok(()) } + + /// Return the humanly readable requested fields of the input descriptor. + pub fn requested_fields(&self) -> Vec { + self.constraints() + .fields() + .iter() + .flat_map(|field| field.requested_fields()) + .collect() + } + + /// Return the credential types of the input descriptor, if any. + pub fn credential_types_hint(&self) -> Vec { + self.constraints() + .fields() + .iter() + .flat_map(|field| field.credential_types_hint()) + .collect() + } } /// Constraints are objects used to describe the constraints that a [Holder](https://identity.foundation/presentation-exchange/spec/v2.0.0/#term:holder) must satisfy to fulfill an Input Descriptor. @@ -605,7 +623,7 @@ impl ConstraintsField { /// /// Multiple credentials can be returned if the input descriptor contains a pattern /// filter that matches multiple credentials. - pub fn credential_type_hint(&self) -> Vec { + pub fn credential_types_hint(&self) -> Vec { // NOTE: There may be other ways to search for a valid the credential type // that meets the input descriptor constraints. // @@ -684,72 +702,3 @@ pub enum ConstraintsLimitDisclosure { Required, Preferred, } - -#[cfg(test)] -mod tests { - use crate::core::presentation_definition::PresentationDefinition; - - use super::*; - - use anyhow::Result; - - #[test] - fn test_input_descriptor_credential_type() -> Result<()> { - let definition: PresentationDefinition = serde_json::from_str(include_str!( - "../../tests/presentation-definition/iso.org.18013.5.1.mdl.json" - ))?; - - let credentials = definition - .input_descriptors() - .iter() - .flat_map(|descriptor| descriptor.constraints().fields()) - .flat_map(|field| field.credential_type_hint()) - .collect::>(); - - assert_eq!( - credentials.first(), - Some(&"iso.org.18013.5.1.mDL".to_string()) - ); - - Ok(()) - } - - #[test] - fn test_input_descriptor_multi_credential_types_pattern() -> Result<()> { - let definition: PresentationDefinition = serde_json::from_str(include_str!( - "../../tests/presentation-definition/multi-credential-pattern.json" - ))?; - - let credentials = definition - .input_descriptors() - .iter() - .flat_map(|descriptor| descriptor.constraints().fields()) - .flat_map(|field| field.credential_type_hint()) - .collect::>(); - - assert!(credentials.contains(&"PassportCredential".into())); - assert!(credentials.contains(&"DriversLicenseCredential".into())); - assert!(credentials.contains(&"NationalIDCredential".into())); - - Ok(()) - } - - #[test] - fn test_input_descriptor_multi_credential_types_array() -> Result<()> { - let definition: PresentationDefinition = serde_json::from_str(include_str!( - "../../tests/presentation-definition/multi-credential-array.json" - ))?; - - let credentials = definition - .input_descriptors() - .iter() - .flat_map(|descriptor| descriptor.constraints().fields()) - .flat_map(|field| field.credential_type_hint()) - .collect::>(); - - assert!(credentials.contains(&"IdentityCredential".into())); - assert!(credentials.contains(&"EducationalCredential".into())); - - Ok(()) - } -} diff --git a/src/core/presentation_definition.rs b/src/core/presentation_definition.rs index 2212e70..8b8e0dd 100644 --- a/src/core/presentation_definition.rs +++ b/src/core/presentation_definition.rs @@ -190,14 +190,16 @@ impl PresentationDefinition { pub fn requested_fields(&self) -> Vec { self.input_descriptors .iter() - .flat_map(|input_descriptor| { - input_descriptor - .constraints() - .fields() - .iter() - .map(|constraint| constraint.requested_fields()) - }) - .flatten() + .flat_map(|descriptor| descriptor.requested_fields()) + .collect() + } + + /// Return the credential types requested in the presentation definition, + /// if any. + pub fn credential_types_hint(&self) -> Vec { + self.input_descriptors + .iter() + .flat_map(|descriptor| descriptor.credential_types_hint()) .collect() } @@ -371,3 +373,55 @@ pub struct SubmissionRequirementPick { pub min: Option, pub max: Option, } + +#[cfg(test)] +mod tests { + use super::*; + + use anyhow::Result; + + #[test] + fn test_input_descriptor_credential_type() -> Result<()> { + let definition: PresentationDefinition = serde_json::from_str(include_str!( + "../../tests/presentation-definition/iso.org.18013.5.1.mdl.json" + ))?; + + let credentials = definition.credential_types_hint(); + + assert_eq!( + credentials.first(), + Some(&"iso.org.18013.5.1.mDL".to_string()) + ); + + Ok(()) + } + + #[test] + fn test_input_descriptor_multi_credential_types_pattern() -> Result<()> { + let definition: PresentationDefinition = serde_json::from_str(include_str!( + "../../tests/presentation-definition/multi-credential-pattern.json" + ))?; + + let credentials = definition.credential_types_hint(); + + assert!(credentials.contains(&"PassportCredential".into())); + assert!(credentials.contains(&"DriversLicenseCredential".into())); + assert!(credentials.contains(&"NationalIDCredential".into())); + + Ok(()) + } + + #[test] + fn test_input_descriptor_multi_credential_types_array() -> Result<()> { + let definition: PresentationDefinition = serde_json::from_str(include_str!( + "../../tests/presentation-definition/multi-credential-array.json" + ))?; + + let credentials = definition.credential_types_hint(); + + assert!(credentials.contains(&"IdentityCredential".into())); + assert!(credentials.contains(&"EducationalCredential".into())); + + Ok(()) + } +}