role_system/
batch.rs

1//! Batch operations API for high-performance bulk operations
2
3use crate::{Error, Permission, Resource, Role, RoleSystem, Subject};
4
5/// Result of a batch operation
6#[derive(Debug, Clone)]
7pub struct BatchResult<T> {
8    /// Successful operations with their results
9    pub successes: Vec<(usize, T)>,
10    /// Failed operations with their errors
11    pub failures: Vec<(usize, Error)>,
12}
13
14impl<T> BatchResult<T> {
15    /// Create a new empty batch result
16    pub fn new() -> Self {
17        Self {
18            successes: Vec::new(),
19            failures: Vec::new(),
20        }
21    }
22
23    /// Add a successful result
24    pub fn add_success(&mut self, index: usize, result: T) {
25        self.successes.push((index, result));
26    }
27
28    /// Add a failed result
29    pub fn add_failure(&mut self, index: usize, error: Error) {
30        self.failures.push((index, error));
31    }
32
33    /// Get success rate as a percentage
34    pub fn success_rate(&self) -> f64 {
35        let total = self.successes.len() + self.failures.len();
36        if total == 0 {
37            return 0.0;
38        }
39        (self.successes.len() as f64 / total as f64) * 100.0
40    }
41
42    /// Check if all operations succeeded
43    pub fn all_succeeded(&self) -> bool {
44        self.failures.is_empty()
45    }
46
47    /// Get total number of operations
48    pub fn total_operations(&self) -> usize {
49        self.successes.len() + self.failures.len()
50    }
51}
52
53impl<T> Default for BatchResult<T> {
54    fn default() -> Self {
55        Self::new()
56    }
57}
58
59/// Batch permission check request
60#[derive(Debug, Clone)]
61pub struct BatchPermissionCheck {
62    pub subject: Subject,
63    pub permission: Permission,
64    pub resource: Resource,
65}
66
67impl BatchPermissionCheck {
68    /// Create a new batch permission check
69    pub fn new(subject: Subject, permission: Permission, resource: Resource) -> Self {
70        Self {
71            subject,
72            permission,
73            resource,
74        }
75    }
76}
77
78/// Batch role assignment request
79#[derive(Debug, Clone)]
80pub struct BatchRoleAssignment {
81    pub subject: Subject,
82    pub role: Role,
83    pub assign: bool, // true for assign, false for revoke
84}
85
86impl BatchRoleAssignment {
87    /// Create a new batch role assignment
88    pub fn new_assignment(subject: Subject, role: Role) -> Self {
89        Self {
90            subject,
91            role,
92            assign: true,
93        }
94    }
95
96    /// Create a new batch role revocation
97    pub fn new_revocation(subject: Subject, role: Role) -> Self {
98        Self {
99            subject,
100            role,
101            assign: false,
102        }
103    }
104}
105
106/// Batch operations configuration
107#[derive(Debug, Clone)]
108pub struct BatchConfig {
109    /// Maximum number of operations to process concurrently
110    pub max_concurrency: usize,
111    /// Whether to stop on first failure or continue processing
112    pub fail_fast: bool,
113    /// Timeout for the entire batch operation (in milliseconds)
114    pub timeout_ms: Option<u64>,
115}
116
117impl Default for BatchConfig {
118    fn default() -> Self {
119        Self {
120            max_concurrency: num_cpus::get().max(1),
121            fail_fast: false,
122            timeout_ms: None,
123        }
124    }
125}
126
127/// Extension trait for RoleSystem to support batch operations
128pub trait BatchOperations {
129    /// Perform batch permission checks
130    fn batch_check_permissions(
131        &self,
132        checks: Vec<BatchPermissionCheck>,
133    ) -> Result<BatchResult<bool>, Error>;
134
135    /// Perform batch role assignments and revocations (requires mutable access)
136    fn batch_role_operations(
137        &mut self,
138        operations: Vec<BatchRoleAssignment>,
139    ) -> Result<BatchResult<()>, Error>;
140}
141
142impl BatchOperations for RoleSystem {
143    fn batch_check_permissions(
144        &self,
145        checks: Vec<BatchPermissionCheck>,
146    ) -> Result<BatchResult<bool>, Error> {
147        let mut result = BatchResult::new();
148
149        for (i, check) in checks.iter().enumerate() {
150            match self.check_permission(&check.subject, check.permission.action(), &check.resource)
151            {
152                Ok(allowed) => result.add_success(i, allowed),
153                Err(error) => result.add_failure(i, error),
154            }
155        }
156
157        Ok(result)
158    }
159
160    fn batch_role_operations(
161        &mut self,
162        operations: Vec<BatchRoleAssignment>,
163    ) -> Result<BatchResult<()>, Error> {
164        let mut result = BatchResult::new();
165
166        for (i, operation) in operations.iter().enumerate() {
167            let op_result = if operation.assign {
168                self.assign_role(&operation.subject, operation.role.name())
169            } else {
170                self.remove_role(&operation.subject, operation.role.name())
171            };
172
173            match op_result {
174                Ok(()) => result.add_success(i, ()),
175                Err(error) => result.add_failure(i, error),
176            }
177        }
178
179        Ok(result)
180    }
181}