1use crate::role::Role;
7#[cfg(feature = "persistence")]
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone)]
32#[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))]
33pub struct RoleHierarchyTree {
34 pub root: RoleNode,
36 pub total_roles: usize,
38 pub max_depth: usize,
40 pub metadata: HierarchyMetadata,
42}
43
44#[derive(Debug, Clone)]
49#[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))]
50pub struct RoleNode {
51 pub role: Role,
53 pub children: Vec<RoleNode>,
55 pub depth: usize,
57 pub descendant_count: usize,
59}
60
61#[derive(Debug, Clone)]
63#[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))]
64pub struct HierarchyMetadata {
65 #[cfg(feature = "persistence")]
67 pub generated_at: chrono::DateTime<chrono::Utc>,
68 pub schema_version: String,
70 pub total_permissions: usize,
72 pub generation_time_ms: u64,
74}
75
76#[derive(Debug, Clone)]
81#[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))]
82pub struct RoleRelationship {
83 pub child_role_id: String,
85 pub parent_role_id: String,
87 pub relationship_type: RelationshipType,
89 #[cfg(feature = "persistence")]
91 pub created_at: Option<chrono::DateTime<chrono::Utc>>,
92 pub metadata: HashMap<String, String>,
94}
95
96#[derive(Debug, Clone, PartialEq, Eq)]
98#[cfg_attr(feature = "persistence", derive(Serialize, Deserialize))]
99pub enum RelationshipType {
100 Direct,
102 Inherited,
104}
105
106#[derive(Debug, Clone)]
111pub struct HierarchyConfig {
112 pub enable_hierarchy_access: bool,
114 pub max_hierarchy_depth: usize,
116 pub cache_hierarchy: bool,
118 pub max_traversal_size: usize,
120 pub include_permission_counts: bool,
122}
123
124impl Default for HierarchyConfig {
125 fn default() -> Self {
126 Self {
127 enable_hierarchy_access: false, max_hierarchy_depth: 10,
129 cache_hierarchy: true,
130 max_traversal_size: 1000,
131 include_permission_counts: true,
132 }
133 }
134}
135
136pub struct HierarchyConfigBuilder {
149 config: HierarchyConfig,
150}
151
152impl HierarchyConfigBuilder {
153 pub fn new() -> Self {
155 Self {
156 config: HierarchyConfig::default(),
157 }
158 }
159
160 pub fn enable_hierarchy_access(mut self, enable: bool) -> Self {
162 self.config.enable_hierarchy_access = enable;
163 self
164 }
165
166 pub fn max_depth(mut self, depth: usize) -> Self {
168 self.config.max_hierarchy_depth = depth;
169 self
170 }
171
172 pub fn enable_caching(mut self, enable: bool) -> Self {
174 self.config.cache_hierarchy = enable;
175 self
176 }
177
178 pub fn max_traversal_size(mut self, size: usize) -> Self {
180 self.config.max_traversal_size = size;
181 self
182 }
183
184 pub fn include_permission_counts(mut self, include: bool) -> Self {
186 self.config.include_permission_counts = include;
187 self
188 }
189
190 pub fn build(self) -> HierarchyConfig {
192 self.config
193 }
194}
195
196impl Default for HierarchyConfigBuilder {
197 fn default() -> Self {
198 Self::new()
199 }
200}
201
202impl RoleHierarchyTree {
203 pub fn new(root: RoleNode) -> Self {
205 let total_roles = root.descendant_count + 1;
206 let max_depth = Self::calculate_max_depth(&root);
207
208 Self {
209 root,
210 total_roles,
211 max_depth,
212 metadata: HierarchyMetadata {
213 #[cfg(feature = "persistence")]
214 generated_at: chrono::Utc::now(),
215 schema_version: "1.1.0".to_string(),
216 total_permissions: 0, generation_time_ms: 0,
218 },
219 }
220 }
221
222 fn calculate_max_depth(node: &RoleNode) -> usize {
224 if node.children.is_empty() {
225 node.depth
226 } else {
227 node.children
228 .iter()
229 .map(Self::calculate_max_depth)
230 .max()
231 .unwrap_or(node.depth)
232 }
233 }
234
235 pub fn flatten(&self) -> Vec<&Role> {
237 let mut roles = Vec::new();
238 Self::flatten_node(&self.root, &mut roles);
239 roles
240 }
241
242 fn flatten_node<'a>(node: &'a RoleNode, roles: &mut Vec<&'a Role>) {
244 roles.push(&node.role);
245 for child in &node.children {
246 Self::flatten_node(child, roles);
247 }
248 }
249
250 pub fn find_node(&self, role_id: &str) -> Option<&RoleNode> {
252 Self::find_node_recursive(&self.root, role_id)
253 }
254
255 fn find_node_recursive<'a>(node: &'a RoleNode, role_id: &str) -> Option<&'a RoleNode> {
257 if node.role.id() == role_id {
258 return Some(node);
259 }
260
261 for child in &node.children {
262 if let Some(found) = Self::find_node_recursive(child, role_id) {
263 return Some(found);
264 }
265 }
266
267 None
268 }
269}
270
271impl RoleNode {
272 pub fn new(role: Role, depth: usize) -> Self {
274 Self {
275 role,
276 children: Vec::new(),
277 depth,
278 descendant_count: 0,
279 }
280 }
281
282 pub fn add_child(&mut self, child: RoleNode) {
284 self.descendant_count += child.descendant_count + 1;
285 self.children.push(child);
286 }
287
288 pub fn get_descendant_ids(&self) -> Vec<String> {
290 let mut ids = Vec::new();
291 for child in &self.children {
292 ids.push(child.role.id().to_string());
293 ids.extend(child.get_descendant_ids());
294 }
295 ids
296 }
297
298 pub fn is_leaf(&self) -> bool {
300 self.children.is_empty()
301 }
302
303 pub fn is_root(&self) -> bool {
305 self.depth == 0
306 }
307}
308
309impl RoleRelationship {
310 pub fn new(
312 child_role_id: String,
313 parent_role_id: String,
314 relationship_type: RelationshipType,
315 ) -> Self {
316 Self {
317 child_role_id,
318 parent_role_id,
319 relationship_type,
320 #[cfg(feature = "persistence")]
321 created_at: Some(chrono::Utc::now()),
322 metadata: HashMap::new(),
323 }
324 }
325
326 pub fn direct(child_role_id: String, parent_role_id: String) -> Self {
328 Self::new(child_role_id, parent_role_id, RelationshipType::Direct)
329 }
330
331 pub fn inherited(child_role_id: String, parent_role_id: String) -> Self {
333 Self::new(child_role_id, parent_role_id, RelationshipType::Inherited)
334 }
335
336 pub fn with_metadata(mut self, key: String, value: String) -> Self {
338 self.metadata.insert(key, value);
339 self
340 }
341
342 pub fn is_direct(&self) -> bool {
344 self.relationship_type == RelationshipType::Direct
345 }
346
347 pub fn is_inherited(&self) -> bool {
349 self.relationship_type == RelationshipType::Inherited
350 }
351}
352
353#[cfg(test)]
354mod tests {
355 use super::*;
356 use crate::role::Role;
357
358 #[test]
359 fn test_hierarchy_config_builder() {
360 let config = HierarchyConfigBuilder::new()
361 .enable_hierarchy_access(true)
362 .max_depth(15)
363 .enable_caching(false)
364 .max_traversal_size(500)
365 .build();
366
367 assert!(config.enable_hierarchy_access);
368 assert_eq!(config.max_hierarchy_depth, 15);
369 assert!(!config.cache_hierarchy);
370 assert_eq!(config.max_traversal_size, 500);
371 }
372
373 #[test]
374 fn test_role_node_creation() {
375 let role = Role::new("test_role");
376 let node = RoleNode::new(role, 2);
377
378 assert_eq!(node.depth, 2);
379 assert_eq!(node.descendant_count, 0);
380 assert!(node.is_leaf());
381 assert!(!node.is_root());
382 }
383
384 #[test]
385 fn test_role_relationship_creation() {
386 let rel = RoleRelationship::direct("child".to_string(), "parent".to_string());
387
388 assert_eq!(rel.child_role_id, "child");
389 assert_eq!(rel.parent_role_id, "parent");
390 assert!(rel.is_direct());
391 assert!(!rel.is_inherited());
392 }
393
394 #[test]
395 fn test_hierarchy_tree_creation() {
396 let role = Role::new("root");
397 let root_node = RoleNode::new(role, 0);
398 let tree = RoleHierarchyTree::new(root_node);
399
400 assert_eq!(tree.total_roles, 1);
401 assert_eq!(tree.max_depth, 0);
402 assert_eq!(tree.metadata.schema_version, "1.1.0");
403 }
404}