1use cyfs_base::*;
2
3use std::str::FromStr;
4
5#[derive(Debug, Clone, Eq, PartialEq)]
6pub enum AclDirection {
7 Any = 0,
8
9 In = 1,
10 Out = 2,
11}
12
13impl AclDirection {
14 pub fn as_str(&self) -> &str {
15 match *self {
16 Self::Any => "*",
17 Self::In => "in",
18 Self::Out => "out",
19 }
20 }
21}
22
23impl FromStr for AclDirection {
24 type Err = BuckyError;
25
26 fn from_str(s: &str) -> Result<Self, Self::Err> {
27 let ret = match s {
28 "*" => Self::Any,
29 "in" => Self::In,
30 "out" => Self::Out,
31
32 _ => {
33 let msg = format!("unknown acl direction: {}", s);
34 error!("{}", msg);
35 return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
36 }
37 };
38
39 Ok(ret)
40 }
41}
42
43impl ToString for AclDirection {
44 fn to_string(&self) -> String {
45 self.as_str().to_owned()
46 }
47}
48
49#[derive(Debug, Clone, Eq, PartialEq)]
50pub enum AclOperationCategory {
51 Both,
52 Read,
53 Write,
54}
55
56#[derive(Debug, Clone, Eq, PartialEq)]
57pub enum AclOperation {
58 Any = 0,
59
60 GetObject = 1,
61 PutObject = 2,
62 PostObject = 3,
63 SelectObject = 4,
64 DeleteObject = 5,
65
66 SignObject = 6,
67 VerifyObject = 7,
68
69 PutData = 8,
70 GetData = 9,
71 DeleteData = 10,
72 QueryFile = 11,
73
74 ReadRootState = 15,
76 WriteRootState = 16,
77
78 Get = 20,
80 Put = 21,
81 Delete = 22,
82
83 Read = 23,
84 Write = 24,
85
86 Crypto = 25,
88}
89
90impl AclOperation {
91 pub fn category(&self) -> AclOperationCategory {
92 match *self {
93 Self::Any => AclOperationCategory::Both,
94
95 Self::GetObject
96 | Self::SelectObject
97 | Self::VerifyObject
98 | Self::GetData
99 | Self::ReadRootState
100 | Self::Get
101 | Self::Read
102 | Self::QueryFile => AclOperationCategory::Read,
103
104 Self::PutObject
105 | Self::PostObject
106 | Self::DeleteObject
107 | Self::SignObject
108 | Self::PutData
109 | Self::DeleteData
110 | Self::WriteRootState
111 | Self::Put
112 | Self::Delete
113 | Self::Write
114 | Self::Crypto => AclOperationCategory::Write,
115 }
116 }
117
118 pub fn as_str(&self) -> &str {
119 match *self {
120 Self::Any => "*",
121 Self::GetObject => "get-object",
122 Self::PutObject => "put-object",
123 Self::PostObject => "post-object",
124 Self::SelectObject => "select-object",
125 Self::DeleteObject => "delete-object",
126
127 Self::SignObject => "sign-object",
128 Self::VerifyObject => "verify-object",
129
130 Self::PutData => "put-data",
131 Self::GetData => "get-data",
132 Self::DeleteData => "delete-data",
133 Self::QueryFile => "query-file",
134
135 Self::WriteRootState => "write-root-state",
136 Self::ReadRootState => "read-root-state",
137
138 Self::Get => "get",
139 Self::Put => "put",
140 Self::Delete => "delete",
141
142 Self::Read => "read",
143 Self::Write => "write",
144
145 Self::Crypto => "crypto",
146 }
147 }
148
149 pub fn is_get(&self) -> bool {
150 match *self {
151 Self::GetObject | Self::GetData | Self::Get | Self::Any => true,
152 _ => false,
153 }
154 }
155
156 pub fn is_put(&self) -> bool {
157 match *self {
158 Self::PutObject | Self::PutData | Self::Put | Self::Any => true,
159 _ => false,
160 }
161 }
162
163 pub fn is_delete(&self) -> bool {
164 match *self {
165 Self::DeleteObject | Self::DeleteData | Self::Delete | Self::Any => true,
166 _ => false,
167 }
168 }
169
170 pub fn is_crypto(&self) -> bool {
171 match *self {
172 Self::SignObject | Self::VerifyObject => true,
173 _ => false,
174 }
175 }
176
177 pub fn is_read(&self) -> bool {
178 match self.category() {
179 AclOperationCategory::Read | AclOperationCategory::Both => true,
180 _ => false,
181 }
182 }
183
184 pub fn is_write(&self) -> bool {
185 match self.category() {
186 AclOperationCategory::Write | AclOperationCategory::Both => true,
187 _ => false,
188 }
189 }
190}
191
192impl FromStr for AclOperation {
193 type Err = BuckyError;
194
195 fn from_str(s: &str) -> Result<Self, Self::Err> {
196 let ret = match s {
197 "*" => Self::Any,
198 "get-object" => Self::GetObject,
199 "put-object" => Self::PutObject,
200 "post-object" => Self::PostObject,
201 "select-object" => Self::SelectObject,
202 "delete-object" => Self::DeleteObject,
203
204 "sign-object" => Self::SignObject,
205 "verify-object" => Self::VerifyObject,
206 "crypto" => Self::Crypto,
207
208 "put-data" => Self::PutData,
209 "get-data" => Self::GetData,
210 "delete-data" => Self::DeleteData,
211 "query-file" => Self::QueryFile,
212
213 "read-root-state" => Self::ReadRootState,
214 "write-root-state" => Self::WriteRootState,
215
216 "put" => Self::Put,
217 "get" => Self::Get,
218 "delete" => Self::Delete,
219
220 "read" => Self::Read,
221 "write" => Self::Write,
222
223 _ => {
224 let msg = format!("unknown acl operation: {}", s);
225 error!("{}", msg);
226 return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
227 }
228 };
229
230 Ok(ret)
231 }
232}
233
234impl ToString for AclOperation {
235 fn to_string(&self) -> String {
236 self.as_str().to_owned()
237 }
238}
239
240#[derive(Debug, Clone)]
241pub struct AclAction {
242 pub direction: AclDirection,
243 pub operation: AclOperation,
244}
245
246impl Default for AclAction {
247 fn default() -> Self {
248 Self {
249 direction: AclDirection::Any,
250 operation: AclOperation::Any,
251 }
252 }
253}
254
255impl AclAction {
256 pub fn new(direction: AclDirection, operation: AclOperation) -> Self {
257 Self {
258 direction,
259 operation,
260 }
261 }
262
263 pub fn is_match(&self, req: &Self) -> bool {
264 assert_ne!(req.direction, AclDirection::Any);
265 assert_ne!(req.operation, AclOperation::Any);
266
267 match &self.direction {
268 AclDirection::Any => {}
269 _ => {
270 if self.direction != req.direction {
271 return false;
272 }
273 }
274 }
275
276 if self.operation == req.operation {
277 return true;
278 }
279
280 match &self.operation {
282 AclOperation::Any => true,
283 AclOperation::Get => req.operation.is_get(),
284 AclOperation::Put => req.operation.is_put(),
285 AclOperation::Delete => req.operation.is_delete(),
286 AclOperation::Read => req.operation.is_read(),
287 AclOperation::Write => req.operation.is_write(),
288 AclOperation::Crypto => req.operation.is_crypto(),
289 _ => false,
290 }
291 }
292
293 pub fn parse(s: &str) -> BuckyResult<Self> {
294 let ret = if s == "*" {
295 Self {
296 direction: AclDirection::Any,
297 operation: AclOperation::Any,
298 }
299 } else {
300 let parts: Vec<&str> = s.split('-').collect();
302 if parts.len() < 2 {
303 let msg = format!("invalid action format: {}", s);
304 error!("{}", msg);
305 return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
306 }
307
308 let direction = AclDirection::from_str(parts[0])?;
309 let operation = AclOperation::from_str(&parts[1..].join("-"))?;
310
311 Self {
312 direction,
313 operation,
314 }
315 };
316
317 Ok(ret)
318 }
319}