use coz::{Czd, Pay, Thumbprint};
#[derive(Debug, Clone)]
pub struct Action {
pub(crate) typ: String,
pub(crate) signer: Thumbprint,
pub(crate) now: i64,
pub(crate) czd: Czd,
pub(crate) pay: Pay,
pub(crate) raw: coz::CozJson,
}
impl Action {
pub(crate) fn new(
typ: String,
signer: Thumbprint,
now: i64,
czd: Czd,
raw: coz::CozJson,
) -> Self {
Self {
typ,
signer,
now,
czd,
pay: Pay::default(), raw,
}
}
#[cfg(test)]
pub(crate) fn from_pay(pay: &Pay, czd: Czd, raw: coz::CozJson) -> Option<Self> {
let signer = pay.tmb.clone()?;
let now = pay.now?;
let typ = pay.typ.clone()?;
Some(Self {
typ,
signer,
now,
czd,
pay: pay.clone(),
raw,
})
}
pub fn typ(&self) -> &str {
&self.typ
}
pub fn signer(&self) -> &Thumbprint {
&self.signer
}
pub fn now(&self) -> i64 {
self.now
}
pub fn czd(&self) -> &Czd {
&self.czd
}
pub fn raw(&self) -> &coz::CozJson {
&self.raw
}
pub fn get_field(&self, key: &str) -> Option<&serde_json::Value> {
self.pay.extra.get(key)
}
pub fn msg(&self) -> Option<&str> {
self.pay.msg.as_deref()
}
}
#[cfg(test)]
mod tests {
use coz::{PayBuilder, Thumbprint};
use serde_json::json;
use super::*;
fn to_raw(pay: &Pay) -> coz::CozJson {
coz::CozJson {
pay: serde_json::to_value(pay).unwrap(),
sig: vec![0; 64],
}
}
#[test]
fn action_from_pay_basic() {
let pay = PayBuilder::new()
.typ("cyphr.me/comment/create")
.alg("ES256")
.now(1000)
.tmb(Thumbprint::from_bytes(vec![0xAA; 32]))
.msg("Hello, world!")
.build();
let czd = Czd::from_bytes(vec![0xBB; 32]);
let action = Action::from_pay(&pay, czd.clone(), to_raw(&pay)).unwrap();
assert_eq!(action.typ, "cyphr.me/comment/create");
assert_eq!(action.now, 1000);
assert_eq!(action.msg(), Some("Hello, world!"));
assert_eq!(action.czd.as_bytes(), czd.as_bytes());
}
#[test]
fn action_from_pay_with_custom_fields() {
let mut pay = PayBuilder::new()
.typ("example/data")
.alg("ES256")
.now(1000)
.tmb(Thumbprint::from_bytes(vec![0xAA; 32]))
.build();
pay.extra.insert("custom".into(), json!("value"));
let czd = Czd::from_bytes(vec![0xDD; 32]);
let action = Action::from_pay(&pay, czd, to_raw(&pay)).unwrap();
assert_eq!(action.get_field("custom"), Some(&json!("value")));
}
#[test]
fn action_from_pay_missing_tmb_returns_none() {
let pay = PayBuilder::new()
.typ("example/test")
.alg("ES256")
.now(1000)
.build();
let czd = Czd::from_bytes(vec![0; 32]);
assert!(Action::from_pay(&pay, czd, to_raw(&pay)).is_none());
}
}