elif_auth/
rbac.rs

1//! Role-Based Access Control (RBAC) system
2//!
3//! This module provides a comprehensive RBAC implementation with roles,
4//! permissions, hierarchical role support, and efficient authorization checking.
5
6use 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/// Represents a role in the RBAC system
14#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
15pub struct Role {
16    /// Unique role identifier
17    pub id: String,
18
19    /// Human-readable role name
20    pub name: String,
21
22    /// Optional description of the role
23    pub description: Option<String>,
24
25    /// Parent roles (for hierarchical RBAC)
26    pub parent_roles: Vec<String>,
27
28    /// Direct permissions assigned to this role
29    pub permissions: Vec<String>,
30
31    /// Whether this role is active
32    pub is_active: bool,
33
34    /// Creation timestamp
35    pub created_at: DateTime<Utc>,
36
37    /// Last update timestamp
38    pub updated_at: DateTime<Utc>,
39}
40
41impl Role {
42    /// Create a new role
43    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    /// Add a parent role (for hierarchical RBAC)
58    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    /// Add a permission to this role
66    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    /// Remove a permission from this role
74    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    /// Check if role has a specific permission directly
82    pub fn has_direct_permission(&self, permission: &str) -> bool {
83        self.permissions.contains(&permission.to_string())
84    }
85}
86
87/// Represents a permission in the RBAC system
88#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
89pub struct Permission {
90    /// Unique permission identifier
91    pub id: String,
92
93    /// Human-readable permission name
94    pub name: String,
95
96    /// Optional description of the permission
97    pub description: Option<String>,
98
99    /// Resource this permission applies to
100    pub resource: String,
101
102    /// Action this permission allows
103    pub action: String,
104
105    /// Optional conditions for this permission
106    pub conditions: HashMap<String, serde_json::Value>,
107
108    /// Whether this permission is active
109    pub is_active: bool,
110
111    /// Creation timestamp
112    pub created_at: DateTime<Utc>,
113
114    /// Last update timestamp
115    pub updated_at: DateTime<Utc>,
116}
117
118impl Permission {
119    /// Create a new permission
120    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    /// Add a condition to this permission
136    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    /// Check if this permission matches a resource and action
142    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    /// Check if conditions are satisfied
149    pub fn check_conditions(&self, context: &HashMap<String, serde_json::Value>) -> bool {
150        if self.conditions.is_empty() {
151            return true;
152        }
153
154        // All conditions must be satisfied
155        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/// User role assignment
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct UserRole {
169    /// User ID
170    pub user_id: String,
171
172    /// Role ID
173    pub role_id: String,
174
175    /// When this assignment was created
176    pub assigned_at: DateTime<Utc>,
177
178    /// Optional expiration time for the role assignment
179    pub expires_at: Option<DateTime<Utc>>,
180
181    /// Who assigned this role
182    pub assigned_by: Option<String>,
183
184    /// Whether this assignment is active
185    pub is_active: bool,
186}
187
188impl UserRole {
189    /// Create a new user role assignment
190    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    /// Check if this role assignment is currently valid
202    pub fn is_valid(&self) -> bool {
203        self.is_active && !self.is_expired()
204    }
205
206    /// Check if this role assignment has expired
207    pub fn is_expired(&self) -> bool {
208        self.expires_at.is_some_and(|exp| Utc::now() > exp)
209    }
210}
211
212/// RBAC authorization provider trait
213#[async_trait]
214pub trait RbacProvider: Send + Sync {
215    /// Get a role by ID
216    async fn get_role(&self, role_id: &str) -> AuthResult<Option<Role>>;
217
218    /// Get a permission by ID
219    async fn get_permission(&self, permission_id: &str) -> AuthResult<Option<Permission>>;
220
221    /// Get all roles for a user
222    async fn get_user_roles(&self, user_id: &str) -> AuthResult<Vec<Role>>;
223
224    /// Get all permissions for a user (direct and through roles)
225    async fn get_user_permissions(&self, user_id: &str) -> AuthResult<Vec<Permission>>;
226
227    /// Assign a role to a user
228    async fn assign_role_to_user(&self, user_id: &str, role_id: &str) -> AuthResult<()>;
229
230    /// Remove a role from a user
231    async fn remove_role_from_user(&self, user_id: &str, role_id: &str) -> AuthResult<()>;
232
233    /// Check if a user has a specific role (including inherited roles)
234    async fn user_has_role(&self, user_id: &str, role_id: &str) -> AuthResult<bool>;
235
236    /// Check if a user has a specific permission
237    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    /// Get effective roles for a user (including inherited roles)
246    async fn get_effective_user_roles(&self, user_id: &str) -> AuthResult<Vec<Role>>;
247}
248
249/// In-memory RBAC provider for testing and simple use cases
250#[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    /// Create a new in-memory RBAC provider
259    pub fn new() -> Self {
260        Self {
261            roles: HashMap::new(),
262            permissions: HashMap::new(),
263            user_roles: HashMap::new(),
264        }
265    }
266
267    /// Add a role
268    pub fn add_role(&mut self, role: Role) {
269        self.roles.insert(role.id.clone(), role);
270    }
271
272    /// Add a permission
273    pub fn add_permission(&mut self, permission: Permission) {
274        self.permissions.insert(permission.id.clone(), permission);
275    }
276
277    /// Assign a role to a user
278    pub fn assign_role_to_user_mut(&mut self, user_id: &str, role_id: &str) -> AuthResult<()> {
279        // Check if role exists
280        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        // Check if user already has this role
290        if user_roles
291            .iter()
292            .any(|ur| ur.role_id == role_id && ur.is_valid())
293        {
294            return Ok(()); // Already assigned
295        }
296
297        // Add the role assignment
298        let assignment = UserRole::new(user_id.to_string(), role_id.to_string());
299        user_roles.push(assignment);
300
301        Ok(())
302    }
303
304    /// Remove a role from a user
305    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    /// Get all users with a specific role
313    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    /// Get role assignment statistics
329    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    /// Get all roles transitively inherited by a role
341    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; // Prevent cycles
346        }
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            // Add parent roles recursively
354            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        // Collect permissions from all roles
402        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        // Note: This is a read-only method in the current trait design
417        // In a real implementation with mutable storage, this would work
418        // For now, we need to use the mutable methods on the provider directly
419        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        // Note: This is a read-only method in the current trait design
426        // In a real implementation with mutable storage, this would work
427        // For now, we need to use the mutable methods on the provider directly
428        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        // Get all roles including inherited ones
463        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
478/// Adapter that implements AuthorizationProvider using RbacProvider
479pub 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    /// Create a new RBAC authorization adapter
494    pub fn new(rbac_provider: R) -> Self {
495        Self {
496            rbac_provider,
497            _phantom: std::marker::PhantomData,
498        }
499    }
500
501    /// Get the underlying RBAC provider
502    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        // For backwards compatibility, parse permission as "resource.action"
525        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            // If not in expected format, try direct permission lookup
535            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        // Test wildcard resource
626        permission.resource = "*".to_string();
627        assert!(permission.matches("articles", "create"));
628        assert!(permission.matches("users", "create"));
629
630        // Test wildcard action
631        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        // Create test role and permission
673        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        // Test role retrieval
687        let retrieved_role = provider.get_role("admin").await.unwrap();
688        assert_eq!(retrieved_role, Some(admin_role));
689
690        // Test non-existent role
691        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        // Create role hierarchy: admin -> manager -> employee
700        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        // Add permissions
716        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        // Test that employee role inherits from manager and admin
740        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    // Mock user for testing
750    #[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        // Create test role and permission
779        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        // Create adapter
793        let adapter = RbacAuthorizationAdapter::<_, MockUser>::new(rbac_provider);
794
795        // Create test user
796        let user = MockUser {
797            id: "user123".to_string(),
798            username: "admin@example.com".to_string(),
799        };
800
801        // Test permission checking (backwards compatibility)
802        let has_permission = adapter.has_permission(&user, "users.create").await.unwrap();
803        // This will be false because we haven't assigned the role to the user yet
804        assert!(!has_permission);
805
806        // Test permission with context
807        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        // Test role checking
814        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        // Create test role and permissions
823        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        // Initially user has no roles
848        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        // Assign admin role to user
855        provider.assign_role_to_user_mut(user_id, "admin").unwrap();
856
857        // Now user should have admin role and permissions
858        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        // Test role assignment twice (should be idempotent)
873        provider.assign_role_to_user_mut(user_id, "admin").unwrap();
874        assert!(provider.user_has_role(user_id, "admin").await.unwrap());
875
876        // Test role removal
877        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        // Test assigning non-existent role
887        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        // Create a role with conditional permission
896        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        // Add condition: user can only edit their own articles
907        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        // Test without context (should fail because of condition)
916        assert!(!provider
917            .user_has_permission(user_id, "articles", "edit", None)
918            .await
919            .unwrap());
920
921        // Test with wrong context
922        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        // Test with correct context
930        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        // Create roles
943        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        // Initially no users assigned
950        let stats = provider.get_role_stats();
951        assert_eq!(stats.get("admin"), Some(&0));
952        assert_eq!(stats.get("editor"), Some(&0));
953
954        // Assign roles to users
955        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        // Test getting users with role
964        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}