1+ /* *****************************************************************************
2+ * # License
3+ * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
4+ ******************************************************************************
5+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
6+ * software is governed by the terms of Silicon Labs Master Software License
7+ * Agreement (MSLA) available at
8+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
9+ * software is distributed to you in Source Code format and is governed by the
10+ * sections of the MSLA applicable to Source Code.
11+ *
12+ *****************************************************************************/
13+ // Get attribute store names
14+ #include " user_credential_helpers.hpp"
15+
16+ #include " boost/format.hpp"
17+
18+ namespace user_credential_helpers
19+ {
20+
21+
22+ void set_operation_type (attribute_store::attribute base_node,
23+ attribute_store_type_t operation_type_node_type,
24+ user_credential_operation_type_t operation_type)
25+ {
26+ auto operation_type_node = base_node.emplace_node (operation_type_node_type);
27+
28+ // Undefine reported to be sure that we can so the same operation twice in a row
29+ operation_type_node.clear_reported ();
30+ operation_type_node.set_desired (operation_type);
31+ }
32+
33+ void set_user_operation_type (attribute_store_node_t user_node,
34+ user_credential_operation_type_t operation_type)
35+ {
36+ set_operation_type (
37+ user_node,
38+ ATTRIBUTE (USER_OPERATION_TYPE),
39+ operation_type);
40+ }
41+
42+ void set_credential_operation_type (
43+ attribute_store_node_t slot_node,
44+ user_credential_operation_type_t operation_type)
45+ {
46+ set_operation_type (slot_node,
47+ ATTRIBUTE (CREDENTIAL_OPERATION_TYPE),
48+ operation_type);
49+ }
50+
51+ void set_credential_learn_operation_type (
52+ attribute_store_node_t slot_node,
53+ user_credential_operation_type_t operation_type)
54+ {
55+ set_operation_type (slot_node,
56+ ATTRIBUTE (CREDENTIAL_LEARN_OPERATION_TYPE),
57+ operation_type);
58+ }
59+
60+ bool user_exists (attribute_store::attribute endpoint_node,
61+ user_credential_user_unique_id_t user_id)
62+ {
63+ return endpoint_node
64+ .child_by_type_and_value (ATTRIBUTE (USER_UNIQUE_ID),
65+ user_id,
66+ REPORTED_ATTRIBUTE)
67+ .is_valid ();
68+ }
69+
70+ attribute_store::attribute
71+ get_user_unique_id_node (attribute_store::attribute endpoint_node,
72+ user_credential_user_unique_id_t user_id,
73+ attribute_store_node_value_state_t state)
74+ {
75+ attribute_store::attribute user_id_node
76+ = endpoint_node.child_by_type_and_value (ATTRIBUTE (USER_UNIQUE_ID),
77+ user_id,
78+ state);
79+
80+ if (!user_id_node.is_valid ()) {
81+ throw std::runtime_error (
82+ (boost::format (" User ID %1% not found (state : %2%)." ) % user_id % state)
83+ .str ());
84+ }
85+
86+ return user_id_node;
87+ }
88+
89+
90+ attribute_store::attribute
91+ get_credential_type_node (attribute_store::attribute user_id_node,
92+ user_credential_type_t cred_type,
93+ attribute_store_node_value_state_t state)
94+ {
95+ if (!user_id_node.is_valid ()) {
96+ throw std::runtime_error (
97+ " get_credential_type_node: User ID node is not valid." );
98+ }
99+
100+ attribute_store::attribute cred_type_node
101+ = user_id_node.child_by_type_and_value (ATTRIBUTE (CREDENTIAL_TYPE),
102+ cred_type,
103+ state);
104+
105+ if (!cred_type_node.is_valid ()) {
106+ throw std::runtime_error (
107+ (boost::format (" Credential type %1% (state : %2%) not found for %3%." )
108+ % cred_type % state % user_id_node.value_to_string ())
109+ .str ());
110+ }
111+
112+ return cred_type_node;
113+ }
114+
115+ attribute_store::attribute
116+ get_credential_slot_node (attribute_store::attribute cred_type_node,
117+ user_credential_slot_t cred_slot,
118+ attribute_store_node_value_state_t state)
119+ {
120+ if (!cred_type_node.is_valid ()) {
121+ throw std::runtime_error (
122+ " get_credential_slot_node: Credential Type node is not valid." );
123+ }
124+
125+ attribute_store::attribute cred_slot_node
126+ = cred_type_node.child_by_type_and_value (ATTRIBUTE (CREDENTIAL_SLOT),
127+ cred_slot,
128+ state);
129+
130+ if (!cred_slot_node.is_valid ()) {
131+ throw std::runtime_error (
132+ (boost::format (
133+ " Credential slot %1% (state : %2%) not found for %3% / %4%." )
134+ % cred_slot % state % cred_type_node.value_to_string ()
135+ % cred_type_node.parent ().value_to_string ())
136+ .str ());
137+ }
138+
139+ return cred_slot_node;
140+ }
141+
142+ void for_each_credential_type_nodes_for_user (
143+ attribute_store::attribute user_id_node,
144+ const attribute_callback &callback,
145+ user_credential_type_t credential_type)
146+ {
147+ auto credential_type_nodes
148+ = user_id_node.children (ATTRIBUTE (CREDENTIAL_TYPE));
149+ for (auto &credential_type_node: credential_type_nodes) {
150+ // Call
151+ if (credential_type == 0
152+ || (credential_type_node.reported_exists ()
153+ && credential_type_node.reported <user_credential_type_t >()
154+ == credential_type)) {
155+ callback (credential_type_node);
156+ }
157+ }
158+ }
159+
160+ void for_each_credential_type_nodes (attribute_store::attribute endpoint_node,
161+ const attribute_callback &callback,
162+ user_credential_type_t credential_type)
163+ {
164+ auto user_nodes = endpoint_node.children (ATTRIBUTE (USER_UNIQUE_ID));
165+ for (auto &user_node: user_nodes) {
166+ for_each_credential_type_nodes_for_user (user_node,
167+ callback,
168+ credential_type);
169+ }
170+ }
171+
172+
173+ bool is_credential_available (attribute_store_node_t endpoint_node,
174+ user_credential_type_t credential_type,
175+ user_credential_slot_t credential_slot)
176+ {
177+ bool credential_available = true ;
178+
179+ for_each_credential_type_nodes (
180+ endpoint_node,
181+ [&](attribute_store::attribute &credential_type_node) {
182+ for (auto &credential_slot_node:
183+ credential_type_node.children (ATTRIBUTE (CREDENTIAL_SLOT))) {
184+ // If this credential slot node doesn't have a reported value, check the next one
185+ if (!credential_slot_node.reported_exists ()) {
186+ continue ;
187+ }
188+
189+ if (credential_slot_node.reported <user_credential_slot_t >()
190+ == credential_slot) {
191+ credential_available = false ;
192+ return ;
193+ }
194+ }
195+ },
196+ credential_type);
197+
198+ return credential_available;
199+ }
200+
201+
202+ credential_id_nodes
203+ get_credential_identifier_nodes (attribute_store_node_t child_node)
204+ {
205+ attribute_store::attribute slot_node (child_node);
206+ slot_node = slot_node.first_parent_or_self (ATTRIBUTE (CREDENTIAL_SLOT));
207+ attribute_store::attribute type_node
208+ = slot_node.first_parent (ATTRIBUTE (CREDENTIAL_TYPE));
209+ attribute_store::attribute user_unique_id_node
210+ = type_node.first_parent (ATTRIBUTE (USER_UNIQUE_ID));
211+
212+ if (!slot_node.is_valid ()) {
213+ throw std::runtime_error (
214+ " get_credential_identifier_nodes: Can't get credential slot node." );
215+ }
216+
217+ if (!type_node.is_valid ()) {
218+ throw std::runtime_error (
219+ " get_credential_identifier_nodes: Can't get credential type node." );
220+ }
221+
222+ if (!user_unique_id_node.is_valid ()) {
223+ throw std::runtime_error (
224+ " get_credential_identifier_nodes: Can't get user unique ID node." );
225+ }
226+
227+ return {.slot_node = slot_node,
228+ .type_node = type_node,
229+ .user_unique_id_node = user_unique_id_node};
230+ }
231+
232+ credential_id_nodes get_credential_identifier_nodes (
233+ const attribute_store::attribute &endpoint_node,
234+ identifier_state<user_credential_user_unique_id_t > user_id,
235+ identifier_state<user_credential_type_t > credential_type,
236+ identifier_state<user_credential_slot_t > credential_slot)
237+ {
238+ credential_id_nodes nodes;
239+
240+ nodes.user_unique_id_node
241+ = get_user_unique_id_node (endpoint_node, user_id.value , user_id.state );
242+
243+ if (!nodes.user_unique_id_node .is_valid ()) {
244+ throw std::runtime_error (
245+ " get_credential_identifier_nodes: Can't get user unique ID "
246+ + std::to_string (user_id.value ));
247+ }
248+
249+ nodes.type_node = get_credential_type_node (nodes.user_unique_id_node ,
250+ credential_type.value ,
251+ credential_type.state );
252+
253+ if (!nodes.type_node .is_valid ()) {
254+ throw std::runtime_error (
255+ (boost::format (" get_credential_identifier_nodes: Can't get credential "
256+ " type %1% for user %2%" )
257+ % credential_type.value % user_id.value )
258+ .str ());
259+ }
260+
261+ nodes.slot_node = get_credential_slot_node (nodes.type_node ,
262+ credential_slot.value ,
263+ credential_slot.state );
264+
265+ if (!nodes.slot_node .is_valid ()) {
266+ throw std::runtime_error (
267+ (boost::format (" get_credential_identifier_nodes: Can't get credential "
268+ " slot %1% for credential type %2% / user %3%" )
269+ % credential_slot.value % credential_type.value % user_id.value )
270+ .str ());
271+ }
272+ return nodes;
273+ }
274+
275+ } // namespace user_credential_helpers
0 commit comments