trace2e_core/traceability/
o2m.rs1use std::{future::Future, pin::Pin, task::Poll};
28
29use tower::Service;
30#[cfg(feature = "trace2e_tracing")]
31use tracing::info;
32
33use crate::traceability::{
34 api::{
35 ComplianceRequest, ComplianceResponse, O2mRequest, O2mResponse, ProvenanceRequest,
36 ProvenanceResponse,
37 },
38 error::TraceabilityError,
39 naming::NodeId,
40};
41
42#[derive(Debug, Clone)]
48pub struct O2mApiService<P, C> {
49 provenance: P,
51 compliance: C,
53}
54
55impl<P, C> O2mApiService<P, C> {
56 pub fn new(provenance: P, compliance: C) -> Self {
58 Self { provenance, compliance }
59 }
60}
61
62impl<P, C> Service<O2mRequest> for O2mApiService<P, C>
63where
64 P: Service<ProvenanceRequest, Response = ProvenanceResponse, Error = TraceabilityError>
65 + Clone
66 + Send
67 + NodeId
68 + 'static,
69 P::Future: Send,
70 C: Service<ComplianceRequest, Response = ComplianceResponse, Error = TraceabilityError>
71 + Clone
72 + Send
73 + 'static,
74 C::Future: Send,
75{
76 type Response = O2mResponse;
77 type Error = TraceabilityError;
78 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
79
80 fn poll_ready(&mut self, _: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
81 Poll::Ready(Ok(()))
82 }
83
84 fn call(&mut self, request: O2mRequest) -> Self::Future {
85 let mut provenance = self.provenance.clone();
86 let mut compliance = self.compliance.clone();
87 Box::pin(async move {
88 match request {
89 O2mRequest::GetPolicies(resources) => {
90 #[cfg(feature = "trace2e_tracing")]
91 info!("[o2m-{}] GetPolicies: resources: {:?}", provenance.node_id(), resources);
92 match compliance.call(ComplianceRequest::GetPolicies(resources)).await? {
93 ComplianceResponse::Policies(policies) => {
94 Ok(O2mResponse::Policies(policies))
95 }
96 _ => Err(TraceabilityError::InternalTrace2eError),
97 }
98 }
99 O2mRequest::SetPolicy { resource, policy } => {
100 #[cfg(feature = "trace2e_tracing")]
101 info!(
102 "[o2m-{}] SetPolicy: resource: {:?}, policy: {:?}",
103 provenance.node_id(),
104 resource,
105 policy
106 );
107 match compliance.call(ComplianceRequest::SetPolicy { resource, policy }).await?
108 {
109 ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
110 _ => Err(TraceabilityError::InternalTrace2eError),
111 }
112 }
113 O2mRequest::SetConfidentiality { resource, confidentiality } => {
114 #[cfg(feature = "trace2e_tracing")]
115 info!(
116 "[o2m-{}] SetConfidentiality: resource: {:?}, confidentiality: {:?}",
117 provenance.node_id(),
118 resource,
119 confidentiality
120 );
121 match compliance
122 .call(ComplianceRequest::SetConfidentiality { resource, confidentiality })
123 .await?
124 {
125 ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
126 _ => Err(TraceabilityError::InternalTrace2eError),
127 }
128 }
129 O2mRequest::SetIntegrity { resource, integrity } => {
130 #[cfg(feature = "trace2e_tracing")]
131 info!(
132 "[o2m-{}] SetIntegrity: resource: {:?}, integrity: {:?}",
133 provenance.node_id(),
134 resource,
135 integrity
136 );
137 match compliance
138 .call(ComplianceRequest::SetIntegrity { resource, integrity })
139 .await?
140 {
141 ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
142 _ => Err(TraceabilityError::InternalTrace2eError),
143 }
144 }
145 O2mRequest::SetDeleted(resource) => {
146 #[cfg(feature = "trace2e_tracing")]
147 info!("[o2m-{}] SetDeleted: resource: {:?}", provenance.node_id(), resource,);
148 match compliance.call(ComplianceRequest::SetDeleted(resource)).await? {
149 ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
150 _ => Err(TraceabilityError::InternalTrace2eError),
151 }
152 }
153 O2mRequest::SetConsent(resource) => {
154 #[cfg(feature = "trace2e_tracing")]
155 info!("[o2m-{}] SetConsent: resource: {:?}", provenance.node_id(), resource);
156 match compliance
157 .call(ComplianceRequest::SetConsent { resource, consent: true })
158 .await?
159 {
160 ComplianceResponse::PolicyUpdated => Ok(O2mResponse::Ack),
161 _ => Err(TraceabilityError::InternalTrace2eError),
162 }
163 }
164 O2mRequest::GetReferences(resource) => {
165 #[cfg(feature = "trace2e_tracing")]
166 info!("[o2m-{}] GetReferences: resource: {:?}", provenance.node_id(), resource);
167 match provenance.call(ProvenanceRequest::GetReferences(resource)).await? {
168 ProvenanceResponse::Provenance(references) => {
169 Ok(O2mResponse::References(references))
170 }
171 _ => Err(TraceabilityError::InternalTrace2eError),
172 }
173 }
174 }
175 })
176 }
177}