use async_trait::async_trait;
use serde_json::Value;
use crate::{
dynamic_assertion::{AsyncPostValidator, PartialClaim},
identity::IdentityAssertion,
status_tracker::StatusTracker,
ManifestAssertion,
};
pub struct CawgValidator;
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl AsyncPostValidator for CawgValidator {
async fn validate(
&self,
label: &str,
assertion: &ManifestAssertion,
uri: &str,
partial_claim: &PartialClaim,
tracker: &mut StatusTracker,
) -> crate::Result<Option<Value>> {
if label == "cawg.identity" || label.starts_with("cawg.identity__") {
let identity_assertion: IdentityAssertion = assertion.to_assertion()?;
tracker.push_current_uri(uri.to_string());
let result = identity_assertion
.validate_partial_claim(partial_claim, tracker)
.await
.ok();
tracker.pop_current_uri();
return Ok(result);
};
Ok(None)
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::panic)]
#![allow(clippy::unwrap_used)]
use std::io::Cursor;
use c2pa_macros::c2pa_test_async;
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
use wasm_bindgen_test::wasm_bindgen_test;
use crate::{Reader, ValidationState};
const CONNECTED_IDENTITIES_VALID: &[u8] =
include_bytes!("tests/fixtures/claim_aggregation/adobe_connected_identities.jpg");
const NO_HARD_BINDING: &[u8] =
include_bytes!("tests/fixtures/validation_method/no_hard_binding.jpg");
const MULTIPLE_IDENTITIES_VALID: &[u8] =
include_bytes!("tests/fixtures/claim_aggregation/ims_multiple_manifests.jpg");
#[c2pa_test_async]
async fn test_connected_identities_valid() {
crate::settings::set_settings_value("verify.verify_trust", false).unwrap();
let mut stream = Cursor::new(CONNECTED_IDENTITIES_VALID);
let reader = Reader::default()
.with_stream_async("image/jpeg", &mut stream)
.await
.unwrap();
assert_eq!(
reader
.validation_results()
.unwrap()
.active_manifest()
.unwrap()
.success()
.last()
.unwrap()
.code(),
"cawg.ica.credential_valid"
);
}
#[c2pa_test_async]
async fn test_multiple_identities_valid() {
crate::settings::set_settings_value("verify.verify_trust", false).unwrap();
let mut stream = Cursor::new(MULTIPLE_IDENTITIES_VALID);
let reader = Reader::default()
.with_stream_async("image/jpeg", &mut stream)
.await
.unwrap();
println!("validation results: {reader}");
assert_eq!(
reader
.validation_results()
.unwrap()
.ingredient_deltas()
.unwrap()
.len(),
1
);
assert_eq!(reader.validation_state(), ValidationState::Valid);
}
#[c2pa_test_async]
async fn test_cawg_validate_with_hard_binding_missing() {
let mut stream = Cursor::new(NO_HARD_BINDING);
let reader = Reader::default()
.with_stream_async("image/jpeg", &mut stream)
.await
.unwrap();
assert_eq!(
reader
.validation_results()
.unwrap()
.active_manifest()
.unwrap()
.failure()[0]
.code(),
"cawg.identity.hard_binding_missing"
);
}
}