#![cfg(feature = "network")]
use async_trait::async_trait;
use crate::remittance::error::RemittanceError;
use crate::remittance::types::{
IdentityVerificationAcknowledgment, IdentityVerificationRequest, IdentityVerificationResponse,
ModuleContext, Termination,
};
#[derive(Debug)]
pub enum RespondToRequestResult {
Respond {
response: IdentityVerificationResponse,
},
Terminate { termination: Termination },
}
#[derive(Debug)]
pub enum AssessIdentityResult {
Acknowledge(IdentityVerificationAcknowledgment),
Terminate(Termination),
}
#[async_trait]
pub trait IdentityLayer: Send + Sync {
async fn determine_certificates_to_request(
&self,
counterparty: &str,
thread_id: &str,
ctx: &ModuleContext,
) -> Result<IdentityVerificationRequest, RemittanceError>;
async fn respond_to_request(
&self,
counterparty: &str,
thread_id: &str,
request: &IdentityVerificationRequest,
ctx: &ModuleContext,
) -> Result<RespondToRequestResult, RemittanceError>;
async fn assess_received_certificate_sufficiency(
&self,
counterparty: &str,
received: &IdentityVerificationResponse,
thread_id: &str,
) -> Result<AssessIdentityResult, RemittanceError>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::remittance::types::{
IdentityRequest, IdentityVerificationAcknowledgment, IdentityVerificationResponse,
RemittanceKind, Termination,
};
use std::collections::HashMap;
use std::sync::Arc;
struct MockIdentity;
#[async_trait]
impl IdentityLayer for MockIdentity {
async fn determine_certificates_to_request(
&self,
_counterparty: &str,
thread_id: &str,
_ctx: &ModuleContext,
) -> Result<IdentityVerificationRequest, RemittanceError> {
Ok(IdentityVerificationRequest {
kind: RemittanceKind::IdentityVerificationRequest,
thread_id: thread_id.to_string(),
request: IdentityRequest {
types: HashMap::new(),
certifiers: vec![],
},
})
}
async fn respond_to_request(
&self,
_counterparty: &str,
thread_id: &str,
_request: &IdentityVerificationRequest,
_ctx: &ModuleContext,
) -> Result<RespondToRequestResult, RemittanceError> {
Ok(RespondToRequestResult::Respond {
response: IdentityVerificationResponse {
kind: RemittanceKind::IdentityVerificationResponse,
thread_id: thread_id.to_string(),
certificates: vec![],
},
})
}
async fn assess_received_certificate_sufficiency(
&self,
_counterparty: &str,
received: &IdentityVerificationResponse,
_thread_id: &str,
) -> Result<AssessIdentityResult, RemittanceError> {
Ok(AssessIdentityResult::Acknowledge(
IdentityVerificationAcknowledgment {
kind: RemittanceKind::IdentityVerificationAcknowledgment,
thread_id: received.thread_id.clone(),
},
))
}
}
#[test]
fn identity_layer_is_object_safe() {
let _: Arc<dyn IdentityLayer> = Arc::new(MockIdentity);
}
#[test]
fn respond_to_request_result_variants() {
let respond = RespondToRequestResult::Respond {
response: IdentityVerificationResponse {
kind: RemittanceKind::IdentityVerificationResponse,
thread_id: "t1".into(),
certificates: vec![],
},
};
let terminate = RespondToRequestResult::Terminate {
termination: Termination {
code: "NO_CERTS".into(),
message: "no certificates available".into(),
details: None,
},
};
assert!(matches!(respond, RespondToRequestResult::Respond { .. }));
assert!(matches!(
terminate,
RespondToRequestResult::Terminate { .. }
));
}
#[test]
fn assess_identity_result_variants() {
let ack = AssessIdentityResult::Acknowledge(IdentityVerificationAcknowledgment {
kind: RemittanceKind::IdentityVerificationAcknowledgment,
thread_id: "t1".into(),
});
let terminate = AssessIdentityResult::Terminate(Termination {
code: "INSUFFICIENT".into(),
message: "certs do not satisfy requirements".into(),
details: None,
});
assert!(matches!(ack, AssessIdentityResult::Acknowledge(_)));
assert!(matches!(terminate, AssessIdentityResult::Terminate(_)));
}
}