kanidmd_lib/valueset/
json.rs
1use crate::prelude::*;
2use crate::schema::SchemaAttribute;
3use crate::valueset::ScimResolveStatus;
4use crate::valueset::{DbValueSetV2, ValueSet};
5use kanidm_proto::internal::Filter as ProtoFilter;
6use smolset::SmolSet;
7
8#[derive(Debug, Clone)]
9pub struct ValueSetJsonFilter {
10 set: SmolSet<[ProtoFilter; 1]>,
11}
12
13impl ValueSetJsonFilter {
14 pub fn new(b: ProtoFilter) -> Box<Self> {
15 let mut set = SmolSet::new();
16 set.insert(b);
17 Box::new(ValueSetJsonFilter { set })
18 }
19
20 pub fn push(&mut self, b: ProtoFilter) -> bool {
21 self.set.insert(b)
22 }
23
24 pub fn from_dbvs2(data: &[String]) -> Result<ValueSet, OperationError> {
25 let set = data
26 .iter()
27 .map(|s| serde_json::from_str(s).map_err(|_| OperationError::SerdeJsonError))
28 .collect::<Result<_, _>>()?;
29 Ok(Box::new(ValueSetJsonFilter { set }))
30 }
31
32 #[allow(clippy::should_implement_trait)]
35 pub fn from_iter<T>(iter: T) -> Option<Box<Self>>
36 where
37 T: IntoIterator<Item = ProtoFilter>,
38 {
39 let set = iter.into_iter().collect();
40 Some(Box::new(ValueSetJsonFilter { set }))
41 }
42}
43
44impl ValueSetT for ValueSetJsonFilter {
45 fn insert_checked(&mut self, value: Value) -> Result<bool, OperationError> {
46 match value {
47 Value::JsonFilt(u) => Ok(self.set.insert(u)),
48 _ => {
49 debug_assert!(false);
50 Err(OperationError::InvalidValueState)
51 }
52 }
53 }
54
55 fn clear(&mut self) {
56 self.set.clear();
57 }
58
59 fn remove(&mut self, pv: &PartialValue, _cid: &Cid) -> bool {
60 match pv {
61 PartialValue::JsonFilt(u) => self.set.remove(u),
62 _ => {
63 debug_assert!(false);
64 true
65 }
66 }
67 }
68
69 fn contains(&self, pv: &PartialValue) -> bool {
70 match pv {
71 PartialValue::JsonFilt(u) => self.set.contains(u),
72 _ => false,
73 }
74 }
75
76 fn substring(&self, _pv: &PartialValue) -> bool {
77 false
78 }
79
80 fn startswith(&self, _pv: &PartialValue) -> bool {
81 false
82 }
83
84 fn endswith(&self, _pv: &PartialValue) -> bool {
85 false
86 }
87
88 fn lessthan(&self, _pv: &PartialValue) -> bool {
89 false
90 }
91
92 fn len(&self) -> usize {
93 self.set.len()
94 }
95
96 fn generate_idx_eq_keys(&self) -> Vec<String> {
97 self.set
98 .iter()
99 .map(|s| {
100 #[allow(clippy::expect_used)]
101 serde_json::to_string(s).expect("A json filter value was corrupted during run-time")
102 })
103 .collect()
104 }
105
106 fn syntax(&self) -> SyntaxType {
107 SyntaxType::JsonFilter
108 }
109
110 fn validate(&self, _schema_attr: &SchemaAttribute) -> bool {
111 true
112 }
113
114 fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
115 Box::new(self.set.iter().filter_map(|i| {
116 serde_json::to_string(i)
117 .inspect_err(|err| {
118 error!(?err, "A json filter value was corrupted during run-time")
119 })
120 .ok()
121 }))
122 }
123
124 fn to_scim_value(&self) -> Option<ScimResolveStatus> {
125 Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
126 self.set
127 .iter()
128 .filter_map(|s| {
129 serde_json::to_string(s)
130 .inspect_err(|err| {
131 error!(?err, "A json filter value was corrupted during run-time")
132 })
133 .ok()
134 })
135 .collect::<Vec<_>>(),
136 )))
137 }
138
139 fn to_db_valueset_v2(&self) -> DbValueSetV2 {
140 DbValueSetV2::JsonFilter(
141 self.set
142 .iter()
143 .filter_map(|s| {
144 serde_json::to_string(s)
145 .inspect_err(|err| {
146 error!(?err, "A json filter value was corrupted during run-time")
147 })
148 .ok()
149 })
150 .collect(),
151 )
152 }
153
154 fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
155 Box::new(self.set.iter().cloned().map(PartialValue::JsonFilt))
156 }
157
158 fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
159 Box::new(self.set.iter().cloned().map(Value::JsonFilt))
160 }
161
162 fn equal(&self, other: &ValueSet) -> bool {
163 if let Some(other) = other.as_json_filter_set() {
164 &self.set == other
165 } else {
166 debug_assert!(false);
167 false
168 }
169 }
170
171 fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError> {
172 if let Some(b) = other.as_json_filter_set() {
173 mergesets!(self.set, b)
174 } else {
175 debug_assert!(false);
176 Err(OperationError::InvalidValueState)
177 }
178 }
179
180 fn to_json_filter_single(&self) -> Option<&ProtoFilter> {
181 if self.set.len() == 1 {
182 self.set.iter().take(1).next()
183 } else {
184 None
185 }
186 }
187
188 fn as_json_filter_set(&self) -> Option<&SmolSet<[ProtoFilter; 1]>> {
189 Some(&self.set)
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::{ProtoFilter, ValueSetJsonFilter};
196 use crate::prelude::{Attribute, ValueSet};
197
198 #[test]
199 fn test_scim_json_filter() {
200 let filter = ProtoFilter::Pres(Attribute::Class.to_string());
201 let vs: ValueSet = ValueSetJsonFilter::new(filter);
202
203 let data = r#"
204[
205 "{\"pres\":\"class\"}"
206]
207 "#;
208 crate::valueset::scim_json_reflexive(&vs, data);
209
210 }
213}