Skip to content

Commit

Permalink
Add StatusTracker to the IdentityAssertion entry points
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe committed Feb 26, 2025
1 parent 16b2a31 commit 6a4a7cc
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 25 deletions.
37 changes: 27 additions & 10 deletions cawg_identity/src/identity_assertion/assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::{
};

use c2pa::{Manifest, Reader};
use c2pa_status_tracker::StatusTracker;
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;

Expand Down Expand Up @@ -63,9 +64,10 @@ impl IdentityAssertion {
/// Iterator returns a [`Result`] because each assertion may fail to parse.
///
/// Aside from CBOR parsing, no further validation is performed.
pub fn from_manifest(
manifest: &Manifest,
) -> impl Iterator<Item = Result<Self, c2pa::Error>> + use<'_> {
pub fn from_manifest<'a>(
manifest: &'a Manifest,
_status_tracker: &'a mut StatusTracker,
) -> impl Iterator<Item = Result<Self, c2pa::Error>> + use<'a> {
manifest
.assertions()
.iter()
Expand All @@ -83,25 +85,28 @@ impl IdentityAssertion {
pub async fn to_summary<SV: SignatureVerifier>(
&self,
manifest: &Manifest,
status_tracker: &mut StatusTracker,
verifier: &SV,
) -> impl Serialize
where
<SV as SignatureVerifier>::Output: 'static,
{
self.to_summary_impl(manifest, verifier).await
self.to_summary_impl(manifest, status_tracker, verifier)
.await
}

pub(crate) async fn to_summary_impl<SV: SignatureVerifier>(
&self,
manifest: &Manifest,
status_tracker: &mut StatusTracker,
verifier: &SV,
) -> IdentityAssertionReport<
<<SV as SignatureVerifier>::Output as ToCredentialSummary>::CredentialSummary,
>
where
<SV as SignatureVerifier>::Output: 'static,
{
match self.validate(manifest, verifier).await {
match self.validate(manifest, status_tracker, verifier).await {
Ok(named_actor) => {
let summary = named_actor.to_summary();

Expand All @@ -120,13 +125,15 @@ impl IdentityAssertion {
/// Summarize all of the identity assertions found for a [`Manifest`].
pub async fn summarize_all<SV: SignatureVerifier>(
manifest: &Manifest,
status_tracker: &mut StatusTracker,
verifier: &SV,
) -> impl Serialize {
Self::summarize_all_impl(manifest, verifier).await
Self::summarize_all_impl(manifest, status_tracker, verifier).await
}

pub(crate) async fn summarize_all_impl<SV: SignatureVerifier>(
manifest: &Manifest,
status_tracker: &mut StatusTracker,
verifier: &SV,
) -> IdentityAssertionsForManifest<
<<SV as SignatureVerifier>::Output as ToCredentialSummary>::CredentialSummary,
Expand All @@ -139,9 +146,16 @@ impl IdentityAssertion {
>,
> = vec![];

for assertion in Self::from_manifest(manifest) {
let assertion_results: Vec<Result<IdentityAssertion, c2pa::Error>> =
Self::from_manifest(manifest, status_tracker).collect();

for assertion in assertion_results {
let report = match assertion {
Ok(assertion) => assertion.to_summary_impl(manifest, verifier).await,
Ok(assertion) => {
assertion
.to_summary_impl(manifest, status_tracker, verifier)
.await
}
Err(_) => {
todo!("Handle assertion failed to parse case");
}
Expand All @@ -163,6 +177,7 @@ impl IdentityAssertion {
#[cfg(feature = "v1_api")]
pub async fn summarize_manifest_store<SV: SignatureVerifier>(
store: &c2pa::ManifestStore,
status_tracker: &mut StatusTracker,
verifier: &SV,
) -> impl Serialize {
// NOTE: We can't write this using .map(...).collect() because there are async
Expand All @@ -175,7 +190,7 @@ impl IdentityAssertion {
> = BTreeMap::new();

for (id, manifest) in store.manifests() {
let report = Self::summarize_all_impl(manifest, verifier).await;
let report = Self::summarize_all_impl(manifest, status_tracker, verifier).await;
reports.insert(id.clone(), report);
}

Expand All @@ -189,6 +204,7 @@ impl IdentityAssertion {
/// Summarize all of the identity assertions found for a [`Reader`].
pub async fn summarize_from_reader<SV: SignatureVerifier>(
reader: &Reader,
status_tracker: &mut StatusTracker,
verifier: &SV,
) -> impl Serialize {
// NOTE: We can't write this using .map(...).collect() because there are async
Expand All @@ -201,7 +217,7 @@ impl IdentityAssertion {
> = BTreeMap::new();

for (id, manifest) in reader.manifests() {
let report = Self::summarize_all_impl(manifest, verifier).await;
let report = Self::summarize_all_impl(manifest, status_tracker, verifier).await;
reports.insert(id.clone(), report);
}

Expand All @@ -222,6 +238,7 @@ impl IdentityAssertion {
pub async fn validate<SV: SignatureVerifier>(
&self,
manifest: &Manifest,
_status_tracker: &mut StatusTracker,
verifier: &SV,
) -> Result<SV::Output, ValidationError<SV::Error>> {
self.check_padding()?;
Expand Down
17 changes: 9 additions & 8 deletions cawg_identity/src/tests/builder/simple_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use std::io::{Cursor, Seek};

use c2pa::{Builder, Reader, SigningAlg};
use c2pa_status_tracker::StatusTracker;
use serde_json::json;
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
use wasm_bindgen_test::wasm_bindgen_test;
Expand Down Expand Up @@ -70,17 +71,17 @@ async fn simple_case() {
assert_eq!(manifest_store.validation_status(), None);

let manifest = manifest_store.active_manifest().unwrap();
let mut ia_iter = IdentityAssertion::from_manifest(manifest);
let mut st = StatusTracker::default();
let mut ia_iter = IdentityAssertion::from_manifest(manifest, &mut st);

// Should find exactly one identity assertion.
let ia = ia_iter.next().unwrap().unwrap();
dbg!(&ia);

assert!(ia_iter.next().is_none());
drop(ia_iter);

// And that identity assertion should be valid for this manifest.
let nsv = NaiveSignatureVerifier {};
let naive_credential = ia.validate(manifest, &nsv).await.unwrap();
let naive_credential = ia.validate(manifest, &mut st, &nsv).await.unwrap();

let nc_summary = naive_credential.to_summary();
let nc_json = serde_json::to_string(&nc_summary).unwrap();
Expand Down Expand Up @@ -125,17 +126,17 @@ async fn simple_case_async() {
assert_eq!(manifest_store.validation_status(), None);

let manifest = manifest_store.active_manifest().unwrap();
let mut ia_iter = IdentityAssertion::from_manifest(manifest);
let mut st = StatusTracker::default();
let mut ia_iter = IdentityAssertion::from_manifest(manifest, &mut st);

// Should find exactly one identity assertion.
let ia = ia_iter.next().unwrap().unwrap();
dbg!(&ia);

assert!(ia_iter.next().is_none());
drop(ia_iter);

// And that identity assertion should be valid for this manifest.
let nsv = NaiveSignatureVerifier {};
let naive_credential = ia.validate(manifest, &nsv).await.unwrap();
let naive_credential = ia.validate(manifest, &mut st, &nsv).await.unwrap();

let nc_summary = naive_credential.to_summary();
let nc_json = serde_json::to_string(&nc_summary).unwrap();
Expand Down
16 changes: 11 additions & 5 deletions cawg_identity/src/tests/claim_aggregation/interop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use std::{io::Cursor, str::FromStr};

use c2pa::{HashedUri, Reader};
use c2pa_status_tracker::StatusTracker;
use chrono::{DateTime, FixedOffset};
use iref::UriBuf;
use non_empty_string::NonEmptyString;
Expand Down Expand Up @@ -41,15 +42,17 @@ async fn adobe_connected_identities() {
assert_eq!(reader.validation_status(), None);

let manifest = reader.active_manifest().unwrap();
let mut ia_iter = IdentityAssertion::from_manifest(manifest);
let mut st = StatusTracker::default();
let mut ia_iter = IdentityAssertion::from_manifest(manifest, &mut st);

// Should find exactly one identity assertion.
let ia = ia_iter.next().unwrap().unwrap();
assert!(ia_iter.next().is_none());
drop(ia_iter);

// And that identity assertion should be valid for this manifest.
let isv = IcaSignatureVerifier {};
let ica = ia.validate(manifest, &isv).await.unwrap();
let ica = ia.validate(manifest, &mut st, &isv).await.unwrap();

// There should be exactly one verified identity.
let ica_vc = ica.credential_subjects.first();
Expand Down Expand Up @@ -87,7 +90,8 @@ async fn adobe_connected_identities() {
);

// Check the summary report for the entire manifest store.
let ia_summary = IdentityAssertion::summarize_from_reader(&reader, &isv).await;
let mut st = StatusTracker::default();
let ia_summary = IdentityAssertion::summarize_from_reader(&reader, &mut st, &isv).await;
let ia_json = serde_json::to_string(&ia_summary).unwrap();

assert_eq!(
Expand All @@ -96,7 +100,8 @@ async fn adobe_connected_identities() {
);

// Check the summary report for this manifest.
let ia_summary = IdentityAssertion::summarize_all(manifest, &isv).await;
let mut st = StatusTracker::default();
let ia_summary = IdentityAssertion::summarize_all(manifest, &mut st, &isv).await;
let ia_json = serde_json::to_string(&ia_summary).unwrap();

assert_eq!(
Expand All @@ -121,8 +126,9 @@ async fn ims_multiple_manifests() {
assert_eq!(reader.validation_status(), None);

// Check the summary report for the entire manifest store.
let mut st = StatusTracker::default();
let isv = IcaSignatureVerifier {};
let ia_summary = IdentityAssertion::summarize_from_reader(&reader, &isv).await;
let ia_summary = IdentityAssertion::summarize_from_reader(&reader, &mut st, &isv).await;
let ia_json = serde_json::to_string(&ia_summary).unwrap();

assert_eq!(
Expand Down
10 changes: 8 additions & 2 deletions cawg_identity/src/tests/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::io::{Cursor, Seek};

use c2pa::{Builder, Reader, SigningAlg};
use c2pa_crypto::raw_signature;
use c2pa_status_tracker::StatusTracker;
use serde_json::json;
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
use wasm_bindgen_test::wasm_bindgen_test;
Expand Down Expand Up @@ -78,15 +79,20 @@ async fn simple_case() {
assert_eq!(manifest_store.validation_status(), None);

let manifest = manifest_store.active_manifest().unwrap();
let mut ia_iter = IdentityAssertion::from_manifest(manifest);
let mut st = StatusTracker::default();
let mut ia_iter = IdentityAssertion::from_manifest(manifest, &mut st);

// Should find exactly one identity assertion.
let ia = ia_iter.next().unwrap().unwrap();
assert!(ia_iter.next().is_none());
drop(ia_iter);

// And that identity assertion should be valid for this manifest.
let x509_verifier = X509SignatureVerifier {};
let sig_info = ia.validate(manifest, &x509_verifier).await.unwrap();
let sig_info = ia
.validate(manifest, &mut st, &x509_verifier)
.await
.unwrap();

let cert_info = &sig_info.cert_info;
assert_eq!(cert_info.alg.unwrap(), SigningAlg::Ed25519);
Expand Down

0 comments on commit 6a4a7cc

Please sign in to comment.