Skip to content

Commit

Permalink
parse the credential type from an input descriptor constraint field
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Tate <[email protected]>
  • Loading branch information
Ryanmtate committed Sep 2, 2024
1 parent 51d5f6e commit 027f6ed
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 56 deletions.
6 changes: 6 additions & 0 deletions src/core/credential_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ impl From<ClaimFormatDesignation> for String {
}
}

impl std::fmt::Display for ClaimFormatDesignation {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", String::from(self.clone()))
}
}

/// Credential types that may be requested in a credential request.
///
/// Credential types can be presented in a number of formats.
Expand Down
123 changes: 67 additions & 56 deletions src/core/input_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,62 +148,6 @@ impl InputDescriptor {
self.format.as_ref().map(|f| f.keys().collect())
}

/// Return the credential format(s) of the input descriptor, if it can be determined
/// from the format field of the input descriptor constraints fields.
pub fn credential_type(&self) -> Option<Vec<CredentialType>> {
self.constraints.fields.as_ref().map(|fields| {
fields
.iter()
.filter(|field| {
// Check if field path contains "type"
field
.path
.as_ref()
.iter()
// Check if any of the paths contain a reference to type.
// NOTE: I am not sure if this is normative to add a `type` field to the path
// for a verifiable credential.
.any(|path| path.contains(&"type".to_string()))
})
.filter_map(|field| {
// Check the filter field to determine what the `const`.
// Use this to determine what the credential type is.
if let Some(credential) = field
.filter
.as_ref()
.map(|filter| {
filter
.get("const")
.and_then(Value::as_str)
.map(CredentialType::from)
})
.flatten()
{
return Some(credential);
}

// The `type` field may be an array with a nested const value.
if let Some(credential) = field
.filter
.as_ref()
.map(|filter| {
filter
.get("contains")
.and_then(|value| value.get("const"))
.and_then(Value::as_str)
.map(CredentialType::from)
})
.flatten()
{
return Some(credential);
}

None
})
.collect()
})
}

/// Set the group of the constraints field.
pub fn set_group(mut self, group: Vec<GroupId>) -> Self {
self.group = Some(group);
Expand Down Expand Up @@ -386,6 +330,16 @@ impl Constraints {
.map(|fields| fields.iter().any(|field| field.is_required()))
.unwrap_or(false)
}

/// Intent to retain.
///
/// Returns whether any of the contraint fields have an intent
/// to retain the data by the verifier.
pub fn intend_to_retain(&self) -> bool {
self.fields()
.map(|fields| fields.iter().any(|field| field.intent_to_retain()))
.unwrap_or(false)
}
}

/// ConstraintsField objects are used to describe the constraints that a
Expand Down Expand Up @@ -657,6 +611,63 @@ impl ConstraintsField {
})
.collect()
}

/// Return the Credential Type of the constraints field
pub fn credential_type(&self) -> Option<CredentialType> {
// NOTE: There may be other ways to search for a valid the credential type
// that meets the input descriptor constraints.
//
// A more exhaustive search may require parsing each credential to
// check if it contains a certain field, e.g. `firstName`, `familyName`, etc.,
// and see if it will satisfy the constraints.
//
// For now, we explicity check the type of the credential if it is present
// in the credential `type` field.

if self
.path
.as_ref()
.iter()
// Check if any of the paths contain a reference to type.
// NOTE: I am not sure if this is normative to add a `type` field to the path
// for a verifiable credential.
.any(|path| path.contains(&"type".to_string()))
{
// Check the filter field to determine the `const`
// value for the credential type, e.g. `iso.org.18013.5.1.mDL`, etc.
if let Some(credential) = self
.filter
.as_ref()
.map(|filter| {
filter
.get("const")
.and_then(Value::as_str)
.map(CredentialType::from)
})
.flatten()
{
return Some(credential);
}

// The `type` field may be an array with a nested const value.
if let Some(credential) = self
.filter
.as_ref()
.map(|filter| {
filter
.get("contains")
.and_then(|value| value.get("const"))
.and_then(Value::as_str)
.map(CredentialType::from)
})
.flatten()
{
return Some(credential);
}
}

None
}
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
Expand Down

0 comments on commit 027f6ed

Please sign in to comment.