iam_rs/core/
action.rs

1use crate::validation::{Validate, ValidationContext, ValidationResult, helpers};
2use serde::{Deserialize, Serialize};
3
4/// Represents an action in an IAM policy
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(untagged)]
7pub enum Action {
8    /// A single action (e.g., "s3:GetObject")
9    Single(String),
10    /// Multiple actions
11    Multiple(Vec<String>),
12}
13
14impl Validate for Action {
15    fn validate(&self, context: &mut ValidationContext) -> ValidationResult {
16        context.with_segment("Action", |ctx| match self {
17            Action::Single(action) => helpers::validate_action(action, ctx),
18            Action::Multiple(actions) => {
19                if actions.is_empty() {
20                    return Err(crate::validation::ValidationError::InvalidValue {
21                        field: "Action".to_string(),
22                        value: "[]".to_string(),
23                        reason: "Action list cannot be empty".to_string(),
24                    });
25                }
26
27                let results: Vec<ValidationResult> = actions
28                    .iter()
29                    .enumerate()
30                    .map(|(i, action)| {
31                        ctx.with_segment(&format!("[{}]", i), |nested_ctx| {
32                            helpers::validate_action(action, nested_ctx)
33                        })
34                    })
35                    .collect();
36
37                helpers::collect_errors(results)
38            }
39        })
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn test_action_validation() {
49        let valid_single = Action::Single("s3:GetObject".to_string());
50        assert!(valid_single.is_valid());
51
52        let valid_wildcard = Action::Single("*".to_string());
53        assert!(valid_wildcard.is_valid());
54
55        let valid_multiple =
56            Action::Multiple(vec!["s3:GetObject".to_string(), "s3:PutObject".to_string()]);
57        assert!(valid_multiple.is_valid());
58
59        let invalid_single = Action::Single("invalid-action".to_string());
60        assert!(!invalid_single.is_valid());
61
62        let empty_multiple = Action::Multiple(vec![]);
63        assert!(!empty_multiple.is_valid());
64
65        let invalid_multiple = Action::Multiple(vec![
66            "s3:GetObject".to_string(),
67            "invalid-action".to_string(),
68        ]);
69        assert!(!invalid_multiple.is_valid());
70    }
71}