chronon_core/
actor_policy.rs1use serde_json::Value;
9
10use crate::error::{ChrononError, Result};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum EnqueueTrust {
15 Internal,
17 External,
19}
20
21pub trait ActorJsonPolicy: Send + Sync {
27 fn validate(&self, trust: EnqueueTrust, actor_json: &Value) -> Result<()>;
33}
34
35#[derive(Debug, Default, Clone, Copy)]
39pub struct RejectExternalSystemActor;
40
41impl ActorJsonPolicy for RejectExternalSystemActor {
42 fn validate(&self, trust: EnqueueTrust, actor_json: &Value) -> Result<()> {
43 if trust == EnqueueTrust::External && actor_json.get("System").is_some() {
44 return Err(ChrononError::ParamError(
45 "external enqueue cannot use System-shaped actor_json".into(),
46 ));
47 }
48 Ok(())
49 }
50}
51
52#[must_use]
57pub fn default_http_enqueue_actor() -> Value {
58 serde_json::json!({"Service": {"name": "chronon_api"}})
59}
60
61#[must_use]
63pub fn is_system_shaped_actor(actor_json: &Value) -> bool {
64 actor_json.get("System").is_some()
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn reject_external_system() {
73 let policy = RejectExternalSystemActor;
74 let system = serde_json::json!({"System": {"operation": "x"}});
75 assert!(policy
76 .validate(EnqueueTrust::External, &system)
77 .unwrap_err()
78 .to_string()
79 .contains("System"));
80 assert!(policy.validate(EnqueueTrust::Internal, &system).is_ok());
81 }
82
83 #[test]
84 fn allow_external_service() {
85 let policy = RejectExternalSystemActor;
86 let service = default_http_enqueue_actor();
87 assert!(!is_system_shaped_actor(&service));
88 assert!(policy.validate(EnqueueTrust::External, &service).is_ok());
89 }
90}