use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CandidateStrategy {
Static {
#[serde(default)]
users: Vec<String>,
#[serde(default)]
roles: Vec<String>,
},
Dynamic { expr: String },
Capability {
capability_name: String,
#[serde(default)]
args: serde_json::Value,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum ApprovalStrategyType {
#[default]
AndSign,
OrSign,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum FaultStrategy {
#[default]
Fail,
Skip,
Retry,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Transition {
pub from: String,
pub to: String,
pub event: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub guard: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn candidate_strategy_static_serde() {
let s = CandidateStrategy::Static {
users: vec!["u1".into()],
roles: vec!["admin".into()],
};
let json = serde_json::to_string(&s).unwrap();
let back: CandidateStrategy = serde_json::from_str(&json).unwrap();
assert_eq!(s, back);
}
#[test]
fn candidate_strategy_dynamic_serde() {
let s = CandidateStrategy::Dynamic {
expr: "$.candidates".into(),
};
let json = serde_json::to_string(&s).unwrap();
assert!(json.contains("\"type\":\"dynamic\""));
let back: CandidateStrategy = serde_json::from_str(&json).unwrap();
assert_eq!(s, back);
}
#[test]
fn candidate_strategy_capability_serde() {
let s = CandidateStrategy::Capability {
capability_name: "hr.get_managers".into(),
args: serde_json::json!({"dept": "tech"}),
};
let json = serde_json::to_string(&s).unwrap();
let back: CandidateStrategy = serde_json::from_str(&json).unwrap();
assert_eq!(s, back);
}
#[test]
fn approval_strategy_type_serde() {
let json = serde_json::to_string(&ApprovalStrategyType::AndSign).unwrap();
assert_eq!(json, "\"and_sign\"");
let json = serde_json::to_string(&ApprovalStrategyType::OrSign).unwrap();
assert_eq!(json, "\"or_sign\"");
}
#[test]
fn fault_strategy_serde() {
assert_eq!(
serde_json::to_string(&FaultStrategy::Fail).unwrap(),
"\"fail\""
);
assert_eq!(
serde_json::to_string(&FaultStrategy::Skip).unwrap(),
"\"skip\""
);
assert_eq!(
serde_json::to_string(&FaultStrategy::Retry).unwrap(),
"\"retry\""
);
}
#[test]
fn transition_serde() {
let t = Transition {
from: "draft".into(),
to: "review".into(),
event: "submit".into(),
guard: Some("$.amount > 100".into()),
};
let json = serde_json::to_string(&t).unwrap();
let back: Transition = serde_json::from_str(&json).unwrap();
assert_eq!(t, back);
let t2 = Transition {
from: "draft".into(),
to: "review".into(),
event: "submit".into(),
guard: None,
};
let json2 = serde_json::to_string(&t2).unwrap();
assert!(!json2.contains("guard"));
}
}