Skip to main content

geode_client/
auth.rs

1//! Authentication and authorization client.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6/// User in the system
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct User {
9    pub id: i64,
10    pub username: String,
11    pub email: String,
12    pub is_active: bool,
13    pub created_at: DateTime<Utc>,
14    pub roles: Vec<String>,
15}
16
17/// Role in the RBAC system
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct Role {
20    pub id: i64,
21    pub name: String,
22    pub description: String,
23    pub permissions: Vec<String>,
24}
25
26/// Permission
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct Permission {
29    pub id: i64,
30    pub name: String,
31    pub resource: String,
32    pub action: String,
33}
34
35/// RLS Policy
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct RLSPolicy {
38    pub id: i64,
39    pub name: String,
40    pub table: String,
41    pub operation: String,
42    pub enabled: bool,
43}
44
45/// Session information
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct SessionInfo {
48    pub token: String,
49    pub user_id: i64,
50    pub username: String,
51    pub expires_at: DateTime<Utc>,
52    pub roles: Vec<String>,
53}
54
55/// Authentication client
56pub struct AuthClient {
57    // Connection reference would go here
58}
59
60impl AuthClient {
61    pub fn new() -> Self {
62        Self {}
63    }
64}
65
66impl Default for AuthClient {
67    fn default() -> Self {
68        Self::new()
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    use chrono::TimeZone;
76
77    // ==================== User Tests ====================
78
79    #[test]
80    fn test_user_creation() {
81        let user = User {
82            id: 1,
83            username: "alice".to_string(),
84            email: "alice@example.com".to_string(),
85            is_active: true,
86            created_at: Utc.with_ymd_and_hms(2024, 1, 15, 10, 30, 0).unwrap(),
87            roles: vec!["admin".to_string(), "user".to_string()],
88        };
89        assert_eq!(user.id, 1);
90        assert_eq!(user.username, "alice");
91        assert_eq!(user.email, "alice@example.com");
92        assert!(user.is_active);
93        assert_eq!(user.roles.len(), 2);
94    }
95
96    #[test]
97    fn test_user_clone() {
98        let user = User {
99            id: 1,
100            username: "bob".to_string(),
101            email: "bob@example.com".to_string(),
102            is_active: false,
103            created_at: Utc::now(),
104            roles: vec![],
105        };
106        let cloned = user.clone();
107        assert_eq!(cloned.id, user.id);
108        assert_eq!(cloned.username, user.username);
109    }
110
111    #[test]
112    fn test_user_serialization() {
113        let user = User {
114            id: 1,
115            username: "test".to_string(),
116            email: "test@example.com".to_string(),
117            is_active: true,
118            created_at: Utc.with_ymd_and_hms(2024, 1, 15, 10, 30, 0).unwrap(),
119            roles: vec!["user".to_string()],
120        };
121        let json = serde_json::to_string(&user).unwrap();
122        assert!(json.contains("\"username\":\"test\""));
123        assert!(json.contains("\"email\":\"test@example.com\""));
124    }
125
126    #[test]
127    fn test_user_deserialization() {
128        let json = r#"{
129            "id": 42,
130            "username": "alice",
131            "email": "alice@test.com",
132            "is_active": true,
133            "created_at": "2024-01-15T10:30:00Z",
134            "roles": ["admin"]
135        }"#;
136        let user: User = serde_json::from_str(json).unwrap();
137        assert_eq!(user.id, 42);
138        assert_eq!(user.username, "alice");
139        assert_eq!(user.roles, vec!["admin"]);
140    }
141
142    #[test]
143    fn test_user_debug() {
144        let user = User {
145            id: 1,
146            username: "debug_test".to_string(),
147            email: "debug@test.com".to_string(),
148            is_active: true,
149            created_at: Utc::now(),
150            roles: vec![],
151        };
152        let debug_str = format!("{:?}", user);
153        assert!(debug_str.contains("User"));
154        assert!(debug_str.contains("debug_test"));
155    }
156
157    // ==================== Role Tests ====================
158
159    #[test]
160    fn test_role_creation() {
161        let role = Role {
162            id: 1,
163            name: "admin".to_string(),
164            description: "Administrator role".to_string(),
165            permissions: vec![
166                "read".to_string(),
167                "write".to_string(),
168                "delete".to_string(),
169            ],
170        };
171        assert_eq!(role.id, 1);
172        assert_eq!(role.name, "admin");
173        assert_eq!(role.permissions.len(), 3);
174    }
175
176    #[test]
177    fn test_role_clone() {
178        let role = Role {
179            id: 2,
180            name: "user".to_string(),
181            description: "Regular user".to_string(),
182            permissions: vec!["read".to_string()],
183        };
184        let cloned = role.clone();
185        assert_eq!(cloned.name, "user");
186    }
187
188    #[test]
189    fn test_role_serialization() {
190        let role = Role {
191            id: 1,
192            name: "moderator".to_string(),
193            description: "Can moderate content".to_string(),
194            permissions: vec!["read".to_string(), "moderate".to_string()],
195        };
196        let json = serde_json::to_string(&role).unwrap();
197        assert!(json.contains("\"name\":\"moderator\""));
198    }
199
200    #[test]
201    fn test_role_deserialization() {
202        let json = r#"{
203            "id": 5,
204            "name": "viewer",
205            "description": "Read-only access",
206            "permissions": ["read"]
207        }"#;
208        let role: Role = serde_json::from_str(json).unwrap();
209        assert_eq!(role.id, 5);
210        assert_eq!(role.name, "viewer");
211    }
212
213    // ==================== Permission Tests ====================
214
215    #[test]
216    fn test_permission_creation() {
217        let perm = Permission {
218            id: 1,
219            name: "users:read".to_string(),
220            resource: "users".to_string(),
221            action: "read".to_string(),
222        };
223        assert_eq!(perm.id, 1);
224        assert_eq!(perm.name, "users:read");
225        assert_eq!(perm.resource, "users");
226        assert_eq!(perm.action, "read");
227    }
228
229    #[test]
230    fn test_permission_clone() {
231        let perm = Permission {
232            id: 2,
233            name: "posts:write".to_string(),
234            resource: "posts".to_string(),
235            action: "write".to_string(),
236        };
237        let cloned = perm.clone();
238        assert_eq!(cloned.action, "write");
239    }
240
241    #[test]
242    fn test_permission_serialization() {
243        let perm = Permission {
244            id: 1,
245            name: "nodes:delete".to_string(),
246            resource: "nodes".to_string(),
247            action: "delete".to_string(),
248        };
249        let json = serde_json::to_string(&perm).unwrap();
250        assert!(json.contains("\"action\":\"delete\""));
251    }
252
253    #[test]
254    fn test_permission_deserialization() {
255        let json = r#"{
256            "id": 10,
257            "name": "graphs:create",
258            "resource": "graphs",
259            "action": "create"
260        }"#;
261        let perm: Permission = serde_json::from_str(json).unwrap();
262        assert_eq!(perm.id, 10);
263        assert_eq!(perm.resource, "graphs");
264    }
265
266    // ==================== RLSPolicy Tests ====================
267
268    #[test]
269    fn test_rls_policy_creation() {
270        let policy = RLSPolicy {
271            id: 1,
272            name: "user_isolation".to_string(),
273            table: "nodes".to_string(),
274            operation: "SELECT".to_string(),
275            enabled: true,
276        };
277        assert_eq!(policy.id, 1);
278        assert_eq!(policy.name, "user_isolation");
279        assert!(policy.enabled);
280    }
281
282    #[test]
283    fn test_rls_policy_disabled() {
284        let policy = RLSPolicy {
285            id: 2,
286            name: "disabled_policy".to_string(),
287            table: "edges".to_string(),
288            operation: "INSERT".to_string(),
289            enabled: false,
290        };
291        assert!(!policy.enabled);
292    }
293
294    #[test]
295    fn test_rls_policy_clone() {
296        let policy = RLSPolicy {
297            id: 3,
298            name: "test_policy".to_string(),
299            table: "test_table".to_string(),
300            operation: "UPDATE".to_string(),
301            enabled: true,
302        };
303        let cloned = policy.clone();
304        assert_eq!(cloned.operation, "UPDATE");
305    }
306
307    #[test]
308    fn test_rls_policy_serialization() {
309        let policy = RLSPolicy {
310            id: 1,
311            name: "row_filter".to_string(),
312            table: "users".to_string(),
313            operation: "DELETE".to_string(),
314            enabled: true,
315        };
316        let json = serde_json::to_string(&policy).unwrap();
317        assert!(json.contains("\"enabled\":true"));
318    }
319
320    #[test]
321    fn test_rls_policy_deserialization() {
322        let json = r#"{
323            "id": 7,
324            "name": "tenant_isolation",
325            "table": "tenants",
326            "operation": "ALL",
327            "enabled": true
328        }"#;
329        let policy: RLSPolicy = serde_json::from_str(json).unwrap();
330        assert_eq!(policy.id, 7);
331        assert_eq!(policy.table, "tenants");
332    }
333
334    // ==================== SessionInfo Tests ====================
335
336    #[test]
337    fn test_session_info_creation() {
338        let session = SessionInfo {
339            token: "abc123xyz".to_string(),
340            user_id: 42,
341            username: "alice".to_string(),
342            expires_at: Utc.with_ymd_and_hms(2024, 12, 31, 23, 59, 59).unwrap(),
343            roles: vec!["admin".to_string(), "user".to_string()],
344        };
345        assert_eq!(session.token, "abc123xyz");
346        assert_eq!(session.user_id, 42);
347        assert_eq!(session.roles.len(), 2);
348    }
349
350    #[test]
351    fn test_session_info_clone() {
352        let session = SessionInfo {
353            token: "token123".to_string(),
354            user_id: 1,
355            username: "bob".to_string(),
356            expires_at: Utc::now(),
357            roles: vec![],
358        };
359        let cloned = session.clone();
360        assert_eq!(cloned.token, "token123");
361    }
362
363    #[test]
364    fn test_session_info_serialization() {
365        let session = SessionInfo {
366            token: "secret_token".to_string(),
367            user_id: 100,
368            username: "testuser".to_string(),
369            expires_at: Utc.with_ymd_and_hms(2024, 6, 15, 12, 0, 0).unwrap(),
370            roles: vec!["viewer".to_string()],
371        };
372        let json = serde_json::to_string(&session).unwrap();
373        assert!(json.contains("\"user_id\":100"));
374    }
375
376    #[test]
377    fn test_session_info_deserialization() {
378        let json = r#"{
379            "token": "jwt_token_here",
380            "user_id": 99,
381            "username": "session_user",
382            "expires_at": "2024-12-25T00:00:00Z",
383            "roles": ["guest"]
384        }"#;
385        let session: SessionInfo = serde_json::from_str(json).unwrap();
386        assert_eq!(session.token, "jwt_token_here");
387        assert_eq!(session.user_id, 99);
388    }
389
390    // ==================== AuthClient Tests ====================
391
392    #[test]
393    fn test_auth_client_new() {
394        let client = AuthClient::new();
395        // AuthClient is currently a stub, just verify it can be created
396        let _ = client;
397    }
398
399    #[test]
400    fn test_auth_client_default() {
401        let client = AuthClient::default();
402        let _ = client;
403    }
404}