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.to_string());
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.to_string());
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::parse(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
75 .into_iter()
76 .map(|(_, s)| ID::parse(s))
77 .collect::<crate::Result<Vec<_>>>()?;
78 }
79
80 Ok(TreeReference { root, tips })
81 }
82}
83
84impl From<DelegatedTreeRef> for Value {
85 fn from(dtref: DelegatedTreeRef) -> Value {
86 Value::Doc(Doc::from(dtref))
87 }
88}
89
90impl From<DelegatedTreeRef> for Doc {
91 fn from(dtref: DelegatedTreeRef) -> Doc {
92 let mut doc = Doc::atomic();
93 doc.set("permission_bounds", dtref.permission_bounds);
94 doc.set("tree", dtref.tree);
95 doc
96 }
97}
98
99impl TryFrom<&Doc> for DelegatedTreeRef {
100 type Error = crate::Error;
101
102 fn try_from(doc: &Doc) -> crate::Result<Self> {
103 let pb_doc = match doc.get("permission_bounds") {
104 Some(Value::Doc(d)) => d,
105 _ => {
106 return Err(CRDTError::ElementNotFound {
107 key: "permission_bounds".to_string(),
108 }
109 .into());
110 }
111 };
112 let permission_bounds = PermissionBounds::try_from(pb_doc)?;
113
114 let tree_doc = match doc.get("tree") {
115 Some(Value::Doc(d)) => d,
116 _ => {
117 return Err(CRDTError::ElementNotFound {
118 key: "tree".to_string(),
119 }
120 .into());
121 }
122 };
123 let tree = TreeReference::try_from(tree_doc)?;
124
125 Ok(DelegatedTreeRef {
126 permission_bounds,
127 tree,
128 })
129 }
130}