mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +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>,
|
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
|
/// 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
|
/// since on a deserialisation path we can not know the intent of the sender
|
||||||
/// to how we deserialise strings. Additionally during deserialisation we need
|
/// to how we deserialise strings. Additionally during deserialisation we need
|
||||||
|
@ -196,6 +204,9 @@ pub enum ScimValueKanidm {
|
||||||
DateTime(#[serde_as(as = "Rfc3339")] OffsetDateTime),
|
DateTime(#[serde_as(as = "Rfc3339")] OffsetDateTime),
|
||||||
Reference(Url),
|
Reference(Url),
|
||||||
Uuid(Uuid),
|
Uuid(Uuid),
|
||||||
|
EntryReference(ScimReference),
|
||||||
|
EntryReferences(Vec<ScimReference>),
|
||||||
|
|
||||||
// Other strong outbound types.
|
// Other strong outbound types.
|
||||||
ArrayString(Vec<String>),
|
ArrayString(Vec<String>),
|
||||||
ArrayDateTime(#[serde_as(as = "Vec<Rfc3339>")] Vec<OffsetDateTime>),
|
ArrayDateTime(#[serde_as(as = "Vec<Rfc3339>")] Vec<OffsetDateTime>),
|
||||||
|
|
|
@ -227,6 +227,6 @@ impl QueryServerReadV1 {
|
||||||
idms_prox_read
|
idms_prox_read
|
||||||
.qs_read
|
.qs_read
|
||||||
.impersonate_search_ext_uuid(target_uuid, &ident)
|
.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::collections::{BTreeMap as Map, BTreeMap, BTreeSet};
|
||||||
use std::sync::Arc;
|
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::dbentry::{DbEntry, DbEntryVers};
|
||||||
use crate::be::dbvalue::DbValueSetV2;
|
use crate::be::dbvalue::DbValueSetV2;
|
||||||
use crate::be::{IdxKey, IdxSlope};
|
use crate::be::{IdxKey, IdxSlope};
|
||||||
|
@ -58,13 +41,30 @@ use crate::prelude::*;
|
||||||
use crate::repl::cid::Cid;
|
use crate::repl::cid::Cid;
|
||||||
use crate::repl::entry::EntryChangeState;
|
use crate::repl::entry::EntryChangeState;
|
||||||
use crate::repl::proto::{ReplEntryV1, ReplIncrementalEntryV1};
|
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::schema::{SchemaAttribute, SchemaClass, SchemaTransaction};
|
||||||
use crate::value::{
|
use crate::value::{
|
||||||
ApiToken, CredentialType, IndexType, IntentTokenState, Oauth2Session, PartialValue, Session,
|
ApiToken, CredentialType, IndexType, IntentTokenState, Oauth2Session, PartialValue, Session,
|
||||||
SyntaxType, Value,
|
SyntaxType, Value,
|
||||||
};
|
};
|
||||||
use crate::valueset::{self, ValueSet};
|
use crate::valueset::{self, ScimResolveStatus, ScimValueIntermediate, ValueSet};
|
||||||
|
|
||||||
pub type EntryInitNew = Entry<EntryInit, EntryNew>;
|
pub type EntryInitNew = Entry<EntryInit, EntryNew>;
|
||||||
pub type EntryInvalidNew = Entry<EntryInvalid, EntryNew>;
|
pub type EntryInvalidNew = Entry<EntryInvalid, EntryNew>;
|
||||||
|
@ -2230,15 +2230,32 @@ impl Entry<EntryReduced, EntryCommitted> {
|
||||||
Ok(ProtoEntry { attrs: attrs? })
|
Ok(ProtoEntry { attrs: attrs? })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_scim_kanidm(&self) -> Result<ScimEntryKanidm, OperationError> {
|
pub fn to_scim_kanidm(
|
||||||
let attrs = self
|
&self,
|
||||||
|
mut read_txn: QueryServerReadTransaction,
|
||||||
|
) -> Result<ScimEntryKanidm, OperationError> {
|
||||||
|
let result: Result<BTreeMap<Attribute, ScimValueKanidm>, OperationError> = self
|
||||||
.attrs
|
.attrs
|
||||||
.iter()
|
.iter()
|
||||||
// We want to skip some attributes as they are already in the header.
|
// We want to skip some attributes as they are already in the header.
|
||||||
.filter(|(k, _vs)| **k != Attribute::Uuid)
|
.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();
|
.collect();
|
||||||
|
|
||||||
|
let attrs = result?;
|
||||||
|
|
||||||
let id = self.get_uuid();
|
let id = self.get_uuid();
|
||||||
|
|
||||||
// Not sure how I want to handle this yet, I think we need some schema changes
|
// 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<STATE> Entry<EntryValid, STATE> {
|
||||||
impl<VALID, STATE> Entry<VALID, 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.
|
/// 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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use kanidm_proto::scim_v1::server::ScimReference;
|
||||||
|
|
||||||
#[qs_test]
|
#[qs_test]
|
||||||
async fn test_name_to_uuid(server: &QueryServer) {
|
async fn test_name_to_uuid(server: &QueryServer) {
|
||||||
|
@ -2613,4 +2614,66 @@ mod tests {
|
||||||
server_txn.commit().expect("should not fail");
|
server_txn.commit().expect("should not fail");
|
||||||
// Commit.
|
// 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::schema::SchemaAttribute;
|
||||||
use crate::utils::trigraph_iter;
|
use crate::utils::trigraph_iter;
|
||||||
use crate::value::{Address, VALIDATE_EMAIL_RE};
|
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};
|
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()))
|
Box::new(self.set.iter().map(|a| a.formatted.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set
|
self.set
|
||||||
.iter()
|
.iter()
|
||||||
.map(|a| ScimAddress {
|
.map(|a| ScimAddress {
|
||||||
|
@ -150,7 +150,7 @@ impl ValueSetT for ValueSetAddress {
|
||||||
country: a.country.clone(),
|
country: a.country.clone(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -427,8 +427,8 @@ impl ValueSetT for ValueSetEmailAddress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set
|
self.set
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mail| {
|
.map(|mail| {
|
||||||
|
@ -439,7 +439,7 @@ impl ValueSetT for ValueSetEmailAddress {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
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::credential::{apppwd::ApplicationPassword, Password};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use kanidm_proto::scim_v1::server::ScimApplicationPassword;
|
use kanidm_proto::scim_v1::server::ScimApplicationPassword;
|
||||||
|
@ -183,8 +184,8 @@ impl ValueSetT for ValueSetApplicationPassword {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.values()
|
.values()
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -194,7 +195,7 @@ impl ValueSetT for ValueSetApplicationPassword {
|
||||||
label: app_pwd.label.clone(),
|
label: app_pwd.label.clone(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::repl::cid::Cid;
|
use crate::repl::cid::Cid;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
use kanidm_proto::scim_v1::server::ScimAuditString;
|
use kanidm_proto::scim_v1::server::ScimAuditString;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -109,8 +110,8 @@ impl ValueSetT for ValueSetAuditLogString {
|
||||||
Box::new(self.map.iter().map(|(d, s)| format!("{d}-{s}")))
|
Box::new(self.map.iter().map(|(d, s)| format!("{d}-{s}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(cid, strdata)| {
|
.map(|(cid, strdata)| {
|
||||||
|
@ -121,7 +122,7 @@ impl ValueSetT for ValueSetAuditLogString {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use base64urlsafedata::Base64UrlSafeData;
|
use base64urlsafedata::Base64UrlSafeData;
|
||||||
use std::collections::btree_map::Entry as BTreeEntry;
|
use std::collections::btree_map::Entry as BTreeEntry;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -107,7 +108,7 @@ impl ValueSetT for ValueSetPrivateBinary {
|
||||||
Box::new(self.set.iter().map(|_| "private_binary".to_string()))
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,8 +278,8 @@ impl ValueSetT for ValueSetPublicBinary {
|
||||||
Box::new(self.map.keys().cloned())
|
Box::new(self.map.keys().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(tag, bin)| ScimBinary {
|
.map(|(tag, bin)| ScimBinary {
|
||||||
|
@ -286,7 +287,7 @@ impl ValueSetT for ValueSetPublicBinary {
|
||||||
value: bin.clone(),
|
value: bin.clone(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetBool {
|
pub struct ValueSetBool {
|
||||||
|
@ -105,7 +105,7 @@ impl ValueSetT for ValueSetBool {
|
||||||
Box::new(self.set.iter().map(|b| b.to_string()))
|
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 {
|
if self.len() == 1 {
|
||||||
// Because self.len == 1 we know this has to yield a value.
|
// Because self.len == 1 we know this has to yield a value.
|
||||||
let b = self.set.iter().copied().next().unwrap_or_default();
|
let b = self.set.iter().copied().next().unwrap_or_default();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::be::dbvalue::DbValueCertificate;
|
use crate::be::dbvalue::DbValueCertificate;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
use kanidm_proto::scim_v1::server::ScimCertificate;
|
use kanidm_proto::scim_v1::server::ScimCertificate;
|
||||||
use std::collections::BTreeMap;
|
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
|
let vals: Vec<ScimCertificate> = self
|
||||||
.map
|
.map
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -216,7 +217,7 @@ impl ValueSetT for ValueSetCertificate {
|
||||||
if vals.is_empty() {
|
if vals.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} 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 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 {
|
let cert = match scim_value {
|
||||||
ScimValueKanidm::ArrayCertificate(mut set) => set.pop().unwrap(),
|
ScimValueKanidm::ArrayCertificate(mut set) => set.pop().unwrap(),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::be::dbvalue::DbCidV1;
|
use crate::be::dbvalue::DbCidV1;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::repl::cid::Cid;
|
use crate::repl::cid::Cid;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetCid {
|
pub struct ValueSetCid {
|
||||||
|
@ -115,7 +115,7 @@ impl ValueSetT for ValueSetCid {
|
||||||
Box::new(self.set.iter().map(|c| c.to_string()))
|
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());
|
let mut iter = self.set.iter().map(|cid| cid.to_string());
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
let v = iter.next().unwrap_or_default();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use smolset::SmolSet;
|
use smolset::SmolSet;
|
||||||
use std::collections::btree_map::Entry as BTreeEntry;
|
use std::collections::btree_map::Entry as BTreeEntry;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -141,7 +142,7 @@ impl ValueSetT for ValueSetCredential {
|
||||||
Box::new(self.map.keys().cloned())
|
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
|
// Currently I think we don't need to yield cred info as that's part of the
|
||||||
// cred update session instead.
|
// cred update session instead.
|
||||||
None
|
None
|
||||||
|
@ -366,8 +367,8 @@ impl ValueSetT for ValueSetIntentToken {
|
||||||
Box::new(self.map.keys().cloned())
|
Box::new(self.map.keys().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(token_id, intent_token_state)| {
|
.map(|(token_id, intent_token_state)| {
|
||||||
|
@ -392,7 +393,7 @@ impl ValueSetT for ValueSetIntentToken {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -609,7 +610,7 @@ impl ValueSetT for ValueSetPasskey {
|
||||||
Box::new(self.map.values().map(|(t, _)| t).cloned())
|
Box::new(self.map.values().map(|(t, _)| t).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +783,7 @@ impl ValueSetT for ValueSetAttestedPasskey {
|
||||||
Box::new(self.map.values().map(|(t, _)| t).cloned())
|
Box::new(self.map.values().map(|(t, _)| t).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,10 +948,10 @@ impl ValueSetT for ValueSetCredentialType {
|
||||||
Box::new(self.set.iter().map(|ct| ct.to_string()))
|
Box::new(self.set.iter().map(|ct| ct.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set.iter().map(|ct| ct.to_string()).collect::<Vec<_>>(),
|
self.set.iter().map(|ct| ct.to_string()).collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -1089,15 +1090,15 @@ impl ValueSetT for ValueSetWebauthnAttestationCaList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.ca_list
|
self.ca_list
|
||||||
.cas()
|
.cas()
|
||||||
.values()
|
.values()
|
||||||
.flat_map(|att_ca| att_ca.aaguids().values())
|
.flat_map(|att_ca| att_ca.aaguids().values())
|
||||||
.map(|device| device.description_en().to_string())
|
.map(|device| device.description_en().to_string())
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = PartialValue> + '_> {
|
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::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetDateTime {
|
pub struct ValueSetDateTime {
|
||||||
set: SmolSet<[OffsetDateTime; 1]>,
|
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();
|
let mut iter = self.set.iter().copied();
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or(OffsetDateTime::UNIX_EPOCH);
|
let v = iter.next().unwrap_or(OffsetDateTime::UNIX_EPOCH);
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use std::iter::{self};
|
use std::iter::{self};
|
||||||
|
|
||||||
|
use super::ValueSet;
|
||||||
use crate::be::dbvalue::DbValueSetV2;
|
use crate::be::dbvalue::DbValueSetV2;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::value::{PartialValue, SyntaxType, Value};
|
use crate::value::{PartialValue, SyntaxType, Value};
|
||||||
|
|
||||||
use openssl::ec::EcKey;
|
use openssl::ec::EcKey;
|
||||||
use openssl::pkey::{Private, Public};
|
use openssl::pkey::{Private, Public};
|
||||||
|
|
||||||
use super::ValueSet;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct EcKeyPrivate {
|
struct EcKeyPrivate {
|
||||||
priv_key: EcKey<Private>,
|
priv_key: EcKey<Private>,
|
||||||
|
@ -128,7 +129,7 @@ impl ValueSetT for ValueSetEcKeyPrivate {
|
||||||
Box::new(iter::once(String::from("hidden")))
|
Box::new(iter::once(String::from("hidden")))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetHexString {
|
pub struct ValueSetHexString {
|
||||||
set: BTreeSet<String>,
|
set: BTreeSet<String>,
|
||||||
|
@ -127,7 +128,7 @@ impl ValueSetT for ValueSetHexString {
|
||||||
Box::new(self.set.iter().cloned())
|
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();
|
let mut iter = self.set.iter().cloned();
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
let v = iter.next().unwrap_or_default();
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use std::fmt::Display;
|
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::be::dbvalue::DbValueImage;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetImage {
|
pub struct ValueSetImage {
|
||||||
|
@ -388,7 +388,7 @@ impl ValueSetT for ValueSetImage {
|
||||||
Box::new(self.set.iter().map(|image| image.hash_imagevalue()))
|
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!
|
// 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
|
// Does this mean we need to pass in the domain / origin so we can render
|
||||||
// these URL's correctly?
|
// these URL's correctly?
|
||||||
|
@ -398,12 +398,12 @@ impl ValueSetT for ValueSetImage {
|
||||||
//
|
//
|
||||||
// TODO: Scim supports a "type" field here, but do we care?
|
// TODO: Scim supports a "type" field here, but do we care?
|
||||||
|
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set
|
self.set
|
||||||
.iter()
|
.iter()
|
||||||
.map(|image| image.hash_imagevalue())
|
.map(|image| image.hash_imagevalue())
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::utils::trigraph_iter;
|
use crate::utils::trigraph_iter;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetIname {
|
pub struct ValueSetIname {
|
||||||
set: BTreeSet<String>,
|
set: BTreeSet<String>,
|
||||||
|
@ -138,7 +139,7 @@ impl ValueSetT for ValueSetIname {
|
||||||
Box::new(self.set.iter().cloned())
|
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();
|
let mut iter = self.set.iter().cloned();
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
let v = iter.next().unwrap_or_default();
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetIndex {
|
pub struct ValueSetIndex {
|
||||||
set: SmolSet<[IndexType; 3]>,
|
set: SmolSet<[IndexType; 3]>,
|
||||||
|
@ -105,10 +106,10 @@ impl ValueSetT for ValueSetIndex {
|
||||||
Box::new(self.set.iter().map(|b| b.to_string()))
|
Box::new(self.set.iter().map(|b| b.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use super::iname::ValueSetIname;
|
use super::iname::ValueSetIname;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::utils::trigraph_iter;
|
use crate::utils::trigraph_iter;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetIutf8 {
|
pub struct ValueSetIutf8 {
|
||||||
set: BTreeSet<String>,
|
set: BTreeSet<String>,
|
||||||
|
@ -136,7 +137,7 @@ impl ValueSetT for ValueSetIutf8 {
|
||||||
Box::new(self.set.iter().cloned())
|
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();
|
let mut iter = self.set.iter().cloned();
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
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::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
use kanidm_proto::internal::Filter as ProtoFilter;
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetJsonFilter {
|
pub struct ValueSetJsonFilter {
|
||||||
|
@ -121,8 +122,8 @@ impl ValueSetT for ValueSetJsonFilter {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set
|
self.set
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|s| {
|
.filter_map(|s| {
|
||||||
|
@ -133,7 +134,7 @@ impl ValueSetT for ValueSetJsonFilter {
|
||||||
.ok()
|
.ok()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
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 base64urlsafedata::Base64UrlSafeData;
|
||||||
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer, JwsSigner};
|
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer, JwsSigner};
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::schema::SchemaAttribute;
|
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetJwsKeyEs256 {
|
pub struct ValueSetJwsKeyEs256 {
|
||||||
set: HashSet<JwsEs256Signer>,
|
set: HashSet<JwsEs256Signer>,
|
||||||
|
@ -129,7 +129,7 @@ impl ValueSetT for ValueSetJwsKeyEs256 {
|
||||||
Box::new(self.set.iter().map(|k| k.get_kid().to_string()))
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ impl ValueSetT for ValueSetJwsKeyRs256 {
|
||||||
Box::new(self.set.iter().map(|k| k.get_kid().to_string()))
|
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
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
|
|
||||||
use crate::server::keys::KeyId;
|
use crate::server::keys::KeyId;
|
||||||
use crate::value::{KeyStatus, KeyUsage};
|
use crate::value::{KeyStatus, KeyUsage};
|
||||||
|
@ -282,8 +283,8 @@ impl ValueSetT for ValueSetKeyInternal {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(kid, key_object)| {
|
.map(|(kid, key_object)| {
|
||||||
|
@ -298,7 +299,7 @@ impl ValueSetT for ValueSetKeyInternal {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -8,6 +8,8 @@ use kanidm_proto::internal::ImageValue;
|
||||||
use openssl::ec::EcKey;
|
use openssl::ec::EcKey;
|
||||||
use openssl::pkey::Private;
|
use openssl::pkey::Private;
|
||||||
use openssl::pkey::Public;
|
use openssl::pkey::Public;
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde_with::serde_as;
|
||||||
use smolset::SmolSet;
|
use smolset::SmolSet;
|
||||||
use sshkey_attest::proto::PublicKey as SshPublicKey;
|
use sshkey_attest::proto::PublicKey as SshPublicKey;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
@ -15,8 +17,6 @@ use webauthn_rs::prelude::AttestationCaList;
|
||||||
use webauthn_rs::prelude::AttestedPasskey as AttestedPasskeyV4;
|
use webauthn_rs::prelude::AttestedPasskey as AttestedPasskeyV4;
|
||||||
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
use webauthn_rs::prelude::Passkey as PasskeyV4;
|
||||||
|
|
||||||
use kanidm_proto::internal::{Filter as ProtoFilter, UiHint};
|
|
||||||
|
|
||||||
use crate::be::dbvalue::DbValueSetV2;
|
use crate::be::dbvalue::DbValueSetV2;
|
||||||
use crate::credential::{apppwd::ApplicationPassword, totp::Totp, Credential};
|
use crate::credential::{apppwd::ApplicationPassword, totp::Totp, Credential};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
@ -24,6 +24,7 @@ use crate::repl::cid::Cid;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::server::keys::KeyId;
|
use crate::server::keys::KeyId;
|
||||||
use crate::value::{Address, ApiToken, CredentialType, IntentTokenState, Oauth2Session, Session};
|
use crate::value::{Address, ApiToken, CredentialType, IntentTokenState, Oauth2Session, Session};
|
||||||
|
use kanidm_proto::internal::{Filter as ProtoFilter, UiHint};
|
||||||
|
|
||||||
pub use self::address::{ValueSetAddress, ValueSetEmailAddress};
|
pub use self::address::{ValueSetAddress, ValueSetEmailAddress};
|
||||||
use self::apppwd::ValueSetApplicationPassword;
|
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_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;
|
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 {
|
pub fn uuid_to_proto_string(u: Uuid) -> String {
|
||||||
u.as_hyphenated().to_string()
|
u.as_hyphenated().to_string()
|
||||||
}
|
}
|
||||||
|
@ -877,7 +918,21 @@ pub fn from_db_valueset_v2(dbvs: DbValueSetV2) -> Result<ValueSet, OperationErro
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn scim_json_reflexive(vs: ValueSet, data: &str) {
|
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();
|
let strout = serde_json::to_string_pretty(&scim_value).unwrap();
|
||||||
eprintln!("{}", strout);
|
eprintln!("{}", strout);
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::value::NSUNIQUEID_RE;
|
use crate::value::NSUNIQUEID_RE;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetNsUniqueId {
|
pub struct ValueSetNsUniqueId {
|
||||||
set: SmolSet<[String; 1]>,
|
set: SmolSet<[String; 1]>,
|
||||||
|
@ -106,7 +107,7 @@ impl ValueSetT for ValueSetNsUniqueId {
|
||||||
Box::new(self.set.iter().cloned())
|
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();
|
let mut iter = self.set.iter().cloned();
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
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::btree_map::Entry as BTreeEntry;
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
|
@ -112,8 +113,8 @@ impl ValueSetT for ValueSetOauthScope {
|
||||||
Box::new(self.set.iter().cloned())
|
Box::new(self.set.iter().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(str_join(&self.set).into())
|
Some(ScimResolveStatus::Resolved(str_join(&self.set).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -289,8 +290,8 @@ impl ValueSetT for ValueSetOauthScopeMap {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(uuid, scopes)| {
|
.map(|(uuid, scopes)| {
|
||||||
|
@ -301,7 +302,7 @@ impl ValueSetT for ValueSetOauthScopeMap {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -620,8 +621,8 @@ impl ValueSetT for ValueSetOauthClaimMap {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(claim_name, mappings)| {
|
.flat_map(|(claim_name, mappings)| {
|
||||||
|
@ -636,7 +637,7 @@ impl ValueSetT for ValueSetOauthClaimMap {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::utils::trigraph_iter;
|
use crate::utils::trigraph_iter;
|
||||||
|
use crate::valueset::ScimResolveStatus;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ValueSet};
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetRestricted {
|
pub struct ValueSetRestricted {
|
||||||
set: BTreeSet<String>,
|
set: BTreeSet<String>,
|
||||||
|
@ -138,7 +139,7 @@ impl ValueSetT for ValueSetRestricted {
|
||||||
Box::new(self.set.iter().cloned())
|
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();
|
let mut iter = self.set.iter().cloned();
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
let v = iter.next().unwrap_or_default();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetSecret {
|
pub struct ValueSetSecret {
|
||||||
|
@ -96,7 +96,7 @@ impl ValueSetT for ValueSetSecret {
|
||||||
Box::new(self.set.iter().map(|_| "hidden".to_string()))
|
Box::new(self.set.iter().map(|_| "hidden".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,8 +145,7 @@ impl ValueSetT for ValueSetSecret {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::ValueSetSecret;
|
use crate::valueset::{ValueSet, ValueSetSecret};
|
||||||
use crate::prelude::ValueSet;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_scim_secret() {
|
fn test_scim_secret() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::schema::SchemaAttribute;
|
||||||
use crate::value::{
|
use crate::value::{
|
||||||
ApiToken, ApiTokenScope, AuthType, Oauth2Session, Session, SessionScope, SessionState,
|
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::ScimApiToken;
|
||||||
use kanidm_proto::scim_v1::server::ScimAuthSession;
|
use kanidm_proto::scim_v1::server::ScimAuthSession;
|
||||||
|
@ -354,8 +354,8 @@ impl ValueSetT for ValueSetSession {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(session_id, session)| {
|
.map(|(session_id, session)| {
|
||||||
|
@ -381,7 +381,7 @@ impl ValueSetT for ValueSetSession {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -855,8 +855,8 @@ impl ValueSetT for ValueSetOauth2Session {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(session_id, session)| {
|
.map(|(session_id, session)| {
|
||||||
|
@ -879,7 +879,7 @@ impl ValueSetT for ValueSetOauth2Session {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -1196,8 +1196,8 @@ impl ValueSetT for ValueSetApiToken {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(token_id, token)| ScimApiToken {
|
.map(|(token_id, token)| ScimApiToken {
|
||||||
|
@ -1209,7 +1209,7 @@ impl ValueSetT for ValueSetApiToken {
|
||||||
scope: token.scope.to_string(),
|
scope: token.scope.to_string(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetSpn {
|
pub struct ValueSetSpn {
|
||||||
|
@ -110,7 +110,7 @@ impl ValueSetT for ValueSetSpn {
|
||||||
Box::new(self.set.iter().map(|(n, d)| format!("{n}@{d}")))
|
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}"));
|
let mut iter = self.set.iter().map(|(n, d)| format!("{n}@{d}"));
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
let v = iter.next().unwrap_or_default();
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::be::dbvalue::DbValueTaggedStringV1;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::utils::trigraph_iter;
|
use crate::utils::trigraph_iter;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
use sshkey_attest::proto::PublicKey as SshPublicKey;
|
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)))
|
Box::new(self.map.iter().map(|(tag, pk)| format!("{}: {}", tag, pk)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(label, value)| ScimSshPublicKey {
|
.map(|(label, value)| ScimSshPublicKey {
|
||||||
|
@ -146,7 +146,7 @@ impl ValueSetT for ValueSetSshKey {
|
||||||
value: value.clone(),
|
value: value.clone(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetSyntax {
|
pub struct ValueSetSyntax {
|
||||||
|
@ -105,10 +105,10 @@ impl ValueSetT for ValueSetSyntax {
|
||||||
Box::new(self.set.iter().map(|b| b.to_string()))
|
Box::new(self.set.iter().map(|b| b.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
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::credential::totp::Totp;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use std::collections::btree_map::Entry as BTreeEntry;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::be::dbvalue::DbTotpV1;
|
use crate::be::dbvalue::DbTotpV1;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetTotpSecret {
|
pub struct ValueSetTotpSecret {
|
||||||
|
@ -117,7 +117,7 @@ impl ValueSetT for ValueSetTotpSecret {
|
||||||
Box::new(self.map.keys().cloned())
|
Box::new(self.map.keys().cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeSet;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
use kanidm_proto::internal::UiHint;
|
use kanidm_proto::internal::UiHint;
|
||||||
|
|
||||||
|
@ -94,10 +94,10 @@ impl ValueSetT for ValueSetUiHint {
|
||||||
Box::new(self.set.iter().map(|u| u.to_string()))
|
Box::new(self.set.iter().map(|u| u.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(ScimValueKanidm::from(
|
Some(ScimResolveStatus::Resolved(ScimValueKanidm::from(
|
||||||
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
self.set.iter().map(|u| u.to_string()).collect::<Vec<_>>(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetUint32 {
|
pub struct ValueSetUint32 {
|
||||||
|
@ -108,7 +108,7 @@ impl ValueSetT for ValueSetUint32 {
|
||||||
Box::new(self.set.iter().map(|b| b.to_string()))
|
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 {
|
if self.len() == 1 {
|
||||||
// Because self.len == 1 we know this has to yield a value.
|
// Because self.len == 1 we know this has to yield a value.
|
||||||
let b = self.set.iter().copied().next().unwrap_or_default();
|
let b = self.set.iter().copied().next().unwrap_or_default();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
|
use smolset::SmolSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetUrl {
|
pub struct ValueSetUrl {
|
||||||
|
@ -102,7 +102,7 @@ impl ValueSetT for ValueSetUrl {
|
||||||
Box::new(self.set.iter().map(|i| i.to_string()))
|
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());
|
let mut iter = self.set.iter().map(|url| url.to_string());
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
let v = iter.next().unwrap_or_default();
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
use crate::schema::SchemaAttribute;
|
||||||
use crate::utils::trigraph_iter;
|
use crate::utils::trigraph_iter;
|
||||||
use crate::valueset::{DbValueSetV2, ValueSet};
|
use crate::valueset::{DbValueSetV2, ScimResolveStatus, ValueSet};
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetUtf8 {
|
pub struct ValueSetUtf8 {
|
||||||
|
@ -140,7 +140,7 @@ impl ValueSetT for ValueSetUtf8 {
|
||||||
Box::new(self.set.iter().cloned())
|
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();
|
let mut iter = self.set.iter().cloned();
|
||||||
if self.len() == 1 {
|
if self.len() == 1 {
|
||||||
let v = iter.next().unwrap_or_default();
|
let v = iter.next().unwrap_or_default();
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use smolset::SmolSet;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::schema::SchemaAttribute;
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValueSetUuid {
|
pub struct ValueSetUuid {
|
||||||
|
@ -113,8 +114,12 @@ impl ValueSetT for ValueSetUuid {
|
||||||
Box::new(self.set.iter().copied().map(uuid_to_proto_string))
|
Box::new(self.set.iter().copied().map(uuid_to_proto_string))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
self.set.iter().next().copied().map(ScimValueKanidm::Uuid)
|
self.set
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.copied()
|
||||||
|
.map(|uuid| ScimResolveStatus::NeedsResolution(ScimValueIntermediate::Refer(uuid)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
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))
|
Box::new(self.set.iter().copied().map(uuid_to_proto_string))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_scim_value(&self) -> Option<ScimValueKanidm> {
|
fn to_scim_value(&self) -> Option<ScimResolveStatus> {
|
||||||
Some(self.set.iter().copied().collect::<Vec<_>>().into())
|
let uuids = self.set.iter().copied().collect::<Vec<_>>();
|
||||||
|
Some(ScimResolveStatus::NeedsResolution(
|
||||||
|
ScimValueIntermediate::ReferMany(uuids),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
fn to_db_valueset_v2(&self) -> DbValueSetV2 {
|
||||||
|
@ -346,17 +354,17 @@ mod tests {
|
||||||
fn test_scim_uuid() {
|
fn test_scim_uuid() {
|
||||||
let vs: ValueSet = ValueSetUuid::new(uuid::uuid!("4d21d04a-dc0e-42eb-b850-34dd180b107f"));
|
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]
|
#[test]
|
||||||
fn test_scim_refer() {
|
fn test_scim_refer() {
|
||||||
let vs: ValueSet = ValueSetRefer::new(uuid::uuid!("4d21d04a-dc0e-42eb-b850-34dd180b107f"));
|
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