eidetica/auth/types/
delegation.rs1use serde::{Deserialize, Serialize};
6
7use super::permissions::PermissionBounds;
8use crate::crdt::{CRDTError, Doc, doc::Value};
9use crate::entry::ID;
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
14pub struct TreeReference {
15 pub root: ID,
17 pub tips: Vec<ID>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
23pub struct DelegatedTreeRef {
24 #[serde(rename = "permission-bounds")]
26 pub permission_bounds: PermissionBounds,
27 pub tree: TreeReference,
29}
30
31impl From<TreeReference> for Value {
34 fn from(tree_ref: TreeReference) -> Value {
35 Value::Doc(Doc::from(tree_ref))
36 }
37}
38
39impl From<TreeReference> for Doc {
40 fn from(tree_ref: TreeReference) -> Doc {
41 let mut doc = Doc::new();
42 doc.set("root", tree_ref.root.as_str());
43 let mut tips_doc = Doc::new();
44 for (i, tip) in tree_ref.tips.iter().enumerate() {
45 tips_doc.set(i.to_string(), tip.as_str());
46 }
47 doc.set("tips", tips_doc);
48 doc
49 }
50}
51
52impl TryFrom<&Doc> for TreeReference {
53 type Error = crate::Error;
54
55 fn try_from(doc: &Doc) -> crate::Result<Self> {
56 let root_str = doc
57 .get_as::<&str>("root")
58 .ok_or_else(|| CRDTError::ElementNotFound {
59 key: "root".to_string(),
60 })?;
61 let root = ID::new(root_str);
62
63 let mut tips = Vec::new();
64 if let Some(Value::Doc(tips_doc)) = doc.get("tips") {
65 let mut entries: Vec<(usize, &str)> = tips_doc
66 .iter()
67 .filter_map(|(k, v)| {
68 let idx: usize = k.parse().ok()?;
69 let s = v.as_text()?;
70 Some((idx, s))
71 })
72 .collect();
73 entries.sort_by_key(|(idx, _)| *idx);
74 tips = entries.into_iter().map(|(_, s)| ID::new(s)).collect();
75 }
76
77 Ok(TreeReference { root, tips })
78 }
79}
80
81impl From<DelegatedTreeRef> for Value {
82 fn from(dtref: DelegatedTreeRef) -> Value {
83 Value::Doc(Doc::from(dtref))
84 }
85}
86
87impl From<DelegatedTreeRef> for Doc {
88 fn from(dtref: DelegatedTreeRef) -> Doc {
89 let mut doc = Doc::atomic();
90 doc.set("permission_bounds", dtref.permission_bounds);
91 doc.set("tree", dtref.tree);
92 doc
93 }
94}
95
96impl TryFrom<&Doc> for DelegatedTreeRef {
97 type Error = crate::Error;
98
99 fn try_from(doc: &Doc) -> crate::Result<Self> {
100 let pb_doc = match doc.get("permission_bounds") {
101 Some(Value::Doc(d)) => d,
102 _ => {
103 return Err(CRDTError::ElementNotFound {
104 key: "permission_bounds".to_string(),
105 }
106 .into());
107 }
108 };
109 let permission_bounds = PermissionBounds::try_from(pb_doc)?;
110
111 let tree_doc = match doc.get("tree") {
112 Some(Value::Doc(d)) => d,
113 _ => {
114 return Err(CRDTError::ElementNotFound {
115 key: "tree".to_string(),
116 }
117 .into());
118 }
119 };
120 let tree = TreeReference::try_from(tree_doc)?;
121
122 Ok(DelegatedTreeRef {
123 permission_bounds,
124 tree,
125 })
126 }
127}