mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 04:27:02 +01:00
Scim add EntryReference (#3079)
Allow references to be displayed as a complex object
This commit is contained in:
parent
12236a39f5
commit
4e125b5043
|
@ -180,6 +180,14 @@ pub struct ScimOAuth2ClaimMap {
|
|||
pub values: BTreeSet<String>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Debug, Clone, PartialEq, Eq, ToSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ScimReference {
|
||||
pub uuid: Uuid,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
/// This is a strongly typed ScimValue for Kanidm. It is for serialisation only
|
||||
/// since on a deserialisation path we can not know the intent of the sender
|
||||
/// to how we deserialise strings. Additionally during deserialisation we need
|
||||
|
@ -196,6 +204,9 @@ pub enum ScimValueKanidm {
|
|||
DateTime(#[serde_as(as = "Rfc3339")] OffsetDateTime),
|
||||
Reference(Url),
|
||||
Uuid(Uuid),
|
||||
EntryReference(ScimReference),
|
||||
EntryReferences(Vec<ScimReference>),
|
||||
|
||||
// Other strong outbound types.
|
||||
ArrayString(Vec<String>),
|
||||
ArrayDateTime(#[serde_as(as = "Vec<Rfc3339>")] Vec<OffsetDateTime>),
|
||||
|
|
|
@ -227,6 +227,6 @@ impl QueryServerReadV1 {
|
|||
idms_prox_read
|
||||
.qs_read
|
||||
.impersonate_search_ext_uuid(target_uuid, &ident)
|
||||
.and_then(|entry| entry.to_scim_kanidm())
|
||||
.and_then(|entry| entry.to_scim_kanidm(idms_prox_read.qs_read))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,23 +29,6 @@ pub use std::collections::BTreeSet as Set;
|
|||
use std::collections::{BTreeMap as Map, BTreeMap, BTreeSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use compact_jwt::JwsEs256Signer;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
use kanidm_proto::internal::{
|
||||
ConsistencyError, Filter as ProtoFilter, OperationError, SchemaError, UiHint,
|
||||
};
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry};
|
||||
use openssl::ec::EcKey;
|
||||
use openssl::pkey::{Private, Public};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{
|
||||
AttestationCaList, AttestedPasskey as AttestedPasskeyV4, Passkey as PasskeyV4,
|
||||
};
|
||||
|
||||
use crate::be::dbentry::{DbEntry, DbEntryVers};
|
||||
use crate::be::dbvalue::DbValueSetV2;
|
||||
use crate::be::{IdxKey, IdxSlope};
|
||||
|
@ -58,13 +41,30 @@ use crate::prelude::*;
|
|||
use crate::repl::cid::Cid;
|
||||
use crate::repl::entry::EntryChangeState;
|
||||
use crate::repl::proto::{ReplEntryV1, ReplIncrementalEntryV1};
|
||||
use compact_jwt::JwsEs256Signer;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
use kanidm_proto::internal::{
|
||||
ConsistencyError, Filter as ProtoFilter, OperationError, SchemaError, UiHint,
|
||||
};
|
||||
use kanidm_proto::scim_v1::server::ScimReference;
|
||||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry};
|
||||
use openssl::ec::EcKey;
|
||||
use openssl::pkey::{Private, Public};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::trace;
|
||||
use uuid::Uuid;
|
||||
use webauthn_rs::prelude::{
|
||||
AttestationCaList, AttestedPasskey as AttestedPasskeyV4, Passkey as PasskeyV4,
|
||||
};
|
||||
|
||||
use crate::schema::{SchemaAttribute, SchemaClass, SchemaTransaction};
|
||||
use crate::value::{
|
||||
ApiToken, CredentialType, IndexType, IntentTokenState, Oauth2Session, PartialValue, Session,
|
||||
SyntaxType, Value,
|
||||
};
|
||||
use crate::valueset::{self, ValueSet};
|
||||
use crate::valueset::{self, ScimResolveStatus, ScimValueIntermediate, ValueSet};
|
||||
|
||||
pub type EntryInitNew = Entry<EntryInit, EntryNew>;
|
||||
pub type EntryInvalidNew = Entry<EntryInvalid, EntryNew>;
|
||||
|
@ -2230,15 +2230,32 @@ impl Entry<EntryReduced, EntryCommitted> {
|
|||
Ok(ProtoEntry { attrs: attrs? })
|
||||
}
|
||||
|
||||
pub fn to_scim_kanidm(&self) -> Result<ScimEntryKanidm, OperationError> {
|
||||
let attrs = self
|
||||
pub fn to_scim_kanidm(
|
||||
&self,
|
||||
mut read_txn: QueryServerReadTransaction,
|
||||
) -> Result<ScimEntryKanidm, OperationError> {
|
||||
let result: Result<BTreeMap<Attribute, ScimValueKanidm>, OperationError> = self
|
||||
.attrs
|
||||
.iter()
|
||||
// We want to skip some attributes as they are already in the header.
|
||||
.filter(|(k, _vs)| **k != Attribute::Uuid)
|
||||
.filter_map(|(k, vs)| vs.to_scim_value().map(|scim_value| (k.clone(), scim_value)))
|
||||
.filter_map(|(k, vs)| {
|
||||
let opt_resolve_status = vs.to_scim_value();
|
||||
let res_opt_scim_value = match opt_resolve_status {
|
||||
None => Ok(None),
|
||||
Some(ScimResolveStatus::Resolved(scim_value_kani)) => Ok(Some(scim_value_kani)),
|
||||
Some(ScimResolveStatus::NeedsResolution(scim_value_interim)) => {
|
||||
resolve_scim_interim(scim_value_interim, &mut read_txn)
|
||||
}
|
||||
};
|
||||
res_opt_scim_value
|
||||
.transpose()
|
||||
.map(|scim_res| scim_res.map(|scim_value| (k.clone(), scim_value)))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let attrs = result?;
|
||||
|
||||
let id = self.get_uuid();
|
||||
|
||||
// Not sure how I want to handle this yet, I think we need some schema changes
|
||||
|
@ -2353,6 +2370,37 @@ impl Entry<EntryReduced, EntryCommitted> {
|
|||
}
|
||||
}
|
||||
|
||||
fn resolve_scim_interim(
|
||||
scim_value_intermediate: ScimValueIntermediate,
|
||||
read_txn: &mut QueryServerReadTransaction,
|
||||
) -> Result<Option<ScimValueKanidm>, OperationError> {
|
||||
match scim_value_intermediate {
|
||||
ScimValueIntermediate::Refer(uuid) => {
|
||||
if let Some(option) = read_txn.uuid_to_spn(uuid)? {
|
||||
Ok(Some(ScimValueKanidm::EntryReference(ScimReference {
|
||||
uuid,
|
||||
value: option.to_proto_string_clone(),
|
||||
})))
|
||||
} else {
|
||||
// TODO: didn't have spn, fallback to uuid.to_string ?
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
ScimValueIntermediate::ReferMany(uuids) => {
|
||||
let mut scim_references = vec![];
|
||||
for uuid in uuids {
|
||||
if let Some(option) = read_txn.uuid_to_spn(uuid)? {
|
||||
scim_references.push(ScimReference {
|
||||
uuid,
|
||||
value: option.to_proto_string_clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
Ok(Some(ScimValueKanidm::EntryReferences(scim_references)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl<STATE> Entry<EntryValid, STATE> {
|
||||
impl<VALID, STATE> Entry<VALID, STATE> {
|
||||
/// This internally adds an AVA to the entry. If the entry was newly added, then true is returned.
|
||||
|
|
|
@ -2268,6 +2268,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::prelude::*;
|
||||
use kanidm_proto::scim_v1::server::ScimReference;
|
||||
|
||||
#[qs_test]
|
||||
async fn test_name_to_uuid(server: &QueryServer) {
|
||||
|
@ -2613,4 +2614,66 @@ mod tests {
|
|||
server_txn.commit().expect("should not fail");
|
||||
// Commit.
|
||||
}
|
||||
|
||||
#[qs_test]
|
||||
async fn test_scim_entry_structure(server: &QueryServer) {
|
||||
let mut read_txn = server.read().await.unwrap();
|
||||
|
||||
// Query entry (A buitin one ?)
|
||||
let entry = read_txn
|
||||
.internal_search_uuid(UUID_IDM_PEOPLE_SELF_NAME_WRITE)
|
||||
.unwrap();
|
||||
|
||||
// Convert entry into scim
|
||||
let reduced = entry.as_ref().clone().into_reduced();
|
||||
let scim_entry = reduced.to_scim_kanidm(read_txn).unwrap();
|
||||
|
||||
// Assert scim entry attributes are as expected
|
||||
assert_eq!(scim_entry.header.id, UUID_IDM_PEOPLE_SELF_NAME_WRITE);
|
||||
let name_scim = scim_entry.attrs.get(&Attribute::Name).unwrap();
|
||||
match name_scim {
|
||||
ScimValueKanidm::String(name) => {
|
||||
assert_eq!(name.clone(), "idm_people_self_name_write")
|
||||
}
|
||||
_ => {
|
||||
panic!("expected String, actual {:?}", name_scim);
|
||||
}
|
||||
}
|
||||
|
||||
// such as returning a new struct type for `members` attributes or `managed_by`
|
||||
let entry_managed_by_scim = scim_entry.attrs.get(&Attribute::EntryManagedBy).unwrap();
|
||||
match entry_managed_by_scim {
|
||||
ScimValueKanidm::EntryReferences(managed_by) => {
|
||||
assert_eq!(
|
||||
managed_by.first().unwrap().clone(),
|
||||
ScimReference {
|
||||
uuid: UUID_IDM_ADMINS,
|
||||
value: "idm_admins@example.com".to_string()
|
||||
}
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
panic!(
|
||||
"expected EntryReference, actual {:?}",
|
||||
entry_managed_by_scim
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let members_scim = scim_entry.attrs.get(&Attribute::Member).unwrap();
|
||||
match members_scim {
|
||||
ScimValueKanidm::EntryReferences(members) => {
|
||||
assert_eq!(
|
||||
members.first().unwrap().clone(),
|
||||
ScimReference {
|
||||
uuid: UUID_IDM_ALL_PERSONS,
|
||||
value: "idm_all_persons@example.com".to_string()
|
||||
}
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
panic!("expected EntryReferences, actual {:?}", members_scim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::prelude::*;
|
|||
use crate::schema::SchemaAttribute;
|
||||
use crate::utils::trigraph_iter;
|
||||
use crate::value::{Address, VALIDATE_EMAIL_RE};
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use kanidm_proto::scim_v1::server::{ScimAddress, ScimMail};
|
||||
|
||||
|
@ -137,8 +137,8 @@ impl ValueSetT for ValueSetAddress {
|
|||
Box::new(self.set.iter().map(|a| a.formatted.clone()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set
|
||||
.iter()
|
||||
.map(|a| ScimAddress {
|
||||
|
@ -150,7 +150,7 @@ impl ValueSetT for ValueSetAddress {
|
|||
country: a.country.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -427,8 +427,8 @@ impl ValueSetT for ValueSetEmailAddress {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set
|
||||
.iter()
|
||||
.map(|mail| {
|
||||
|
@ -439,7 +439,7 @@ impl ValueSetT for ValueSetEmailAddress {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::be::dbvalue::{DbValueApplicationPassword, DbValueSetV2};
|
|||
use crate::credential::{apppwd::ApplicationPassword, Password};
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use kanidm_proto::scim_v1::server::ScimApplicationPassword;
|
||||
|
@ -183,8 +184,8 @@ impl ValueSetT for ValueSetApplicationPassword {
|
|||
}))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.values()
|
||||
.flatten()
|
||||
|
@ -194,7 +195,7 @@ impl ValueSetT for ValueSetApplicationPassword {
|
|||
label: app_pwd.label.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use kanidm_proto::scim_v1::server::ScimAuditString;
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -109,8 +110,8 @@ impl ValueSetT for ValueSetAuditLogString {
|
|||
Box::new(self.map.iter().map(|(d, s)| format!("{d}-{s}")))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(cid, strdata)| {
|
||||
|
@ -121,7 +122,7 @@ impl ValueSetT for ValueSetAuditLogString {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::valueset::ScimResolveStatus;
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use std::collections::btree_map::Entry as BTreeEntry;
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -107,7 +108,7 @@ impl ValueSetT for ValueSetPrivateBinary {
|
|||
Box::new(self.set.iter().map(|_| "private_binary".to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -277,8 +278,8 @@ impl ValueSetT for ValueSetPublicBinary {
|
|||
Box::new(self.map.keys().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(tag, bin)| ScimBinary {
|
||||
|
@ -286,7 +287,7 @@ impl ValueSetT for ValueSetPublicBinary {
|
|||
value: bin.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetBool {
|
||||
|
@ -105,7 +105,7 @@ impl ValueSetT for ValueSetBool {
|
|||
Box::new(self.set.iter().map(|b| b.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
if self.len() == 1 {
|
||||
// Because self.len == 1 we know this has to yield a value.
|
||||
let b = self.set.iter().copied().next().unwrap_or_default();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::be::dbvalue::DbValueCertificate;
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use kanidm_proto::scim_v1::server::ScimCertificate;
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -191,7 +192,7 @@ impl ValueSetT for ValueSetCertificate {
|
|||
}))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let vals: Vec<ScimCertificate> = self
|
||||
.map
|
||||
.iter()
|
||||
|
@ -216,7 +217,7 @@ impl ValueSetT for ValueSetCertificate {
|
|||
if vals.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ScimValueKanidm::from(vals))
|
||||
Some(ScimValueKanidm::from(vals).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +301,7 @@ raBy6edj7W0EIH+yQxkDEwIhAI0nVKaI6duHLAvtKW6CfEQFG6jKg7dyk37YYiRD
|
|||
|
||||
let vs: ValueSet = ValueSetCertificate::new(Box::new(cert)).unwrap();
|
||||
|
||||
let scim_value = vs.to_scim_value().unwrap();
|
||||
let scim_value = vs.to_scim_value().unwrap().assume_resolved();
|
||||
|
||||
let cert = match scim_value {
|
||||
ScimValueKanidm::ArrayCertificate(mut set) => set.pop().unwrap(),
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::be::dbvalue::DbCidV1;
|
||||
use crate::prelude::*;
|
||||
use crate::repl::cid::Cid;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetCid {
|
||||
|
@ -115,7 +115,7 @@ impl ValueSetT for ValueSetCid {
|
|||
Box::new(self.set.iter().map(|c| c.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().map(|cid| cid.to_string());
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::valueset::ScimResolveStatus;
|
||||
use smolset::SmolSet;
|
||||
use std::collections::btree_map::Entry as BTreeEntry;
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -141,7 +142,7 @@ impl ValueSetT for ValueSetCredential {
|
|||
Box::new(self.map.keys().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
// Currently I think we don't need to yield cred info as that's part of the
|
||||
// cred update session instead.
|
||||
None
|
||||
|
@ -366,8 +367,8 @@ impl ValueSetT for ValueSetIntentToken {
|
|||
Box::new(self.map.keys().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(token_id, intent_token_state)| {
|
||||
|
@ -392,7 +393,7 @@ impl ValueSetT for ValueSetIntentToken {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -609,7 +610,7 @@ impl ValueSetT for ValueSetPasskey {
|
|||
Box::new(self.map.values().map(|(t, _)| t).cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -782,7 +783,7 @@ impl ValueSetT for ValueSetAttestedPasskey {
|
|||
Box::new(self.map.values().map(|(t, _)| t).cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -947,10 +948,10 @@ impl ValueSetT for ValueSetCredentialType {
|
|||
Box::new(self.set.iter().map(|ct| ct.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set.iter().map(|ct| ct.to_string()).collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -1089,15 +1090,15 @@ impl ValueSetT for ValueSetWebauthnAttestationCaList {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.ca_list
|
||||
.cas()
|
||||
.values()
|
||||
.flat_map(|att_ca| att_ca.aaguids().values())
|
||||
.map(|device| device.description_en().to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use smolset::SmolSet;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetDateTime {
|
||||
set: SmolSet<[OffsetDateTime; 1]>,
|
||||
|
@ -123,7 +124,7 @@ impl ValueSetT for ValueSetDateTime {
|
|||
}))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().copied();
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or(OffsetDateTime::UNIX_EPOCH);
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use crate::valueset::ScimResolveStatus;
|
||||
use std::iter::{self};
|
||||
|
||||
use super::ValueSet;
|
||||
use crate::be::dbvalue::DbValueSetV2;
|
||||
use crate::prelude::*;
|
||||
use crate::value::{PartialValue, SyntaxType, Value};
|
||||
|
||||
use openssl::ec::EcKey;
|
||||
use openssl::pkey::{Private, Public};
|
||||
|
||||
use super::ValueSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct EcKeyPrivate {
|
||||
priv_key: EcKey<Private>,
|
||||
|
@ -128,7 +129,7 @@ impl ValueSetT for ValueSetEcKeyPrivate {
|
|||
Box::new(iter::once(String::from("hidden")))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetHexString {
|
||||
set: BTreeSet<String>,
|
||||
|
@ -127,7 +128,7 @@ impl ValueSetT for ValueSetHexString {
|
|||
Box::new(self.set.iter().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().cloned();
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#![allow(dead_code)]
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use std::fmt::Display;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use image::codecs::gif::GifDecoder;
|
||||
use image::codecs::webp::WebPDecoder;
|
||||
use image::ImageDecoder;
|
||||
use kanidm_proto::internal::{ImageType, ImageValue};
|
||||
|
||||
use crate::be::dbvalue::DbValueImage;
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use hashbrown::HashSet;
|
||||
use image::codecs::gif::GifDecoder;
|
||||
use image::codecs::webp::WebPDecoder;
|
||||
use image::ImageDecoder;
|
||||
use kanidm_proto::internal::{ImageType, ImageValue};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetImage {
|
||||
|
@ -388,7 +388,7 @@ impl ValueSetT for ValueSetImage {
|
|||
Box::new(self.set.iter().map(|image| image.hash_imagevalue()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
// TODO: This should be a reference to the image URL, not the image itself!
|
||||
// Does this mean we need to pass in the domain / origin so we can render
|
||||
// these URL's correctly?
|
||||
|
@ -398,12 +398,12 @@ impl ValueSetT for ValueSetImage {
|
|||
//
|
||||
// TODO: Scim supports a "type" field here, but do we care?
|
||||
|
||||
Some(ScimValueKanidm::from(
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set
|
||||
.iter()
|
||||
.map(|image| image.hash_imagevalue())
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::utils::trigraph_iter;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetIname {
|
||||
set: BTreeSet<String>,
|
||||
|
@ -138,7 +139,7 @@ impl ValueSetT for ValueSetIname {
|
|||
Box::new(self.set.iter().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().cloned();
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetIndex {
|
||||
set: SmolSet<[IndexType; 3]>,
|
||||
|
@ -105,10 +106,10 @@ impl ValueSetT for ValueSetIndex {
|
|||
Box::new(self.set.iter().map(|b| b.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use super::iname::ValueSetIname;
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::utils::trigraph_iter;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetIutf8 {
|
||||
set: BTreeSet<String>,
|
||||
|
@ -136,7 +137,7 @@ impl ValueSetT for ValueSetIutf8 {
|
|||
Box::new(self.set.iter().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().cloned();
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetJsonFilter {
|
||||
|
@ -121,8 +122,8 @@ impl ValueSetT for ValueSetJsonFilter {
|
|||
}))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set
|
||||
.iter()
|
||||
.filter_map(|s| {
|
||||
|
@ -133,7 +134,7 @@ impl ValueSetT for ValueSetJsonFilter {
|
|||
.ok()
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer, JwsSigner};
|
||||
use hashbrown::HashSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetJwsKeyEs256 {
|
||||
set: HashSet<JwsEs256Signer>,
|
||||
|
@ -129,7 +129,7 @@ impl ValueSetT for ValueSetJwsKeyEs256 {
|
|||
Box::new(self.set.iter().map(|k| k.get_kid().to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,7 @@ impl ValueSetT for ValueSetJwsKeyRs256 {
|
|||
Box::new(self.set.iter().map(|k| k.get_kid().to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::prelude::*;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
|
||||
use crate::server::keys::KeyId;
|
||||
use crate::value::{KeyStatus, KeyUsage};
|
||||
|
@ -282,8 +283,8 @@ impl ValueSetT for ValueSetKeyInternal {
|
|||
}))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(kid, key_object)| {
|
||||
|
@ -298,7 +299,7 @@ impl ValueSetT for ValueSetKeyInternal {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -8,6 +8,8 @@ use kanidm_proto::internal::ImageValue;
|
|||
use openssl::ec::EcKey;
|
||||
use openssl::pkey::Private;
|
||||
use openssl::pkey::Public;
|
||||
use serde::Serialize;
|
||||
use serde_with::serde_as;
|
||||
use smolset::SmolSet;
|
||||
use sshkey_attest::proto::PublicKey as SshPublicKey;
|
||||
use time::OffsetDateTime;
|
||||
|
@ -15,8 +17,6 @@ use webauthn_rs::prelude::AttestationCaList;
|
|||
use webauthn_rs::prelude::AttestedPasskey as AttestedPasskeyV4;
|
||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||
|
||||
use kanidm_proto::internal::{Filter as ProtoFilter, UiHint};
|
||||
|
||||
use crate::be::dbvalue::DbValueSetV2;
|
||||
use crate::credential::{apppwd::ApplicationPassword, totp::Totp, Credential};
|
||||
use crate::prelude::*;
|
||||
|
@ -24,6 +24,7 @@ use crate::repl::cid::Cid;
|
|||
use crate::schema::SchemaAttribute;
|
||||
use crate::server::keys::KeyId;
|
||||
use crate::value::{Address, ApiToken, CredentialType, IntentTokenState, Oauth2Session, Session};
|
||||
use kanidm_proto::internal::{Filter as ProtoFilter, UiHint};
|
||||
|
||||
pub use self::address::{ValueSetAddress, ValueSetEmailAddress};
|
||||
use self::apppwd::ValueSetApplicationPassword;
|
||||
|
@ -144,7 +145,7 @@ pub trait ValueSetT: std::fmt::Debug + DynClone {
|
|||
|
||||
fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_>;
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm>;
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus>;
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2;
|
||||
|
||||
|
@ -666,6 +667,46 @@ impl PartialEq for ValueSet {
|
|||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ScimValueIntermediate {
|
||||
Refer(Uuid),
|
||||
ReferMany(Vec<Uuid>),
|
||||
}
|
||||
|
||||
pub enum ScimResolveStatus {
|
||||
Resolved(ScimValueKanidm),
|
||||
NeedsResolution(ScimValueIntermediate),
|
||||
}
|
||||
|
||||
impl<T> From<T> for ScimResolveStatus
|
||||
where
|
||||
T: Into<ScimValueKanidm>,
|
||||
{
|
||||
fn from(v: T) -> Self {
|
||||
Self::Resolved(v.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl ScimResolveStatus {
|
||||
pub fn assume_resolved(self) -> ScimValueKanidm {
|
||||
match self {
|
||||
ScimResolveStatus::Resolved(v) => v,
|
||||
ScimResolveStatus::NeedsResolution(_) => {
|
||||
panic!("assume_resolved called on NeedsResolution")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assume_unresolved(self) -> ScimValueIntermediate {
|
||||
match self {
|
||||
ScimResolveStatus::Resolved(_) => panic!("assume_unresolved called on Resolved"),
|
||||
ScimResolveStatus::NeedsResolution(svi) => svi,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uuid_to_proto_string(u: Uuid) -> String {
|
||||
u.as_hyphenated().to_string()
|
||||
}
|
||||
|
@ -877,7 +918,21 @@ pub fn from_db_valueset_v2(dbvs: DbValueSetV2) -> Result<ValueSet, OperationErro
|
|||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn scim_json_reflexive(vs: ValueSet, data: &str) {
|
||||
let scim_value = vs.to_scim_value().unwrap();
|
||||
let scim_value = vs.to_scim_value().unwrap().assume_resolved();
|
||||
|
||||
let strout = serde_json::to_string_pretty(&scim_value).unwrap();
|
||||
eprintln!("{}", strout);
|
||||
|
||||
let json_value: serde_json::Value = serde_json::to_value(&scim_value).unwrap();
|
||||
|
||||
let expect: serde_json::Value = serde_json::from_str(data).unwrap();
|
||||
|
||||
assert_eq!(json_value, expect);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn scim_json_reflexive_unresolved(vs: ValueSet, data: &str) {
|
||||
let scim_value = vs.to_scim_value().unwrap().assume_unresolved();
|
||||
|
||||
let strout = serde_json::to_string_pretty(&scim_value).unwrap();
|
||||
eprintln!("{}", strout);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::value::NSUNIQUEID_RE;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetNsUniqueId {
|
||||
set: SmolSet<[String; 1]>,
|
||||
|
@ -106,7 +107,7 @@ impl ValueSetT for ValueSetNsUniqueId {
|
|||
Box::new(self.set.iter().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().cloned();
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::valueset::ScimResolveStatus;
|
||||
use std::collections::btree_map::Entry as BTreeEntry;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
|
@ -112,8 +113,8 @@ impl ValueSetT for ValueSetOauthScope {
|
|||
Box::new(self.set.iter().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(str_join(&self.set).into())
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(str_join(&self.set).into()))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -289,8 +290,8 @@ impl ValueSetT for ValueSetOauthScopeMap {
|
|||
)
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(uuid, scopes)| {
|
||||
|
@ -301,7 +302,7 @@ impl ValueSetT for ValueSetOauthScopeMap {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -620,8 +621,8 @@ impl ValueSetT for ValueSetOauthClaimMap {
|
|||
}))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.flat_map(|(claim_name, mappings)| {
|
||||
|
@ -636,7 +637,7 @@ impl ValueSetT for ValueSetOauthClaimMap {
|
|||
})
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::utils::trigraph_iter;
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetRestricted {
|
||||
set: BTreeSet<String>,
|
||||
|
@ -138,7 +139,7 @@ impl ValueSetT for ValueSetRestricted {
|
|||
Box::new(self.set.iter().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().cloned();
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetSecret {
|
||||
|
@ -96,7 +96,7 @@ impl ValueSetT for ValueSetSecret {
|
|||
Box::new(self.set.iter().map(|_| "hidden".to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,7 @@ impl ValueSetT for ValueSetSecret {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ValueSetSecret;
|
||||
use crate::prelude::ValueSet;
|
||||
use crate::valueset::{ValueSet, ValueSetSecret};
|
||||
|
||||
#[test]
|
||||
fn test_scim_secret() {
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::schema::SchemaAttribute;
|
|||
use crate::value::{
|
||||
ApiToken, ApiTokenScope, AuthType, Oauth2Session, Session, SessionScope, SessionState,
|
||||
};
|
||||
use crate::valueset::{uuid_to_proto_string, DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{uuid_to_proto_string, DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use kanidm_proto::scim_v1::server::ScimApiToken;
|
||||
use kanidm_proto::scim_v1::server::ScimAuthSession;
|
||||
|
@ -354,8 +354,8 @@ impl ValueSetT for ValueSetSession {
|
|||
)
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(session_id, session)| {
|
||||
|
@ -381,7 +381,7 @@ impl ValueSetT for ValueSetSession {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -855,8 +855,8 @@ impl ValueSetT for ValueSetOauth2Session {
|
|||
)
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(session_id, session)| {
|
||||
|
@ -879,7 +879,7 @@ impl ValueSetT for ValueSetOauth2Session {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -1196,8 +1196,8 @@ impl ValueSetT for ValueSetApiToken {
|
|||
)
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(token_id, token)| ScimApiToken {
|
||||
|
@ -1209,7 +1209,7 @@ impl ValueSetT for ValueSetApiToken {
|
|||
scope: token.scope.to_string(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetSpn {
|
||||
|
@ -110,7 +110,7 @@ impl ValueSetT for ValueSetSpn {
|
|||
Box::new(self.set.iter().map(|(n, d)| format!("{n}@{d}")))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().map(|(n, d)| format!("{n}@{d}"));
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::be::dbvalue::DbValueTaggedStringV1;
|
|||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::utils::trigraph_iter;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use sshkey_attest::proto::PublicKey as SshPublicKey;
|
||||
|
||||
|
@ -137,8 +137,8 @@ impl ValueSetT for ValueSetSshKey {
|
|||
Box::new(self.map.iter().map(|(tag, pk)| format!("{}: {}", tag, pk)))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.map
|
||||
.iter()
|
||||
.map(|(label, value)| ScimSshPublicKey {
|
||||
|
@ -146,7 +146,7 @@ impl ValueSetT for ValueSetSshKey {
|
|||
value: value.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetSyntax {
|
||||
|
@ -105,10 +105,10 @@ impl ValueSetT for ValueSetSyntax {
|
|||
Box::new(self.set.iter().map(|b| b.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use std::collections::btree_map::Entry as BTreeEntry;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::credential::totp::Totp;
|
||||
use crate::prelude::*;
|
||||
|
||||
use std::collections::btree_map::Entry as BTreeEntry;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::be::dbvalue::DbTotpV1;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetTotpSecret {
|
||||
|
@ -117,7 +117,7 @@ impl ValueSetT for ValueSetTotpSecret {
|
|||
Box::new(self.map.keys().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeSet;
|
|||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use kanidm_proto::internal::UiHint;
|
||||
|
||||
|
@ -94,10 +94,10 @@ impl ValueSetT for ValueSetUiHint {
|
|||
Box::new(self.set.iter().map(|u| u.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(ScimValueKanidm::from(
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetUint32 {
|
||||
|
@ -108,7 +108,7 @@ impl ValueSetT for ValueSetUint32 {
|
|||
Box::new(self.set.iter().map(|b| b.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
if self.len() == 1 {
|
||||
// Because self.len == 1 we know this has to yield a value.
|
||||
let b = self.set.iter().copied().next().unwrap_or_default();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetUrl {
|
||||
|
@ -102,7 +102,7 @@ impl ValueSetT for ValueSetUrl {
|
|||
Box::new(self.set.iter().map(|i| i.to_string()))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().map(|url| url.to_string());
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::utils::trigraph_iter;
|
||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetUtf8 {
|
||||
|
@ -140,7 +140,7 @@ impl ValueSetT for ValueSetUtf8 {
|
|||
Box::new(self.set.iter().cloned())
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let mut iter = self.set.iter().cloned();
|
||||
if self.len() == 1 {
|
||||
let v = iter.next().unwrap_or_default();
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use smolset::SmolSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaAttribute;
|
||||
use crate::valueset::{uuid_to_proto_string, DbValueSetV2, ValueSet};
|
||||
use crate::valueset::{
|
||||
uuid_to_proto_string, DbValueSetV2, ScimResolveStatus, ScimValueIntermediate, ValueSet,
|
||||
};
|
||||
use smolset::SmolSet;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetUuid {
|
||||
|
@ -113,8 +114,12 @@ impl ValueSetT for ValueSetUuid {
|
|||
Box::new(self.set.iter().copied().map(uuid_to_proto_string))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
self.set.iter().next().copied().map(ScimValueKanidm::Uuid)
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
self.set
|
||||
.iter()
|
||||
.next()
|
||||
.copied()
|
||||
.map(|uuid| ScimResolveStatus::NeedsResolution(ScimValueIntermediate::Refer(uuid)))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -282,8 +287,11 @@ impl ValueSetT for ValueSetRefer {
|
|||
Box::new(self.set.iter().copied().map(uuid_to_proto_string))
|
||||
}
|
||||
|
||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
||||
Some(self.set.iter().copied().collect::<Vec<_>>().into())
|
||||
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||
let uuids = self.set.iter().copied().collect::<Vec<_>>();
|
||||
Some(ScimResolveStatus::NeedsResolution(
|
||||
ScimValueIntermediate::ReferMany(uuids),
|
||||
))
|
||||
}
|
||||
|
||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||
|
@ -346,17 +354,17 @@ mod tests {
|
|||
fn test_scim_uuid() {
|
||||
let vs: ValueSet = ValueSetUuid::new(uuid::uuid!("4d21d04a-dc0e-42eb-b850-34dd180b107f"));
|
||||
|
||||
let data = r#""4d21d04a-dc0e-42eb-b850-34dd180b107f""#;
|
||||
let data = r#"{"Refer": "4d21d04a-dc0e-42eb-b850-34dd180b107f"}"#;
|
||||
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive_unresolved(vs, data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scim_refer() {
|
||||
let vs: ValueSet = ValueSetRefer::new(uuid::uuid!("4d21d04a-dc0e-42eb-b850-34dd180b107f"));
|
||||
|
||||
let data = r#"["4d21d04a-dc0e-42eb-b850-34dd180b107f"]"#;
|
||||
let data = r#"{"ReferMany": ["4d21d04a-dc0e-42eb-b850-34dd180b107f"]}"#;
|
||||
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive_unresolved(vs, data);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue