koprogo_api/domain/entities/
gdpr_rectification.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
10pub struct GdprRectificationRequest {
11 pub id: Uuid,
12 pub user_id: Uuid,
13 pub organization_id: Option<Uuid>,
14 pub requested_at: DateTime<Utc>,
15 pub status: RectificationStatus,
16 pub changes: Vec<FieldChange>,
17 pub reason: Option<String>,
18 pub processed_at: Option<DateTime<Utc>>,
19 pub processed_by: Option<Uuid>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
23pub enum RectificationStatus {
24 Pending,
25 Approved,
26 Rejected,
27 Applied,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
31pub struct FieldChange {
32 pub entity_type: String, pub entity_id: Uuid,
34 pub field_name: String,
35 pub old_value: Option<String>,
36 pub new_value: String,
37}
38
39impl GdprRectificationRequest {
40 pub fn new(
42 user_id: Uuid,
43 organization_id: Option<Uuid>,
44 changes: Vec<FieldChange>,
45 reason: Option<String>,
46 ) -> Self {
47 Self {
48 id: Uuid::new_v4(),
49 user_id,
50 organization_id,
51 requested_at: Utc::now(),
52 status: RectificationStatus::Pending,
53 changes,
54 reason,
55 processed_at: None,
56 processed_by: None,
57 }
58 }
59
60 pub fn approve(&mut self, admin_id: Uuid) {
62 self.status = RectificationStatus::Approved;
63 self.processed_at = Some(Utc::now());
64 self.processed_by = Some(admin_id);
65 }
66
67 pub fn reject(&mut self, admin_id: Uuid) {
69 self.status = RectificationStatus::Rejected;
70 self.processed_at = Some(Utc::now());
71 self.processed_by = Some(admin_id);
72 }
73
74 pub fn mark_applied(&mut self) {
76 self.status = RectificationStatus::Applied;
77 }
78
79 pub fn is_pending(&self) -> bool {
81 matches!(self.status, RectificationStatus::Pending)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_create_rectification_request() {
91 let user_id = Uuid::new_v4();
92 let org_id = Uuid::new_v4();
93 let changes = vec![FieldChange {
94 entity_type: "User".to_string(),
95 entity_id: user_id,
96 field_name: "email".to_string(),
97 old_value: Some("old@example.com".to_string()),
98 new_value: "new@example.com".to_string(),
99 }];
100
101 let request = GdprRectificationRequest::new(
102 user_id,
103 Some(org_id),
104 changes.clone(),
105 Some("Email address was incorrect".to_string()),
106 );
107
108 assert_eq!(request.user_id, user_id);
109 assert_eq!(request.organization_id, Some(org_id));
110 assert!(request.is_pending());
111 assert_eq!(request.changes.len(), 1);
112 assert_eq!(request.changes[0].new_value, "new@example.com");
113 }
114
115 #[test]
116 fn test_approve_request() {
117 let user_id = Uuid::new_v4();
118 let admin_id = Uuid::new_v4();
119 let changes = vec![FieldChange {
120 entity_type: "User".to_string(),
121 entity_id: user_id,
122 field_name: "first_name".to_string(),
123 old_value: Some("Jon".to_string()),
124 new_value: "John".to_string(),
125 }];
126
127 let mut request = GdprRectificationRequest::new(user_id, None, changes, None);
128 request.approve(admin_id);
129
130 assert_eq!(request.status, RectificationStatus::Approved);
131 assert!(request.processed_at.is_some());
132 assert_eq!(request.processed_by, Some(admin_id));
133 assert!(!request.is_pending());
134 }
135
136 #[test]
137 fn test_reject_request() {
138 let user_id = Uuid::new_v4();
139 let admin_id = Uuid::new_v4();
140 let changes = vec![FieldChange {
141 entity_type: "User".to_string(),
142 entity_id: user_id,
143 field_name: "email".to_string(),
144 old_value: Some("old@example.com".to_string()),
145 new_value: "invalid-email".to_string(),
146 }];
147
148 let mut request = GdprRectificationRequest::new(user_id, None, changes, None);
149 request.reject(admin_id);
150
151 assert_eq!(request.status, RectificationStatus::Rejected);
152 assert!(request.processed_at.is_some());
153 assert_eq!(request.processed_by, Some(admin_id));
154 }
155
156 #[test]
157 fn test_mark_applied() {
158 let user_id = Uuid::new_v4();
159 let admin_id = Uuid::new_v4();
160 let changes = vec![FieldChange {
161 entity_type: "User".to_string(),
162 entity_id: user_id,
163 field_name: "last_name".to_string(),
164 old_value: Some("Smith".to_string()),
165 new_value: "Smyth".to_string(),
166 }];
167
168 let mut request = GdprRectificationRequest::new(user_id, None, changes, None);
169 request.approve(admin_id);
170 request.mark_applied();
171
172 assert_eq!(request.status, RectificationStatus::Applied);
173 }
174}