1use crate::{
4 core::{RoleSystem, RoleSystemConfig},
5 error::Result,
6 resource::Resource,
7 role::Role,
8 storage::Storage,
9 subject::Subject,
10};
11use std::{
12 collections::{HashMap, HashSet},
13 sync::Arc,
14 time::Duration,
15};
16use tokio::sync::{Mutex, RwLock};
17
18pub struct AsyncRoleSystem<S>
20where
21 S: Storage + Send + Sync,
22{
23 inner: Arc<RwLock<RoleSystem<S>>>,
24}
25
26impl<S> AsyncRoleSystem<S>
27where
28 S: Storage + Send + Sync,
29{
30 pub fn new(role_system: RoleSystem<S>) -> Self {
32 Self {
33 inner: Arc::new(RwLock::new(role_system)),
34 }
35 }
36
37 pub async fn register_role(&self, role: Role) -> Result<()> {
39 let mut system = self.inner.write().await;
40 system.register_role(role)
41 }
42
43 pub async fn get_role(&self, name: &str) -> Result<Option<Role>> {
45 let system = self.inner.read().await;
46 system.get_role(name)
47 }
48
49 pub async fn add_role_inheritance(&self, child: &str, parent: &str) -> Result<()> {
51 let mut system = self.inner.write().await;
52 system.add_role_inheritance(child, parent)
53 }
54
55 pub async fn remove_role_inheritance(&self, child: &str, parent: &str) -> Result<()> {
57 let mut system = self.inner.write().await;
58 system.remove_role_inheritance(child, parent)
59 }
60
61 pub async fn assign_role(&self, subject: &Subject, role_name: &str) -> Result<()> {
63 let mut system = self.inner.write().await;
64 system.assign_role(subject, role_name)
65 }
66
67 pub async fn remove_role(&self, subject: &Subject, role_name: &str) -> Result<()> {
69 let mut system = self.inner.write().await;
70 system.remove_role(subject, role_name)
71 }
72
73 pub async fn elevate_role(
75 &self,
76 subject: &Subject,
77 role_name: &str,
78 duration: Option<Duration>,
79 ) -> Result<()> {
80 let mut system = self.inner.write().await;
81 system.elevate_role(subject, role_name, duration)
82 }
83
84 pub async fn check_permission(
86 &self,
87 subject: &Subject,
88 action: &str,
89 resource: &Resource,
90 ) -> Result<bool> {
91 let system = self.inner.read().await;
92 system.check_permission(subject, action, resource)
93 }
94
95 pub async fn check_permission_with_context(
97 &self,
98 subject: &Subject,
99 action: &str,
100 resource: &Resource,
101 context: &HashMap<String, String>,
102 ) -> Result<bool> {
103 let system = self.inner.read().await;
104 system.check_permission_with_context(subject, action, resource, context)
105 }
106
107 pub async fn get_subject_roles(&self, subject: &Subject) -> Result<HashSet<String>> {
109 let system = self.inner.read().await;
110 system.get_subject_roles(subject)
111 }
112
113 pub async fn batch_check_permissions(
115 &self,
116 subject: &Subject,
117 checks: &[(String, Resource)], ) -> Result<Vec<(String, Resource, bool)>> {
119 let system = self.inner.read().await;
120 let mut results = Vec::new();
121
122 for (action, resource) in checks {
123 let granted = system.check_permission(subject, action, resource)?;
124 results.push((action.clone(), resource.clone(), granted));
125 }
126
127 Ok(results)
128 }
129
130 pub async fn atomic_role_operations<F, R>(&self, operations: F) -> Result<R>
132 where
133 F: FnOnce(&mut RoleSystem<S>) -> Result<R> + Send,
134 {
135 let mut system = self.inner.write().await;
136 operations(&mut *system)
137 }
138
139 pub async fn with_read_access<F, R>(&self, operation: F) -> R
141 where
142 F: FnOnce(&RoleSystem<S>) -> R + Send,
143 {
144 let system = self.inner.read().await;
145 operation(&*system)
146 }
147
148 pub async fn get_hierarchy_tree(
181 &self,
182 config: Option<crate::hierarchy::HierarchyConfig>,
183 ) -> Result<crate::hierarchy::RoleHierarchyTree> {
184 use crate::hierarchy::{RoleHierarchyTree, RoleNode};
185 use std::time::Instant;
186
187 let config = config.unwrap_or_default();
188
189 if !config.enable_hierarchy_access {
190 return Err(crate::error::Error::InvalidResource(
191 "Hierarchy access is disabled in configuration".to_string(),
192 ));
193 }
194
195 let start_time = Instant::now();
196 let _system = self.inner.read().await;
197
198 let all_roles: Vec<crate::role::Role> = vec![];
201
202 if all_roles.is_empty() {
203 let empty_role = crate::role::Role::new("__empty__");
205 let root_node = RoleNode::new(empty_role, 0);
206 let mut tree = RoleHierarchyTree::new(root_node);
207 tree.metadata.generation_time_ms = start_time.elapsed().as_millis() as u64;
208 return Ok(tree);
209 }
210
211 let empty_role = crate::role::Role::new("__empty__");
213 let root_node = RoleNode::new(empty_role, 0);
214 let mut tree = RoleHierarchyTree::new(root_node);
215 tree.metadata.generation_time_ms = start_time.elapsed().as_millis() as u64;
216 tree.metadata.total_permissions = 0;
217
218 Ok(tree)
219 }
220
221 pub async fn get_role_ancestors(
247 &self,
248 role_id: &str,
249 _include_inherited: bool,
250 ) -> Result<Vec<String>> {
251 let system = self.inner.read().await;
252
253 let _role = system.get_role(role_id)?;
255
256 Ok(Vec::new())
259 }
260
261 pub async fn get_role_descendants(
288 &self,
289 role_id: &str,
290 _include_inherited: bool,
291 ) -> Result<Vec<String>> {
292 let system = self.inner.read().await;
293
294 let _role = system.get_role(role_id)?;
296
297 Ok(Vec::new())
300 }
301 pub async fn get_role_siblings(&self, role_id: &str) -> Result<Vec<String>> {
326 let system = self.inner.read().await;
327
328 let _role = system.get_role(role_id)?;
331
332 Ok(Vec::new())
334 }
335
336 pub async fn get_role_relationships(
367 &self,
368 _relationship_type: Option<crate::hierarchy::RelationshipType>,
369 ) -> Result<Vec<crate::hierarchy::RoleRelationship>> {
370 let system = self.inner.read().await;
371
372 drop(system);
376
377 Ok(Vec::new())
379 }
380
381 pub async fn is_role_ancestor(&self, ancestor_id: &str, descendant_id: &str) -> Result<bool> {
410 let system = self.inner.read().await;
411
412 let _ancestor = system.get_role(ancestor_id)?;
415 let _descendant = system.get_role(descendant_id)?;
416
417 Ok(false)
419 }
420
421 pub async fn get_role_depth(&self, role_id: &str) -> Result<usize> {
445 let system = self.inner.read().await;
446
447 let _role = system.get_role(role_id)?;
450
451 Ok(0)
453 }
454}
455
456impl<S> Clone for AsyncRoleSystem<S>
457where
458 S: Storage + Send + Sync,
459{
460 fn clone(&self) -> Self {
461 Self {
462 inner: Arc::clone(&self.inner),
463 }
464 }
465}
466
467#[async_trait::async_trait]
469pub trait AsyncStorage: Send + Sync {
470 async fn store_role(&mut self, role: Role) -> Result<()>;
472
473 async fn get_role(&self, name: &str) -> Result<Option<Role>>;
475
476 async fn role_exists(&self, name: &str) -> Result<bool>;
478
479 async fn delete_role(&mut self, name: &str) -> Result<bool>;
481
482 async fn list_roles(&self) -> Result<Vec<String>>;
484
485 async fn update_role(&mut self, role: Role) -> Result<()>;
487}
488
489#[derive(Debug, Default)]
491pub struct AsyncMemoryStorage {
492 roles: Arc<RwLock<HashMap<String, Role>>>,
493}
494
495impl AsyncMemoryStorage {
496 pub fn new() -> Self {
498 Self {
499 roles: Arc::new(RwLock::new(HashMap::new())),
500 }
501 }
502
503 pub async fn role_count(&self) -> usize {
505 self.roles.read().await.len()
506 }
507
508 pub async fn clear(&self) {
510 self.roles.write().await.clear();
511 }
512}
513
514#[async_trait::async_trait]
515impl AsyncStorage for AsyncMemoryStorage {
516 async fn store_role(&mut self, role: Role) -> Result<()> {
517 let name = role.name().to_string();
518 self.roles.write().await.insert(name, role);
519 Ok(())
520 }
521
522 async fn get_role(&self, name: &str) -> Result<Option<Role>> {
523 Ok(self.roles.read().await.get(name).cloned())
524 }
525
526 async fn role_exists(&self, name: &str) -> Result<bool> {
527 Ok(self.roles.read().await.contains_key(name))
528 }
529
530 async fn delete_role(&mut self, name: &str) -> Result<bool> {
531 Ok(self.roles.write().await.remove(name).is_some())
532 }
533
534 async fn list_roles(&self) -> Result<Vec<String>> {
535 Ok(self.roles.read().await.keys().cloned().collect())
536 }
537
538 async fn update_role(&mut self, role: Role) -> Result<()> {
539 let name = role.name().to_string();
540 self.roles.write().await.insert(name, role);
541 Ok(())
542 }
543}
544
545pub struct AsyncStorageAdapter<S>
547where
548 S: Storage + Send + Sync,
549{
550 storage: Arc<Mutex<S>>,
551}
552
553impl<S> AsyncStorageAdapter<S>
554where
555 S: Storage + Send + Sync,
556{
557 pub fn new(storage: S) -> Self {
559 Self {
560 storage: Arc::new(Mutex::new(storage)),
561 }
562 }
563}
564
565#[async_trait::async_trait]
566impl<S> AsyncStorage for AsyncStorageAdapter<S>
567where
568 S: Storage + Send + Sync,
569{
570 async fn store_role(&mut self, role: Role) -> Result<()> {
571 let mut storage = self.storage.lock().await;
572 storage.store_role(role)
573 }
574
575 async fn get_role(&self, name: &str) -> Result<Option<Role>> {
576 let storage = self.storage.lock().await;
577 storage.get_role(name)
578 }
579
580 async fn role_exists(&self, name: &str) -> Result<bool> {
581 let storage = self.storage.lock().await;
582 storage.role_exists(name)
583 }
584
585 async fn delete_role(&mut self, name: &str) -> Result<bool> {
586 let mut storage = self.storage.lock().await;
587 storage.delete_role(name)
588 }
589
590 async fn list_roles(&self) -> Result<Vec<String>> {
591 let storage = self.storage.lock().await;
592 storage.list_roles()
593 }
594
595 async fn update_role(&mut self, role: Role) -> Result<()> {
596 let mut storage = self.storage.lock().await;
597 storage.update_role(role)
598 }
599}
600
601pub struct AsyncRoleSystemBuilder<S>
603where
604 S: Storage + Send + Sync,
605{
606 config: RoleSystemConfig,
607 storage: Option<S>,
608}
609
610impl<S> AsyncRoleSystemBuilder<S>
611where
612 S: Storage + Send + Sync + Default,
613{
614 pub fn new() -> Self {
616 Self {
617 config: RoleSystemConfig::default(),
618 storage: None,
619 }
620 }
621}
622
623impl<S> Default for AsyncRoleSystemBuilder<S>
624where
625 S: Storage + Send + Sync + Default,
626{
627 fn default() -> Self {
628 Self::new()
629 }
630}
631
632impl<S> AsyncRoleSystemBuilder<S>
633where
634 S: Storage + Send + Sync,
635{
636 pub fn with_storage(storage: S) -> Self {
638 Self {
639 config: RoleSystemConfig::default(),
640 storage: Some(storage),
641 }
642 }
643
644 pub fn config(mut self, config: RoleSystemConfig) -> Self {
646 self.config = config;
647 self
648 }
649
650 pub fn max_hierarchy_depth(mut self, depth: usize) -> Self {
652 self.config.max_hierarchy_depth = depth;
653 self
654 }
655
656 pub fn enable_caching(mut self, enabled: bool) -> Self {
658 self.config.enable_caching = enabled;
659 self
660 }
661
662 pub fn cache_ttl_seconds(mut self, ttl: u64) -> Self {
664 self.config.cache_ttl_seconds = ttl;
665 self
666 }
667
668 pub fn enable_audit(mut self, enabled: bool) -> Self {
670 self.config.enable_audit = enabled;
671 self
672 }
673
674 pub fn build(self) -> AsyncRoleSystem<S>
676 where
677 S: Default,
678 {
679 let storage = self.storage.unwrap_or_default();
680 let role_system = RoleSystem::with_storage(storage, self.config);
681 AsyncRoleSystem::new(role_system)
682 }
683
684 pub fn build_with_storage(self, storage: S) -> AsyncRoleSystem<S> {
686 let role_system = RoleSystem::with_storage(storage, self.config);
687 AsyncRoleSystem::new(role_system)
688 }
689}
690
691#[cfg(test)]
692mod tests {
693 use super::*;
694 use crate::{permission::Permission, storage::MemoryStorage};
695
696 #[tokio::test]
697 async fn test_async_role_system() {
698 let storage = MemoryStorage::new();
699 let config = RoleSystemConfig::default();
700 let role_system = RoleSystem::with_storage(storage, config);
701 let async_system = AsyncRoleSystem::new(role_system);
702
703 let role = Role::new("async-test").add_permission(Permission::new("read", "documents"));
705
706 async_system.register_role(role).await.unwrap();
707
708 let subject = Subject::user("user1");
710 async_system
711 .assign_role(&subject, "async-test")
712 .await
713 .unwrap();
714
715 let resource = Resource::new("doc1", "documents");
717 let can_read = async_system
718 .check_permission(&subject, "read", &resource)
719 .await
720 .unwrap();
721
722 assert!(can_read);
723 }
724
725 #[tokio::test]
726 async fn test_async_batch_permissions() {
727 let storage = MemoryStorage::new();
728 let config = RoleSystemConfig::default();
729 let role_system = RoleSystem::with_storage(storage, config);
730 let async_system = AsyncRoleSystem::new(role_system);
731
732 let role = Role::new("batch-test")
734 .add_permission(Permission::new("read", "documents"))
735 .add_permission(Permission::new("write", "documents"));
736
737 async_system.register_role(role).await.unwrap();
738
739 let subject = Subject::user("user1");
740 async_system
741 .assign_role(&subject, "batch-test")
742 .await
743 .unwrap();
744
745 let checks = vec![
747 ("read".to_string(), Resource::new("doc1", "documents")),
748 ("write".to_string(), Resource::new("doc1", "documents")),
749 ("delete".to_string(), Resource::new("doc1", "documents")),
750 ];
751
752 let results = async_system
753 .batch_check_permissions(&subject, &checks)
754 .await
755 .unwrap();
756
757 assert_eq!(results.len(), 3);
758 assert!(results[0].2); assert!(results[1].2); assert!(!results[2].2); }
762
763 #[tokio::test]
764 async fn test_async_memory_storage() {
765 let mut storage = AsyncMemoryStorage::new();
766
767 let role =
768 Role::new("async-storage-test").add_permission(Permission::new("read", "documents"));
769
770 storage.store_role(role.clone()).await.unwrap();
772 assert_eq!(storage.role_count().await, 1);
773
774 assert!(storage.role_exists("async-storage-test").await.unwrap());
776
777 let retrieved = storage
779 .get_role("async-storage-test")
780 .await
781 .unwrap()
782 .unwrap();
783 assert_eq!(retrieved.name(), "async-storage-test");
784
785 let roles = storage.list_roles().await.unwrap();
787 assert_eq!(roles.len(), 1);
788
789 assert!(storage.delete_role("async-storage-test").await.unwrap());
791 assert_eq!(storage.role_count().await, 0);
792 }
793
794 #[tokio::test]
795 async fn test_async_builder() {
796 let async_system = AsyncRoleSystemBuilder::<MemoryStorage>::new()
797 .max_hierarchy_depth(5)
798 .enable_caching(false)
799 .build();
800
801 let role = Role::new("builder-test");
803 async_system.register_role(role).await.unwrap();
804
805 let retrieved = async_system.get_role("builder-test").await.unwrap();
806 assert!(retrieved.is_some());
807 }
808}