1use crate::traits::{Authenticatable, AuthorizationProvider};
7use crate::{AuthError, AuthResult};
8use async_trait::async_trait;
9use chrono::{DateTime, Utc};
10use serde::{Deserialize, Serialize};
11use std::collections::{HashMap, HashSet};
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
15pub struct Role {
16 pub id: String,
18
19 pub name: String,
21
22 pub description: Option<String>,
24
25 pub parent_roles: Vec<String>,
27
28 pub permissions: Vec<String>,
30
31 pub is_active: bool,
33
34 pub created_at: DateTime<Utc>,
36
37 pub updated_at: DateTime<Utc>,
39}
40
41impl Role {
42 pub fn new(id: String, name: String) -> Self {
44 let now = Utc::now();
45 Self {
46 id,
47 name,
48 description: None,
49 parent_roles: vec![],
50 permissions: vec![],
51 is_active: true,
52 created_at: now,
53 updated_at: now,
54 }
55 }
56
57 pub fn add_parent_role(&mut self, role_id: String) {
59 if !self.parent_roles.contains(&role_id) {
60 self.parent_roles.push(role_id);
61 self.updated_at = Utc::now();
62 }
63 }
64
65 pub fn add_permission(&mut self, permission: String) {
67 if !self.permissions.contains(&permission) {
68 self.permissions.push(permission);
69 self.updated_at = Utc::now();
70 }
71 }
72
73 pub fn remove_permission(&mut self, permission: &str) {
75 if let Some(pos) = self.permissions.iter().position(|p| p == permission) {
76 self.permissions.remove(pos);
77 self.updated_at = Utc::now();
78 }
79 }
80
81 pub fn has_direct_permission(&self, permission: &str) -> bool {
83 self.permissions.contains(&permission.to_string())
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
89pub struct Permission {
90 pub id: String,
92
93 pub name: String,
95
96 pub description: Option<String>,
98
99 pub resource: String,
101
102 pub action: String,
104
105 pub conditions: HashMap<String, serde_json::Value>,
107
108 pub is_active: bool,
110
111 pub created_at: DateTime<Utc>,
113
114 pub updated_at: DateTime<Utc>,
116}
117
118impl Permission {
119 pub fn new(id: String, name: String, resource: String, action: String) -> Self {
121 let now = Utc::now();
122 Self {
123 id,
124 name,
125 description: None,
126 resource,
127 action,
128 conditions: HashMap::new(),
129 is_active: true,
130 created_at: now,
131 updated_at: now,
132 }
133 }
134
135 pub fn add_condition(&mut self, key: String, value: serde_json::Value) {
137 self.conditions.insert(key, value);
138 self.updated_at = Utc::now();
139 }
140
141 pub fn matches(&self, resource: &str, action: &str) -> bool {
143 self.is_active
144 && (self.resource == "*" || self.resource == resource)
145 && (self.action == "*" || self.action == action)
146 }
147
148 pub fn check_conditions(&self, context: &HashMap<String, serde_json::Value>) -> bool {
150 if self.conditions.is_empty() {
151 return true;
152 }
153
154 for (key, expected_value) in &self.conditions {
156 match context.get(key) {
157 Some(actual_value) if actual_value == expected_value => continue,
158 _ => return false,
159 }
160 }
161
162 true
163 }
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct UserRole {
169 pub user_id: String,
171
172 pub role_id: String,
174
175 pub assigned_at: DateTime<Utc>,
177
178 pub expires_at: Option<DateTime<Utc>>,
180
181 pub assigned_by: Option<String>,
183
184 pub is_active: bool,
186}
187
188impl UserRole {
189 pub fn new(user_id: String, role_id: String) -> Self {
191 Self {
192 user_id,
193 role_id,
194 assigned_at: Utc::now(),
195 expires_at: None,
196 assigned_by: None,
197 is_active: true,
198 }
199 }
200
201 pub fn is_valid(&self) -> bool {
203 self.is_active && !self.is_expired()
204 }
205
206 pub fn is_expired(&self) -> bool {
208 self.expires_at.is_some_and(|exp| Utc::now() > exp)
209 }
210}
211
212#[async_trait]
214pub trait RbacProvider: Send + Sync {
215 async fn get_role(&self, role_id: &str) -> AuthResult<Option<Role>>;
217
218 async fn get_permission(&self, permission_id: &str) -> AuthResult<Option<Permission>>;
220
221 async fn get_user_roles(&self, user_id: &str) -> AuthResult<Vec<Role>>;
223
224 async fn get_user_permissions(&self, user_id: &str) -> AuthResult<Vec<Permission>>;
226
227 async fn assign_role_to_user(&self, user_id: &str, role_id: &str) -> AuthResult<()>;
229
230 async fn remove_role_from_user(&self, user_id: &str, role_id: &str) -> AuthResult<()>;
232
233 async fn user_has_role(&self, user_id: &str, role_id: &str) -> AuthResult<bool>;
235
236 async fn user_has_permission(
238 &self,
239 user_id: &str,
240 resource: &str,
241 action: &str,
242 context: Option<&HashMap<String, serde_json::Value>>,
243 ) -> AuthResult<bool>;
244
245 async fn get_effective_user_roles(&self, user_id: &str) -> AuthResult<Vec<Role>>;
247}
248
249#[derive(Debug, Clone)]
251pub struct InMemoryRbacProvider {
252 roles: HashMap<String, Role>,
253 permissions: HashMap<String, Permission>,
254 user_roles: HashMap<String, Vec<UserRole>>,
255}
256
257impl InMemoryRbacProvider {
258 pub fn new() -> Self {
260 Self {
261 roles: HashMap::new(),
262 permissions: HashMap::new(),
263 user_roles: HashMap::new(),
264 }
265 }
266
267 pub fn add_role(&mut self, role: Role) {
269 self.roles.insert(role.id.clone(), role);
270 }
271
272 pub fn add_permission(&mut self, permission: Permission) {
274 self.permissions.insert(permission.id.clone(), permission);
275 }
276
277 pub fn assign_role_to_user_mut(&mut self, user_id: &str, role_id: &str) -> AuthResult<()> {
279 if !self.roles.contains_key(role_id) {
281 return Err(AuthError::access_denied(format!(
282 "Role '{}' does not exist",
283 role_id
284 )));
285 }
286
287 let user_roles = self.user_roles.entry(user_id.to_string()).or_default();
288
289 if user_roles
291 .iter()
292 .any(|ur| ur.role_id == role_id && ur.is_valid())
293 {
294 return Ok(()); }
296
297 let assignment = UserRole::new(user_id.to_string(), role_id.to_string());
299 user_roles.push(assignment);
300
301 Ok(())
302 }
303
304 pub fn remove_role_from_user_mut(&mut self, user_id: &str, role_id: &str) -> AuthResult<()> {
306 if let Some(user_roles) = self.user_roles.get_mut(user_id) {
307 user_roles.retain(|ur| !(ur.role_id == role_id && ur.is_valid()));
308 }
309 Ok(())
310 }
311
312 pub fn get_users_with_role(&self, role_id: &str) -> Vec<String> {
314 let mut users = Vec::new();
315
316 for (user_id, user_roles) in &self.user_roles {
317 if user_roles
318 .iter()
319 .any(|ur| ur.role_id == role_id && ur.is_valid())
320 {
321 users.push(user_id.clone());
322 }
323 }
324
325 users
326 }
327
328 pub fn get_role_stats(&self) -> HashMap<String, u32> {
330 let mut stats = HashMap::new();
331
332 for role_id in self.roles.keys() {
333 let count = self.get_users_with_role(role_id).len() as u32;
334 stats.insert(role_id.clone(), count);
335 }
336
337 stats
338 }
339
340 fn get_inherited_roles(&self, role_id: &str, visited: &mut HashSet<String>) -> Vec<Role> {
342 let mut inherited = vec![];
343
344 if visited.contains(role_id) {
345 return inherited; }
347
348 visited.insert(role_id.to_string());
349
350 if let Some(role) = self.roles.get(role_id) {
351 inherited.push(role.clone());
352
353 for parent_id in &role.parent_roles {
355 inherited.extend(self.get_inherited_roles(parent_id, visited));
356 }
357 }
358
359 inherited
360 }
361}
362
363impl Default for InMemoryRbacProvider {
364 fn default() -> Self {
365 Self::new()
366 }
367}
368
369#[async_trait]
370impl RbacProvider for InMemoryRbacProvider {
371 async fn get_role(&self, role_id: &str) -> AuthResult<Option<Role>> {
372 Ok(self.roles.get(role_id).cloned())
373 }
374
375 async fn get_permission(&self, permission_id: &str) -> AuthResult<Option<Permission>> {
376 Ok(self.permissions.get(permission_id).cloned())
377 }
378
379 async fn get_user_roles(&self, user_id: &str) -> AuthResult<Vec<Role>> {
380 let empty_vec = vec![];
381 let user_role_assignments = self.user_roles.get(user_id).unwrap_or(&empty_vec);
382 let mut roles = vec![];
383
384 for assignment in user_role_assignments {
385 if assignment.is_valid() {
386 if let Some(role) = self.roles.get(&assignment.role_id) {
387 if role.is_active {
388 roles.push(role.clone());
389 }
390 }
391 }
392 }
393
394 Ok(roles)
395 }
396
397 async fn get_user_permissions(&self, user_id: &str) -> AuthResult<Vec<Permission>> {
398 let roles = self.get_effective_user_roles(user_id).await?;
399 let mut permissions = HashMap::new();
400
401 for role in roles {
403 for permission_id in &role.permissions {
404 if let Some(permission) = self.permissions.get(permission_id) {
405 if permission.is_active {
406 permissions.insert(permission.id.clone(), permission.clone());
407 }
408 }
409 }
410 }
411
412 Ok(permissions.into_values().collect())
413 }
414
415 async fn assign_role_to_user(&self, _user_id: &str, _role_id: &str) -> AuthResult<()> {
416 Err(AuthError::access_denied(
420 "Use assign_role_to_user_mut on the provider directly",
421 ))
422 }
423
424 async fn remove_role_from_user(&self, _user_id: &str, _role_id: &str) -> AuthResult<()> {
425 Err(AuthError::access_denied(
429 "Use remove_role_from_user_mut on the provider directly",
430 ))
431 }
432
433 async fn user_has_role(&self, user_id: &str, role_id: &str) -> AuthResult<bool> {
434 let effective_roles = self.get_effective_user_roles(user_id).await?;
435 Ok(effective_roles.iter().any(|role| role.id == role_id))
436 }
437
438 async fn user_has_permission(
439 &self,
440 user_id: &str,
441 resource: &str,
442 action: &str,
443 context: Option<&HashMap<String, serde_json::Value>>,
444 ) -> AuthResult<bool> {
445 let permissions = self.get_user_permissions(user_id).await?;
446 let empty_context = HashMap::new();
447 let context = context.unwrap_or(&empty_context);
448
449 for permission in permissions {
450 if permission.matches(resource, action) && permission.check_conditions(context) {
451 return Ok(true);
452 }
453 }
454
455 Ok(false)
456 }
457
458 async fn get_effective_user_roles(&self, user_id: &str) -> AuthResult<Vec<Role>> {
459 let direct_roles = self.get_user_roles(user_id).await?;
460 let mut all_roles = HashMap::new();
461
462 for role in direct_roles {
464 let mut visited = HashSet::new();
465 let inherited = self.get_inherited_roles(&role.id, &mut visited);
466
467 for inherited_role in inherited {
468 if inherited_role.is_active {
469 all_roles.insert(inherited_role.id.clone(), inherited_role);
470 }
471 }
472 }
473
474 Ok(all_roles.into_values().collect())
475 }
476}
477
478pub struct RbacAuthorizationAdapter<R, U>
480where
481 R: RbacProvider,
482 U: Authenticatable,
483{
484 rbac_provider: R,
485 _phantom: std::marker::PhantomData<U>,
486}
487
488impl<R, U> RbacAuthorizationAdapter<R, U>
489where
490 R: RbacProvider,
491 U: Authenticatable,
492{
493 pub fn new(rbac_provider: R) -> Self {
495 Self {
496 rbac_provider,
497 _phantom: std::marker::PhantomData,
498 }
499 }
500
501 pub fn rbac_provider(&self) -> &R {
503 &self.rbac_provider
504 }
505}
506
507#[async_trait]
508impl<R, U> AuthorizationProvider for RbacAuthorizationAdapter<R, U>
509where
510 R: RbacProvider + Send + Sync,
511 U: Authenticatable,
512 U::Id: std::fmt::Display,
513{
514 type User = U;
515 type Role = Role;
516 type Permission = Permission;
517
518 async fn has_role(&self, user: &Self::User, role: &str) -> AuthResult<bool> {
519 let user_id = user.id().to_string();
520 self.rbac_provider.user_has_role(&user_id, role).await
521 }
522
523 async fn has_permission(&self, user: &Self::User, permission: &str) -> AuthResult<bool> {
524 let parts: Vec<&str> = permission.split('.').collect();
526 if parts.len() == 2 {
527 let resource = parts[0];
528 let action = parts[1];
529 let user_id = user.id().to_string();
530 self.rbac_provider
531 .user_has_permission(&user_id, resource, action, None)
532 .await
533 } else {
534 let user_id = user.id().to_string();
536 self.rbac_provider
537 .user_has_permission(&user_id, "*", permission, None)
538 .await
539 }
540 }
541
542 async fn has_permission_with_context(
543 &self,
544 user: &Self::User,
545 resource: &str,
546 action: &str,
547 context: Option<&HashMap<String, serde_json::Value>>,
548 ) -> AuthResult<bool> {
549 let user_id = user.id().to_string();
550 self.rbac_provider
551 .user_has_permission(&user_id, resource, action, context)
552 .await
553 }
554
555 async fn get_user_roles(&self, user: &Self::User) -> AuthResult<Vec<Self::Role>> {
556 let user_id = user.id().to_string();
557 self.rbac_provider.get_effective_user_roles(&user_id).await
558 }
559
560 async fn get_user_permissions(&self, user: &Self::User) -> AuthResult<Vec<Self::Permission>> {
561 let user_id = user.id().to_string();
562 self.rbac_provider.get_user_permissions(&user_id).await
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569 use serde_json::json;
570
571 #[test]
572 fn test_role_creation() {
573 let role = Role::new("admin".to_string(), "Administrator".to_string());
574
575 assert_eq!(role.id, "admin");
576 assert_eq!(role.name, "Administrator");
577 assert!(role.is_active);
578 assert!(role.permissions.is_empty());
579 assert!(role.parent_roles.is_empty());
580 }
581
582 #[test]
583 fn test_role_permission_management() {
584 let mut role = Role::new("editor".to_string(), "Content Editor".to_string());
585
586 role.add_permission("articles.create".to_string());
587 role.add_permission("articles.edit".to_string());
588
589 assert!(role.has_direct_permission("articles.create"));
590 assert!(role.has_direct_permission("articles.edit"));
591 assert!(!role.has_direct_permission("articles.delete"));
592
593 role.remove_permission("articles.edit");
594 assert!(!role.has_direct_permission("articles.edit"));
595 }
596
597 #[test]
598 fn test_permission_creation() {
599 let permission = Permission::new(
600 "articles.create".to_string(),
601 "Create Articles".to_string(),
602 "articles".to_string(),
603 "create".to_string(),
604 );
605
606 assert_eq!(permission.id, "articles.create");
607 assert_eq!(permission.resource, "articles");
608 assert_eq!(permission.action, "create");
609 assert!(permission.is_active);
610 }
611
612 #[test]
613 fn test_permission_matching() {
614 let mut permission = Permission::new(
615 "articles.create".to_string(),
616 "Create Articles".to_string(),
617 "articles".to_string(),
618 "create".to_string(),
619 );
620
621 assert!(permission.matches("articles", "create"));
622 assert!(!permission.matches("articles", "delete"));
623 assert!(!permission.matches("users", "create"));
624
625 permission.resource = "*".to_string();
627 assert!(permission.matches("articles", "create"));
628 assert!(permission.matches("users", "create"));
629
630 permission.resource = "articles".to_string();
632 permission.action = "*".to_string();
633 assert!(permission.matches("articles", "create"));
634 assert!(permission.matches("articles", "delete"));
635 assert!(!permission.matches("users", "create"));
636 }
637
638 #[test]
639 fn test_permission_conditions() {
640 let mut permission = Permission::new(
641 "articles.edit".to_string(),
642 "Edit Own Articles".to_string(),
643 "articles".to_string(),
644 "edit".to_string(),
645 );
646
647 permission.add_condition("owner".to_string(), json!("self"));
648
649 let mut context = HashMap::new();
650 context.insert("owner".to_string(), json!("self"));
651
652 assert!(permission.check_conditions(&context));
653
654 context.insert("owner".to_string(), json!("other"));
655 assert!(!permission.check_conditions(&context));
656 }
657
658 #[test]
659 fn test_user_role_assignment() {
660 let assignment = UserRole::new("user123".to_string(), "admin".to_string());
661
662 assert_eq!(assignment.user_id, "user123");
663 assert_eq!(assignment.role_id, "admin");
664 assert!(assignment.is_valid());
665 assert!(!assignment.is_expired());
666 }
667
668 #[tokio::test]
669 async fn test_in_memory_rbac_provider() {
670 let mut provider = InMemoryRbacProvider::new();
671
672 let mut admin_role = Role::new("admin".to_string(), "Administrator".to_string());
674 admin_role.add_permission("users.create".to_string());
675
676 let permission = Permission::new(
677 "users.create".to_string(),
678 "Create Users".to_string(),
679 "users".to_string(),
680 "create".to_string(),
681 );
682
683 provider.add_role(admin_role.clone());
684 provider.add_permission(permission);
685
686 let retrieved_role = provider.get_role("admin").await.unwrap();
688 assert_eq!(retrieved_role, Some(admin_role));
689
690 let non_existent = provider.get_role("nonexistent").await.unwrap();
692 assert_eq!(non_existent, None);
693 }
694
695 #[tokio::test]
696 async fn test_hierarchical_roles() {
697 let mut provider = InMemoryRbacProvider::new();
698
699 let mut admin_role = Role::new("admin".to_string(), "Administrator".to_string());
701 admin_role.add_permission("system.admin".to_string());
702
703 let mut manager_role = Role::new("manager".to_string(), "Manager".to_string());
704 manager_role.add_parent_role("admin".to_string());
705 manager_role.add_permission("team.manage".to_string());
706
707 let mut employee_role = Role::new("employee".to_string(), "Employee".to_string());
708 employee_role.add_parent_role("manager".to_string());
709 employee_role.add_permission("tasks.view".to_string());
710
711 provider.add_role(admin_role);
712 provider.add_role(manager_role);
713 provider.add_role(employee_role);
714
715 let admin_perm = Permission::new(
717 "system.admin".to_string(),
718 "System Administration".to_string(),
719 "system".to_string(),
720 "admin".to_string(),
721 );
722 let manager_perm = Permission::new(
723 "team.manage".to_string(),
724 "Team Management".to_string(),
725 "team".to_string(),
726 "manage".to_string(),
727 );
728 let employee_perm = Permission::new(
729 "tasks.view".to_string(),
730 "View Tasks".to_string(),
731 "tasks".to_string(),
732 "view".to_string(),
733 );
734
735 provider.add_permission(admin_perm);
736 provider.add_permission(manager_perm);
737 provider.add_permission(employee_perm);
738
739 let mut visited = HashSet::new();
741 let inherited = provider.get_inherited_roles("employee", &mut visited);
742
743 let role_ids: Vec<&str> = inherited.iter().map(|r| r.id.as_str()).collect();
744 assert!(role_ids.contains(&"employee"));
745 assert!(role_ids.contains(&"manager"));
746 assert!(role_ids.contains(&"admin"));
747 }
748
749 #[derive(Debug, Clone)]
751 struct MockUser {
752 id: String,
753 username: String,
754 }
755
756 #[async_trait]
757 impl Authenticatable for MockUser {
758 type Id = String;
759 type Credentials = String;
760
761 fn id(&self) -> &Self::Id {
762 &self.id
763 }
764
765 fn username(&self) -> &str {
766 &self.username
767 }
768
769 async fn verify_credentials(&self, _credentials: &Self::Credentials) -> AuthResult<bool> {
770 Ok(true)
771 }
772 }
773
774 #[tokio::test]
775 async fn test_rbac_authorization_adapter() {
776 let mut rbac_provider = InMemoryRbacProvider::new();
777
778 let mut admin_role = Role::new("admin".to_string(), "Administrator".to_string());
780 admin_role.add_permission("users.create".to_string());
781
782 let permission = Permission::new(
783 "users.create".to_string(),
784 "Create Users".to_string(),
785 "users".to_string(),
786 "create".to_string(),
787 );
788
789 rbac_provider.add_role(admin_role);
790 rbac_provider.add_permission(permission);
791
792 let adapter = RbacAuthorizationAdapter::<_, MockUser>::new(rbac_provider);
794
795 let user = MockUser {
797 id: "user123".to_string(),
798 username: "admin@example.com".to_string(),
799 };
800
801 let has_permission = adapter.has_permission(&user, "users.create").await.unwrap();
803 assert!(!has_permission);
805
806 let has_permission_with_context = adapter
808 .has_permission_with_context(&user, "users", "create", None)
809 .await
810 .unwrap();
811 assert!(!has_permission_with_context);
812
813 let has_role = adapter.has_role(&user, "admin").await.unwrap();
815 assert!(!has_role);
816 }
817
818 #[tokio::test]
819 async fn test_role_assignment_and_checking() {
820 let mut provider = InMemoryRbacProvider::new();
821
822 let mut admin_role = Role::new("admin".to_string(), "Administrator".to_string());
824 admin_role.add_permission("users.create".to_string());
825 admin_role.add_permission("users.delete".to_string());
826
827 let create_permission = Permission::new(
828 "users.create".to_string(),
829 "Create Users".to_string(),
830 "users".to_string(),
831 "create".to_string(),
832 );
833
834 let delete_permission = Permission::new(
835 "users.delete".to_string(),
836 "Delete Users".to_string(),
837 "users".to_string(),
838 "delete".to_string(),
839 );
840
841 provider.add_role(admin_role);
842 provider.add_permission(create_permission);
843 provider.add_permission(delete_permission);
844
845 let user_id = "user123";
846
847 assert!(!provider.user_has_role(user_id, "admin").await.unwrap());
849 assert!(!provider
850 .user_has_permission(user_id, "users", "create", None)
851 .await
852 .unwrap());
853
854 provider.assign_role_to_user_mut(user_id, "admin").unwrap();
856
857 assert!(provider.user_has_role(user_id, "admin").await.unwrap());
859 assert!(provider
860 .user_has_permission(user_id, "users", "create", None)
861 .await
862 .unwrap());
863 assert!(provider
864 .user_has_permission(user_id, "users", "delete", None)
865 .await
866 .unwrap());
867 assert!(!provider
868 .user_has_permission(user_id, "posts", "create", None)
869 .await
870 .unwrap());
871
872 provider.assign_role_to_user_mut(user_id, "admin").unwrap();
874 assert!(provider.user_has_role(user_id, "admin").await.unwrap());
875
876 provider
878 .remove_role_from_user_mut(user_id, "admin")
879 .unwrap();
880 assert!(!provider.user_has_role(user_id, "admin").await.unwrap());
881 assert!(!provider
882 .user_has_permission(user_id, "users", "create", None)
883 .await
884 .unwrap());
885
886 let result = provider.assign_role_to_user_mut(user_id, "nonexistent");
888 assert!(result.is_err());
889 }
890
891 #[tokio::test]
892 async fn test_permission_context_checking() {
893 let mut provider = InMemoryRbacProvider::new();
894
895 let mut editor_role = Role::new("editor".to_string(), "Content Editor".to_string());
897 editor_role.add_permission("articles.edit".to_string());
898
899 let mut edit_permission = Permission::new(
900 "articles.edit".to_string(),
901 "Edit Articles".to_string(),
902 "articles".to_string(),
903 "edit".to_string(),
904 );
905
906 edit_permission.add_condition("owner".to_string(), serde_json::json!("self"));
908
909 provider.add_role(editor_role);
910 provider.add_permission(edit_permission);
911
912 let user_id = "user123";
913 provider.assign_role_to_user_mut(user_id, "editor").unwrap();
914
915 assert!(!provider
917 .user_has_permission(user_id, "articles", "edit", None)
918 .await
919 .unwrap());
920
921 let mut wrong_context = HashMap::new();
923 wrong_context.insert("owner".to_string(), serde_json::json!("other"));
924 assert!(!provider
925 .user_has_permission(user_id, "articles", "edit", Some(&wrong_context))
926 .await
927 .unwrap());
928
929 let mut correct_context = HashMap::new();
931 correct_context.insert("owner".to_string(), serde_json::json!("self"));
932 assert!(provider
933 .user_has_permission(user_id, "articles", "edit", Some(&correct_context))
934 .await
935 .unwrap());
936 }
937
938 #[test]
939 fn test_role_statistics() {
940 let mut provider = InMemoryRbacProvider::new();
941
942 let admin_role = Role::new("admin".to_string(), "Administrator".to_string());
944 let editor_role = Role::new("editor".to_string(), "Editor".to_string());
945
946 provider.add_role(admin_role);
947 provider.add_role(editor_role);
948
949 let stats = provider.get_role_stats();
951 assert_eq!(stats.get("admin"), Some(&0));
952 assert_eq!(stats.get("editor"), Some(&0));
953
954 provider.assign_role_to_user_mut("user1", "admin").unwrap();
956 provider.assign_role_to_user_mut("user2", "admin").unwrap();
957 provider.assign_role_to_user_mut("user3", "editor").unwrap();
958
959 let stats = provider.get_role_stats();
960 assert_eq!(stats.get("admin"), Some(&2));
961 assert_eq!(stats.get("editor"), Some(&1));
962
963 let admin_users = provider.get_users_with_role("admin");
965 assert_eq!(admin_users.len(), 2);
966 assert!(admin_users.contains(&"user1".to_string()));
967 assert!(admin_users.contains(&"user2".to_string()));
968
969 let editor_users = provider.get_users_with_role("editor");
970 assert_eq!(editor_users.len(), 1);
971 assert!(editor_users.contains(&"user3".to_string()));
972 }
973}