kanidmd_lib/valueset/
totp.rs

1use crate::be::dbvalue::DbTotpV1;
2use crate::credential::totp::Totp;
3use crate::prelude::*;
4use crate::schema::SchemaAttribute;
5use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
6use std::collections::btree_map::Entry as BTreeEntry;
7use std::collections::BTreeMap;
8
9#[derive(Debug, Clone)]
10pub struct ValueSetTotpSecret {
11    map: BTreeMap<String, Totp>,
12}
13
14impl ValueSetTotpSecret {
15    pub fn new(l: String, t: Totp) -> Box<Self> {
16        let mut map = BTreeMap::new();
17        map.insert(l, t);
18        Box::new(ValueSetTotpSecret { map })
19    }
20
21    pub fn push(&mut self, l: String, t: Totp) -> bool {
22        self.map.insert(l, t).is_none()
23    }
24
25    pub fn from_dbvs2(data: Vec<(String, DbTotpV1)>) -> Result<ValueSet, OperationError> {
26        let map = data
27            .into_iter()
28            .map(|(l, data)| {
29                Totp::try_from(data)
30                    .map_err(|()| OperationError::InvalidValueState)
31                    .map(|t| (l, t))
32            })
33            .collect::<Result<_, _>>()?;
34        Ok(Box::new(ValueSetTotpSecret { map }))
35    }
36
37    // We need to allow this, because rust doesn't allow us to impl FromIterator on foreign
38    // types, and tuples are always foreign.
39    #[allow(clippy::should_implement_trait)]
40    pub fn from_iter<T>(iter: T) -> Option<Box<Self>>
41    where
42        T: IntoIterator<Item = (String, Totp)>,
43    {
44        let map = iter.into_iter().collect();
45        Some(Box::new(ValueSetTotpSecret { map }))
46    }
47}
48
49impl ValueSetT for ValueSetTotpSecret {
50    fn insert_checked(&mut self, value: Value) -> Result<bool, OperationError> {
51        match value {
52            Value::TotpSecret(l, t) => {
53                if let BTreeEntry::Vacant(e) = self.map.entry(l) {
54                    e.insert(t);
55                    Ok(true)
56                } else {
57                    Ok(false)
58                }
59            }
60            _ => Err(OperationError::InvalidValueState),
61        }
62    }
63
64    fn clear(&mut self) {
65        self.map.clear();
66    }
67
68    fn remove(&mut self, pv: &PartialValue, _cid: &Cid) -> bool {
69        match pv {
70            PartialValue::Utf8(l) => self.map.remove(l.as_str()).is_some(),
71            _ => false,
72        }
73    }
74
75    fn contains(&self, pv: &PartialValue) -> bool {
76        match pv {
77            PartialValue::Utf8(l) => self.map.contains_key(l.as_str()),
78            _ => false,
79        }
80    }
81
82    fn substring(&self, _pv: &PartialValue) -> bool {
83        false
84    }
85
86    fn startswith(&self, _pv: &PartialValue) -> bool {
87        false
88    }
89
90    fn endswith(&self, _pv: &PartialValue) -> bool {
91        false
92    }
93
94    fn lessthan(&self, _pv: &PartialValue) -> bool {
95        false
96    }
97
98    fn len(&self) -> usize {
99        self.map.len()
100    }
101
102    fn generate_idx_eq_keys(&self) -> Vec<String> {
103        self.map.keys().cloned().collect()
104    }
105
106    fn syntax(&self) -> SyntaxType {
107        SyntaxType::TotpSecret
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.map.keys().cloned())
116    }
117
118    fn to_scim_value(&self) -> Option<ScimResolveStatus> {
119        None
120    }
121
122    fn to_db_valueset_v2(&self) -> DbValueSetV2 {
123        DbValueSetV2::TotpSecret(
124            self.map
125                .iter()
126                .map(|(label, totp)| (label.clone(), totp.to_dbtotpv1()))
127                .collect(),
128        )
129    }
130
131    fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
132        Box::new(self.map.keys().cloned().map(PartialValue::Utf8))
133    }
134
135    fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
136        Box::new(
137            self.map
138                .iter()
139                .map(|(l, t)| Value::TotpSecret(l.clone(), t.clone())),
140        )
141    }
142
143    fn equal(&self, _other: &ValueSet) -> bool {
144        // Looks like we may not need this?
145        /*
146        if let Some(other) = other.as_credential_map() {
147            &self.map == other
148        } else {
149            // debug_assert!(false);
150            false
151        }
152        */
153        debug_assert!(false);
154        false
155    }
156
157    fn merge(&mut self, _other: &ValueSet) -> Result<(), OperationError> {
158        /*
159        if let Some(b) = other.as_credential_map() {
160            mergemaps!(self.map, b)
161        } else {
162            debug_assert!(false);
163            Err(OperationError::InvalidValueState)
164        }
165        */
166
167        debug_assert!(false);
168        Err(OperationError::InvalidValueState)
169    }
170
171    fn as_totp_map(&self) -> Option<&BTreeMap<String, Totp>> {
172        Some(&self.map)
173    }
174}