koprogo_api/infrastructure/web/handlers/
gdpr_art30_handlers.rs

1use crate::infrastructure::web::{AppState, AuthenticatedUser};
2use actix_web::{get, web, HttpResponse, Responder};
3use serde::Serialize;
4
5#[derive(Debug, Serialize)]
6pub struct DataProcessingActivityDto {
7    pub id: String,
8    pub activity_name: String,
9    pub controller_name: String,
10    pub purpose: String,
11    pub legal_basis: String,
12    pub data_categories: Vec<String>,
13    pub data_subjects: Vec<String>,
14    pub recipients: Vec<String>,
15    pub retention_period: String,
16    pub security_measures: String,
17    pub created_at: String,
18    pub updated_at: String,
19}
20
21#[derive(Debug, Serialize)]
22pub struct DataProcessorAgreementDto {
23    pub id: String,
24    pub processor_name: String,
25    pub service_description: String,
26    pub dpa_signed_at: Option<String>,
27    pub dpa_url: Option<String>,
28    pub transfer_mechanism: Option<String>,
29    pub data_categories: Vec<String>,
30    pub certifications: Option<Vec<String>>,
31    pub created_at: String,
32    pub updated_at: String,
33}
34
35#[derive(Debug, Serialize)]
36pub struct ProcessingActivitiesResponse {
37    pub activities: Vec<DataProcessingActivityDto>,
38    pub total: i64,
39}
40
41#[derive(Debug, Serialize)]
42pub struct ProcessorsResponse {
43    pub processors: Vec<DataProcessorAgreementDto>,
44    pub total: i64,
45}
46
47/// GET /api/v1/admin/gdpr/processing-register — SuperAdmin only
48#[get("/admin/gdpr/processing-register")]
49pub async fn list_processing_activities(
50    data: web::Data<AppState>,
51    auth: AuthenticatedUser,
52) -> impl Responder {
53    if auth.role != "superadmin" {
54        return HttpResponse::Forbidden().json(serde_json::json!({
55            "error": "Access denied. SuperAdmin role required."
56        }));
57    }
58
59    match data.gdpr_art30_use_cases.list_processing_activities().await {
60        Ok(activities) => {
61            let dtos: Vec<DataProcessingActivityDto> = activities
62                .into_iter()
63                .map(|a| DataProcessingActivityDto {
64                    id: a.id.to_string(),
65                    activity_name: a.activity_name,
66                    controller_name: a.controller_name,
67                    purpose: a.purpose,
68                    legal_basis: a.legal_basis,
69                    data_categories: a.data_categories,
70                    data_subjects: a.data_subjects,
71                    recipients: a.recipients,
72                    retention_period: a.retention_period,
73                    security_measures: a.security_measures,
74                    created_at: a.created_at.to_rfc3339(),
75                    updated_at: a.updated_at.to_rfc3339(),
76                })
77                .collect();
78            let total = dtos.len() as i64;
79            HttpResponse::Ok().json(ProcessingActivitiesResponse {
80                activities: dtos,
81                total,
82            })
83        }
84        Err(e) => HttpResponse::InternalServerError().json(
85            serde_json::json!({ "error": format!("Failed to fetch processing activities: {}", e) }),
86        ),
87    }
88}
89
90/// GET /api/v1/admin/gdpr/processors — SuperAdmin only
91#[get("/admin/gdpr/processors")]
92pub async fn list_sub_processors(
93    data: web::Data<AppState>,
94    auth: AuthenticatedUser,
95) -> impl Responder {
96    if auth.role != "superadmin" {
97        return HttpResponse::Forbidden().json(serde_json::json!({
98            "error": "Access denied. SuperAdmin role required."
99        }));
100    }
101
102    match data.gdpr_art30_use_cases.list_processor_agreements().await {
103        Ok(processors) => {
104            let dtos: Vec<DataProcessorAgreementDto> = processors
105                .into_iter()
106                .map(|p| DataProcessorAgreementDto {
107                    id: p.id.to_string(),
108                    processor_name: p.processor_name,
109                    service_description: p.service_description,
110                    dpa_signed_at: p.dpa_signed_at.map(|dt| dt.to_rfc3339()),
111                    dpa_url: p.dpa_url,
112                    transfer_mechanism: p.transfer_mechanism,
113                    data_categories: p.data_categories,
114                    certifications: p.certifications,
115                    created_at: p.created_at.to_rfc3339(),
116                    updated_at: p.updated_at.to_rfc3339(),
117                })
118                .collect();
119            let total = dtos.len() as i64;
120            HttpResponse::Ok().json(ProcessorsResponse {
121                processors: dtos,
122                total,
123            })
124        }
125        Err(e) => HttpResponse::InternalServerError()
126            .json(serde_json::json!({ "error": format!("Failed to fetch sub-processors: {}", e) })),
127    }
128}