warg_server/policy/content/
mod.rs1use thiserror::Error;
3use warg_crypto::hash::AnyHash;
4
5mod wasm;
6
7pub use wasm::*;
8
9#[derive(Debug, Error)]
11pub enum ContentPolicyError {
12 #[error("content was rejected by policy: {0}")]
14 Rejection(String),
15}
16
17pub type ContentPolicyResult<T> = Result<T, ContentPolicyError>;
19
20pub trait ContentPolicy: Send + Sync {
22 fn new_stream_policy(
30 &self,
31 digest: &AnyHash,
32 ) -> ContentPolicyResult<Box<dyn ContentStreamPolicy>>;
33}
34
35pub trait ContentStreamPolicy: Send + Sync {
37 fn check(&mut self, bytes: &[u8]) -> ContentPolicyResult<()>;
42
43 fn finalize(&mut self) -> ContentPolicyResult<()>;
48}
49
50#[derive(Default)]
55pub struct ContentPolicyCollection {
56 policies: Vec<Box<dyn ContentPolicy>>,
57}
58
59impl ContentPolicyCollection {
60 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn push(&mut self, policy: impl ContentPolicy + 'static) {
67 self.policies.push(Box::new(policy));
68 }
69}
70
71impl ContentPolicy for ContentPolicyCollection {
72 fn new_stream_policy(
73 &self,
74 digest: &AnyHash,
75 ) -> ContentPolicyResult<Box<dyn ContentStreamPolicy>> {
76 Ok(Box::new(ContentStreamPolicyCollection {
77 policies: self
78 .policies
79 .iter()
80 .map(|p| p.new_stream_policy(digest))
81 .collect::<ContentPolicyResult<_>>()?,
82 }))
83 }
84}
85
86pub struct ContentStreamPolicyCollection {
87 policies: Vec<Box<dyn ContentStreamPolicy>>,
88}
89
90impl ContentStreamPolicy for ContentStreamPolicyCollection {
91 fn check(&mut self, bytes: &[u8]) -> ContentPolicyResult<()> {
92 for policy in &mut self.policies {
93 policy.check(bytes)?;
94 }
95
96 Ok(())
97 }
98
99 fn finalize(&mut self) -> ContentPolicyResult<()> {
100 for policy in &mut self.policies {
101 policy.finalize()?;
102 }
103
104 Ok(())
105 }
106}