use affinidi_tsp::message::direct::{self, PackedMessage};
use affinidi_tsp::message::routed;
use affinidi_tsp::{MessageType, PrivateVid, ResolvedVid};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::json;
use trust_tasks_rs::{Payload, TrustTask};
use crate::error::TspError;
use crate::handler::TspHandler;
pub const ENVELOPE_TYPE: &str = "https://trusttasks.org/binding/tsp/0.1/envelope";
pub fn pack_trust_task<P>(
doc: &TrustTask<P>,
sender: &PrivateVid,
recipient: &ResolvedVid,
) -> Result<Vec<u8>, TspError>
where
P: Payload + Serialize,
{
Ok(pack_inner_direct(doc, sender, recipient)?.bytes)
}
pub fn pack_trust_task_nested<P>(
doc: &TrustTask<P>,
sender: &PrivateVid,
recipient: &ResolvedVid,
intermediary: &ResolvedVid,
) -> Result<Vec<u8>, TspError>
where
P: Payload + Serialize,
{
let inner = pack_inner_direct(doc, sender, recipient)?;
let outer = routed::pack_nested(
&inner,
&sender.id,
&intermediary.id,
&sender.signing_key,
&sender.decryption_key,
&intermediary.encryption_key,
)?;
Ok(outer.bytes)
}
pub fn pack_trust_task_routed<P>(
doc: &TrustTask<P>,
sender: &PrivateVid,
recipient: &ResolvedVid,
first_hop: &ResolvedVid,
onward_route: &[String],
) -> Result<Vec<u8>, TspError>
where
P: Payload + Serialize,
{
let inner = pack_inner_direct(doc, sender, recipient)?;
let routed = routed::pack_routed(
&inner.bytes,
onward_route,
&sender.id,
&first_hop.id,
&sender.signing_key,
&sender.decryption_key,
&first_hop.encryption_key,
)?;
Ok(routed.bytes)
}
fn pack_inner_direct<P>(
doc: &TrustTask<P>,
sender: &PrivateVid,
recipient: &ResolvedVid,
) -> Result<PackedMessage, TspError>
where
P: Payload + Serialize,
{
let document = serde_json::to_value(doc).map_err(TspError::SerialiseBody)?;
let envelope = json!({ "type": ENVELOPE_TYPE, "document": document });
let payload = serde_json::to_vec(&envelope).map_err(TspError::SerialiseBody)?;
Ok(direct::pack(
&payload,
MessageType::Direct,
&sender.id,
&recipient.id,
&sender.signing_key,
&sender.decryption_key,
&recipient.encryption_key,
)?)
}
pub fn unpack_trust_task<P>(
wire: &[u8],
recipient: &PrivateVid,
sender: &ResolvedVid,
) -> Result<(TrustTask<P>, TspHandler), TspError>
where
P: Payload + DeserializeOwned,
{
let unpacked = direct::unpack(
wire,
&recipient.decryption_key,
&sender.encryption_key,
&sender.signing_key,
)?;
if unpacked.message_type != MessageType::Direct {
return Err(TspError::UnsupportedCarriage(unpacked.message_type));
}
if unpacked.sender != sender.id {
return Err(TspError::SenderMismatch {
claimed: unpacked.sender,
verified: sender.id.clone(),
});
}
let envelope: Envelope =
serde_json::from_slice(&unpacked.payload).map_err(TspError::InvalidBody)?;
if envelope.type_ != ENVELOPE_TYPE {
return Err(TspError::WrongEnvelopeType(envelope.type_));
}
let doc: TrustTask<P> =
serde_json::from_value(envelope.document).map_err(TspError::InvalidBody)?;
let handler = TspHandler::new(Some(unpacked.receiver), Some(sender.id.clone()));
Ok((doc, handler))
}
#[derive(serde::Deserialize)]
struct Envelope {
#[serde(rename = "type")]
type_: String,
document: serde_json::Value,
}