armature_auth/
user.rs

1// User traits and context
2
3use serde::{Deserialize, Serialize};
4
5/// Trait for authenticated users
6pub trait AuthUser: Send + Sync {
7    /// Get user ID
8    fn user_id(&self) -> String;
9
10    /// Check if user is active
11    fn is_active(&self) -> bool {
12        true
13    }
14
15    /// Check if user has a role
16    fn has_role(&self, role: &str) -> bool;
17
18    /// Check if user has any of the roles
19    fn has_any_role(&self, roles: &[&str]) -> bool {
20        roles.iter().any(|role| self.has_role(role))
21    }
22
23    /// Check if user has all roles
24    fn has_all_roles(&self, roles: &[&str]) -> bool {
25        roles.iter().all(|role| self.has_role(role))
26    }
27
28    /// Check if user has a permission
29    fn has_permission(&self, permission: &str) -> bool;
30}
31
32/// User context extracted from requests
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct UserContext {
35    /// User ID
36    pub user_id: String,
37
38    /// User email
39    pub email: Option<String>,
40
41    /// User roles
42    pub roles: Vec<String>,
43
44    /// User permissions
45    pub permissions: Vec<String>,
46
47    /// Custom metadata
48    #[serde(default)]
49    pub metadata: serde_json::Value,
50}
51
52impl UserContext {
53    /// Create a new user context
54    pub fn new(user_id: String) -> Self {
55        Self {
56            user_id,
57            email: None,
58            roles: Vec::new(),
59            permissions: Vec::new(),
60            metadata: serde_json::Value::Null,
61        }
62    }
63
64    /// Set email
65    pub fn with_email(mut self, email: String) -> Self {
66        self.email = Some(email);
67        self
68    }
69
70    /// Add a role
71    pub fn with_role(mut self, role: String) -> Self {
72        self.roles.push(role);
73        self
74    }
75
76    /// Add roles
77    pub fn with_roles(mut self, roles: Vec<String>) -> Self {
78        self.roles = roles;
79        self
80    }
81
82    /// Add a permission
83    pub fn with_permission(mut self, permission: String) -> Self {
84        self.permissions.push(permission);
85        self
86    }
87
88    /// Add permissions
89    pub fn with_permissions(mut self, permissions: Vec<String>) -> Self {
90        self.permissions = permissions;
91        self
92    }
93
94    /// Set metadata
95    pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
96        self.metadata = metadata;
97        self
98    }
99}
100
101impl AuthUser for UserContext {
102    fn user_id(&self) -> String {
103        self.user_id.clone()
104    }
105
106    fn has_role(&self, role: &str) -> bool {
107        self.roles.iter().any(|r| r == role)
108    }
109
110    fn has_permission(&self, permission: &str) -> bool {
111        self.permissions.iter().any(|p| p == permission)
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_user_context() {
121        let user = UserContext::new("user123".to_string())
122            .with_email("user@example.com".to_string())
123            .with_roles(vec!["admin".to_string(), "user".to_string()])
124            .with_permissions(vec!["read".to_string(), "write".to_string()]);
125
126        assert_eq!(user.user_id(), "user123");
127        assert!(user.has_role("admin"));
128        assert!(user.has_role("user"));
129        assert!(!user.has_role("guest"));
130        assert!(user.has_any_role(&["admin", "guest"]));
131        assert!(!user.has_all_roles(&["admin", "guest"]));
132        assert!(user.has_permission("read"));
133        assert!(user.has_permission("write"));
134        assert!(!user.has_permission("delete"));
135    }
136}