Skip to main content

litellm_rs/core/security/
gdpr.rs

1//! GDPR compliance tools
2//!
3//! Tools for managing data retention, consent, and export in compliance with GDPR.
4
5use std::collections::HashMap;
6
7use super::types::*;
8
9/// GDPR compliance tools
10pub struct GDPRCompliance {
11    /// Data retention policies
12    retention_policies: HashMap<String, RetentionPolicy>,
13    /// Consent management
14    consent_manager: ConsentManager,
15    /// Data export tools
16    export_tools: DataExportTools,
17}
18
19impl GDPRCompliance {
20    /// Create a new GDPR compliance instance
21    pub fn new() -> Self {
22        Self {
23            retention_policies: HashMap::new(),
24            consent_manager: ConsentManager::new(),
25            export_tools: DataExportTools::new(),
26        }
27    }
28
29    /// Add a retention policy
30    pub fn add_retention_policy(&mut self, data_type: String, policy: RetentionPolicy) {
31        self.retention_policies.insert(data_type, policy);
32    }
33
34    /// Get retention policy for data type
35    pub fn get_retention_policy(&self, data_type: &str) -> Option<&RetentionPolicy> {
36        self.retention_policies.get(data_type)
37    }
38
39    /// Get consent manager
40    pub fn consent_manager(&self) -> &ConsentManager {
41        &self.consent_manager
42    }
43
44    /// Get mutable consent manager
45    pub fn consent_manager_mut(&mut self) -> &mut ConsentManager {
46        &mut self.consent_manager
47    }
48
49    /// Get export tools
50    pub fn export_tools(&self) -> &DataExportTools {
51        &self.export_tools
52    }
53}
54
55impl Default for GDPRCompliance {
56    fn default() -> Self {
57        Self::new()
58    }
59}
60
61impl ConsentManager {
62    /// Create a new consent manager
63    pub fn new() -> Self {
64        Self {
65            consents: HashMap::new(),
66        }
67    }
68
69    /// Add user consent
70    pub fn add_consent(&mut self, user_id: String, consent: UserConsent) {
71        self.consents.insert(user_id, consent);
72    }
73
74    /// Get user consent
75    pub fn get_consent(&self, user_id: &str) -> Option<&UserConsent> {
76        self.consents.get(user_id)
77    }
78
79    /// Check if user has consented
80    pub fn has_consent(&self, user_id: &str) -> bool {
81        self.consents
82            .get(user_id)
83            .map(|c| c.consented)
84            .unwrap_or(false)
85    }
86
87    /// Revoke user consent
88    pub fn revoke_consent(&mut self, user_id: &str) {
89        if let Some(consent) = self.consents.get_mut(user_id) {
90            consent.consented = false;
91            consent.timestamp = chrono::Utc::now();
92        }
93    }
94}
95
96impl Default for ConsentManager {
97    fn default() -> Self {
98        Self::new()
99    }
100}
101
102impl DataExportTools {
103    /// Create a new data export tools instance
104    pub fn new() -> Self {
105        Self {
106            formats: vec![
107                ExportFormat::Json,
108                ExportFormat::Csv,
109                ExportFormat::Xml,
110                ExportFormat::Pdf,
111            ],
112        }
113    }
114
115    /// Get supported formats
116    pub fn supported_formats(&self) -> &[ExportFormat] {
117        &self.formats
118    }
119
120    /// Check if format is supported
121    pub fn is_format_supported(&self, format: &ExportFormat) -> bool {
122        self.formats.iter().any(|f| {
123            matches!(
124                (f, format),
125                (ExportFormat::Json, ExportFormat::Json)
126                    | (ExportFormat::Csv, ExportFormat::Csv)
127                    | (ExportFormat::Xml, ExportFormat::Xml)
128                    | (ExportFormat::Pdf, ExportFormat::Pdf)
129            )
130        })
131    }
132}
133
134impl Default for DataExportTools {
135    fn default() -> Self {
136        Self::new()
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143    use chrono::Utc;
144
145    // ==================== GDPRCompliance Tests ====================
146
147    #[test]
148    fn test_gdpr_compliance_new() {
149        let gdpr = GDPRCompliance::new();
150        assert!(gdpr.retention_policies.is_empty());
151    }
152
153    #[test]
154    fn test_gdpr_compliance_default() {
155        let gdpr = GDPRCompliance::default();
156        assert!(gdpr.retention_policies.is_empty());
157    }
158
159    #[test]
160    fn test_gdpr_compliance_add_retention_policy() {
161        let mut gdpr = GDPRCompliance::new();
162        let policy = RetentionPolicy {
163            data_type: "logs".to_string(),
164            retention_days: 30,
165            auto_delete: true,
166            anonymization: None,
167        };
168        gdpr.add_retention_policy("logs".to_string(), policy);
169        assert!(gdpr.get_retention_policy("logs").is_some());
170    }
171
172    #[test]
173    fn test_gdpr_compliance_get_retention_policy_not_found() {
174        let gdpr = GDPRCompliance::new();
175        assert!(gdpr.get_retention_policy("nonexistent").is_none());
176    }
177
178    #[test]
179    fn test_gdpr_compliance_multiple_policies() {
180        let mut gdpr = GDPRCompliance::new();
181        gdpr.add_retention_policy(
182            "logs".to_string(),
183            RetentionPolicy {
184                data_type: "logs".to_string(),
185                retention_days: 30,
186                auto_delete: true,
187                anonymization: None,
188            },
189        );
190        gdpr.add_retention_policy(
191            "metrics".to_string(),
192            RetentionPolicy {
193                data_type: "metrics".to_string(),
194                retention_days: 90,
195                auto_delete: false,
196                anonymization: None,
197            },
198        );
199        assert_eq!(
200            gdpr.get_retention_policy("logs").unwrap().retention_days,
201            30
202        );
203        assert_eq!(
204            gdpr.get_retention_policy("metrics").unwrap().retention_days,
205            90
206        );
207    }
208
209    #[test]
210    fn test_gdpr_compliance_consent_manager() {
211        let gdpr = GDPRCompliance::new();
212        let _ = gdpr.consent_manager();
213    }
214
215    #[test]
216    fn test_gdpr_compliance_consent_manager_mut() {
217        let mut gdpr = GDPRCompliance::new();
218        let consent_mgr = gdpr.consent_manager_mut();
219        consent_mgr.add_consent(
220            "user1".to_string(),
221            UserConsent {
222                user_id: "user1".to_string(),
223                consented: true,
224                timestamp: Utc::now(),
225                version: "1.0".to_string(),
226                permissions: vec!["data_processing".to_string()],
227            },
228        );
229        assert!(gdpr.consent_manager().has_consent("user1"));
230    }
231
232    #[test]
233    fn test_gdpr_compliance_export_tools() {
234        let gdpr = GDPRCompliance::new();
235        let tools = gdpr.export_tools();
236        assert!(!tools.supported_formats().is_empty());
237    }
238
239    // ==================== ConsentManager Tests ====================
240
241    #[test]
242    fn test_consent_manager_new() {
243        let manager = ConsentManager::new();
244        assert!(!manager.has_consent("unknown_user"));
245    }
246
247    #[test]
248    fn test_consent_manager_default() {
249        let manager = ConsentManager::default();
250        assert!(!manager.has_consent("unknown_user"));
251    }
252
253    #[test]
254    fn test_consent_manager_add_consent() {
255        let mut manager = ConsentManager::new();
256        let consent = UserConsent {
257            user_id: "user123".to_string(),
258            consented: true,
259            timestamp: Utc::now(),
260            version: "2.0".to_string(),
261            permissions: vec!["analytics".to_string()],
262        };
263        manager.add_consent("user123".to_string(), consent);
264        assert!(manager.has_consent("user123"));
265    }
266
267    #[test]
268    fn test_consent_manager_get_consent() {
269        let mut manager = ConsentManager::new();
270        let consent = UserConsent {
271            user_id: "user456".to_string(),
272            consented: true,
273            timestamp: Utc::now(),
274            version: "1.5".to_string(),
275            permissions: vec!["marketing".to_string()],
276        };
277        manager.add_consent("user456".to_string(), consent);
278        let retrieved = manager.get_consent("user456").unwrap();
279        assert_eq!(retrieved.version, "1.5");
280    }
281
282    #[test]
283    fn test_consent_manager_get_consent_not_found() {
284        let manager = ConsentManager::new();
285        assert!(manager.get_consent("unknown").is_none());
286    }
287
288    #[test]
289    fn test_consent_manager_has_consent_false() {
290        let mut manager = ConsentManager::new();
291        let consent = UserConsent {
292            user_id: "user789".to_string(),
293            consented: false,
294            timestamp: Utc::now(),
295            version: "1.0".to_string(),
296            permissions: vec![],
297        };
298        manager.add_consent("user789".to_string(), consent);
299        assert!(!manager.has_consent("user789"));
300    }
301
302    #[test]
303    fn test_consent_manager_revoke_consent() {
304        let mut manager = ConsentManager::new();
305        let consent = UserConsent {
306            user_id: "user_revoke".to_string(),
307            consented: true,
308            timestamp: Utc::now(),
309            version: "1.0".to_string(),
310            permissions: vec!["all".to_string()],
311        };
312        manager.add_consent("user_revoke".to_string(), consent);
313        assert!(manager.has_consent("user_revoke"));
314        manager.revoke_consent("user_revoke");
315        assert!(!manager.has_consent("user_revoke"));
316    }
317
318    #[test]
319    fn test_consent_manager_revoke_nonexistent() {
320        let mut manager = ConsentManager::new();
321        manager.revoke_consent("nonexistent");
322        // Should not panic
323    }
324
325    // ==================== DataExportTools Tests ====================
326
327    #[test]
328    fn test_data_export_tools_new() {
329        let tools = DataExportTools::new();
330        assert_eq!(tools.supported_formats().len(), 4);
331    }
332
333    #[test]
334    fn test_data_export_tools_default() {
335        let tools = DataExportTools::default();
336        assert_eq!(tools.supported_formats().len(), 4);
337    }
338
339    #[test]
340    fn test_data_export_tools_json_supported() {
341        let tools = DataExportTools::new();
342        assert!(tools.is_format_supported(&ExportFormat::Json));
343    }
344
345    #[test]
346    fn test_data_export_tools_csv_supported() {
347        let tools = DataExportTools::new();
348        assert!(tools.is_format_supported(&ExportFormat::Csv));
349    }
350
351    #[test]
352    fn test_data_export_tools_xml_supported() {
353        let tools = DataExportTools::new();
354        assert!(tools.is_format_supported(&ExportFormat::Xml));
355    }
356
357    #[test]
358    fn test_data_export_tools_pdf_supported() {
359        let tools = DataExportTools::new();
360        assert!(tools.is_format_supported(&ExportFormat::Pdf));
361    }
362}