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