guardian_db/access_controller/
manifest.rs1use crate::error::{GuardianError, Result};
2use crate::ipfs_core_api::client::IpfsClient;
3use cid::Cid;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::sync::{Arc, Mutex};
7
8#[derive(Debug, Serialize, Deserialize, Clone)]
9pub struct Manifest {
10 #[serde(rename = "type")]
12 pub get_type: String,
13
14 #[serde(rename = "params")]
16 pub params: CreateAccessControllerOptions,
17}
18
19#[derive(Debug, Clone)]
21pub struct CreateAccessControllerOptions {
22 pub skip_manifest: bool,
23 pub address: Cid,
24 pub get_type: String,
25 pub name: String,
26 access: Arc<Mutex<HashMap<String, Vec<String>>>>,
27}
28
29impl Serialize for CreateAccessControllerOptions {
31 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
32 where
33 S: serde::Serializer,
34 {
35 use serde::ser::SerializeStruct;
36 let mut state = serializer.serialize_struct("CreateAccessControllerOptions", 5)?;
37 state.serialize_field("skip_manifest", &self.skip_manifest)?;
38 state.serialize_field("address", &self.address)?; state.serialize_field("type", &self.get_type)?;
40 state.serialize_field("name", &self.name)?;
41 if let Ok(access_guard) = self.access.lock()
43 && !access_guard.is_empty()
44 {
45 state.serialize_field("access", &*access_guard)?;
46 }
47 state.end()
48 }
49}
50
51impl<'de> Deserialize<'de> for CreateAccessControllerOptions {
53 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
54 where
55 D: serde::Deserializer<'de>,
56 {
57 use serde::de::{MapAccess, Visitor};
58 use std::fmt;
59 struct OptionsVisitor;
60 impl<'de> Visitor<'de> for OptionsVisitor {
61 type Value = CreateAccessControllerOptions;
62 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
63 formatter.write_str("struct CreateAccessControllerOptions")
64 }
65 fn visit_map<V>(
66 self,
67 mut map: V,
68 ) -> std::result::Result<CreateAccessControllerOptions, V::Error>
69 where
70 V: MapAccess<'de>,
71 {
72 let mut skip_manifest = false;
73 let mut address = Cid::default();
74 let mut type_field = String::new();
75 let mut name = String::new();
76 let mut access = HashMap::new();
77
78 while let Some(key) = map.next_key::<String>()? {
79 match key.as_str() {
80 "skip_manifest" => skip_manifest = map.next_value()?,
81 "address" => {
82 address = map.next_value()?; }
84 "type" => type_field = map.next_value()?,
85 "name" => name = map.next_value()?,
86 "access" => access = map.next_value()?,
87 _ => {
88 let _ = map.next_value::<serde::de::IgnoredAny>()?;
89 }
90 }
91 }
92 Ok(CreateAccessControllerOptions {
93 skip_manifest,
94 address,
95 get_type: type_field,
96 name,
97 access: Arc::new(Mutex::new(access)),
98 })
99 }
100 }
101
102 deserializer.deserialize_struct(
103 "CreateAccessControllerOptions",
104 &["skip_manifest", "address", "type", "name", "access"],
105 OptionsVisitor,
106 )
107 }
108}
109
110impl Default for CreateAccessControllerOptions {
111 fn default() -> Self {
112 Self {
113 skip_manifest: false,
114 address: Cid::default(),
115 get_type: String::new(),
116 name: String::new(),
117 access: Arc::new(Mutex::new(HashMap::new())),
118 }
119 }
120}
121
122pub trait ManifestParams: Send + Sync {
124 fn skip_manifest(&self) -> bool;
125 fn address(&self) -> Cid;
126 fn set_address(&mut self, addr: Cid);
127 fn get_type(&self) -> &str;
128 fn set_type(&mut self, t: String);
129 fn get_name(&self) -> &str;
130 fn set_name(&mut self, name: String);
131 fn set_access(&mut self, role: String, allowed: Vec<String>);
132 fn get_access(&self, role: &str) -> Option<Vec<String>>;
133 fn get_all_access(&self) -> HashMap<String, Vec<String>>;
134
135 fn as_any(&self) -> &dyn std::any::Any;
137}
138
139impl ManifestParams for CreateAccessControllerOptions {
140 fn skip_manifest(&self) -> bool {
141 self.skip_manifest
142 }
143 fn address(&self) -> Cid {
144 self.address
145 }
146 fn set_address(&mut self, addr: Cid) {
147 self.address = addr;
148 }
149 fn get_type(&self) -> &str {
150 &self.get_type
151 }
152 fn set_type(&mut self, t: String) {
153 self.get_type = t;
154 }
155 fn get_name(&self) -> &str {
156 &self.name
157 }
158 fn set_name(&mut self, name: String) {
159 self.name = name;
160 }
161
162 fn set_access(&mut self, role: String, allowed: Vec<String>) {
163 let mut guard = self.access.lock().expect("Failed to acquire lock");
164 guard.insert(role, allowed);
165 }
166
167 fn get_access(&self, role: &str) -> Option<Vec<String>> {
168 let guard = self.access.lock().expect("Failed to acquire lock");
169 guard.get(role).cloned()
170 }
171
172 fn get_all_access(&self) -> HashMap<String, Vec<String>> {
173 let guard = self.access.lock().expect("Failed to acquire lock");
174 guard.clone()
175 }
176
177 fn as_any(&self) -> &dyn std::any::Any {
178 self
179 }
180}
181
182impl CreateAccessControllerOptions {
183 pub fn new(address: Cid, skip_manifest: bool, manifest_type: String) -> Self {
184 Self {
185 address,
186 skip_manifest,
187 get_type: manifest_type,
188 ..Default::default()
189 }
190 }
191
192 pub fn new_empty() -> Self {
193 Default::default()
194 }
195
196 pub fn new_simple(manifest_type: String, access: HashMap<String, Vec<String>>) -> Self {
197 Self {
198 skip_manifest: true,
199 get_type: manifest_type,
200 access: Arc::new(Mutex::new(access)),
201 ..Default::default()
202 }
203 }
204
205 pub fn from_params(params: &CreateAccessControllerOptions) -> Self {
206 params.clone()
207 }
208}
209
210pub async fn create(
212 ipfs: Arc<IpfsClient>,
213 controller_type: String,
214 params: &CreateAccessControllerOptions,
215) -> Result<Cid> {
216 if params.skip_manifest() {
217 return Ok(params.address());
218 }
219
220 if controller_type.is_empty() {
222 return Err(GuardianError::Store(
223 "Controller type cannot be empty".to_string(),
224 ));
225 }
226
227 let manifest = Manifest {
228 get_type: controller_type,
229 params: CreateAccessControllerOptions {
230 skip_manifest: params.skip_manifest(),
231 address: params.address(),
232 get_type: params.get_type().to_string(),
233 name: params.get_name().to_string(),
234 access: params.access.clone(),
235 },
236 };
237
238 let cbor_data = serde_cbor::to_vec(&manifest)
240 .map_err(|e| GuardianError::Store(format!("Failed to serialize manifest: {}", e)))?;
241
242 if cbor_data.is_empty() {
244 return Err(GuardianError::Store(
245 "Serialized manifest is empty".to_string(),
246 ));
247 }
248
249 let response = ipfs
251 .add_bytes(cbor_data)
252 .await
253 .map_err(|e| GuardianError::Store(format!("Failed to store manifest in IPFS: {}", e)))?;
254
255 if response.hash.is_empty() {
257 return Err(GuardianError::Store("IPFS returned empty hash".to_string()));
258 }
259
260 let cid = Cid::try_from(response.hash.as_str())
262 .map_err(|e| GuardianError::Store(format!("Invalid CID returned from IPFS: {}", e)))?;
263
264 Ok(cid)
265}
266
267pub async fn resolve(
269 ipfs: Arc<IpfsClient>,
270 manifest_address: &str,
271 params: &CreateAccessControllerOptions,
272) -> Result<Manifest> {
273 if params.skip_manifest() {
274 if params.get_type().is_empty() {
275 return Err(GuardianError::Store(
276 "Sem manifesto, o tipo do controlador de acesso é obrigatório".to_string(),
277 ));
278 }
279
280 return Ok(Manifest {
281 get_type: params.get_type().to_string(),
282 params: params.clone(),
283 });
284 }
285
286 if manifest_address.is_empty() {
288 return Err(GuardianError::Store(
289 "Manifest address cannot be empty".to_string(),
290 ));
291 }
292
293 let hash = if let Some(stripped) = manifest_address.strip_prefix("/ipfs/") {
295 stripped
296 } else {
297 manifest_address
298 };
299
300 let cid = Cid::try_from(hash)
301 .map_err(|e| GuardianError::Store(format!("Invalid CID format: {}", e)))?;
302
303 use tokio::io::AsyncReadExt;
305
306 let mut data_reader = ipfs.cat(&cid.to_string()).await.map_err(|e| {
307 GuardianError::Store(format!("Failed to retrieve manifest from IPFS: {}", e))
308 })?;
309 let mut data_bytes = Vec::new();
310 data_reader
311 .read_to_end(&mut data_bytes)
312 .await
313 .map_err(|e| GuardianError::Store(format!("Failed to read manifest data: {}", e)))?;
314
315 if data_bytes.is_empty() {
317 return Err(GuardianError::Store(
318 "Retrieved manifest data is empty".to_string(),
319 ));
320 }
321
322 let manifest: Manifest = serde_cbor::from_slice(&data_bytes)
324 .map_err(|e| GuardianError::Store(format!("Failed to deserialize manifest: {}", e)))?;
325
326 if manifest.get_type.is_empty() {
328 return Err(GuardianError::Store(
329 "Manifest type cannot be empty".to_string(),
330 ));
331 }
332
333 Ok(manifest)
334}
335
336pub fn create_manifest_with_validation(
338 controller_type: String,
339 params: CreateAccessControllerOptions,
340) -> Result<Manifest> {
341 if controller_type.is_empty() {
343 return Err(GuardianError::Store(
344 "Controller type cannot be empty".to_string(),
345 ));
346 }
347
348 if controller_type.len() > 255 {
349 return Err(GuardianError::Store(
350 "Controller type too long (max 255 characters)".to_string(),
351 ));
352 }
353
354 let valid_types = ["ipfs", "GuardianDB", "simple"];
356 if !valid_types.contains(&controller_type.as_str()) {
357 return Err(GuardianError::Store(format!(
358 "Unknown controller type: {}",
359 controller_type
360 )));
361 }
362
363 Ok(Manifest {
364 get_type: controller_type,
365 params,
366 })
367}
368
369#[cfg(test)]
370mod tests {
371 use super::*;
372 use std::collections::HashMap;
373
374 #[test]
375 fn test_cid_serialization_deserialization() {
376 let mut access = HashMap::new();
378 access.insert("write".to_string(), vec!["test_key".to_string()]);
379
380 let original_cid = Cid::default();
381 let options = CreateAccessControllerOptions {
382 skip_manifest: false,
383 address: original_cid,
384 get_type: "test".to_string(),
385 name: "test_controller".to_string(),
386 access: Arc::new(std::sync::Mutex::new(access)),
387 };
388
389 let json =
391 serde_json::to_string(&options).expect("CID serializa sem implementação customizada");
392 let deserialized: CreateAccessControllerOptions =
393 serde_json::from_str(&json).expect("CID deserializa sem implementação customizada");
394
395 assert_eq!(deserialized.address, original_cid);
396 assert_eq!(deserialized.get_type, "test");
397 assert_eq!(deserialized.name, "test_controller");
398
399 let cbor = serde_cbor::to_vec(&options).expect("CID serializa em CBOR nativamente");
401 let cbor_deserialized: CreateAccessControllerOptions =
402 serde_cbor::from_slice(&cbor).expect("CID deserializa de CBOR nativamente");
403
404 assert_eq!(cbor_deserialized.address, original_cid);
405 }
406}