Skip to content

Commit

Permalink
add top-level credential_types_hint to presentation definition
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Tate <[email protected]>
  • Loading branch information
Ryanmtate committed Sep 19, 2024
1 parent 521895e commit 74d19ec
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 78 deletions.
89 changes: 19 additions & 70 deletions src/core/input_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,24 @@ impl InputDescriptor {

Ok(())
}

/// Return the humanly readable requested fields of the input descriptor.
pub fn requested_fields(&self) -> Vec<String> {
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<CredentialType> {
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.
Expand Down Expand Up @@ -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<CredentialType> {
pub fn credential_types_hint(&self) -> Vec<CredentialType> {
// NOTE: There may be other ways to search for a valid the credential type
// that meets the input descriptor constraints.
//
Expand Down Expand Up @@ -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::<Vec<CredentialType>>();

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::<Vec<CredentialType>>();

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::<Vec<CredentialType>>();

assert!(credentials.contains(&"IdentityCredential".into()));
assert!(credentials.contains(&"EducationalCredential".into()));

Ok(())
}
}
70 changes: 62 additions & 8 deletions src/core/presentation_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,16 @@ impl PresentationDefinition {
pub fn requested_fields(&self) -> Vec<String> {
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<CredentialType> {
self.input_descriptors
.iter()
.flat_map(|descriptor| descriptor.credential_types_hint())
.collect()
}

Expand Down Expand Up @@ -371,3 +373,55 @@ pub struct SubmissionRequirementPick {
pub min: Option<usize>,
pub max: Option<usize>,
}

#[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(())
}
}

0 comments on commit 74d19ec

Please sign in to comment.