nest_data_source_api/
messages.rs

1use crate::api::ApiError;
2use crate::participant_info::{PEPParticipantInfo, ParticipantInfo};
3use libpep::high_level::contexts::PseudonymizationDomain;
4use paas_client::pseudonym_service::PseudonymService;
5use rand::{CryptoRng, RngCore};
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::fmt::Debug;
9
10pub trait HasParticipantInfo {
11    fn participant_info(&self) -> &ParticipantInfo;
12}
13
14pub trait HasPEPParticipantInfo {
15    fn pep_participant_info(&self) -> &PEPParticipantInfo;
16    fn domain_to(&self) -> &PseudonymizationDomain;
17}
18
19pub trait PEPMessageType: Debug {
20    type PEPMessage: HasPEPParticipantInfo + Serialize + Debug;
21    type Message: HasParticipantInfo + Debug;
22    #[allow(async_fn_in_trait)]
23    async fn pack<R: RngCore + CryptoRng>(
24        request: Self::Message,
25        domain_to: PseudonymizationDomain,
26        ps: &mut PseudonymService,
27        rng: &mut R,
28    ) -> Result<Self::PEPMessage, ApiError>;
29
30    #[allow(async_fn_in_trait)]
31    async fn unpack(
32        request: Self::PEPMessage,
33        ps: &mut PseudonymService,
34    ) -> Result<Self::Message, ApiError>;
35}
36
37#[derive(Debug, Serialize, Deserialize)]
38pub struct PEPActivityRequest {
39    pub participant: PEPParticipantInfo,
40    pub domain_to: PseudonymizationDomain, // We need to know in which domain to create the participant. It may often be 1-1 with the data source, but not always. It may also be 1-1 with the column, but not always.
41    pub activity: String,
42    pub extra_data: Value,
43}
44
45#[derive(Debug)]
46pub struct ActivityRequest {
47    pub participant: ParticipantInfo,
48    pub activity: String,
49    pub extra_data: Value,
50}
51
52#[derive(Debug)]
53pub struct ActivityResponse {
54    pub participant: ParticipantInfo,
55    pub activity: String,
56    pub extra_data: Value,
57}
58
59#[derive(Debug, Serialize, Deserialize)]
60pub struct PEPActivityResponse {
61    pub participant: PEPParticipantInfo,
62    pub domain_to: PseudonymizationDomain,
63    pub activity: String,
64    pub extra_data: Value,
65}
66
67impl HasParticipantInfo for ActivityRequest {
68    fn participant_info(&self) -> &ParticipantInfo {
69        &self.participant
70    }
71}
72
73impl HasPEPParticipantInfo for PEPActivityRequest {
74    fn pep_participant_info(&self) -> &PEPParticipantInfo {
75        &self.participant
76    }
77
78    fn domain_to(&self) -> &PseudonymizationDomain {
79        &self.domain_to
80    }
81}
82
83impl HasParticipantInfo for ActivityResponse {
84    fn participant_info(&self) -> &ParticipantInfo {
85        &self.participant
86    }
87}
88
89impl HasPEPParticipantInfo for PEPActivityResponse {
90    fn pep_participant_info(&self) -> &PEPParticipantInfo {
91        &self.participant
92    }
93
94    fn domain_to(&self) -> &PseudonymizationDomain {
95        &self.domain_to
96    }
97}
98
99#[derive(Debug)]
100pub struct ActivityRequestMessageType;
101
102impl PEPMessageType for ActivityRequestMessageType {
103    type PEPMessage = PEPActivityRequest;
104    type Message = ActivityRequest;
105    async fn pack<R: RngCore + CryptoRng>(
106        request: Self::Message,
107        domain_to: PseudonymizationDomain,
108        ps: &mut PseudonymService,
109        rng: &mut R,
110    ) -> Result<Self::PEPMessage, ApiError> {
111        Ok(Self::PEPMessage {
112            participant: request.participant.encrypt(ps, rng).await?,
113            domain_to,
114            activity: request.activity,
115            extra_data: request.extra_data,
116        })
117    }
118    async fn unpack(
119        request: Self::PEPMessage,
120        ps: &mut PseudonymService,
121    ) -> Result<Self::Message, ApiError> {
122        Ok(Self::Message {
123            participant: request.participant.decrypt(ps, request.domain_to).await?,
124            activity: request.activity,
125            extra_data: request.extra_data,
126        })
127    }
128}
129
130#[derive(Debug)]
131pub struct ActivityResponseMessageType;
132
133impl PEPMessageType for ActivityResponseMessageType {
134    type PEPMessage = PEPActivityResponse;
135    type Message = ActivityResponse;
136    async fn pack<R: RngCore + CryptoRng>(
137        request: Self::Message,
138        domain_to: PseudonymizationDomain,
139        ps: &mut PseudonymService,
140        rng: &mut R,
141    ) -> Result<Self::PEPMessage, ApiError> {
142        Ok(Self::PEPMessage {
143            participant: request.participant.encrypt(ps, rng).await?,
144            domain_to,
145            activity: request.activity,
146            extra_data: request.extra_data,
147        })
148    }
149    async fn unpack(
150        request: Self::PEPMessage,
151        ps: &mut PseudonymService,
152    ) -> Result<Self::Message, ApiError> {
153        Ok(Self::Message {
154            participant: request.participant.decrypt(ps, request.domain_to).await?,
155            activity: request.activity,
156            extra_data: request.extra_data,
157        })
158    }
159}