1use crate::be::dbvalue::DbValueSetV2;
2use crate::credential::{apppwd::ApplicationPassword, totp::Totp, Credential};
3use crate::prelude::*;
4use crate::repl::cid::Cid;
5use crate::schema::SchemaAttribute;
6use crate::server::keys::KeyId;
7use crate::value::{
8 Address, ApiToken, CredentialType, IntentTokenState, Oauth2Session, OauthClaimMapJoin, Session,
9};
10use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer};
11use crypto_glue::{s256::Sha256Output, x509::Certificate};
12use dyn_clone::DynClone;
13use hashbrown::HashSet;
14use kanidm_proto::internal::ImageValue;
15use kanidm_proto::internal::{Filter as ProtoFilter, UiHint};
16use kanidm_proto::scim_v1::JsonValue;
17use kanidm_proto::scim_v1::ScimOauth2ClaimMapJoinChar;
18use kanidm_proto::v1::OutboundMessage;
19use smolset::SmolSet;
20use sshkey_attest::proto::PublicKey as SshPublicKey;
21use std::cmp::Ordering;
22use std::collections::{BTreeMap, BTreeSet};
23use time::OffsetDateTime;
24use webauthn_rs::prelude::AttestationCaList;
25use webauthn_rs::prelude::AttestedPasskey as AttestedPasskeyV4;
26use webauthn_rs::prelude::Passkey as PasskeyV4;
27
28pub use self::address::{ValueSetAddress, ValueSetEmailAddress};
29use self::apppwd::ValueSetApplicationPassword;
30pub use self::auditlogstring::{ValueSetAuditLogString, AUDIT_LOG_STRING_CAPACITY};
31pub use self::binary::{ValueSetPrivateBinary, ValueSetPublicBinary};
32pub use self::bool::ValueSetBool;
33pub use self::certificate::ValueSetCertificate;
34pub use self::cid::ValueSetCid;
35pub use self::cred::{
36 ValueSetAttestedPasskey, ValueSetCredential, ValueSetCredentialType, ValueSetIntentToken,
37 ValueSetPasskey, ValueSetWebauthnAttestationCaList,
38};
39pub use self::datetime::ValueSetDateTime;
40pub use self::hexstring::ValueSetHexString;
41use self::image::ValueSetImage;
42pub use self::iname::ValueSetIname;
43pub use self::index::ValueSetIndex;
44pub use self::int64::ValueSetInt64;
45pub use self::iutf8::ValueSetIutf8;
46pub use self::json::{ValueSetJson, ValueSetJsonFilter};
47pub use self::jws::{ValueSetJwsKeyEs256, ValueSetJwsKeyRs256};
48pub use self::key_internal::{KeyInternalData, ValueSetKeyInternal};
49pub use self::message::ValueSetMessage;
50pub use self::nsuniqueid::ValueSetNsUniqueId;
51pub use self::oauth::{
52 OauthClaimMapping, ValueSetOauthClaimMap, ValueSetOauthScope, ValueSetOauthScopeMap,
53};
54pub use self::restricted::ValueSetRestricted;
55pub use self::s256::ValueSetSha256;
56pub use self::secret::ValueSetSecret;
57pub use self::session::{ValueSetApiToken, ValueSetOauth2Session, ValueSetSession};
58pub use self::spn::ValueSetSpn;
59pub use self::ssh::ValueSetSshKey;
60pub use self::syntax::ValueSetSyntax;
61pub use self::totp::ValueSetTotpSecret;
62pub use self::uihint::ValueSetUiHint;
63pub use self::uint32::ValueSetUint32;
64pub use self::uint64::ValueSetUint64;
65pub use self::url::ValueSetUrl;
66pub use self::utf8::ValueSetUtf8;
67pub use self::uuid::{ValueSetRefer, ValueSetUuid};
68
69mod address;
70mod apppwd;
71mod auditlogstring;
72mod binary;
73mod bool;
74mod certificate;
75mod cid;
76mod cred;
77mod datetime;
78mod hexstring;
79pub mod image;
80mod iname;
81mod index;
82mod int64;
83mod iutf8;
84mod json;
85mod jws;
86mod key_internal;
87mod message;
88mod nsuniqueid;
89mod oauth;
90mod restricted;
91mod s256;
92mod secret;
93mod session;
94mod spn;
95mod ssh;
96mod syntax;
97mod totp;
98mod uihint;
99mod uint32;
100mod uint64;
101mod url;
102mod utf8;
103mod uuid;
104
105pub type ValueSet = Box<dyn ValueSetT + Send + Sync + 'static>;
106
107dyn_clone::clone_trait_object!(ValueSetT);
108
109pub trait ValueSetT: std::fmt::Debug + DynClone {
110 fn insert_checked(&mut self, value: Value) -> Result<bool, OperationError>;
115
116 fn clear(&mut self);
117
118 fn remove(&mut self, pv: &PartialValue, cid: &Cid) -> bool;
119
120 fn purge(&mut self, _cid: &Cid) -> bool {
121 true
123 }
124
125 fn trim(&mut self, _trim_cid: &Cid) {
126 }
128
129 fn contains(&self, pv: &PartialValue) -> bool;
130
131 fn substring(&self, _pv: &crate::value::PartialValue) -> bool {
132 false
133 }
134
135 fn startswith(&self, _pv: &PartialValue) -> bool {
136 false
137 }
138
139 fn endswith(&self, _pv: &PartialValue) -> bool {
140 false
141 }
142
143 fn lessthan(&self, _pv: &crate::value::PartialValue) -> bool {
144 false
145 }
146
147 fn len(&self) -> usize;
148
149 fn generate_idx_eq_keys(&self) -> Vec<String> {
150 Vec::with_capacity(0)
151 }
152
153 fn generate_idx_sub_keys(&self) -> Vec<String> {
154 Vec::with_capacity(0)
155 }
156
157 fn generate_idx_ord_keys(&self) -> Vec<String> {
158 Vec::with_capacity(0)
159 }
160
161 fn syntax(&self) -> SyntaxType;
162
163 fn validate(&self, schema_attr: &SchemaAttribute) -> bool;
164
165 fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_>;
166
167 fn to_scim_value(&self) -> Option<ScimResolveStatus>;
168
169 fn to_db_valueset_v2(&self) -> DbValueSetV2;
170
171 fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_>;
172
173 fn to_value_iter(&self) -> Box<dyn Iterator<Item = Value> + '_>;
174
175 fn equal(&self, other: &ValueSet) -> bool;
176
177 fn cmp(&self, _other: &ValueSet) -> Ordering {
178 error!("cmp should not be called on {:?}", self.syntax());
182 debug_assert!(false);
183 Ordering::Equal
184 }
185
186 fn merge(&mut self, other: &ValueSet) -> Result<(), OperationError>;
187
188 fn is_empty(&self) -> bool {
189 self.len() == 0
190 }
191
192 fn migrate_iutf8_iname(&self) -> Result<Option<ValueSet>, OperationError> {
193 debug_assert!(false);
194 Ok(None)
195 }
196
197 fn get_ssh_tag(&self, _tag: &str) -> Option<&SshPublicKey> {
198 None
199 }
200
201 fn as_ref_uuid_iter(&self) -> Option<Box<dyn Iterator<Item = Uuid> + '_>> {
202 None
203 }
204
205 fn as_utf8_iter(&self) -> Option<Box<dyn Iterator<Item = &str> + '_>> {
206 error!("as_utf8_iter should not be called on {:?}", self.syntax());
207 debug_assert!(false);
208 None
209 }
210
211 fn as_iutf8_iter(&self) -> Option<Box<dyn Iterator<Item = &str> + '_>> {
212 error!("as_iutf8_iter should not be called on {:?}", self.syntax());
213 debug_assert!(false);
214 None
215 }
216
217 fn as_iname_iter(&self) -> Option<Box<dyn Iterator<Item = &str> + '_>> {
218 error!("as_iname_iter should not be called on {:?}", self.syntax());
219 debug_assert!(false);
220 None
221 }
222
223 fn as_indextype_iter(&self) -> Option<Box<dyn Iterator<Item = IndexType> + '_>> {
224 error!(
225 "as_indextype_set should not be called on {:?}",
226 self.syntax()
227 );
228 None
229 }
230
231 fn as_restricted_string_iter(&self) -> Option<Box<dyn Iterator<Item = &str> + '_>> {
232 error!(
233 "as_restricted_string_iter should not be called on {:?}",
234 self.syntax()
235 );
236 None
237 }
238
239 fn as_oauthscope_iter(&self) -> Option<Box<dyn Iterator<Item = &str> + '_>> {
240 error!(
241 "as_oauthscope_iter should not be called on {:?}",
242 self.syntax()
243 );
244 None
245 }
246
247 fn as_sshpubkey_string_iter(&self) -> Option<Box<dyn Iterator<Item = String> + '_>> {
248 None
249 }
250
251 fn as_email_str_iter(&self) -> Option<Box<dyn Iterator<Item = &str> + '_>> {
252 None
253 }
254
255 fn as_utf8_set(&self) -> Option<&BTreeSet<String>> {
256 debug_assert!(false);
257 None
258 }
259
260 fn as_iutf8_set(&self) -> Option<&BTreeSet<String>> {
261 debug_assert!(false);
262 None
263 }
264
265 fn as_iname_set(&self) -> Option<&BTreeSet<String>> {
266 debug_assert!(false);
267 None
268 }
269
270 fn as_uuid_set(&self) -> Option<&SmolSet<[Uuid; 1]>> {
271 None
272 }
273
274 fn as_refer_set(&self) -> Option<&BTreeSet<Uuid>> {
275 None
276 }
277
278 fn as_refer_set_mut(&mut self) -> Option<&mut BTreeSet<Uuid>> {
279 debug_assert!(false);
280 None
281 }
282
283 fn as_bool_set(&self) -> Option<&SmolSet<[bool; 1]>> {
284 debug_assert!(false);
285 None
286 }
287
288 fn as_uint32_set(&self) -> Option<&SmolSet<[u32; 1]>> {
289 debug_assert!(false);
290 None
291 }
292
293 fn as_int64_set(&self) -> Option<&SmolSet<[i64; 1]>> {
294 debug_assert!(false);
295 None
296 }
297
298 fn as_uint64_set(&self) -> Option<&SmolSet<[u64; 1]>> {
299 debug_assert!(false);
300 None
301 }
302
303 fn as_syntax_set(&self) -> Option<&SmolSet<[SyntaxType; 1]>> {
304 debug_assert!(false);
305 None
306 }
307
308 fn as_index_set(&self) -> Option<&SmolSet<[IndexType; 3]>> {
309 debug_assert!(false);
310 None
311 }
312
313 fn as_secret_set(&self) -> Option<&SmolSet<[String; 1]>> {
314 debug_assert!(false);
315 None
316 }
317
318 fn as_restricted_string_set(&self) -> Option<&BTreeSet<String>> {
319 debug_assert!(false);
320 None
321 }
322
323 fn as_spn_set(&self) -> Option<&SmolSet<[(String, String); 1]>> {
324 debug_assert!(false);
325 None
326 }
327
328 fn as_cid_set(&self) -> Option<&SmolSet<[Cid; 1]>> {
329 debug_assert!(false);
330 None
331 }
332
333 fn as_json_filter_set(&self) -> Option<&SmolSet<[ProtoFilter; 1]>> {
334 debug_assert!(false);
335 None
336 }
337
338 fn as_nsuniqueid_set(&self) -> Option<&SmolSet<[String; 1]>> {
339 debug_assert!(false);
340 None
341 }
342
343 fn as_url_set(&self) -> Option<&SmolSet<[Url; 1]>> {
344 debug_assert!(false);
345 None
346 }
347
348 fn as_datetime_set(&self) -> Option<&SmolSet<[OffsetDateTime; 1]>> {
349 debug_assert!(false);
350 None
351 }
352
353 fn as_private_binary_set(&self) -> Option<&SmolSet<[Vec<u8>; 1]>> {
354 debug_assert!(false);
355 None
356 }
357
358 fn as_oauthscope_set(&self) -> Option<&BTreeSet<String>> {
359 debug_assert!(false);
360 None
361 }
362
363 fn as_address_set(&self) -> Option<&SmolSet<[Address; 1]>> {
364 debug_assert!(false);
365 None
366 }
367
368 fn as_credential_map(&self) -> Option<&BTreeMap<String, Credential>> {
369 debug_assert!(false);
370 None
371 }
372
373 fn as_totp_map(&self) -> Option<&BTreeMap<String, Totp>> {
374 debug_assert!(false);
375 None
376 }
377
378 fn as_emailaddress_set(&self) -> Option<(&String, &BTreeSet<String>)> {
379 debug_assert!(false);
380 None
381 }
382
383 fn as_sshkey_map(&self) -> Option<&BTreeMap<String, SshPublicKey>> {
384 None
385 }
386
387 fn as_oauthscopemap(&self) -> Option<&BTreeMap<Uuid, BTreeSet<String>>> {
388 None
395 }
396
397 fn as_publicbinary_map(&self) -> Option<&BTreeMap<String, Vec<u8>>> {
398 debug_assert!(false);
399 None
400 }
401
402 fn as_intenttoken_map(&self) -> Option<&BTreeMap<String, IntentTokenState>> {
403 debug_assert!(false);
404 None
405 }
406
407 fn as_passkey_map(&self) -> Option<&BTreeMap<Uuid, (String, PasskeyV4)>> {
408 debug_assert!(false);
409 None
410 }
411
412 fn as_attestedpasskey_map(&self) -> Option<&BTreeMap<Uuid, (String, AttestedPasskeyV4)>> {
413 debug_assert!(false);
414 None
415 }
416
417 fn as_webauthn_attestation_ca_list(&self) -> Option<&AttestationCaList> {
418 debug_assert!(false);
419 None
420 }
421
422 fn as_oauthclaim_map(&self) -> Option<&BTreeMap<String, OauthClaimMapping>> {
423 None
424 }
425
426 fn as_key_internal_map(&self) -> Option<&BTreeMap<KeyId, KeyInternalData>> {
427 debug_assert!(false);
428 None
429 }
430
431 fn as_hexstring_set(&self) -> Option<&BTreeSet<String>> {
432 debug_assert!(false);
433 None
434 }
435
436 fn as_application_password_map(&self) -> Option<&BTreeMap<Uuid, Vec<ApplicationPassword>>> {
437 debug_assert!(false);
438 None
439 }
440
441 fn to_value_single(&self) -> Option<Value> {
442 if self.len() != 1 {
443 None
444 } else {
445 self.to_value_iter().take(1).next()
446 }
447 }
448
449 fn to_proto_string_single(&self) -> Option<String> {
450 if self.len() != 1 {
451 None
452 } else {
453 self.to_proto_string_clone_iter().take(1).next()
454 }
455 }
456
457 fn to_uuid_single(&self) -> Option<Uuid> {
458 error!("to_uuid_single should not be called on {:?}", self.syntax());
459 None
460 }
461
462 fn to_cid_single(&self) -> Option<Cid> {
463 error!("to_cid_single should not be called on {:?}", self.syntax());
464 None
465 }
466
467 fn to_refer_single(&self) -> Option<Uuid> {
468 error!(
469 "to_refer_single should not be called on {:?}",
470 self.syntax()
471 );
472 debug_assert!(false);
473 None
474 }
475
476 fn to_bool_single(&self) -> Option<bool> {
477 error!("to_bool_single should not be called on {:?}", self.syntax());
478 None
479 }
480
481 fn to_uint32_single(&self) -> Option<u32> {
482 error!(
483 "to_uint32_single should not be called on {:?}",
484 self.syntax()
485 );
486 debug_assert!(false);
487 None
488 }
489
490 fn to_int64_single(&self) -> Option<i64> {
491 error!(
492 "to_int64_single should not be called on {:?}",
493 self.syntax()
494 );
495 debug_assert!(false);
496 None
497 }
498
499 fn to_uint64_single(&self) -> Option<u64> {
500 error!(
501 "to_uint64_single should not be called on {:?}",
502 self.syntax()
503 );
504 debug_assert!(false);
505 None
506 }
507
508 fn to_syntaxtype_single(&self) -> Option<SyntaxType> {
509 error!(
510 "to_syntaxtype_single should not be called on {:?}",
511 self.syntax()
512 );
513 None
514 }
515
516 fn to_credential_single(&self) -> Option<&Credential> {
517 error!(
518 "to_credential_single should not be called on {:?}",
519 self.syntax()
520 );
521 debug_assert!(false);
522 None
523 }
524
525 fn to_secret_single(&self) -> Option<&str> {
526 error!(
527 "to_secret_single should not be called on {:?}",
528 self.syntax()
529 );
530 debug_assert!(false);
531 None
532 }
533
534 fn to_restricted_string_single(&self) -> Option<&str> {
535 error!(
536 "to_restricted_string_single should not be called on {:?}",
537 self.syntax()
538 );
539 debug_assert!(false);
540 None
541 }
542
543 fn to_utf8_single(&self) -> Option<&str> {
544 error!("to_utf8_single should not be called on {:?}", self.syntax());
545 debug_assert!(false);
546 None
547 }
548
549 fn to_iutf8_single(&self) -> Option<&str> {
550 error!(
551 "to_iutf8_single should not be called on {:?}",
552 self.syntax()
553 );
554 debug_assert!(false);
555 None
556 }
557
558 fn to_iname_single(&self) -> Option<&str> {
559 error!(
560 "to_iname_single should not be called on {:?}",
561 self.syntax()
562 );
563 debug_assert!(false);
564 None
565 }
566
567 fn to_datetime_single(&self) -> Option<OffsetDateTime> {
568 error!(
569 "to_datetime_single should not be called on {:?}",
570 self.syntax()
571 );
572 debug_assert!(false);
573 None
574 }
575
576 fn to_url_single(&self) -> Option<&Url> {
577 error!("to_url_single should not be called on {:?}", self.syntax());
578 debug_assert!(false);
579 None
580 }
581
582 fn to_json_filter_single(&self) -> Option<&ProtoFilter> {
583 error!(
584 "to_json_filter_single should not be called on {:?}",
585 self.syntax()
586 );
587 None
589 }
590
591 fn to_email_address_primary_str(&self) -> Option<&str> {
592 debug_assert!(false);
593 None
594 }
595
596 fn to_private_binary_single(&self) -> Option<&[u8]> {
597 debug_assert!(false);
598 None
599 }
600
601 fn to_passkey_single(&self) -> Option<&PasskeyV4> {
602 debug_assert!(false);
603 None
604 }
605
606 fn as_session_map(&self) -> Option<&BTreeMap<Uuid, Session>> {
607 debug_assert!(false);
608 None
609 }
610
611 fn as_apitoken_map(&self) -> Option<&BTreeMap<Uuid, ApiToken>> {
612 debug_assert!(false);
613 None
614 }
615
616 fn as_oauth2session_map(&self) -> Option<&BTreeMap<Uuid, Oauth2Session>> {
617 debug_assert!(false);
618 None
619 }
620
621 fn to_jws_key_es256_single(&self) -> Option<&JwsEs256Signer> {
622 debug_assert!(false);
623 None
624 }
625
626 fn as_jws_key_es256_set(&self) -> Option<&HashSet<JwsEs256Signer>> {
627 debug_assert!(false);
628 None
629 }
630
631 fn to_jws_key_rs256_single(&self) -> Option<&JwsRs256Signer> {
632 debug_assert!(false);
633 None
634 }
635
636 fn as_jws_key_rs256_set(&self) -> Option<&HashSet<JwsRs256Signer>> {
637 debug_assert!(false);
638 None
639 }
640
641 fn as_uihint_set(&self) -> Option<&BTreeSet<UiHint>> {
642 debug_assert!(false);
643 None
644 }
645
646 fn as_uihint_iter(&self) -> Option<Box<dyn Iterator<Item = UiHint> + '_>> {
647 debug_assert!(false);
648 None
649 }
650
651 fn as_audit_log_string(&self) -> Option<&BTreeMap<Cid, String>> {
652 debug_assert!(false);
653 None
654 }
655
656 fn as_imageset(&self) -> Option<&HashSet<ImageValue>> {
657 debug_assert!(false);
658 None
659 }
660
661 fn to_credentialtype_single(&self) -> Option<CredentialType> {
662 debug_assert!(false);
663 None
664 }
665
666 fn as_credentialtype_set(&self) -> Option<&SmolSet<[CredentialType; 1]>> {
667 debug_assert!(false);
668 None
669 }
670
671 fn to_certificate_single(&self) -> Option<&Certificate> {
672 debug_assert!(false);
673 None
674 }
675
676 fn as_certificate_set(&self) -> Option<&BTreeMap<Sha256Output, Box<Certificate>>> {
677 debug_assert!(false);
678 None
679 }
680
681 fn as_json_object(&self) -> Option<&JsonValue> {
682 debug_assert!(false);
683 None
684 }
685
686 fn as_message(&self) -> Option<&OutboundMessage> {
687 debug_assert!(false);
688 None
689 }
690
691 fn as_s256_set(&self) -> Option<&BTreeSet<Sha256Output>> {
692 debug_assert!(false);
693 None
694 }
695
696 fn as_s256_set_mut(&mut self) -> Option<&mut BTreeSet<Sha256Output>> {
697 debug_assert!(false);
698 None
699 }
700
701 fn repl_merge_valueset(
702 &self,
703 _older: &ValueSet,
704 _trim_cid: &Cid, ) -> Option<ValueSet> {
706 None
722 }
723}
724
725pub trait ValueSetScimPut {
726 fn from_scim_json_put(value: JsonValue) -> Result<ValueSetResolveStatus, OperationError>;
727}
728
729impl PartialEq for ValueSet {
730 fn eq(&self, other: &ValueSet) -> bool {
731 self.equal(other)
732 }
733}
734
735pub struct UnresolvedScimValueOauth2ClaimMap {
736 pub group_uuid: Uuid,
737 pub claim: String,
738 pub join_char: ScimOauth2ClaimMapJoinChar,
739 pub values: BTreeSet<String>,
740}
741
742pub struct UnresolvedScimValueOauth2ScopeMap {
743 pub group_uuid: Uuid,
744 pub scopes: BTreeSet<String>,
745}
746
747pub enum ScimValueIntermediate {
748 References(Vec<Uuid>),
749 Oauth2ClaimMap(Vec<UnresolvedScimValueOauth2ClaimMap>),
750 Oauth2ScopeMap(Vec<UnresolvedScimValueOauth2ScopeMap>),
751}
752
753pub enum ScimResolveStatus {
754 Resolved(ScimValueKanidm),
755 NeedsResolution(ScimValueIntermediate),
756}
757
758impl<T> From<T> for ScimResolveStatus
759where
760 T: Into<ScimValueKanidm>,
761{
762 fn from(v: T) -> Self {
763 Self::Resolved(v.into())
764 }
765}
766
767#[cfg(test)]
768impl ScimResolveStatus {
769 pub fn assume_resolved(self) -> ScimValueKanidm {
770 match self {
771 ScimResolveStatus::Resolved(v) => v,
772 ScimResolveStatus::NeedsResolution(_) => {
773 panic!("assume_resolved called on NeedsResolution")
774 }
775 }
776 }
777
778 pub fn assume_unresolved(self) -> ScimValueIntermediate {
779 match self {
780 ScimResolveStatus::Resolved(_) => panic!("assume_unresolved called on Resolved"),
781 ScimResolveStatus::NeedsResolution(svi) => svi,
782 }
783 }
784}
785
786pub enum ValueSetResolveStatus {
787 Resolved(ValueSet),
788 NeedsResolution(ValueSetIntermediate),
789}
790
791#[cfg(test)]
792impl ValueSetResolveStatus {
793 pub fn assume_resolved(self) -> ValueSet {
794 match self {
795 ValueSetResolveStatus::Resolved(v) => v,
796 ValueSetResolveStatus::NeedsResolution(_) => {
797 panic!("assume_resolved called on NeedsResolution")
798 }
799 }
800 }
801
802 pub fn assume_unresolved(self) -> ValueSetIntermediate {
803 match self {
804 ValueSetResolveStatus::Resolved(_) => panic!("assume_unresolved called on Resolved"),
805 ValueSetResolveStatus::NeedsResolution(svi) => svi,
806 }
807 }
808}
809
810pub enum ValueSetIntermediate {
811 References {
812 resolved: BTreeSet<Uuid>,
813 unresolved: Vec<String>,
814 },
815 Oauth2ClaimMap {
816 resolved: Vec<ResolvedValueSetOauth2ClaimMap>,
817 unresolved: Vec<UnresolvedValueSetOauth2ClaimMap>,
818 },
819 Oauth2ScopeMap {
820 resolved: Vec<ResolvedValueSetOauth2ScopeMap>,
821 unresolved: Vec<UnresolvedValueSetOauth2ScopeMap>,
822 },
823}
824
825pub struct UnresolvedValueSetOauth2ClaimMap {
826 pub group_name: String,
827 pub claim: String,
828 pub join_char: OauthClaimMapJoin,
829 pub claim_values: BTreeSet<String>,
830}
831
832pub struct ResolvedValueSetOauth2ClaimMap {
833 pub group_uuid: Uuid,
834 pub claim: String,
835 pub join_char: OauthClaimMapJoin,
836 pub claim_values: BTreeSet<String>,
837}
838
839pub struct UnresolvedValueSetOauth2ScopeMap {
840 pub group_name: String,
841 pub scopes: BTreeSet<String>,
842}
843
844pub struct ResolvedValueSetOauth2ScopeMap {
845 pub group_uuid: Uuid,
846 pub scopes: BTreeSet<String>,
847}
848
849pub fn uuid_to_proto_string(u: Uuid) -> String {
850 u.as_hyphenated().to_string()
851}
852
853pub fn from_result_value_iter(
854 mut iter: impl Iterator<Item = Result<Value, OperationError>>,
855) -> Result<ValueSet, OperationError> {
856 let Some(init) = iter.next() else {
857 trace!("Empty value iterator");
858 return Err(OperationError::InvalidValueState);
859 };
860
861 let init = init?;
862
863 let mut vs: ValueSet = match init {
864 Value::Utf8(s) => ValueSetUtf8::new(s),
865 Value::Iutf8(s) => ValueSetIutf8::new(&s),
866 Value::Iname(s) => ValueSetIname::new(&s),
867 Value::Uuid(u) => ValueSetUuid::new(u),
868 Value::Refer(u) => ValueSetRefer::new(u),
869 Value::Bool(u) => ValueSetBool::new(u),
870 Value::Uint32(u) => ValueSetUint32::new(u),
871 Value::Int64(u) => ValueSetInt64::new(u),
872 Value::Uint64(u) => ValueSetUint64::new(u),
873 Value::Syntax(u) => ValueSetSyntax::new(u),
874 Value::Index(u) => ValueSetIndex::new(u),
875 Value::SecretValue(u) => ValueSetSecret::new(u),
876 Value::RestrictedString(u) => ValueSetRestricted::new(u),
877 Value::Spn(n, d) => ValueSetSpn::new((n, d)),
878 Value::Cid(u) => ValueSetCid::new(u),
879 Value::JsonFilt(u) => ValueSetJsonFilter::new(u),
880 Value::Nsuniqueid(u) => ValueSetNsUniqueId::new(u),
881 Value::Url(u) => ValueSetUrl::new(u),
882 Value::DateTime(u) => ValueSetDateTime::new(u),
883 Value::PrivateBinary(u) => ValueSetPrivateBinary::new(u),
884 Value::OauthScope(u) => ValueSetOauthScope::new(u),
885 Value::Address(u) => ValueSetAddress::new(u),
886 Value::Cred(t, c) => ValueSetCredential::new(t, c),
887 Value::SshKey(t, k) => ValueSetSshKey::new(t, k),
888 Value::OauthScopeMap(u, m) => ValueSetOauthScopeMap::new(u, m),
889 Value::PublicBinary(t, b) => ValueSetPublicBinary::new(t, b),
890 Value::IntentToken(u, s) => ValueSetIntentToken::new(u, s),
891 Value::EmailAddress(a, _) => ValueSetEmailAddress::new(a),
892 Value::UiHint(u) => ValueSetUiHint::new(u),
893 Value::AuditLogString(c, s) => ValueSetAuditLogString::new((c, s)),
894 Value::Image(imagevalue) => image::ValueSetImage::new(imagevalue),
895 Value::CredentialType(c) => ValueSetCredentialType::new(c),
896 Value::Certificate(c) => ValueSetCertificate::new(c)?,
897 Value::WebauthnAttestationCaList(_)
898 | Value::PhoneNumber(_, _)
899 | Value::ApplicationPassword(_)
900 | Value::Passkey(_, _, _)
901 | Value::AttestedPasskey(_, _, _)
902 | Value::TotpSecret(_, _)
903 | Value::Session(_, _)
904 | Value::ApiToken(_, _)
905 | Value::Oauth2Session(_, _)
906 | Value::OauthClaimMap(_, _)
907 | Value::OauthClaimValue(_, _, _)
908 | Value::JwsKeyEs256(_)
909 | Value::JwsKeyRs256(_)
910 | Value::HexString(_)
911 | Value::Json(_)
912 | Value::Sha256(_)
913 | Value::KeyInternal { .. } => {
914 debug_assert!(false);
915 return Err(OperationError::InvalidValueState);
916 }
917 };
918
919 for maybe_v in iter {
920 let v = maybe_v?;
921 vs.insert_checked(v)?;
923 }
924 Ok(vs)
925}
926
927pub fn from_value_iter(mut iter: impl Iterator<Item = Value>) -> Result<ValueSet, OperationError> {
928 let Some(init) = iter.next() else {
929 trace!("Empty value iterator");
930 return Err(OperationError::InvalidValueState);
931 };
932
933 let mut vs: ValueSet = match init {
934 Value::Utf8(s) => ValueSetUtf8::new(s),
935 Value::Iutf8(s) => ValueSetIutf8::new(&s),
936 Value::Iname(s) => ValueSetIname::new(&s),
937 Value::Uuid(u) => ValueSetUuid::new(u),
938 Value::Refer(u) => ValueSetRefer::new(u),
939 Value::Bool(u) => ValueSetBool::new(u),
940 Value::Uint32(u) => ValueSetUint32::new(u),
941 Value::Int64(u) => ValueSetInt64::new(u),
942 Value::Uint64(u) => ValueSetUint64::new(u),
943 Value::Syntax(u) => ValueSetSyntax::new(u),
944 Value::Index(u) => ValueSetIndex::new(u),
945 Value::SecretValue(u) => ValueSetSecret::new(u),
946 Value::RestrictedString(u) => ValueSetRestricted::new(u),
947 Value::Spn(n, d) => ValueSetSpn::new((n, d)),
948 Value::Cid(u) => ValueSetCid::new(u),
949 Value::JsonFilt(u) => ValueSetJsonFilter::new(u),
950 Value::Nsuniqueid(u) => ValueSetNsUniqueId::new(u),
951 Value::Url(u) => ValueSetUrl::new(u),
952 Value::DateTime(u) => ValueSetDateTime::new(u),
953 Value::PrivateBinary(u) => ValueSetPrivateBinary::new(u),
954 Value::OauthScope(u) => ValueSetOauthScope::new(u),
955 Value::Address(u) => ValueSetAddress::new(u),
956 Value::Cred(t, c) => ValueSetCredential::new(t, c),
957 Value::SshKey(t, k) => ValueSetSshKey::new(t, k),
958 Value::OauthScopeMap(u, m) => ValueSetOauthScopeMap::new(u, m),
959 Value::PublicBinary(t, b) => ValueSetPublicBinary::new(t, b),
960 Value::IntentToken(u, s) => ValueSetIntentToken::new(u, s),
961 Value::EmailAddress(a, _) => ValueSetEmailAddress::new(a),
962 Value::Passkey(u, t, k) => ValueSetPasskey::new(u, t, k),
963 Value::AttestedPasskey(u, t, k) => ValueSetAttestedPasskey::new(u, t, k),
964 Value::JwsKeyEs256(k) => ValueSetJwsKeyEs256::new(k),
965 Value::JwsKeyRs256(k) => ValueSetJwsKeyRs256::new(k),
966 Value::Session(u, m) => ValueSetSession::new(u, m),
967 Value::ApiToken(u, m) => ValueSetApiToken::new(u, m),
968 Value::Oauth2Session(u, m) => ValueSetOauth2Session::new(u, m),
969 Value::UiHint(u) => ValueSetUiHint::new(u),
970 Value::TotpSecret(l, t) => ValueSetTotpSecret::new(l, t),
971 Value::AuditLogString(c, s) => ValueSetAuditLogString::new((c, s)),
972 Value::Image(imagevalue) => image::ValueSetImage::new(imagevalue),
973 Value::CredentialType(c) => ValueSetCredentialType::new(c),
974 Value::WebauthnAttestationCaList(ca_list) => {
975 ValueSetWebauthnAttestationCaList::new(ca_list)
976 }
977 Value::OauthClaimMap(name, join) => ValueSetOauthClaimMap::new(name, join),
978 Value::OauthClaimValue(name, group, claims) => {
979 ValueSetOauthClaimMap::new_value(name, group, claims)
980 }
981 Value::HexString(s) => ValueSetHexString::new(s),
982
983 Value::KeyInternal {
984 id,
985 usage,
986 valid_from,
987 status,
988 status_cid,
989 der,
990 } => ValueSetKeyInternal::new(id, usage, valid_from, status, status_cid, der),
991 Value::Certificate(certificate) => ValueSetCertificate::new(certificate)?,
992 Value::PhoneNumber(_, _) => {
993 debug_assert!(false);
994 return Err(OperationError::InvalidValueState);
995 }
996 Value::ApplicationPassword(ap) => ValueSetApplicationPassword::new(ap),
997 Value::Sha256(_) => {
998 debug_assert!(false);
999 return Err(OperationError::InvalidValueState);
1000 }
1001 Value::Json(_) => {
1002 debug_assert!(false);
1003 return Err(OperationError::InvalidValueState);
1004 }
1005 };
1006
1007 for v in iter {
1008 vs.insert_checked(v)?;
1009 }
1010 Ok(vs)
1011}
1012
1013pub fn from_db_valueset_v2(dbvs: DbValueSetV2) -> Result<ValueSet, OperationError> {
1014 match dbvs {
1015 DbValueSetV2::Utf8(set) => ValueSetUtf8::from_dbvs2(set),
1016 DbValueSetV2::Iutf8(set) => ValueSetIutf8::from_dbvs2(set),
1017 DbValueSetV2::Iname(set) => ValueSetIname::from_dbvs2(set),
1018 DbValueSetV2::Uuid(set) => ValueSetUuid::from_dbvs2(set),
1019 DbValueSetV2::Reference(set) => ValueSetRefer::from_dbvs2(set),
1020 DbValueSetV2::Bool(set) => ValueSetBool::from_dbvs2(set),
1021 DbValueSetV2::Uint32(set) => ValueSetUint32::from_dbvs2(set),
1022 DbValueSetV2::Int64(set) => ValueSetInt64::from_dbvs2(set),
1023 DbValueSetV2::Uint64(set) => ValueSetUint64::from_dbvs2(set),
1024 DbValueSetV2::SyntaxType(set) => ValueSetSyntax::from_dbvs2(set),
1025 DbValueSetV2::IndexType(set) => ValueSetIndex::from_dbvs2(set),
1026 DbValueSetV2::SecretValue(set) => ValueSetSecret::from_dbvs2(set),
1027 DbValueSetV2::RestrictedString(set) => ValueSetRestricted::from_dbvs2(set),
1028 DbValueSetV2::Spn(set) => ValueSetSpn::from_dbvs2(set),
1029 DbValueSetV2::Cid(set) => ValueSetCid::from_dbvs2(set),
1030 DbValueSetV2::JsonFilter(set) => ValueSetJsonFilter::from_dbvs2(&set),
1031 DbValueSetV2::NsUniqueId(set) => ValueSetNsUniqueId::from_dbvs2(set),
1032 DbValueSetV2::Url(set) => ValueSetUrl::from_dbvs2(set),
1033 DbValueSetV2::DateTime(set) => ValueSetDateTime::from_dbvs2(set),
1034 DbValueSetV2::PrivateBinary(set) => ValueSetPrivateBinary::from_dbvs2(set),
1035 DbValueSetV2::OauthScope(set) => ValueSetOauthScope::from_dbvs2(set),
1036 DbValueSetV2::Address(set) => ValueSetAddress::from_dbvs2(set),
1037 DbValueSetV2::Credential(set) => ValueSetCredential::from_dbvs2(set),
1038 DbValueSetV2::SshKey(set) => ValueSetSshKey::from_dbvs2(set),
1039 DbValueSetV2::OauthScopeMap(set) => ValueSetOauthScopeMap::from_dbvs2(set),
1040 DbValueSetV2::PublicBinary(set) => ValueSetPublicBinary::from_dbvs2(set),
1041 DbValueSetV2::IntentToken(set) => ValueSetIntentToken::from_dbvs2(set),
1042 DbValueSetV2::EmailAddress(primary, set) => ValueSetEmailAddress::from_dbvs2(primary, set),
1043 DbValueSetV2::Passkey(set) => ValueSetPasskey::from_dbvs2(set),
1044 DbValueSetV2::AttestedPasskey(set) => ValueSetAttestedPasskey::from_dbvs2(set),
1045 DbValueSetV2::Session(set) => ValueSetSession::from_dbvs2(&set),
1046 DbValueSetV2::ApiToken(set) => ValueSetApiToken::from_dbvs2(set),
1047 DbValueSetV2::Oauth2Session(set) => ValueSetOauth2Session::from_dbvs2(set),
1048 DbValueSetV2::JwsKeyEs256(set) => ValueSetJwsKeyEs256::from_dbvs2(&set),
1049 DbValueSetV2::JwsKeyRs256(set) => ValueSetJwsKeyEs256::from_dbvs2(&set),
1050 DbValueSetV2::UiHint(set) => ValueSetUiHint::from_dbvs2(set),
1051 DbValueSetV2::TotpSecret(set) => ValueSetTotpSecret::from_dbvs2(set),
1052 DbValueSetV2::AuditLogString(set) => ValueSetAuditLogString::from_dbvs2(set),
1053 DbValueSetV2::PhoneNumber(_, _) | DbValueSetV2::TrustedDeviceEnrollment(_) => {
1054 debug_assert!(false);
1055 Err(OperationError::InvalidValueState)
1056 }
1057 DbValueSetV2::Image(set) => ValueSetImage::from_dbvs2(&set),
1058 DbValueSetV2::CredentialType(set) => ValueSetCredentialType::from_dbvs2(set),
1059 DbValueSetV2::WebauthnAttestationCaList { ca_list } => {
1060 ValueSetWebauthnAttestationCaList::from_dbvs2(ca_list)
1061 }
1062 DbValueSetV2::OauthClaimMap(set) => ValueSetOauthClaimMap::from_dbvs2(set),
1063 DbValueSetV2::KeyInternal(set) => ValueSetKeyInternal::from_dbvs2(set),
1064 DbValueSetV2::HexString(set) => ValueSetHexString::from_dbvs2(set),
1065 DbValueSetV2::Certificate(set) => ValueSetCertificate::from_dbvs2(set),
1066 DbValueSetV2::ApplicationPassword(set) => ValueSetApplicationPassword::from_dbvs2(set),
1067 DbValueSetV2::Json(object) => Ok(ValueSetJson::new(object)),
1068 DbValueSetV2::Sha256(set) => ValueSetSha256::from_dbvs2(set),
1069 DbValueSetV2::Message(object) => Ok(ValueSetMessage::new(object)),
1070 DbValueSetV2::EcKeyPrivate(_key) => Err(OperationError::InvalidState),
1071 }
1072}
1073
1074#[cfg(test)]
1075pub(crate) fn scim_json_reflexive(vs: &ValueSet, data: &str) {
1076 let scim_value = vs.to_scim_value().unwrap().assume_resolved();
1077
1078 let strout = serde_json::to_string_pretty(&scim_value).unwrap();
1079 eprintln!("{strout}");
1080
1081 let json_value: serde_json::Value = serde_json::to_value(&scim_value).unwrap();
1082
1083 eprintln!("{data}");
1084 let expect: serde_json::Value = serde_json::from_str(data).unwrap();
1085
1086 assert_eq!(json_value, expect);
1087}
1088
1089#[cfg(test)]
1090pub(crate) fn scim_json_reflexive_unresolved(
1091 write_txn: &mut QueryServerWriteTransaction,
1092 vs: &ValueSet,
1093 data: &str,
1094) {
1095 let scim_int_value = vs.to_scim_value().unwrap().assume_unresolved();
1096 let scim_value = write_txn.resolve_scim_interim(scim_int_value).unwrap();
1097
1098 let strout = serde_json::to_string_pretty(&scim_value).expect("Failed to serialize");
1099 eprintln!("{strout}");
1100
1101 let json_value: serde_json::Value =
1102 serde_json::to_value(&scim_value).expect("Failed to convert to JSON");
1103
1104 let expect: serde_json::Value =
1105 serde_json::from_str(data).expect("Failed to parse expected JSON");
1106
1107 assert_eq!(json_value, expect);
1108}
1109
1110#[cfg(test)]
1111pub(crate) fn scim_json_put_reflexive<T: ValueSetScimPut>(
1112 expect_vs: &ValueSet,
1113 additional_tests: &[(JsonValue, ValueSet)],
1114) {
1115 let scim_value = expect_vs.to_scim_value().unwrap().assume_resolved();
1116
1117 let strout = serde_json::to_string_pretty(&scim_value).unwrap();
1118 eprintln!("{strout}");
1119
1120 let generic = serde_json::to_value(scim_value).unwrap();
1121 let vs = T::from_scim_json_put(generic).unwrap().assume_resolved();
1123 assert_eq!(&vs, expect_vs);
1124
1125 for (jv, expect_vs) in additional_tests {
1127 let vs = T::from_scim_json_put(jv.clone()).unwrap().assume_resolved();
1128 assert_eq!(&vs, expect_vs);
1129 }
1130}
1131
1132#[cfg(test)]
1133pub(crate) fn scim_json_put_reflexive_unresolved<T: ValueSetScimPut>(
1134 write_txn: &mut QueryServerWriteTransaction,
1135 expect_vs: &ValueSet,
1136 additional_tests: &[(JsonValue, ValueSet)],
1137) {
1138 let scim_int_value = expect_vs.to_scim_value().unwrap().assume_unresolved();
1139 let scim_value = write_txn.resolve_scim_interim(scim_int_value).unwrap();
1140
1141 let generic = serde_json::to_value(scim_value).unwrap();
1142 let vs_inter = T::from_scim_json_put(generic).unwrap().assume_unresolved();
1144 let vs = write_txn.resolve_valueset_intermediate(vs_inter).unwrap();
1145 assert_eq!(&vs, expect_vs);
1146
1147 for (jv, expect_vs) in additional_tests {
1149 let vs_inter = T::from_scim_json_put(jv.clone())
1150 .unwrap()
1151 .assume_unresolved();
1152 let vs = write_txn.resolve_valueset_intermediate(vs_inter).unwrap();
1153 assert_eq!(&vs, expect_vs);
1154 }
1155}