four/iam/property/
statement.rs

1use crate::iam::property::{action::Action, effect::Effect, principal::Principal};
2use serde::{ser::SerializeMap, Serialize};
3
4#[derive(Debug, Clone)]
5pub struct Statement {
6    effect: Effect,
7    action: ActionOr,
8    principal: Option<PrincipalOr>,
9    resource: Option<String>,
10}
11
12impl Statement {
13    pub fn allow_actions(actions: Vec<Box<dyn Action>>) -> StatementBuilder {
14        StatementBuilder {
15            effect: Effect::Allow,
16            action: ActionOr::Action(actions),
17            principal: None,
18            resource: None,
19        }
20    }
21
22    pub fn deny_actions(actions: Vec<Box<dyn Action>>) -> StatementBuilder {
23        StatementBuilder {
24            effect: Effect::Deny,
25            action: ActionOr::Action(actions),
26            principal: None,
27            resource: None,
28        }
29    }
30
31    pub fn allow_no_actions(actions: Vec<Box<dyn Action>>) -> StatementBuilder {
32        StatementBuilder {
33            effect: Effect::Allow,
34            action: ActionOr::NotAction(actions),
35            principal: None,
36            resource: None,
37        }
38    }
39
40    pub fn deny_no_actions(actions: Vec<Box<dyn Action>>) -> StatementBuilder {
41        StatementBuilder {
42            effect: Effect::Deny,
43            action: ActionOr::NotAction(actions),
44            principal: None,
45            resource: None,
46        }
47    }
48}
49
50impl Serialize for Statement {
51    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
52    where
53        S: serde::Serializer,
54    {
55        let mut map = serializer.serialize_map(None)?;
56        map.serialize_entry("Effect", &self.effect)?;
57        match &self.action {
58            ActionOr::Action(action) => map.serialize_entry("Action", action)?,
59            ActionOr::NotAction(action) => map.serialize_entry("NotAction", action)?,
60        }
61        if let Some(principal) = self.principal.as_ref() {
62            match principal {
63                PrincipalOr::Principal(p) => map.serialize_entry("Principal", p)?,
64                PrincipalOr::NotPrincipal(p) => map.serialize_entry("NotPrincipal", p)?,
65            }
66        }
67        if let Some(resource) = self.resource.as_ref() {
68            map.serialize_entry("Resource", resource)?;
69        }
70
71        map.end()
72    }
73}
74
75#[derive(Debug)]
76pub struct StatementBuilder {
77    effect: Effect,
78    action: ActionOr,
79    principal: Option<PrincipalOr>,
80    resource: Option<String>,
81}
82
83impl StatementBuilder {
84    pub fn build(self) -> Result<Statement, StatementBuildError> {
85        // TODO: ERROR
86
87        let statement = Statement {
88            effect: self.effect,
89            action: self.action,
90            principal: self.principal,
91            resource: self.resource,
92        };
93
94        Ok(statement)
95    }
96
97    pub fn principal(mut self, principal: Principal) -> Self {
98        self.principal = Some(PrincipalOr::Principal(principal));
99        self
100    }
101
102    pub fn no_principal(mut self, principal: Principal) -> Self {
103        self.principal = Some(PrincipalOr::NotPrincipal(principal));
104        self
105    }
106
107    pub fn resource(mut self, resource: &str) -> Self {
108        self.resource = Some(resource.to_string());
109        self
110    }
111}
112
113#[derive(Debug, thiserror::Error)]
114pub enum StatementBuildError {}
115
116#[derive(Debug, Clone)]
117pub enum ActionOr {
118    Action(Vec<Box<dyn Action>>),
119    NotAction(Vec<Box<dyn Action>>),
120}
121
122#[derive(Debug, Clone)]
123pub enum PrincipalOr {
124    Principal(Principal),
125    NotPrincipal(Principal),
126}