protocol/
directory.rs

1use std::convert::TryFrom;
2
3use anyhow::anyhow;
4
5use interface::{BlobMeta, CertificateInfo, Query, StorageNodeInfo};
6
7use rapidquery::Expression;
8
9use serde::{Deserialize, Serialize};
10
11pub mod blobmeta {
12    use super::*;
13
14    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
15    #[serde(deny_unknown_fields)]
16    pub struct ListMetadataRequest {
17        /// Optionally filters which tags to return (defaults to all).
18        pub tags: Option<Vec<String>>,
19
20        /// Optionally filters which fields to return (defaults to all). [e.g. "filetype"]
21        pub fields: Option<Vec<String>>,
22    }
23
24    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
25    #[serde(deny_unknown_fields)]
26    pub struct GetMetaResponse {
27        pub meta: Option<BlobMeta>,
28    }
29}
30
31pub mod routing {
32    use interface::RoutingConfig;
33
34    use super::*;
35
36    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
37    #[serde(deny_unknown_fields)]
38    pub struct GetRoutingConfigResponse {
39        pub routing_config: Option<RoutingConfig>,
40    }
41
42    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
43    #[serde(deny_unknown_fields)]
44    pub struct SetRoutingConfigRequest {
45        pub routing_config: RoutingConfig,
46    }
47}
48
49pub mod auth {
50    use super::*;
51
52    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
53    #[serde(deny_unknown_fields)]
54    pub struct LoginRequest {
55        pub username: String,
56        pub password: String,
57    }
58
59    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
60    #[serde(deny_unknown_fields)]
61    pub struct LoginResponse {
62        pub token: String,
63    }
64
65    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
66    #[serde(deny_unknown_fields)]
67    pub struct RegisterRequest {
68        pub username: String,
69        pub password: String,
70    }
71}
72
73pub mod storage {
74    use super::*;
75
76    #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
77    #[serde(deny_unknown_fields)]
78    pub struct ListStorageNodesResponse {
79        pub storage_nodes: Vec<StorageNodeInfo>,
80    }
81
82    #[derive(Clone, Debug, Deserialize, Serialize)]
83    #[serde(deny_unknown_fields)]
84    pub struct MoveRequest {
85        pub blob_id: String,
86        pub destination_url: String,
87        pub owner_username: String,
88    }
89
90    #[derive(Clone, Debug, Deserialize, Serialize)]
91    #[serde(deny_unknown_fields)]
92    pub struct RegisterResponse {
93        pub message: String,
94        pub certificates: Option<CertificateInfo>,
95        pub rebuild_requested: bool,
96        pub move_requests: Vec<MoveRequest>,
97    }
98}
99
100pub mod query {
101    use interface::{ExpressionField, FieldValue, SortOrder};
102
103    use super::*;
104
105    #[derive(Clone, Debug, Deserialize, Hash, PartialEq, Eq, Serialize)]
106    #[serde(untagged)]
107    pub enum RawExpression {
108        /// Tag expression.
109        ///
110        /// Evaluates to resolver items where the tag is present.
111        Tag { tag: String },
112        /// Key/Value expression.
113        ///
114        /// Evaluates to resolver items where the given field/value pair is present.
115        Field { key: String, value: FieldValue },
116        /// HasField expression.
117        ///
118        /// Evaluates to resolver items where the given field is present.
119        HasField { key: String },
120        /// And expression.
121        ///
122        /// Evaluates to the intersection of its two sub-expressions.
123        And {
124            and: (Box<RawExpression>, Box<RawExpression>),
125        },
126        /// Or expression.
127        /// Evaluates to the union of its two sub-expressions.
128        Or {
129            or: (Box<RawExpression>, Box<RawExpression>),
130        },
131        /// Not expression.
132        /// Evaluates to the negation of its sub-expression.
133        Not { not: Box<RawExpression> },
134
135        /// Raw sub-expression. Will be parsed before being turned in a real expression.
136        Raw { raw: String },
137
138        /// Empty expression.
139        /// Evaluates to all items resolvable by the resolver.
140        Empty,
141    }
142
143    impl TryFrom<RawExpression> for Expression<ExpressionField> {
144        type Error = anyhow::Error;
145
146        fn try_from(value: RawExpression) -> Result<Self, Self::Error> {
147            let expr = match value {
148                RawExpression::Empty => Self::Empty,
149                RawExpression::Raw { raw } => {
150                    Expression::parse(raw).map_err(|e| anyhow!("{}", e))?
151                }
152                RawExpression::Not { not } => Self::Not {
153                    not: Box::new(Expression::try_from(*not)?),
154                },
155                RawExpression::Or { or: (a, b) } => Self::Or {
156                    or: (
157                        Box::new(Expression::try_from(*a)?),
158                        Box::new(Expression::try_from(*b)?),
159                    ),
160                },
161                RawExpression::And { and: (a, b) } => Self::And {
162                    and: (
163                        Box::new(Expression::try_from(*a)?),
164                        Box::new(Expression::try_from(*b)?),
165                    ),
166                },
167                RawExpression::HasField { key } => Self::Field(ExpressionField::HasField { key }),
168                RawExpression::Field { key, value } => {
169                    Self::Field(ExpressionField::Field { key, value })
170                }
171                RawExpression::Tag { tag } => Self::Field(ExpressionField::Tag { tag }),
172            };
173
174            Ok(expr)
175        }
176    }
177
178    #[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
179    #[serde(deny_unknown_fields)]
180    #[serde(untagged)]
181    pub enum ExpressionRequest {
182        Expr(RawExpression),
183        Raw(String),
184    }
185
186    impl Default for ExpressionRequest {
187        fn default() -> Self {
188            ExpressionRequest::Expr(RawExpression::Empty)
189        }
190    }
191
192    fn default_from() -> usize {
193        0
194    }
195
196    fn default_size() -> usize {
197        30
198    }
199
200    fn default_sign_urls() -> bool {
201        true
202    }
203
204    fn default_facets() -> bool {
205        false
206    }
207
208    fn default_sort_order() -> SortOrder {
209        SortOrder::CreationAscending
210    }
211
212    #[derive(Clone, Debug, Deserialize, Hash, Serialize, PartialEq, Eq)]
213    #[serde(deny_unknown_fields)]
214    pub struct QueryRequest {
215        #[serde(default = "ExpressionRequest::default")]
216        pub expression: ExpressionRequest,
217
218        #[serde(default = "default_from")]
219        pub from: usize,
220
221        #[serde(default = "default_size")]
222        pub size: usize,
223
224        #[serde(default = "default_sign_urls")]
225        pub sign_urls: bool,
226
227        #[serde(default = "default_facets")]
228        pub facets: bool, // TODO: Permit requesting facets for specific tags instead of doing it for all.
229
230        #[serde(default = "default_sort_order")]
231        pub sort_order: SortOrder,
232    }
233
234    impl TryFrom<QueryRequest> for Query {
235        type Error = anyhow::Error;
236
237        fn try_from(request: QueryRequest) -> Result<Self, Self::Error> {
238            let expression = match request.expression {
239                ExpressionRequest::Expr(e) => Expression::try_from(e)?,
240                ExpressionRequest::Raw(raw) => Expression::parse(raw)?,
241            };
242
243            Ok(Query {
244                expression,
245                from: request.from,
246                size: request.size,
247                sign_urls: request.sign_urls,
248                facets: request.facets,
249                sort_order: request.sort_order,
250            })
251        }
252    }
253}
254
255#[cfg(test)]
256mod tests {
257    use interface::{Expression, ExpressionField};
258
259    use super::query::RawExpression;
260
261    #[test]
262    fn mixed_expression_parsing() {
263        let manual_expr = Expression::And {
264            and: (
265                Box::new(Expression::Field(ExpressionField::Tag { tag: "a".into() })),
266                Box::new(Expression::And {
267                    and: (
268                        Box::new(Expression::Field(ExpressionField::Tag { tag: "b".into() })),
269                        Box::new(Expression::Field(ExpressionField::Tag { tag: "c".into() })),
270                    ),
271                }),
272            ),
273        };
274
275        let auto_expr = Expression::try_from(RawExpression::And {
276            and: (
277                Box::new(RawExpression::Tag {
278                    tag: String::from("a"),
279                }),
280                Box::new(RawExpression::Raw {
281                    raw: String::from("b && c"),
282                }),
283            ),
284        })
285        .unwrap();
286
287        assert_eq!(manual_expr, auto_expr);
288    }
289}