eidetica/auth/
permission.rs1use crate::auth::types::{Permission, PermissionBounds};
8
9pub fn clamp_permission(delegated_permission: Permission, bounds: &PermissionBounds) -> Permission {
41 if !validate_permission_bounds(bounds) {
43 tracing::warn!(
44 "Invalid permission bounds detected (min > max). Applying only max bound as fallback."
45 );
46 if delegated_permission > bounds.max {
48 return bounds.max;
49 }
50 return delegated_permission;
51 }
52
53 if delegated_permission > bounds.max {
55 return bounds.max;
56 }
57
58 if let Some(min) = &bounds.min
60 && delegated_permission < *min
61 {
62 return *min;
63 }
64
65 delegated_permission
66}
67
68pub fn validate_permission_bounds(bounds: &PermissionBounds) -> bool {
79 if let Some(min) = &bounds.min {
81 min <= &bounds.max
82 } else {
83 true }
85}
86
87pub fn can_delegate_with_bounds(
98 delegating_permission: &Permission,
99 bounds: &PermissionBounds,
100) -> bool {
101 if bounds.max > *delegating_permission {
103 return false;
104 }
105 validate_permission_bounds(bounds)
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_clamp_permission_max_bound() {
114 let bounds = PermissionBounds {
115 max: Permission::Write(10),
116 min: None,
117 };
118
119 let result = clamp_permission(Permission::Admin(5), &bounds);
121 assert_eq!(result, Permission::Write(10));
122
123 let result = clamp_permission(Permission::Write(20), &bounds);
125 assert_eq!(result, Permission::Write(20));
126
127 let result = clamp_permission(Permission::Write(5), &bounds);
129 assert_eq!(result, Permission::Write(10));
130
131 let result = clamp_permission(Permission::Read, &bounds);
133 assert_eq!(result, Permission::Read);
134 }
135
136 #[test]
137 fn test_clamp_permission_min_bound() {
138 let bounds = PermissionBounds {
139 max: Permission::Admin(5),
140 min: Some(Permission::Write(10)),
141 };
142
143 let result = clamp_permission(Permission::Admin(5), &bounds);
145 assert_eq!(result, Permission::Admin(5));
146
147 let result = clamp_permission(Permission::Write(15), &bounds);
149 assert_eq!(result, Permission::Write(10));
150
151 let result = clamp_permission(Permission::Write(5), &bounds);
153 assert_eq!(result, Permission::Write(5));
154
155 let result = clamp_permission(Permission::Read, &bounds);
157 assert_eq!(result, Permission::Write(10));
158 }
159
160 #[test]
161 fn test_clamp_permission_both_bounds() {
162 let bounds = PermissionBounds {
163 max: Permission::Write(5), min: Some(Permission::Write(15)), };
166
167 let result = clamp_permission(Permission::Admin(1), &bounds);
169 assert_eq!(result, Permission::Write(5));
170
171 let result = clamp_permission(Permission::Write(20), &bounds);
173 assert_eq!(result, Permission::Write(15));
174
175 let result = clamp_permission(Permission::Write(12), &bounds);
177 assert_eq!(result, Permission::Write(12));
178
179 let result = clamp_permission(Permission::Write(3), &bounds);
181 assert_eq!(result, Permission::Write(5));
182
183 let result = clamp_permission(Permission::Read, &bounds);
185 assert_eq!(result, Permission::Write(15));
186 }
187
188 #[test]
189 fn test_validate_permission_bounds_valid() {
190 let bounds = PermissionBounds {
192 max: Permission::Write(10),
193 min: None,
194 };
195 assert!(validate_permission_bounds(&bounds));
196
197 let bounds = PermissionBounds {
199 max: Permission::Write(10),
200 min: Some(Permission::Write(10)),
201 };
202 assert!(validate_permission_bounds(&bounds));
203
204 let bounds = PermissionBounds {
206 max: Permission::Admin(5),
207 min: Some(Permission::Write(10)),
208 };
209 assert!(validate_permission_bounds(&bounds));
210 }
211
212 #[test]
213 fn test_validate_permission_bounds_invalid() {
214 let bounds = PermissionBounds {
216 max: Permission::Write(10),
217 min: Some(Permission::Admin(5)),
218 };
219 assert!(!validate_permission_bounds(&bounds));
220
221 let bounds = PermissionBounds {
223 max: Permission::Read,
224 min: Some(Permission::Write(10)),
225 };
226 assert!(!validate_permission_bounds(&bounds));
227 }
228
229 #[test]
230 fn test_can_delegate_with_bounds_valid() {
231 let delegating_permission = Permission::Admin(5);
232
233 let bounds = PermissionBounds {
235 max: Permission::Write(10),
236 min: Some(Permission::Read),
237 };
238 assert!(can_delegate_with_bounds(&delegating_permission, &bounds));
239
240 let bounds = PermissionBounds {
242 max: Permission::Admin(5),
243 min: None,
244 };
245 assert!(can_delegate_with_bounds(&delegating_permission, &bounds));
246 }
247
248 #[test]
249 fn test_can_delegate_with_bounds_invalid() {
250 let delegating_permission = Permission::Write(10);
251
252 let bounds = PermissionBounds {
254 max: Permission::Admin(5),
255 min: None,
256 };
257 assert!(!can_delegate_with_bounds(&delegating_permission, &bounds));
258
259 let bounds = PermissionBounds {
261 max: Permission::Write(20),
262 min: Some(Permission::Admin(1)),
263 };
264 assert!(!can_delegate_with_bounds(&delegating_permission, &bounds));
265
266 let bounds = PermissionBounds {
268 max: Permission::Write(5), min: Some(Permission::Read),
270 };
271 assert!(!can_delegate_with_bounds(&delegating_permission, &bounds));
272 }
273
274 #[test]
275 fn test_permission_clamping_edge_cases() {
276 let bounds = PermissionBounds {
278 max: Permission::Write(10),
279 min: Some(Permission::Write(10)),
280 };
281
282 let result = clamp_permission(Permission::Write(10), &bounds);
283 assert_eq!(result, Permission::Write(10));
284
285 let result = clamp_permission(Permission::Admin(5), &bounds);
286 assert_eq!(result, Permission::Write(10));
287
288 let result = clamp_permission(Permission::Read, &bounds);
289 assert_eq!(result, Permission::Write(10));
290 }
291
292 #[test]
293 fn test_permission_priority_clamping() {
294 let bounds = PermissionBounds {
296 max: Permission::Write(5),
297 min: Some(Permission::Write(15)),
298 };
299
300 let result = clamp_permission(Permission::Write(12), &bounds);
302 assert_eq!(result, Permission::Write(12));
303
304 let result = clamp_permission(Permission::Write(20), &bounds);
306 assert_eq!(result, Permission::Write(15));
307
308 let result = clamp_permission(Permission::Write(3), &bounds);
310 assert_eq!(result, Permission::Write(5));
311 }
312}