eidetica/auth/types/
permissions.rs1use serde::{Deserialize, Serialize};
6
7use super::super::permission::clamp_permission;
8use crate::crdt::{CRDTError, Doc, doc::Value};
9
10#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
12pub enum Permission {
13 Admin(u32),
17 Write(u32),
20 Read,
22}
23
24impl PartialOrd for Permission {
25 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
26 Some(self.cmp(other))
27 }
28}
29
30impl Ord for Permission {
31 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
32 self.ordering_value().cmp(&other.ordering_value())
33 }
34}
35
36impl Permission {
37 fn ordering_value(&self) -> u64 {
41 match self {
42 Permission::Read => 0,
43 Permission::Write(p) => 1 + (u32::MAX as u64) - (*p as u64),
44 Permission::Admin(p) => 2 + (2 * u32::MAX as u64) - (*p as u64),
45 }
46 }
47
48 pub fn priority(&self) -> Option<u32> {
50 match self {
51 Permission::Read => None,
52 Permission::Write(priority) => Some(*priority),
53 Permission::Admin(priority) => Some(*priority),
54 }
55 }
56
57 pub fn can_write(&self) -> bool {
59 matches!(self, Permission::Write(_) | Permission::Admin(_))
60 }
61
62 pub fn can_admin(&self) -> bool {
64 matches!(self, Permission::Admin(_))
65 }
66
67 pub fn clamp_to(&self, max_permission: &Permission) -> Permission {
73 use std::cmp::min;
74 min(*self, *max_permission)
75 }
76
77 pub fn clamp_to_bounds(&self, bounds: &PermissionBounds) -> Permission {
83 clamp_permission(*self, bounds)
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
89pub enum KeyStatus {
90 Active,
92 Revoked,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
99pub struct PermissionBounds {
100 pub max: Permission,
102 pub min: Option<Permission>,
104}
105
106impl Default for PermissionBounds {
107 fn default() -> Self {
108 Self {
109 max: Permission::Read,
110 min: None,
111 }
112 }
113}
114
115impl From<Permission> for Value {
118 fn from(perm: Permission) -> Value {
119 Value::Doc(Doc::from(perm))
120 }
121}
122
123impl From<Permission> for Doc {
124 fn from(perm: Permission) -> Doc {
125 let mut doc = Doc::new();
126 match perm {
127 Permission::Admin(p) => {
128 doc.set("type", "Admin");
129 doc.set("priority", p);
130 }
131 Permission::Write(p) => {
132 doc.set("type", "Write");
133 doc.set("priority", p);
134 }
135 Permission::Read => {
136 doc.set("type", "Read");
137 }
138 }
139 doc
140 }
141}
142
143impl TryFrom<&Doc> for Permission {
144 type Error = crate::Error;
145
146 fn try_from(doc: &Doc) -> crate::Result<Self> {
147 let ptype = doc
148 .get_as::<&str>("type")
149 .ok_or_else(|| CRDTError::ElementNotFound {
150 key: "type".to_string(),
151 })?;
152 match ptype {
153 "Admin" => {
154 let p =
155 doc.get_as::<i64>("priority")
156 .ok_or_else(|| CRDTError::ElementNotFound {
157 key: "priority".to_string(),
158 })?;
159 Ok(Permission::Admin(p as u32))
160 }
161 "Write" => {
162 let p =
163 doc.get_as::<i64>("priority")
164 .ok_or_else(|| CRDTError::ElementNotFound {
165 key: "priority".to_string(),
166 })?;
167 Ok(Permission::Write(p as u32))
168 }
169 "Read" => Ok(Permission::Read),
170 other => Err(CRDTError::DeserializationFailed {
171 reason: format!("unknown Permission type: {other}"),
172 }
173 .into()),
174 }
175 }
176}
177
178impl From<PermissionBounds> for Value {
179 fn from(bounds: PermissionBounds) -> Value {
180 Value::Doc(Doc::from(bounds))
181 }
182}
183
184impl From<PermissionBounds> for Doc {
185 fn from(bounds: PermissionBounds) -> Doc {
186 let mut doc = Doc::new();
187 doc.set("max", bounds.max);
188 if let Some(min) = bounds.min {
189 doc.set("min", min);
190 }
191 doc
192 }
193}
194
195impl TryFrom<&Doc> for PermissionBounds {
196 type Error = crate::Error;
197
198 fn try_from(doc: &Doc) -> crate::Result<Self> {
199 let max_doc = match doc.get("max") {
200 Some(Value::Doc(d)) => d,
201 _ => {
202 return Err(CRDTError::ElementNotFound {
203 key: "max".to_string(),
204 }
205 .into());
206 }
207 };
208 let max = Permission::try_from(max_doc)?;
209
210 let min = match doc.get("min") {
211 Some(Value::Doc(d)) => Some(Permission::try_from(d)?),
212 _ => None,
213 };
214
215 Ok(PermissionBounds { max, min })
216 }
217}
218
219#[derive(Debug, Clone, PartialEq, Eq)]
221pub enum Operation {
222 WriteData,
224 WriteSettings,
226}