eth_id/privacy/
virtualizer.rs1use crate::error::{Result, EthIdError};
2use crate::parser::ParsedDocument;
3use crate::claims::DateClaim;
4use chrono::{NaiveDate, Utc};
5
6pub struct DataVirtualizer;
7
8impl DataVirtualizer {
9 pub fn new() -> Self {
10 Self
11 }
12
13 pub fn virtualize_date_check(
14 &self,
15 document: &ParsedDocument,
16 date_claim: &DateClaim,
17 ) -> Result<bool> {
18 if let Some(age_threshold) = date_claim.age_threshold {
19 return self.check_age_threshold(document, age_threshold);
20 }
21
22 if let Some(days_threshold) = date_claim.days_threshold {
23 return self.check_days_threshold(document, days_threshold);
24 }
25
26 Ok(false)
27 }
28
29 fn check_age_threshold(&self, document: &ParsedDocument, threshold: u32) -> Result<bool> {
30 let dob_str = document.get_field("date_of_birth")
31 .ok_or_else(|| EthIdError::PrivacyFilter("Date of birth not found".to_string()))?;
32
33 let dob = self.parse_date(dob_str)?;
34 let today = Utc::now().naive_utc().date();
35
36 let age_days = (today - dob).num_days();
37 let age_years = age_days / 365;
38
39 tracing::debug!("Calculated age: {} years (threshold: {})", age_years, threshold);
40
41 Ok(age_years >= threshold as i64)
42 }
43
44 fn check_days_threshold(&self, document: &ParsedDocument, threshold: i64) -> Result<bool> {
45 let date_fields = ["date_of_birth", "expiry_date", "date_0", "date_1"];
46
47 for field in &date_fields {
48 if let Some(date_str) = document.get_field(*field) {
49 if let Ok(date) = self.parse_date(date_str) {
50 let today = Utc::now().naive_utc().date();
51 let days_diff = (today - date).num_days().abs();
52
53 tracing::debug!("Days difference for {}: {} (threshold: {})", field, days_diff, threshold);
54
55 if days_diff <= threshold {
56 return Ok(true);
57 }
58 }
59 }
60 }
61
62 Ok(false)
63 }
64
65 fn parse_date(&self, date_str: &str) -> Result<NaiveDate> {
66 let formats = [
67 "%d/%m/%Y",
68 "%Y-%m-%d",
69 "%d-%m-%Y",
70 "%m/%d/%Y",
71 ];
72
73 for format in &formats {
74 if let Ok(date) = NaiveDate::parse_from_str(date_str.trim(), format) {
75 return Ok(date);
76 }
77 }
78
79 Err(EthIdError::PrivacyFilter(
80 format!("Unable to parse date: {}", date_str)
81 ))
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::parser::DocumentType;
89
90 #[test]
91 fn test_parse_date_formats() {
92 let virtualizer = DataVirtualizer::new();
93
94 assert!(virtualizer.parse_date("15/03/1990").is_ok());
95 assert!(virtualizer.parse_date("1990-03-15").is_ok());
96 assert!(virtualizer.parse_date("15-03-1990").is_ok());
97 }
98}