mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 04:27:02 +01:00
20240906 Attribute as an Enum Type (#3025)
Changes attribute from a string to an enum - this provides many performance improvements and memory savings throughout the server.
This commit is contained in:
parent
a20a3bc673
commit
938ad90f3b
|
@ -17,10 +17,10 @@ doctest = true
|
|||
|
||||
[features]
|
||||
wasm = ["webauthn-rs-proto/wasm"]
|
||||
test = []
|
||||
|
||||
[dependencies]
|
||||
base32 = { workspace = true }
|
||||
enum-iterator = { workspace = true }
|
||||
num_enum = { workspace = true }
|
||||
scim_proto = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
@ -34,3 +34,6 @@ urlencoding = { workspace = true }
|
|||
utoipa = { workspace = true }
|
||||
uuid = { workspace = true, features = ["serde"] }
|
||||
webauthn-rs-proto = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
enum-iterator = { workspace = true }
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
use enum_iterator::Sequence;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::internal::OperationError;
|
||||
use std::fmt;
|
||||
use tracing::trace;
|
||||
|
||||
pub use smartstring::alias::String as AttrString;
|
||||
|
||||
#[derive(
|
||||
Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Sequence, Hash,
|
||||
)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Default)]
|
||||
#[cfg_attr(test, derive(enum_iterator::Sequence))]
|
||||
#[serde(rename_all = "lowercase", try_from = "&str", into = "AttrString")]
|
||||
pub enum Attribute {
|
||||
Account,
|
||||
|
@ -29,6 +26,7 @@ pub enum Attribute {
|
|||
ApiTokenSession,
|
||||
ApplicationPassword,
|
||||
AttestedPasskeys,
|
||||
#[default]
|
||||
Attr,
|
||||
AttributeName,
|
||||
AttributeType,
|
||||
|
@ -171,28 +169,30 @@ pub enum Attribute {
|
|||
Version,
|
||||
WebauthnAttestationCaList,
|
||||
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
NonExist,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TestAttr,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TestNumber,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
Extra,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TestNotAllowed,
|
||||
// Custom(AttrString),
|
||||
|
||||
#[cfg(not(test))]
|
||||
Custom(AttrString),
|
||||
}
|
||||
|
||||
impl AsRef<str> for Attribute {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.into()
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Attribute> for &'static str {
|
||||
fn from(value: &Attribute) -> Self {
|
||||
(*value).into()
|
||||
impl AsRef<Attribute> for Attribute {
|
||||
fn as_ref(&self) -> &Attribute {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,192 +200,31 @@ impl TryFrom<&AttrString> for Attribute {
|
|||
type Error = OperationError;
|
||||
|
||||
fn try_from(value: &AttrString) -> Result<Self, Self::Error> {
|
||||
Attribute::try_from(value.as_str())
|
||||
Ok(Attribute::from_str(value.as_str()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for Attribute {
|
||||
type Error = OperationError;
|
||||
fn try_from(val: &'a str) -> Result<Self, OperationError> {
|
||||
let res = match val {
|
||||
ATTR_ACCOUNT => Attribute::Account,
|
||||
ATTR_ACCOUNT_EXPIRE => Attribute::AccountExpire,
|
||||
ATTR_ACCOUNT_VALID_FROM => Attribute::AccountValidFrom,
|
||||
ATTR_ACP_CREATE_ATTR => Attribute::AcpCreateAttr,
|
||||
ATTR_ACP_CREATE_CLASS => Attribute::AcpCreateClass,
|
||||
ATTR_ACP_ENABLE => Attribute::AcpEnable,
|
||||
ATTR_ACP_MODIFY_CLASS => Attribute::AcpModifyClass,
|
||||
ATTR_ACP_MODIFY_PRESENTATTR => Attribute::AcpModifyPresentAttr,
|
||||
ATTR_ACP_MODIFY_REMOVEDATTR => Attribute::AcpModifyRemovedAttr,
|
||||
ATTR_ACP_RECEIVER => Attribute::AcpReceiver,
|
||||
ATTR_ACP_RECEIVER_GROUP => Attribute::AcpReceiverGroup,
|
||||
ATTR_ACP_SEARCH_ATTR => Attribute::AcpSearchAttr,
|
||||
ATTR_ACP_TARGET_SCOPE => Attribute::AcpTargetScope,
|
||||
ATTR_API_TOKEN_SESSION => Attribute::ApiTokenSession,
|
||||
ATTR_APPLICATION_PASSWORD => Attribute::ApplicationPassword,
|
||||
ATTR_ATTESTED_PASSKEYS => Attribute::AttestedPasskeys,
|
||||
ATTR_ATTR => Attribute::Attr,
|
||||
ATTR_ATTRIBUTENAME => Attribute::AttributeName,
|
||||
ATTR_ATTRIBUTETYPE => Attribute::AttributeType,
|
||||
ATTR_AUTH_SESSION_EXPIRY => Attribute::AuthSessionExpiry,
|
||||
ATTR_AUTH_PASSWORD_MINIMUM_LENGTH => Attribute::AuthPasswordMinimumLength,
|
||||
ATTR_BADLIST_PASSWORD => Attribute::BadlistPassword,
|
||||
ATTR_CERTIFICATE => Attribute::Certificate,
|
||||
ATTR_CLAIM => Attribute::Claim,
|
||||
ATTR_CLASS => Attribute::Class,
|
||||
ATTR_CLASSNAME => Attribute::ClassName,
|
||||
ATTR_CN => Attribute::Cn,
|
||||
ATTR_COOKIE_PRIVATE_KEY => Attribute::CookiePrivateKey,
|
||||
ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN => Attribute::CredentialUpdateIntentToken,
|
||||
ATTR_CREDENTIAL_TYPE_MINIMUM => Attribute::CredentialTypeMinimum,
|
||||
ATTR_DENIED_NAME => Attribute::DeniedName,
|
||||
ATTR_DESCRIPTION => Attribute::Description,
|
||||
ATTR_DIRECTMEMBEROF => Attribute::DirectMemberOf,
|
||||
ATTR_DISPLAYNAME => Attribute::DisplayName,
|
||||
ATTR_DN => Attribute::Dn,
|
||||
ATTR_DOMAIN => Attribute::Domain,
|
||||
ATTR_DOMAIN_DISPLAY_NAME => Attribute::DomainDisplayName,
|
||||
ATTR_DOMAIN_DEVELOPMENT_TAINT => Attribute::DomainDevelopmentTaint,
|
||||
ATTR_DOMAIN_LDAP_BASEDN => Attribute::DomainLdapBasedn,
|
||||
ATTR_DOMAIN_NAME => Attribute::DomainName,
|
||||
ATTR_DOMAIN_SSID => Attribute::DomainSsid,
|
||||
ATTR_DOMAIN_TOKEN_KEY => Attribute::DomainTokenKey,
|
||||
ATTR_DOMAIN_UUID => Attribute::DomainUuid,
|
||||
ATTR_DYNGROUP => Attribute::DynGroup,
|
||||
ATTR_DYNGROUP_FILTER => Attribute::DynGroupFilter,
|
||||
ATTR_DYNMEMBER => Attribute::DynMember,
|
||||
ATTR_EMAIL => Attribute::Email,
|
||||
ATTR_EMAIL_ALTERNATIVE => Attribute::EmailAlternative,
|
||||
ATTR_EMAIL_PRIMARY => Attribute::EmailPrimary,
|
||||
ATTR_ENTRYDN => Attribute::EntryDn,
|
||||
ATTR_ENTRY_MANAGED_BY => Attribute::EntryManagedBy,
|
||||
ATTR_ENTRYUUID => Attribute::EntryUuid,
|
||||
ATTR_ES256_PRIVATE_KEY_DER => Attribute::Es256PrivateKeyDer,
|
||||
ATTR_EXCLUDES => Attribute::Excludes,
|
||||
ATTR_FERNET_PRIVATE_KEY_STR => Attribute::FernetPrivateKeyStr,
|
||||
ATTR_GECOS => Attribute::Gecos,
|
||||
ATTR_GIDNUMBER => Attribute::GidNumber,
|
||||
ATTR_GRANT_UI_HINT => Attribute::GrantUiHint,
|
||||
ATTR_GROUP => Attribute::Group,
|
||||
ATTR_ID_VERIFICATION_ECKEY => Attribute::IdVerificationEcKey,
|
||||
ATTR_IMAGE => Attribute::Image,
|
||||
ATTR_INDEX => Attribute::Index,
|
||||
ATTR_IPANTHASH => Attribute::IpaNtHash,
|
||||
ATTR_IPASSHPUBKEY => Attribute::IpaSshPubKey,
|
||||
ATTR_JWS_ES256_PRIVATE_KEY => Attribute::JwsEs256PrivateKey,
|
||||
ATTR_KEY_ACTION_ROTATE => Attribute::KeyActionRotate,
|
||||
ATTR_KEY_ACTION_REVOKE => Attribute::KeyActionRevoke,
|
||||
ATTR_KEY_ACTION_IMPORT_JWS_ES256 => Attribute::KeyActionImportJwsEs256,
|
||||
ATTR_KEY_INTERNAL_DATA => Attribute::KeyInternalData,
|
||||
ATTR_KEY_PROVIDER => Attribute::KeyProvider,
|
||||
ATTR_LAST_MODIFIED_CID => Attribute::LastModifiedCid,
|
||||
ATTR_LDAP_ALLOW_UNIX_PW_BIND => Attribute::LdapAllowUnixPwBind,
|
||||
ATTR_LDAP_EMAIL_ADDRESS => Attribute::LdapEmailAddress,
|
||||
ATTR_LDAP_KEYS => Attribute::LdapKeys,
|
||||
ATTR_SSH_PUBLICKEY => Attribute::SshPublicKey,
|
||||
ATTR_LEGALNAME => Attribute::LegalName,
|
||||
ATTR_LINKEDGROUP => Attribute::LinkedGroup,
|
||||
ATTR_LOGINSHELL => Attribute::LoginShell,
|
||||
ATTR_LIMIT_SEARCH_MAX_RESULTS => Attribute::LimitSearchMaxResults,
|
||||
ATTR_LIMIT_SEARCH_MAX_FILTER_TEST => Attribute::LimitSearchMaxFilterTest,
|
||||
ATTR_MAIL => Attribute::Mail,
|
||||
ATTR_MAY => Attribute::May,
|
||||
ATTR_MEMBER => Attribute::Member,
|
||||
ATTR_MEMBEROF => Attribute::MemberOf,
|
||||
ATTR_MULTIVALUE => Attribute::MultiValue,
|
||||
ATTR_MUST => Attribute::Must,
|
||||
ATTR_NAME => Attribute::Name,
|
||||
ATTR_NAME_HISTORY => Attribute::NameHistory,
|
||||
ATTR_NO_INDEX => Attribute::NoIndex,
|
||||
ATTR_NSUNIQUEID => Attribute::NsUniqueId,
|
||||
ATTR_NSACCOUNTLOCK => Attribute::NsAccountLock,
|
||||
ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE => {
|
||||
Attribute::OAuth2AllowInsecureClientDisablePkce
|
||||
}
|
||||
ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT => Attribute::OAuth2AllowLocalhostRedirect,
|
||||
ATTR_OAUTH2_CONSENT_SCOPE_MAP => Attribute::OAuth2ConsentScopeMap,
|
||||
ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE => Attribute::OAuth2JwtLegacyCryptoEnable,
|
||||
ATTR_OAUTH2_PREFER_SHORT_USERNAME => Attribute::OAuth2PreferShortUsername,
|
||||
ATTR_OAUTH2_RS_BASIC_SECRET => Attribute::OAuth2RsBasicSecret,
|
||||
ATTR_OAUTH2_RS_CLAIM_MAP => Attribute::OAuth2RsClaimMap,
|
||||
ATTR_OAUTH2_RS_IMPLICIT_SCOPES => Attribute::OAuth2RsImplicitScopes,
|
||||
ATTR_OAUTH2_RS_NAME => Attribute::OAuth2RsName,
|
||||
ATTR_OAUTH2_RS_ORIGIN => Attribute::OAuth2RsOrigin,
|
||||
ATTR_OAUTH2_RS_ORIGIN_LANDING => Attribute::OAuth2RsOriginLanding,
|
||||
ATTR_OAUTH2_RS_SCOPE_MAP => Attribute::OAuth2RsScopeMap,
|
||||
ATTR_OAUTH2_RS_SUP_SCOPE_MAP => Attribute::OAuth2RsSupScopeMap,
|
||||
ATTR_OAUTH2_RS_TOKEN_KEY => Attribute::OAuth2RsTokenKey,
|
||||
ATTR_OAUTH2_SESSION => Attribute::OAuth2Session,
|
||||
ATTR_OAUTH2_STRICT_REDIRECT_URI => Attribute::OAuth2StrictRedirectUri,
|
||||
ATTR_OBJECTCLASS => Attribute::ObjectClass,
|
||||
ATTR_OTHER_NO_INDEX => Attribute::OtherNoIndex,
|
||||
ATTR_PASSKEYS => Attribute::PassKeys,
|
||||
ATTR_PASSWORD_IMPORT => Attribute::PasswordImport,
|
||||
ATTR_PATCH_LEVEL => Attribute::PatchLevel,
|
||||
ATTR_PHANTOM => Attribute::Phantom,
|
||||
ATTR_PRIMARY_CREDENTIAL => Attribute::PrimaryCredential,
|
||||
ATTR_PRIVATE_COOKIE_KEY => Attribute::PrivateCookieKey,
|
||||
ATTR_PRIVILEGE_EXPIRY => Attribute::PrivilegeExpiry,
|
||||
ATTR_RADIUS_SECRET => Attribute::RadiusSecret,
|
||||
ATTR_RECYCLEDDIRECTMEMBEROF => Attribute::RecycledDirectMemberOf,
|
||||
ATTR_REFERS => Attribute::Refers,
|
||||
ATTR_REPLICATED => Attribute::Replicated,
|
||||
ATTR_RS256_PRIVATE_KEY_DER => Attribute::Rs256PrivateKeyDer,
|
||||
ATTR_SCOPE => Attribute::Scope,
|
||||
ATTR_SOURCE_UUID => Attribute::SourceUuid,
|
||||
ATTR_SPN => Attribute::Spn,
|
||||
ATTR_LDAP_SSHPUBLICKEY => Attribute::LdapSshPublicKey,
|
||||
ATTR_SUDOHOST => Attribute::SudoHost,
|
||||
ATTR_SUPPLEMENTS => Attribute::Supplements,
|
||||
ATTR_SYNC_ALLOWED => Attribute::SyncAllowed,
|
||||
ATTR_SYNC_CLASS => Attribute::SyncClass,
|
||||
ATTR_SYNC_COOKIE => Attribute::SyncCookie,
|
||||
ATTR_SYNC_CREDENTIAL_PORTAL => Attribute::SyncCredentialPortal,
|
||||
ATTR_SYNC_EXTERNAL_ID => Attribute::SyncExternalId,
|
||||
ATTR_SYNC_PARENT_UUID => Attribute::SyncParentUuid,
|
||||
ATTR_SYNC_TOKEN_SESSION => Attribute::SyncTokenSession,
|
||||
ATTR_SYNC_YIELD_AUTHORITY => Attribute::SyncYieldAuthority,
|
||||
ATTR_SYNTAX => Attribute::Syntax,
|
||||
ATTR_SYSTEMEXCLUDES => Attribute::SystemExcludes,
|
||||
ATTR_SYSTEMMAY => Attribute::SystemMay,
|
||||
ATTR_SYSTEMMUST => Attribute::SystemMust,
|
||||
ATTR_SYSTEMSUPPLEMENTS => Attribute::SystemSupplements,
|
||||
ATTR_TERM => Attribute::Term,
|
||||
ATTR_TOTP_IMPORT => Attribute::TotpImport,
|
||||
ATTR_UID => Attribute::Uid,
|
||||
ATTR_UIDNUMBER => Attribute::UidNumber,
|
||||
ATTR_UNIQUE => Attribute::Unique,
|
||||
ATTR_UNIX_PASSWORD => Attribute::UnixPassword,
|
||||
ATTR_UNIX_PASSWORD_IMPORT => Attribute::UnixPasswordImport,
|
||||
ATTR_USER_AUTH_TOKEN_SESSION => Attribute::UserAuthTokenSession,
|
||||
ATTR_USERID => Attribute::UserId,
|
||||
ATTR_USERPASSWORD => Attribute::UserPassword,
|
||||
ATTR_UUID => Attribute::Uuid,
|
||||
ATTR_VERSION => Attribute::Version,
|
||||
ATTR_WEBAUTHN_ATTESTATION_CA_LIST => Attribute::WebauthnAttestationCaList,
|
||||
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
TEST_ATTR_NON_EXIST => Attribute::NonExist,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
TEST_ATTR_TEST_ATTR => Attribute::TestAttr,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
TEST_ATTR_EXTRA => Attribute::Extra,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
TEST_ATTR_NUMBER => Attribute::TestNumber,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
TEST_ATTR_NOTALLOWED => Attribute::TestNotAllowed,
|
||||
_ => {
|
||||
trace!("Failed to convert {} to Attribute", val);
|
||||
return Err(OperationError::InvalidAttributeName(val.to_string()));
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
impl From<&str> for Attribute {
|
||||
fn from(value: &str) -> Self {
|
||||
Self::from_str(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Attribute> for &'static str {
|
||||
impl<'a> From<&'a Attribute> for &'a str {
|
||||
fn from(val: &'a Attribute) -> Self {
|
||||
val.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Attribute> for AttrString {
|
||||
fn from(val: Attribute) -> Self {
|
||||
match val {
|
||||
AttrString::from(val.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
Attribute::Account => ATTR_ACCOUNT,
|
||||
Attribute::AccountExpire => ATTR_ACCOUNT_EXPIRE,
|
||||
Attribute::AccountValidFrom => ATTR_ACCOUNT_VALID_FROM,
|
||||
|
@ -542,30 +381,210 @@ impl From<Attribute> for &'static str {
|
|||
Attribute::Version => ATTR_VERSION,
|
||||
Attribute::WebauthnAttestationCaList => ATTR_WEBAUTHN_ATTESTATION_CA_LIST,
|
||||
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
Attribute::NonExist => TEST_ATTR_NON_EXIST,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
Attribute::TestAttr => TEST_ATTR_TEST_ATTR,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
Attribute::Extra => TEST_ATTR_EXTRA,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
Attribute::TestNumber => TEST_ATTR_NUMBER,
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
Attribute::TestNotAllowed => TEST_ATTR_NOTALLOWED,
|
||||
|
||||
#[cfg(not(test))]
|
||||
Attribute::Custom(value) => value.as_str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Attribute> for AttrString {
|
||||
fn from(val: Attribute) -> Self {
|
||||
AttrString::from(val.to_string())
|
||||
// We allow this because the standard lib from_str is fallible, and we want an infallible version.
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(value: &str) -> Self {
|
||||
// Could this be something like heapless to save allocations? Also gives a way
|
||||
// to limit length of str?
|
||||
match value.to_lowercase().as_str() {
|
||||
ATTR_ACCOUNT => Attribute::Account,
|
||||
ATTR_ACCOUNT_EXPIRE => Attribute::AccountExpire,
|
||||
ATTR_ACCOUNT_VALID_FROM => Attribute::AccountValidFrom,
|
||||
ATTR_ACP_CREATE_ATTR => Attribute::AcpCreateAttr,
|
||||
ATTR_ACP_CREATE_CLASS => Attribute::AcpCreateClass,
|
||||
ATTR_ACP_ENABLE => Attribute::AcpEnable,
|
||||
ATTR_ACP_MODIFY_CLASS => Attribute::AcpModifyClass,
|
||||
ATTR_ACP_MODIFY_PRESENTATTR => Attribute::AcpModifyPresentAttr,
|
||||
ATTR_ACP_MODIFY_REMOVEDATTR => Attribute::AcpModifyRemovedAttr,
|
||||
ATTR_ACP_RECEIVER => Attribute::AcpReceiver,
|
||||
ATTR_ACP_RECEIVER_GROUP => Attribute::AcpReceiverGroup,
|
||||
ATTR_ACP_SEARCH_ATTR => Attribute::AcpSearchAttr,
|
||||
ATTR_ACP_TARGET_SCOPE => Attribute::AcpTargetScope,
|
||||
ATTR_API_TOKEN_SESSION => Attribute::ApiTokenSession,
|
||||
ATTR_APPLICATION_PASSWORD => Attribute::ApplicationPassword,
|
||||
ATTR_ATTESTED_PASSKEYS => Attribute::AttestedPasskeys,
|
||||
ATTR_ATTR => Attribute::Attr,
|
||||
ATTR_ATTRIBUTENAME => Attribute::AttributeName,
|
||||
ATTR_ATTRIBUTETYPE => Attribute::AttributeType,
|
||||
ATTR_AUTH_SESSION_EXPIRY => Attribute::AuthSessionExpiry,
|
||||
ATTR_AUTH_PASSWORD_MINIMUM_LENGTH => Attribute::AuthPasswordMinimumLength,
|
||||
ATTR_BADLIST_PASSWORD => Attribute::BadlistPassword,
|
||||
ATTR_CERTIFICATE => Attribute::Certificate,
|
||||
ATTR_CLAIM => Attribute::Claim,
|
||||
ATTR_CLASS => Attribute::Class,
|
||||
ATTR_CLASSNAME => Attribute::ClassName,
|
||||
ATTR_CN => Attribute::Cn,
|
||||
ATTR_COOKIE_PRIVATE_KEY => Attribute::CookiePrivateKey,
|
||||
ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN => Attribute::CredentialUpdateIntentToken,
|
||||
ATTR_CREDENTIAL_TYPE_MINIMUM => Attribute::CredentialTypeMinimum,
|
||||
ATTR_DENIED_NAME => Attribute::DeniedName,
|
||||
ATTR_DESCRIPTION => Attribute::Description,
|
||||
ATTR_DIRECTMEMBEROF => Attribute::DirectMemberOf,
|
||||
ATTR_DISPLAYNAME => Attribute::DisplayName,
|
||||
ATTR_DN => Attribute::Dn,
|
||||
ATTR_DOMAIN => Attribute::Domain,
|
||||
ATTR_DOMAIN_DISPLAY_NAME => Attribute::DomainDisplayName,
|
||||
ATTR_DOMAIN_DEVELOPMENT_TAINT => Attribute::DomainDevelopmentTaint,
|
||||
ATTR_DOMAIN_LDAP_BASEDN => Attribute::DomainLdapBasedn,
|
||||
ATTR_DOMAIN_NAME => Attribute::DomainName,
|
||||
ATTR_DOMAIN_SSID => Attribute::DomainSsid,
|
||||
ATTR_DOMAIN_TOKEN_KEY => Attribute::DomainTokenKey,
|
||||
ATTR_DOMAIN_UUID => Attribute::DomainUuid,
|
||||
ATTR_DYNGROUP => Attribute::DynGroup,
|
||||
ATTR_DYNGROUP_FILTER => Attribute::DynGroupFilter,
|
||||
ATTR_DYNMEMBER => Attribute::DynMember,
|
||||
ATTR_EMAIL => Attribute::Email,
|
||||
ATTR_EMAIL_ALTERNATIVE => Attribute::EmailAlternative,
|
||||
ATTR_EMAIL_PRIMARY => Attribute::EmailPrimary,
|
||||
ATTR_ENTRYDN => Attribute::EntryDn,
|
||||
ATTR_ENTRY_MANAGED_BY => Attribute::EntryManagedBy,
|
||||
ATTR_ENTRYUUID => Attribute::EntryUuid,
|
||||
ATTR_ES256_PRIVATE_KEY_DER => Attribute::Es256PrivateKeyDer,
|
||||
ATTR_EXCLUDES => Attribute::Excludes,
|
||||
ATTR_FERNET_PRIVATE_KEY_STR => Attribute::FernetPrivateKeyStr,
|
||||
ATTR_GECOS => Attribute::Gecos,
|
||||
ATTR_GIDNUMBER => Attribute::GidNumber,
|
||||
ATTR_GRANT_UI_HINT => Attribute::GrantUiHint,
|
||||
ATTR_GROUP => Attribute::Group,
|
||||
ATTR_ID_VERIFICATION_ECKEY => Attribute::IdVerificationEcKey,
|
||||
ATTR_IMAGE => Attribute::Image,
|
||||
ATTR_INDEX => Attribute::Index,
|
||||
ATTR_IPANTHASH => Attribute::IpaNtHash,
|
||||
ATTR_IPASSHPUBKEY => Attribute::IpaSshPubKey,
|
||||
ATTR_JWS_ES256_PRIVATE_KEY => Attribute::JwsEs256PrivateKey,
|
||||
ATTR_KEY_ACTION_ROTATE => Attribute::KeyActionRotate,
|
||||
ATTR_KEY_ACTION_REVOKE => Attribute::KeyActionRevoke,
|
||||
ATTR_KEY_ACTION_IMPORT_JWS_ES256 => Attribute::KeyActionImportJwsEs256,
|
||||
ATTR_KEY_INTERNAL_DATA => Attribute::KeyInternalData,
|
||||
ATTR_KEY_PROVIDER => Attribute::KeyProvider,
|
||||
ATTR_LAST_MODIFIED_CID => Attribute::LastModifiedCid,
|
||||
ATTR_LDAP_ALLOW_UNIX_PW_BIND => Attribute::LdapAllowUnixPwBind,
|
||||
ATTR_LDAP_EMAIL_ADDRESS => Attribute::LdapEmailAddress,
|
||||
ATTR_LDAP_KEYS => Attribute::LdapKeys,
|
||||
ATTR_SSH_PUBLICKEY => Attribute::SshPublicKey,
|
||||
ATTR_LEGALNAME => Attribute::LegalName,
|
||||
ATTR_LINKEDGROUP => Attribute::LinkedGroup,
|
||||
ATTR_LOGINSHELL => Attribute::LoginShell,
|
||||
ATTR_LIMIT_SEARCH_MAX_RESULTS => Attribute::LimitSearchMaxResults,
|
||||
ATTR_LIMIT_SEARCH_MAX_FILTER_TEST => Attribute::LimitSearchMaxFilterTest,
|
||||
ATTR_MAIL => Attribute::Mail,
|
||||
ATTR_MAY => Attribute::May,
|
||||
ATTR_MEMBER => Attribute::Member,
|
||||
ATTR_MEMBEROF => Attribute::MemberOf,
|
||||
ATTR_MULTIVALUE => Attribute::MultiValue,
|
||||
ATTR_MUST => Attribute::Must,
|
||||
ATTR_NAME => Attribute::Name,
|
||||
ATTR_NAME_HISTORY => Attribute::NameHistory,
|
||||
ATTR_NO_INDEX => Attribute::NoIndex,
|
||||
ATTR_NSUNIQUEID => Attribute::NsUniqueId,
|
||||
ATTR_NSACCOUNTLOCK => Attribute::NsAccountLock,
|
||||
ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE => {
|
||||
Attribute::OAuth2AllowInsecureClientDisablePkce
|
||||
}
|
||||
ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT => Attribute::OAuth2AllowLocalhostRedirect,
|
||||
ATTR_OAUTH2_CONSENT_SCOPE_MAP => Attribute::OAuth2ConsentScopeMap,
|
||||
ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE => Attribute::OAuth2JwtLegacyCryptoEnable,
|
||||
ATTR_OAUTH2_PREFER_SHORT_USERNAME => Attribute::OAuth2PreferShortUsername,
|
||||
ATTR_OAUTH2_RS_BASIC_SECRET => Attribute::OAuth2RsBasicSecret,
|
||||
ATTR_OAUTH2_RS_CLAIM_MAP => Attribute::OAuth2RsClaimMap,
|
||||
ATTR_OAUTH2_RS_IMPLICIT_SCOPES => Attribute::OAuth2RsImplicitScopes,
|
||||
ATTR_OAUTH2_RS_NAME => Attribute::OAuth2RsName,
|
||||
ATTR_OAUTH2_RS_ORIGIN => Attribute::OAuth2RsOrigin,
|
||||
ATTR_OAUTH2_RS_ORIGIN_LANDING => Attribute::OAuth2RsOriginLanding,
|
||||
ATTR_OAUTH2_RS_SCOPE_MAP => Attribute::OAuth2RsScopeMap,
|
||||
ATTR_OAUTH2_RS_SUP_SCOPE_MAP => Attribute::OAuth2RsSupScopeMap,
|
||||
ATTR_OAUTH2_RS_TOKEN_KEY => Attribute::OAuth2RsTokenKey,
|
||||
ATTR_OAUTH2_SESSION => Attribute::OAuth2Session,
|
||||
ATTR_OAUTH2_STRICT_REDIRECT_URI => Attribute::OAuth2StrictRedirectUri,
|
||||
ATTR_OBJECTCLASS => Attribute::ObjectClass,
|
||||
ATTR_OTHER_NO_INDEX => Attribute::OtherNoIndex,
|
||||
ATTR_PASSKEYS => Attribute::PassKeys,
|
||||
ATTR_PASSWORD_IMPORT => Attribute::PasswordImport,
|
||||
ATTR_PATCH_LEVEL => Attribute::PatchLevel,
|
||||
ATTR_PHANTOM => Attribute::Phantom,
|
||||
ATTR_PRIMARY_CREDENTIAL => Attribute::PrimaryCredential,
|
||||
ATTR_PRIVATE_COOKIE_KEY => Attribute::PrivateCookieKey,
|
||||
ATTR_PRIVILEGE_EXPIRY => Attribute::PrivilegeExpiry,
|
||||
ATTR_RADIUS_SECRET => Attribute::RadiusSecret,
|
||||
ATTR_RECYCLEDDIRECTMEMBEROF => Attribute::RecycledDirectMemberOf,
|
||||
ATTR_REFERS => Attribute::Refers,
|
||||
ATTR_REPLICATED => Attribute::Replicated,
|
||||
ATTR_RS256_PRIVATE_KEY_DER => Attribute::Rs256PrivateKeyDer,
|
||||
ATTR_SCOPE => Attribute::Scope,
|
||||
ATTR_SOURCE_UUID => Attribute::SourceUuid,
|
||||
ATTR_SPN => Attribute::Spn,
|
||||
ATTR_LDAP_SSHPUBLICKEY => Attribute::LdapSshPublicKey,
|
||||
ATTR_SUDOHOST => Attribute::SudoHost,
|
||||
ATTR_SUPPLEMENTS => Attribute::Supplements,
|
||||
ATTR_SYNC_ALLOWED => Attribute::SyncAllowed,
|
||||
ATTR_SYNC_CLASS => Attribute::SyncClass,
|
||||
ATTR_SYNC_COOKIE => Attribute::SyncCookie,
|
||||
ATTR_SYNC_CREDENTIAL_PORTAL => Attribute::SyncCredentialPortal,
|
||||
ATTR_SYNC_EXTERNAL_ID => Attribute::SyncExternalId,
|
||||
ATTR_SYNC_PARENT_UUID => Attribute::SyncParentUuid,
|
||||
ATTR_SYNC_TOKEN_SESSION => Attribute::SyncTokenSession,
|
||||
ATTR_SYNC_YIELD_AUTHORITY => Attribute::SyncYieldAuthority,
|
||||
ATTR_SYNTAX => Attribute::Syntax,
|
||||
ATTR_SYSTEMEXCLUDES => Attribute::SystemExcludes,
|
||||
ATTR_SYSTEMMAY => Attribute::SystemMay,
|
||||
ATTR_SYSTEMMUST => Attribute::SystemMust,
|
||||
ATTR_SYSTEMSUPPLEMENTS => Attribute::SystemSupplements,
|
||||
ATTR_TERM => Attribute::Term,
|
||||
ATTR_TOTP_IMPORT => Attribute::TotpImport,
|
||||
ATTR_UID => Attribute::Uid,
|
||||
ATTR_UIDNUMBER => Attribute::UidNumber,
|
||||
ATTR_UNIQUE => Attribute::Unique,
|
||||
ATTR_UNIX_PASSWORD => Attribute::UnixPassword,
|
||||
ATTR_UNIX_PASSWORD_IMPORT => Attribute::UnixPasswordImport,
|
||||
ATTR_USER_AUTH_TOKEN_SESSION => Attribute::UserAuthTokenSession,
|
||||
ATTR_USERID => Attribute::UserId,
|
||||
ATTR_USERPASSWORD => Attribute::UserPassword,
|
||||
ATTR_UUID => Attribute::Uuid,
|
||||
ATTR_VERSION => Attribute::Version,
|
||||
ATTR_WEBAUTHN_ATTESTATION_CA_LIST => Attribute::WebauthnAttestationCaList,
|
||||
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TEST_ATTR_NON_EXIST => Attribute::NonExist,
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TEST_ATTR_TEST_ATTR => Attribute::TestAttr,
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TEST_ATTR_EXTRA => Attribute::Extra,
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TEST_ATTR_NUMBER => Attribute::TestNumber,
|
||||
#[cfg(any(debug_assertions, test, feature = "test"))]
|
||||
TEST_ATTR_NOTALLOWED => Attribute::TestNotAllowed,
|
||||
|
||||
#[cfg(not(test))]
|
||||
_ => Attribute::Custom(AttrString::from(value)),
|
||||
// Allowed only in tests
|
||||
#[allow(clippy::unreachable)]
|
||||
#[cfg(test)]
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Attribute {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let s: &'static str = (*self).into();
|
||||
write!(f, "{}", s)
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -575,7 +594,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_valueattribute_as_str() {
|
||||
assert!(Attribute::Class.as_ref() == "class");
|
||||
assert!(Attribute::Class.as_str() == "class");
|
||||
assert!(Attribute::Class.to_string() == *"class");
|
||||
}
|
||||
|
||||
|
@ -585,8 +604,7 @@ mod test {
|
|||
use enum_iterator::all;
|
||||
let the_list = all::<Attribute>().collect::<Vec<_>>();
|
||||
for attr in the_list {
|
||||
let s: &'static str = attr.into();
|
||||
let attr2 = Attribute::try_from(s).unwrap();
|
||||
let attr2 = Attribute::from(attr.as_str());
|
||||
assert!(attr == attr2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use utoipa::ToSchema;
|
|||
use uuid::Uuid;
|
||||
|
||||
use super::credupdate::PasswordFeedback;
|
||||
use crate::attribute::Attribute;
|
||||
|
||||
/* ===== errors ===== */
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
|
||||
|
@ -13,7 +14,7 @@ pub enum SchemaError {
|
|||
NotImplemented,
|
||||
NoClassFound,
|
||||
InvalidClass(Vec<String>),
|
||||
MissingMustAttribute(Vec<String>),
|
||||
MissingMustAttribute(Vec<Attribute>),
|
||||
InvalidAttribute(String),
|
||||
InvalidAttributeSyntax(String),
|
||||
AttributeNotValidForClass(String),
|
||||
|
|
|
@ -520,7 +520,8 @@ mod tests {
|
|||
assert_eq!(at, super::AccessTokenType::DPoP);
|
||||
}
|
||||
|
||||
for testcase in ["cheese"] {
|
||||
{
|
||||
let testcase = "cheese";
|
||||
let at = serde_json::from_str::<super::AccessTokenType>(&format!("\"{}\"", testcase));
|
||||
assert!(at.is_err())
|
||||
}
|
||||
|
|
|
@ -77,14 +77,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Invalid identity");
|
||||
error!(?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
// Make an event from the request
|
||||
let search =
|
||||
SearchEvent::from_message(ident, &req, &mut idms_prox_read.qs_read).map_err(|e| {
|
||||
admin_error!(?e, "Failed to begin search");
|
||||
error!(?e, "Failed to begin search");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -120,7 +120,7 @@ impl QueryServerReadV1 {
|
|||
// Convert the AuthRequest to an AuthEvent that the idm server
|
||||
// can use.
|
||||
let ae = AuthEvent::from_message(sessionid, req).map_err(|e| {
|
||||
admin_error!(err = ?e, "Failed to parse AuthEvent");
|
||||
error!(err = ?e, "Failed to parse AuthEvent");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -160,7 +160,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idm_auth
|
||||
.validate_client_auth_info_to_ident(client_auth_info.clone(), ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Invalid identity");
|
||||
error!(?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -333,12 +333,12 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Invalid identity");
|
||||
error!(?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let srch =
|
||||
SearchEvent::from_whoami_request(ident, &idms_prox_read.qs_read).map_err(|e| {
|
||||
admin_error!(?e, "Failed to begin whoami");
|
||||
error!(?e, "Failed to begin whoami");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -378,7 +378,7 @@ impl QueryServerReadV1 {
|
|||
idms_prox_read
|
||||
.validate_client_auth_info_to_uat(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Invalid identity");
|
||||
error!(?e, "Invalid identity");
|
||||
e
|
||||
})
|
||||
}
|
||||
|
@ -396,7 +396,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity in handle_oauth2_rs_image_get_image");
|
||||
error!(err = ?e, "Invalid identity in handle_oauth2_rs_image_get_image");
|
||||
e
|
||||
})?;
|
||||
let attrs = vec![Attribute::Image.to_string()];
|
||||
|
@ -431,7 +431,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
// Make an event from the request
|
||||
|
@ -443,7 +443,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin internal api search: {:?}", e);
|
||||
error!("Failed to begin internal api search: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -475,16 +475,15 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let target_uuid = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
// Update the filter with the target_uuid
|
||||
|
@ -502,7 +501,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin internal api search: {:?}", e);
|
||||
error!("Failed to begin internal api search: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -534,7 +533,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
// Make an event from the request
|
||||
|
@ -546,7 +545,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin recycled search: {:?}", e);
|
||||
error!("Failed to begin recycled search: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -576,16 +575,15 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let target_uuid = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
// Make an event from the request
|
||||
|
@ -596,7 +594,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin radius read: {:?}", e);
|
||||
error!("Failed to begin radius read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -637,16 +635,15 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let target_uuid = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
// Make an event from the request
|
||||
|
@ -657,7 +654,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin radius token read: {:?}", e);
|
||||
error!("Failed to begin radius token read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -684,7 +681,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -710,7 +707,7 @@ impl QueryServerReadV1 {
|
|||
let rate = match UnixUserTokenEvent::from_parts(ident, target_uuid) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin unix token read: {:?}", e);
|
||||
error!("Failed to begin unix token read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -736,7 +733,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -756,7 +753,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin unix group token read: {:?}", e);
|
||||
error!("Failed to begin unix group token read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -782,15 +779,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
let target_uuid = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
// Make an event from the request
|
||||
|
@ -801,7 +797,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin ssh key read: {:?}", e);
|
||||
error!("Failed to begin ssh key read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -845,15 +841,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
let target_uuid = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_info!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
admin_info!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
// Make an event from the request
|
||||
|
@ -864,7 +859,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin sshkey tag read: {:?}", e);
|
||||
error!("Failed to begin sshkey tag read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -909,15 +904,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
let target = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
let lte = ListApiTokenEvent { ident, target };
|
||||
|
@ -941,15 +935,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
let target = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
let lte = ListUserAuthTokenEvent { ident, target };
|
||||
|
@ -975,14 +968,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
let target = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(&other_id)
|
||||
.map_err(|e| {
|
||||
admin_error!("No user found with the provided ID: {:?}", e);
|
||||
error!("No user found with the provided ID: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
match user_request {
|
||||
|
@ -1016,7 +1009,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idm_auth
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1031,7 +1024,7 @@ impl QueryServerReadV1 {
|
|||
let uuae = match UnixUserAuthEvent::from_parts(ident, target_uuid, cred) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin unix auth");
|
||||
error!(err = ?e, "Failed to begin unix auth");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1065,14 +1058,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let target_uuid = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1084,7 +1077,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin credential status read");
|
||||
error!(err = ?e, "Failed to begin credential status read");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1111,15 +1104,14 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
let target_uuid = idms_prox_read
|
||||
.qs_read
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
// Make an event from the request
|
||||
|
@ -1130,7 +1122,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin backup code read: {:?}", e);
|
||||
error!("Failed to begin backup code read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1164,7 +1156,7 @@ impl QueryServerReadV1 {
|
|||
idms_cred_update
|
||||
.credential_update_status(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_update_status",
|
||||
);
|
||||
|
@ -1200,7 +1192,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::PrimaryRemove => idms_cred_update
|
||||
.credential_primary_delete(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_delete",
|
||||
);
|
||||
|
@ -1209,7 +1201,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::Password(pw) => idms_cred_update
|
||||
.credential_primary_set_password(&session_token, ct, &pw)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_set_password",
|
||||
);
|
||||
|
@ -1218,7 +1210,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::CancelMFAReg => idms_cred_update
|
||||
.credential_update_cancel_mfareg(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_update_cancel_mfareg",
|
||||
);
|
||||
|
@ -1227,7 +1219,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::TotpGenerate => idms_cred_update
|
||||
.credential_primary_init_totp(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_init_totp",
|
||||
);
|
||||
|
@ -1236,7 +1228,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::TotpVerify(totp_chal, label) => idms_cred_update
|
||||
.credential_primary_check_totp(&session_token, ct, totp_chal, &label)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_check_totp",
|
||||
);
|
||||
|
@ -1245,7 +1237,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::TotpAcceptSha1 => idms_cred_update
|
||||
.credential_primary_accept_sha1_totp(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_accept_sha1_totp",
|
||||
);
|
||||
|
@ -1254,7 +1246,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::TotpRemove(label) => idms_cred_update
|
||||
.credential_primary_remove_totp(&session_token, ct, &label)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_remove_totp",
|
||||
);
|
||||
|
@ -1263,7 +1255,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::BackupCodeGenerate => idms_cred_update
|
||||
.credential_primary_init_backup_codes(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_init_backup_codes",
|
||||
);
|
||||
|
@ -1272,7 +1264,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::BackupCodeRemove => idms_cred_update
|
||||
.credential_primary_remove_backup_codes(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_primary_remove_backup_codes",
|
||||
);
|
||||
|
@ -1281,7 +1273,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::PasskeyInit => idms_cred_update
|
||||
.credential_passkey_init(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_passkey_init",
|
||||
);
|
||||
|
@ -1290,7 +1282,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::PasskeyFinish(label, rpkc) => idms_cred_update
|
||||
.credential_passkey_finish(&session_token, ct, label, &rpkc)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_passkey_finish",
|
||||
);
|
||||
|
@ -1299,7 +1291,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::PasskeyRemove(uuid) => idms_cred_update
|
||||
.credential_passkey_remove(&session_token, ct, uuid)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_passkey_remove",
|
||||
);
|
||||
|
@ -1308,7 +1300,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::AttestedPasskeyInit => idms_cred_update
|
||||
.credential_attested_passkey_init(&session_token, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_attested_passkey_init",
|
||||
);
|
||||
|
@ -1317,7 +1309,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::AttestedPasskeyFinish(label, rpkc) => idms_cred_update
|
||||
.credential_attested_passkey_finish(&session_token, ct, label, &rpkc)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_attested_passkey_finish",
|
||||
);
|
||||
|
@ -1326,7 +1318,7 @@ impl QueryServerReadV1 {
|
|||
CURequest::AttestedPasskeyRemove(uuid) => idms_cred_update
|
||||
.credential_attested_passkey_remove(&session_token, ct, uuid)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin credential_attested_passkey_remove",
|
||||
);
|
||||
|
@ -1352,7 +1344,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1365,7 +1357,7 @@ impl QueryServerReadV1 {
|
|||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
admin_error!("Failed to begin oauth2 basic secret read: {:?}", e);
|
||||
error!("Failed to begin oauth2 basic secret read: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1409,7 +1401,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
Oauth2Error::AuthenticationRequired
|
||||
})?;
|
||||
|
||||
|
@ -1433,7 +1425,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1538,7 +1530,7 @@ impl QueryServerReadV1 {
|
|||
let ident = idms_prox_read
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1563,7 +1555,7 @@ impl QueryServerReadV1 {
|
|||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map(|_| ())
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid identity: {:?}", e);
|
||||
error!("Invalid identity: {:?}", e);
|
||||
e
|
||||
})
|
||||
}
|
||||
|
@ -1602,7 +1594,7 @@ impl QueryServerReadV1 {
|
|||
.do_op(&self.idms, server_op, uat, ip_addr, eventid)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
admin_error!("do_op failed -> {:?}", e);
|
||||
error!("do_op failed -> {:?}", e);
|
||||
LdapResponseState::Disconnect(DisconnectionNotice::gen(
|
||||
LdapResultCode::Other,
|
||||
format!("Internal Server Error {:?}", &eventid).as_str(),
|
||||
|
|
|
@ -50,7 +50,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -58,7 +58,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -71,7 +71,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err=?e, "Failed to begin modify during modify_from_parts");
|
||||
error!(err=?e, "Failed to begin modify during modify_from_parts");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -98,16 +98,15 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
let target_uuid = idms_prox_write
|
||||
.qs_write
|
||||
.name_to_uuid(uuid_or_name)
|
||||
.map_err(|e| {
|
||||
admin_error!("Error resolving id to target");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Error resolving id to target");
|
||||
})?;
|
||||
|
||||
let f_uuid = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(target_uuid)));
|
||||
|
@ -122,7 +121,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify during modify_from_internal_parts");
|
||||
error!(err = ?e, "Failed to begin modify during modify_from_internal_parts");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -152,7 +151,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -188,14 +187,14 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
let mdf = match ModifyEvent::from_message(ident, &req, &mut idms_prox_write.qs_write) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify during handle_modify");
|
||||
error!(err = ?e, "Failed to begin modify during handle_modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -224,13 +223,13 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let del = match DeleteEvent::from_message(ident, &req, &mut idms_prox_write.qs_write) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin delete");
|
||||
error!(err = ?e, "Failed to begin delete");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -261,21 +260,21 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
// Transform the ProtoEntry to a Modlist
|
||||
let modlist =
|
||||
ModifyList::from_patch(&update, &mut idms_prox_write.qs_write).map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid Patch Request");
|
||||
error!(err = ?e, "Invalid Patch Request");
|
||||
e
|
||||
})?;
|
||||
|
||||
let mdf =
|
||||
ModifyEvent::from_internal_parts(ident, &modlist, &filter, &idms_prox_write.qs_write)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Failed to begin modify during handle_internalpatch");
|
||||
error!(err = ?e, "Failed to begin modify during handle_internalpatch");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -303,13 +302,13 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let del = match DeleteEvent::from_parts(ident, &filter, &mut idms_prox_write.qs_write) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin delete");
|
||||
error!(err = ?e, "Failed to begin delete");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -338,13 +337,13 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let rev = match ReviveRecycledEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin revive");
|
||||
error!(err = ?e, "Failed to begin revive");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -373,7 +372,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -386,12 +385,12 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
let gpe = GeneratePasswordEvent::from_parts(ident, target_uuid).map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin handle_service_account_credential_generate",
|
||||
);
|
||||
|
@ -421,7 +420,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -429,7 +428,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -464,7 +463,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -472,7 +471,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -504,7 +503,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -512,7 +511,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -550,7 +549,7 @@ impl QueryServerWriteV1 {
|
|||
return Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
admin_error!(?err, "Invalid identity");
|
||||
error!(?err, "Invalid identity");
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
@ -561,7 +560,7 @@ impl QueryServerWriteV1 {
|
|||
};
|
||||
|
||||
let target = ident.get_uuid().ok_or_else(|| {
|
||||
admin_error!("Invalid identity - no uuid present");
|
||||
error!("Invalid identity - no uuid present");
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
|
||||
|
@ -594,7 +593,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -602,7 +601,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -610,7 +609,7 @@ impl QueryServerWriteV1 {
|
|||
.init_credential_update(&InitCredentialUpdateEvent::new(ident, target_uuid), ct)
|
||||
.and_then(|tok| idms_prox_write.commit().map(|_| tok))
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin init_credential_update",
|
||||
);
|
||||
|
@ -643,7 +642,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -651,7 +650,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -662,7 +661,7 @@ impl QueryServerWriteV1 {
|
|||
)
|
||||
.and_then(|tok| idms_prox_write.commit().map(|_| tok))
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin init_credential_update_intent",
|
||||
);
|
||||
|
@ -693,7 +692,7 @@ impl QueryServerWriteV1 {
|
|||
.exchange_intent_credential_update(intent_token, ct)
|
||||
.and_then(|tok| idms_prox_write.commit().map(|_| tok))
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin exchange_intent_credential_update",
|
||||
);
|
||||
|
@ -733,7 +732,7 @@ impl QueryServerWriteV1 {
|
|||
.commit_credential_update(&session_token, ct)
|
||||
.and_then(|tok| idms_prox_write.commit().map(|_| tok))
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin commit_credential_update",
|
||||
);
|
||||
|
@ -765,7 +764,7 @@ impl QueryServerWriteV1 {
|
|||
.cancel_credential_update(&session_token, ct)
|
||||
.and_then(|tok| idms_prox_write.commit().map(|_| tok))
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin commit_credential_cancel",
|
||||
);
|
||||
|
@ -789,14 +788,14 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let target_uuid = idms_prox_write
|
||||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -821,7 +820,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -829,7 +828,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -839,7 +838,7 @@ impl QueryServerWriteV1 {
|
|||
target_uuid,
|
||||
)
|
||||
.map_err(|e| {
|
||||
admin_error!(
|
||||
error!(
|
||||
err = ?e,
|
||||
"Failed to begin idm_account_regenerate_radius",
|
||||
);
|
||||
|
@ -869,18 +868,18 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let target_uuid = idms_prox_write
|
||||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
let target_attr = Attribute::try_from(attr.as_str())?;
|
||||
let target_attr = Attribute::from(attr.as_str());
|
||||
let mdf = match ModifyEvent::from_target_uuid_attr_purge(
|
||||
ident,
|
||||
target_uuid,
|
||||
|
@ -890,7 +889,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify during purge attribute");
|
||||
error!(err = ?e, "Failed to begin modify during purge attribute");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -922,14 +921,14 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
let target_uuid = idms_prox_write
|
||||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving id to target");
|
||||
error!(err = ?e, "Error resolving id to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -949,7 +948,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1061,24 +1060,24 @@ impl QueryServerWriteV1 {
|
|||
// The filter_map here means we only create the mods if the gidnumber or shell are set
|
||||
// in the actual request.
|
||||
let mods: Vec<_> = iter::once(Some(Modify::Present(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::PosixAccount.into(),
|
||||
)))
|
||||
.chain(iter::once(
|
||||
gidnumber
|
||||
.as_ref()
|
||||
.map(|_| Modify::Purged(Attribute::GidNumber.into())),
|
||||
.map(|_| Modify::Purged(Attribute::GidNumber)),
|
||||
))
|
||||
.chain(iter::once(gidnumber.map(|n| {
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(n))
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(n))
|
||||
})))
|
||||
.chain(iter::once(
|
||||
shell
|
||||
.as_ref()
|
||||
.map(|_| Modify::Purged(Attribute::LoginShell.into())),
|
||||
.map(|_| Modify::Purged(Attribute::LoginShell)),
|
||||
))
|
||||
.chain(iter::once(shell.map(|s| {
|
||||
Modify::Present(Attribute::LoginShell.into(), Value::new_iutf8(s.as_str()))
|
||||
Modify::Present(Attribute::LoginShell, Value::new_iutf8(s.as_str()))
|
||||
})))
|
||||
.flatten()
|
||||
.collect();
|
||||
|
@ -1109,9 +1108,9 @@ impl QueryServerWriteV1 {
|
|||
|
||||
let gidnumber_mods = if let Some(gid) = gx.gidnumber {
|
||||
[
|
||||
Some(Modify::Purged(Attribute::GidNumber.into())),
|
||||
Some(Modify::Purged(Attribute::GidNumber)),
|
||||
Some(Modify::Present(
|
||||
Attribute::GidNumber.into(),
|
||||
Attribute::GidNumber,
|
||||
Value::new_uint32(gid),
|
||||
)),
|
||||
]
|
||||
|
@ -1119,7 +1118,7 @@ impl QueryServerWriteV1 {
|
|||
[None, None]
|
||||
};
|
||||
let mods: Vec<_> = iter::once(Some(Modify::Present(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::PosixGroup.into(),
|
||||
)))
|
||||
.chain(gidnumber_mods)
|
||||
|
@ -1151,7 +1150,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1159,9 +1158,8 @@ impl QueryServerWriteV1 {
|
|||
idms_prox_write
|
||||
.qs_write
|
||||
.name_to_uuid(uuid_or_name.as_str())
|
||||
.map_err(|e| {
|
||||
admin_info!("Error resolving as gidnumber continuing ...");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
info!(?err, "Error resolving as gidnumber continuing ...");
|
||||
})
|
||||
})?;
|
||||
|
||||
|
@ -1172,7 +1170,7 @@ impl QueryServerWriteV1 {
|
|||
cred,
|
||||
)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Failed to begin UnixPasswordChangeEvent");
|
||||
error!(err = ?e, "Failed to begin UnixPasswordChangeEvent");
|
||||
e
|
||||
})?;
|
||||
idms_prox_write
|
||||
|
@ -1240,7 +1238,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1248,7 +1246,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(group.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving group name to target");
|
||||
error!(err = ?e, "Error resolving group name to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1267,7 +1265,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1298,7 +1296,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1306,7 +1304,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(group.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving group name to target");
|
||||
error!(err = ?e, "Error resolving group name to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1321,7 +1319,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1356,7 +1354,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1364,7 +1362,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(group.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving group name to target");
|
||||
error!(err = ?e, "Error resolving group name to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1384,7 +1382,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1418,7 +1416,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1441,7 +1439,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1473,7 +1471,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1481,7 +1479,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(group.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving group name to target");
|
||||
error!(err = ?e, "Error resolving group name to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1498,7 +1496,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1532,7 +1530,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1540,7 +1538,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(group.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving group name to target");
|
||||
error!(err = ?e, "Error resolving group name to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1559,7 +1557,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1590,7 +1588,7 @@ impl QueryServerWriteV1 {
|
|||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1598,7 +1596,7 @@ impl QueryServerWriteV1 {
|
|||
.qs_write
|
||||
.name_to_uuid(group.as_str())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Error resolving group name to target");
|
||||
error!(err = ?e, "Error resolving group name to target");
|
||||
e
|
||||
})?;
|
||||
|
||||
|
@ -1615,7 +1613,7 @@ impl QueryServerWriteV1 {
|
|||
) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
admin_error!(err = ?e, "Failed to begin modify");
|
||||
error!(err = ?e, "Failed to begin modify");
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
@ -1644,9 +1642,8 @@ impl QueryServerWriteV1 {
|
|||
|
||||
let ident = idms_prox_write
|
||||
.validate_client_auth_info_to_ident(client_auth_info, ct)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Invalid identity");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Invalid identity");
|
||||
})?;
|
||||
|
||||
idms_prox_write
|
||||
|
|
|
@ -149,10 +149,7 @@ pub(crate) async fn manifest(DomainInfo(domain_info): DomainInfo) -> impl IntoRe
|
|||
let domain_display_name = domain_info.display_name().to_string();
|
||||
// TODO: fix the None here to make it the request host
|
||||
let manifest_string =
|
||||
match serde_json::to_string_pretty(&manifest_data(None, domain_display_name)) {
|
||||
Ok(val) => val,
|
||||
Err(_) => String::from(""),
|
||||
};
|
||||
serde_json::to_string_pretty(&manifest_data(None, domain_display_name)).unwrap_or_default();
|
||||
let mut res = Response::new(manifest_string);
|
||||
|
||||
res.headers_mut()
|
||||
|
|
|
@ -485,7 +485,7 @@ async fn repl_task(
|
|||
match task {
|
||||
ReplConsumerCtrl::Stop => break,
|
||||
ReplConsumerCtrl::Refresh ( refresh_coord ) => {
|
||||
last_working_address = match repl_run_consumer_refresh(
|
||||
last_working_address = (repl_run_consumer_refresh(
|
||||
refresh_coord,
|
||||
domain,
|
||||
&sorted_socket_addrs,
|
||||
|
@ -493,10 +493,7 @@ async fn repl_task(
|
|||
&idms,
|
||||
&consumer_conn_settings
|
||||
)
|
||||
.await {
|
||||
Ok(val) => val,
|
||||
Err(_) => None
|
||||
};
|
||||
.await).unwrap_or_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,8 +109,12 @@ compact_jwt = { workspace = true, features = ["openssl", "hsm-crypto", "unsafe_r
|
|||
criterion = { workspace = true, features = ["html_reports"] }
|
||||
futures = { workspace = true }
|
||||
kanidmd_lib_macros = { workspace = true }
|
||||
# This is needed so that we can use a test feature across the crate boundary to proto
|
||||
# so we can enable certain hidden test only attributes.
|
||||
kanidm_proto = { workspace = true, features = ["test"] }
|
||||
webauthn-authenticator-rs = { workspace = true }
|
||||
|
||||
|
||||
[target.'cfg(not(target_os = "illumos"))'.dev-dependencies]
|
||||
mimalloc = { workspace = true }
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::time::Duration;
|
|||
|
||||
use nonempty::NonEmpty;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::dbrepl::{DbEntryChangeState, DbReplMeta};
|
||||
|
@ -14,12 +13,12 @@ use crate::prelude::OperationError;
|
|||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DbEntryV1 {
|
||||
pub attrs: BTreeMap<AttrString, NonEmpty<DbValueV1>>,
|
||||
pub attrs: BTreeMap<Attribute, NonEmpty<DbValueV1>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DbEntryV2 {
|
||||
pub attrs: BTreeMap<AttrString, DbValueSetV2>,
|
||||
pub attrs: BTreeMap<Attribute, DbValueSetV2>,
|
||||
}
|
||||
|
||||
// REMEMBER: If you add a new version here, you MUST
|
||||
|
@ -31,7 +30,7 @@ pub enum DbEntryVers {
|
|||
V2(DbEntryV2),
|
||||
V3 {
|
||||
changestate: DbEntryChangeState,
|
||||
attrs: BTreeMap<AttrString, DbValueSetV2>,
|
||||
attrs: BTreeMap<Attribute, DbValueSetV2>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -469,7 +468,7 @@ impl std::fmt::Debug for DbEntry {
|
|||
writeln!(f, "\nlive {at:>32}")?;
|
||||
for (attr, cid) in changes {
|
||||
write!(f, "\n{attr:>32} - {cid} ")?;
|
||||
if let Some(vs) = attrs.get(attr.as_str()) {
|
||||
if let Some(vs) = attrs.get(attr) {
|
||||
write!(f, "{vs:?}")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
|
@ -491,7 +490,7 @@ impl std::fmt::Display for DbEntry {
|
|||
match &self.ent {
|
||||
DbEntryVers::V1(dbe_v1) => {
|
||||
write!(f, "v1 - {{ ")?;
|
||||
match dbe_v1.attrs.get(Attribute::Uuid.as_ref()) {
|
||||
match dbe_v1.attrs.get(&Attribute::Uuid) {
|
||||
Some(uuids) => {
|
||||
for uuid in uuids {
|
||||
write!(f, "{uuid:?}, ")?;
|
||||
|
@ -499,17 +498,17 @@ impl std::fmt::Display for DbEntry {
|
|||
}
|
||||
None => write!(f, "Uuid(INVALID), ")?,
|
||||
};
|
||||
if let Some(names) = dbe_v1.attrs.get(Attribute::Name.as_ref()) {
|
||||
if let Some(names) = dbe_v1.attrs.get(&Attribute::Name) {
|
||||
for name in names {
|
||||
write!(f, "{name:?}, ")?;
|
||||
}
|
||||
}
|
||||
if let Some(names) = dbe_v1.attrs.get(Attribute::AttributeName.as_ref()) {
|
||||
if let Some(names) = dbe_v1.attrs.get(&Attribute::AttributeName) {
|
||||
for name in names {
|
||||
write!(f, "{name:?}, ")?;
|
||||
}
|
||||
}
|
||||
if let Some(names) = dbe_v1.attrs.get(Attribute::ClassName.as_ref()) {
|
||||
if let Some(names) = dbe_v1.attrs.get(&Attribute::ClassName) {
|
||||
for name in names {
|
||||
write!(f, "{name:?}, ")?;
|
||||
}
|
||||
|
@ -518,26 +517,26 @@ impl std::fmt::Display for DbEntry {
|
|||
}
|
||||
DbEntryVers::V2(dbe_v2) => {
|
||||
write!(f, "v2 - {{ ")?;
|
||||
match dbe_v2.attrs.get(Attribute::Uuid.as_ref()) {
|
||||
match dbe_v2.attrs.get(&Attribute::Uuid) {
|
||||
Some(uuids) => {
|
||||
write!(f, "{uuids:?}, ")?;
|
||||
}
|
||||
None => write!(f, "Uuid(INVALID), ")?,
|
||||
};
|
||||
if let Some(names) = dbe_v2.attrs.get(Attribute::Name.as_ref()) {
|
||||
if let Some(names) = dbe_v2.attrs.get(&Attribute::Name) {
|
||||
write!(f, "{names:?}, ")?;
|
||||
}
|
||||
if let Some(names) = dbe_v2.attrs.get(Attribute::AttributeName.as_ref()) {
|
||||
if let Some(names) = dbe_v2.attrs.get(&Attribute::AttributeName) {
|
||||
write!(f, "{names:?}, ")?;
|
||||
}
|
||||
if let Some(names) = dbe_v2.attrs.get(Attribute::ClassName.as_ref()) {
|
||||
if let Some(names) = dbe_v2.attrs.get(&Attribute::ClassName) {
|
||||
write!(f, "{names:?}, ")?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
}
|
||||
DbEntryVers::V3 { changestate, attrs } => {
|
||||
write!(f, "v3 - {{ ")?;
|
||||
match attrs.get(Attribute::Uuid.as_ref()) {
|
||||
match attrs.get(&Attribute::Uuid) {
|
||||
Some(uuids) => {
|
||||
write!(f, "{uuids:?}, ")?;
|
||||
}
|
||||
|
@ -547,13 +546,13 @@ impl std::fmt::Display for DbEntry {
|
|||
match changestate {
|
||||
DbEntryChangeState::V1Live { at, changes: _ } => {
|
||||
write!(f, "created: {at}, ")?;
|
||||
if let Some(names) = attrs.get(Attribute::Name.as_ref()) {
|
||||
if let Some(names) = attrs.get(&Attribute::Name) {
|
||||
write!(f, "{names:?}, ")?;
|
||||
}
|
||||
if let Some(names) = attrs.get(Attribute::AttributeName.as_ref()) {
|
||||
if let Some(names) = attrs.get(&Attribute::AttributeName) {
|
||||
write!(f, "{names:?}, ")?;
|
||||
}
|
||||
if let Some(names) = attrs.get(Attribute::ClassName.as_ref()) {
|
||||
if let Some(names) = attrs.get(&Attribute::ClassName) {
|
||||
write!(f, "{names:?}, ")?;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::dbvalue::DbCidV1;
|
||||
use crate::prelude::entries::Attribute;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -7,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||
pub enum DbEntryChangeState {
|
||||
V1Live {
|
||||
at: DbCidV1,
|
||||
changes: BTreeMap<String, DbCidV1>,
|
||||
changes: BTreeMap<Attribute, DbCidV1>,
|
||||
},
|
||||
V1Tombstone {
|
||||
at: DbCidV1,
|
||||
|
|
|
@ -199,7 +199,7 @@ macro_rules! get_idl {
|
|||
let db_r = $self.db.get_idl($attr, $itype, $idx_key)?;
|
||||
if let Some(ref idl) = db_r {
|
||||
let ncache_key = IdlCacheKey {
|
||||
a: $attr.into(),
|
||||
a: $attr.clone(),
|
||||
i: $itype.clone(),
|
||||
k: $idx_key.into(),
|
||||
};
|
||||
|
@ -346,7 +346,7 @@ pub trait IdlArcSqliteTransaction {
|
|||
|
||||
fn get_idl(
|
||||
&mut self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
) -> Result<Option<IDLBitRange>, OperationError>;
|
||||
|
@ -404,7 +404,7 @@ impl<'a> IdlArcSqliteTransaction for IdlArcSqliteReadTransaction<'a> {
|
|||
#[instrument(level = "trace", skip_all)]
|
||||
fn get_idl(
|
||||
&mut self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
) -> Result<Option<IDLBitRange>, OperationError> {
|
||||
|
@ -499,7 +499,7 @@ impl<'a> IdlArcSqliteTransaction for IdlArcSqliteWriteTransaction<'a> {
|
|||
#[instrument(level = "trace", skip_all)]
|
||||
fn get_idl(
|
||||
&mut self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
) -> Result<Option<IDLBitRange>, OperationError> {
|
||||
|
@ -626,7 +626,7 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
.iter_mut_mark_clean()
|
||||
.try_for_each(|(k, v)| {
|
||||
match v {
|
||||
Some(idl) => db.write_idl(k.a.as_str(), k.i, k.k.as_str(), idl),
|
||||
Some(idl) => db.write_idl(&k.a, k.i, k.k.as_str(), idl),
|
||||
#[allow(clippy::unreachable)]
|
||||
None => {
|
||||
// Due to how we remove items, we always write an empty idl
|
||||
|
@ -759,13 +759,13 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
|
||||
pub fn write_idl(
|
||||
&mut self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
idl: &IDLBitRange,
|
||||
) -> Result<(), OperationError> {
|
||||
let cache_key = IdlCacheKey {
|
||||
a: attr.into(),
|
||||
a: attr.clone(),
|
||||
i: itype,
|
||||
k: idx_key.into(),
|
||||
};
|
||||
|
@ -1127,7 +1127,7 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_idx(&self, attr: Attribute, itype: IndexType) -> Result<(), OperationError> {
|
||||
pub fn create_idx(&self, attr: &Attribute, itype: IndexType) -> Result<(), OperationError> {
|
||||
// We don't need to affect this, so pass it down.
|
||||
self.db.create_idx(attr, itype)
|
||||
}
|
||||
|
|
|
@ -219,15 +219,15 @@ pub(crate) trait IdlSqliteTransaction {
|
|||
}
|
||||
}
|
||||
|
||||
fn exists_idx(&self, attr: &str, itype: IndexType) -> Result<bool, OperationError> {
|
||||
let tname = format!("idx_{}_{}", itype.as_idx_str(), attr);
|
||||
fn exists_idx(&self, attr: &Attribute, itype: IndexType) -> Result<bool, OperationError> {
|
||||
let tname = format!("idx_{}_{}", itype.as_idx_str(), attr.as_str());
|
||||
self.exists_table(&tname)
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip_all)]
|
||||
fn get_idl(
|
||||
&self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
) -> Result<Option<IDLBitRange>, OperationError> {
|
||||
|
@ -244,7 +244,7 @@ pub(crate) trait IdlSqliteTransaction {
|
|||
"SELECT idl FROM {}.idx_{}_{} WHERE key = :idx_key",
|
||||
self.get_db_name(),
|
||||
itype.as_idx_str(),
|
||||
attr
|
||||
attr.as_str()
|
||||
);
|
||||
let mut stmt = self.get_conn()?.prepare(&query).map_err(sqlite_error)?;
|
||||
let idl_raw: Option<Vec<u8>> = stmt
|
||||
|
@ -867,7 +867,7 @@ impl IdlSqliteWriteTransaction {
|
|||
|
||||
pub fn write_idl(
|
||||
&self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
idl: &IDLBitRange,
|
||||
|
@ -879,7 +879,7 @@ impl IdlSqliteWriteTransaction {
|
|||
"DELETE FROM {}.idx_{}_{} WHERE key = :key",
|
||||
self.get_db_name(),
|
||||
itype.as_idx_str(),
|
||||
attr
|
||||
attr.as_str()
|
||||
);
|
||||
|
||||
self.get_conn()?
|
||||
|
@ -895,7 +895,7 @@ impl IdlSqliteWriteTransaction {
|
|||
"INSERT OR REPLACE INTO {}.idx_{}_{} (key, idl) VALUES(:key, :idl)",
|
||||
self.get_db_name(),
|
||||
itype.as_idx_str(),
|
||||
attr
|
||||
attr.as_str()
|
||||
);
|
||||
|
||||
self.get_conn()?
|
||||
|
@ -1205,7 +1205,7 @@ impl IdlSqliteWriteTransaction {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn create_idx(&self, attr: Attribute, itype: IndexType) -> Result<(), OperationError> {
|
||||
pub fn create_idx(&self, attr: &Attribute, itype: IndexType) -> Result<(), OperationError> {
|
||||
// Is there a better way than formatting this? I can't seem
|
||||
// to template into the str.
|
||||
//
|
||||
|
@ -1214,7 +1214,7 @@ impl IdlSqliteWriteTransaction {
|
|||
"CREATE TABLE IF NOT EXISTS {}.idx_{}_{} (key TEXT PRIMARY KEY, idl BLOB)",
|
||||
self.get_db_name(),
|
||||
itype.as_idx_str(),
|
||||
attr
|
||||
attr.as_str(),
|
||||
);
|
||||
|
||||
self.get_conn()?
|
||||
|
|
|
@ -1,45 +1,39 @@
|
|||
use crate::prelude::entries::Attribute;
|
||||
use crate::value::IndexType;
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use smartstring::alias::String as AttrString;
|
||||
|
||||
use crate::prelude::entries::Attribute;
|
||||
use crate::value::IndexType;
|
||||
|
||||
pub type IdxSlope = u8;
|
||||
|
||||
// Huge props to https://github.com/sunshowers/borrow-complex-key-example/blob/master/src/lib.rs
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct IdxKey {
|
||||
pub attr: AttrString,
|
||||
pub attr: Attribute,
|
||||
pub itype: IndexType,
|
||||
}
|
||||
|
||||
impl IdxKey {
|
||||
pub fn new(attr: Attribute, itype: IndexType) -> Self {
|
||||
IdxKey {
|
||||
attr: attr.into(),
|
||||
itype,
|
||||
}
|
||||
IdxKey { attr, itype }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct IdxKeyRef<'a> {
|
||||
pub attr: &'a str,
|
||||
pub attr: &'a Attribute,
|
||||
pub itype: &'a IndexType,
|
||||
}
|
||||
|
||||
impl<'a> IdxKeyRef<'a> {
|
||||
pub fn new(attr: &'a str, itype: &'a IndexType) -> Self {
|
||||
pub fn new(attr: &'a Attribute, itype: &'a IndexType) -> Self {
|
||||
IdxKeyRef { attr, itype }
|
||||
}
|
||||
|
||||
pub fn as_key(&self) -> IdxKey {
|
||||
IdxKey {
|
||||
attr: self.attr.into(),
|
||||
attr: self.attr.clone(),
|
||||
itype: *self.itype,
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +53,7 @@ impl<'a> IdxKeyToRef for IdxKeyRef<'a> {
|
|||
impl IdxKeyToRef for IdxKey {
|
||||
fn keyref(&self) -> IdxKeyRef<'_> {
|
||||
IdxKeyRef {
|
||||
attr: self.attr.as_str(),
|
||||
attr: &self.attr,
|
||||
itype: &self.itype,
|
||||
}
|
||||
}
|
||||
|
@ -89,14 +83,14 @@ impl<'a> Hash for (dyn IdxKeyToRef + 'a) {
|
|||
|
||||
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
pub struct IdlCacheKey {
|
||||
pub a: AttrString,
|
||||
pub a: Attribute,
|
||||
pub i: IndexType,
|
||||
pub k: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
pub struct IdlCacheKeyRef<'a> {
|
||||
pub a: &'a str,
|
||||
pub a: &'a Attribute,
|
||||
pub i: IndexType,
|
||||
pub k: &'a str,
|
||||
}
|
||||
|
@ -123,7 +117,7 @@ impl<'a> IdlCacheKeyToRef for IdlCacheKeyRef<'a> {
|
|||
impl IdlCacheKeyToRef for IdlCacheKey {
|
||||
fn keyref(&self) -> IdlCacheKeyRef<'_> {
|
||||
IdlCacheKeyRef {
|
||||
a: self.a.as_str(),
|
||||
a: &self.a,
|
||||
i: self.i,
|
||||
k: self.k.as_str(),
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ use hashbrown::{HashMap as Map, HashSet};
|
|||
use idlset::v2::IDLBitRange;
|
||||
use idlset::AndNot;
|
||||
use kanidm_proto::internal::{ConsistencyError, OperationError};
|
||||
use smartstring::alias::String as AttrString;
|
||||
use tracing::{trace, trace_span};
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -566,7 +565,7 @@ pub trait BackendTransaction {
|
|||
|
||||
fn filter2idl_sub(
|
||||
&mut self,
|
||||
attr: &AttrString,
|
||||
attr: &Attribute,
|
||||
sub_idx_key: String,
|
||||
) -> Result<(IdList, FilterPlan), OperationError> {
|
||||
// Now given that idx_key, we will iterate over the possible graphemes.
|
||||
|
@ -1209,11 +1208,9 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
let ctx_ent_uuid = ctx_ent.get_uuid();
|
||||
let idx_key = ctx_ent_uuid.as_hyphenated().to_string();
|
||||
|
||||
let idl = self.get_idlayer().get_idl(
|
||||
Attribute::Uuid.as_ref(),
|
||||
IndexType::Equality,
|
||||
&idx_key,
|
||||
)?;
|
||||
let idl =
|
||||
self.get_idlayer()
|
||||
.get_idl(&Attribute::Uuid, IndexType::Equality, &idx_key)?;
|
||||
|
||||
let entry = match idl {
|
||||
Some(idl) if idl.is_empty() => {
|
||||
|
@ -1591,7 +1588,7 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
Some(mut idl) => {
|
||||
idl.insert_id(e_id);
|
||||
if cfg!(debug_assertions)
|
||||
&& attr == Attribute::Uuid.as_ref() && itype == IndexType::Equality {
|
||||
&& *attr == Attribute::Uuid && itype == IndexType::Equality {
|
||||
// This means a duplicate UUID has appeared in the index.
|
||||
if idl.len() > 1 {
|
||||
trace!(duplicate_idl = ?idl, ?idx_key);
|
||||
|
@ -1614,7 +1611,7 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
match self.idlayer.get_idl(attr, itype, &idx_key)? {
|
||||
Some(mut idl) => {
|
||||
idl.remove_id(e_id);
|
||||
if cfg!(debug_assertions) && attr == Attribute::Uuid.as_ref() && itype == IndexType::Equality {
|
||||
if cfg!(debug_assertions) && *attr == Attribute::Uuid && itype == IndexType::Equality {
|
||||
// This means a duplicate UUID has appeared in the index.
|
||||
if idl.len() > 1 {
|
||||
trace!(duplicate_idl = ?idl, ?idx_key);
|
||||
|
@ -1638,7 +1635,7 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn missing_idxs(&mut self) -> Result<Vec<(AttrString, IndexType)>, OperationError> {
|
||||
fn missing_idxs(&mut self) -> Result<Vec<(Attribute, IndexType)>, OperationError> {
|
||||
let idx_table_list = self.get_idlayer().list_idxs()?;
|
||||
|
||||
// Turn the vec to a real set
|
||||
|
@ -1677,10 +1674,10 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
trace!("Creating index -> uuid2rdn");
|
||||
self.idlayer.create_uuid2rdn()?;
|
||||
|
||||
self.idxmeta_wr.idxkeys.keys().try_for_each(|ikey| {
|
||||
let attr: Attribute = (&ikey.attr).try_into()?;
|
||||
self.idlayer.create_idx(attr, ikey.itype)
|
||||
})
|
||||
self.idxmeta_wr
|
||||
.idxkeys
|
||||
.keys()
|
||||
.try_for_each(|ikey| self.idlayer.create_idx(&ikey.attr, ikey.itype))
|
||||
}
|
||||
|
||||
pub fn upgrade_reindex(&mut self, v: i64) -> Result<(), OperationError> {
|
||||
|
@ -1765,7 +1762,7 @@ impl<'a> BackendWriteTransaction<'a> {
|
|||
#[cfg(test)]
|
||||
pub fn load_test_idl(
|
||||
&mut self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
itype: IndexType,
|
||||
idx_key: &str,
|
||||
) -> Result<Option<IDLBitRange>, OperationError> {
|
||||
|
@ -2297,7 +2294,7 @@ mod tests {
|
|||
macro_rules! idl_state {
|
||||
($be:expr, $attr:expr, $itype:expr, $idx_key:expr, $expect:expr) => {{
|
||||
let t_idl = $be
|
||||
.load_test_idl(&$attr.to_string(), $itype, &$idx_key.to_string())
|
||||
.load_test_idl(&$attr, $itype, &$idx_key.to_string())
|
||||
.expect("IdList Load failed");
|
||||
let t = $expect.map(|v: Vec<u64>| IDLBitRange::from_iter(v));
|
||||
assert_eq!(t_idl, t);
|
||||
|
@ -2745,7 +2742,7 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
IndexType::Equality,
|
||||
"william",
|
||||
Some(vec![1])
|
||||
|
@ -2753,7 +2750,7 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
IndexType::Equality,
|
||||
"claire",
|
||||
Some(vec![2])
|
||||
|
@ -2764,7 +2761,7 @@ mod tests {
|
|||
] {
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
IndexType::SubString,
|
||||
sub,
|
||||
Some(vec![1])
|
||||
|
@ -2776,7 +2773,7 @@ mod tests {
|
|||
] {
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
IndexType::SubString,
|
||||
sub,
|
||||
Some(vec![2])
|
||||
|
@ -2786,7 +2783,7 @@ mod tests {
|
|||
for sub in ["i", "a", "l"] {
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
IndexType::SubString,
|
||||
sub,
|
||||
Some(vec![1, 2])
|
||||
|
@ -2795,7 +2792,7 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
IndexType::Presence,
|
||||
"_",
|
||||
Some(vec![1, 2])
|
||||
|
@ -2803,7 +2800,7 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Uuid.as_ref(),
|
||||
Attribute::Uuid,
|
||||
IndexType::Equality,
|
||||
"db237e8a-0079-4b8c-8a56-593b22aa44d1",
|
||||
Some(vec![1])
|
||||
|
@ -2811,7 +2808,7 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Uuid.as_ref(),
|
||||
Attribute::Uuid,
|
||||
IndexType::Equality,
|
||||
"bd651620-00dd-426b-aaa0-4494f7b7906f",
|
||||
Some(vec![2])
|
||||
|
@ -2819,7 +2816,7 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Uuid.as_ref(),
|
||||
Attribute::Uuid,
|
||||
IndexType::Presence,
|
||||
"_",
|
||||
Some(vec![1, 2])
|
||||
|
@ -2829,7 +2826,7 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
IndexType::Equality,
|
||||
"not-exist",
|
||||
Some(Vec::with_capacity(0))
|
||||
|
@ -2837,14 +2834,14 @@ mod tests {
|
|||
|
||||
idl_state!(
|
||||
be,
|
||||
Attribute::Uuid.as_ref(),
|
||||
Attribute::Uuid,
|
||||
IndexType::Equality,
|
||||
"fake-0079-4b8c-8a56-593b22aa44d1",
|
||||
Some(Vec::with_capacity(0))
|
||||
);
|
||||
|
||||
let uuid_p_idl = be
|
||||
.load_test_idl("not_indexed", IndexType::Presence, "_")
|
||||
.load_test_idl(&Attribute::from("not_indexed"), IndexType::Presence, "_")
|
||||
.unwrap(); // unwrap the result
|
||||
assert_eq!(uuid_p_idl, None);
|
||||
|
||||
|
@ -3683,7 +3680,7 @@ mod tests {
|
|||
|
||||
assert!(single_result.is_ok());
|
||||
let filt = e
|
||||
.filter_from_attrs(&[Attribute::NonExist.into()])
|
||||
.filter_from_attrs(&[Attribute::NonExist])
|
||||
.expect("failed to generate filter")
|
||||
.into_valid_resolved();
|
||||
// check allow on allids
|
||||
|
@ -3721,7 +3718,7 @@ mod tests {
|
|||
assert!(single_result.is_ok());
|
||||
|
||||
let filt = e
|
||||
.filter_from_attrs(&[Attribute::NonExist.into()])
|
||||
.filter_from_attrs(&[Attribute::NonExist])
|
||||
.expect("failed to generate filter")
|
||||
.into_valid_resolved();
|
||||
|
||||
|
@ -3824,7 +3821,7 @@ mod tests {
|
|||
|
||||
// This is a demo idxmeta, purely for testing.
|
||||
let idxmeta = vec![IdxKey {
|
||||
attr: Attribute::Uuid.into(),
|
||||
attr: Attribute::Uuid,
|
||||
itype: IndexType::Equality,
|
||||
}];
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -76,7 +76,7 @@ pub struct SearchEvent {
|
|||
pub filter: Filter<FilterValid>,
|
||||
// This is the original filter, for the purpose of ACI checking.
|
||||
pub filter_orig: Filter<FilterValid>,
|
||||
pub attrs: Option<BTreeSet<AttrString>>,
|
||||
pub attrs: Option<BTreeSet<Attribute>>,
|
||||
}
|
||||
|
||||
impl SearchEvent {
|
||||
|
@ -108,7 +108,7 @@ impl SearchEvent {
|
|||
attrs: Option<&[String]>,
|
||||
qs: &mut QueryServerReadTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
let r_attrs: Option<BTreeSet<AttrString>> = attrs.map(|vs| {
|
||||
let r_attrs: Option<BTreeSet<Attribute>> = attrs.map(|vs| {
|
||||
vs.iter()
|
||||
.filter_map(|a| qs.get_schema().normalise_attr_if_exists(a.as_str()))
|
||||
.collect()
|
||||
|
@ -141,9 +141,13 @@ impl SearchEvent {
|
|||
attrs: Option<&[String]>,
|
||||
qs: &QueryServerReadTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
let r_attrs: Option<BTreeSet<AttrString>> = attrs.map(|vs| {
|
||||
let r_attrs: Option<BTreeSet<Attribute>> = attrs.map(|vs| {
|
||||
vs.iter()
|
||||
.filter_map(|a| qs.get_schema().normalise_attr_if_exists(a.as_str()))
|
||||
.filter_map(|a| {
|
||||
qs.get_schema()
|
||||
.normalise_attr_if_exists(a.as_str())
|
||||
.map(|a_str| Attribute::from(a_str.as_str()))
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
|
@ -293,7 +297,7 @@ impl SearchEvent {
|
|||
qs: &mut QueryServerReadTransaction,
|
||||
ident: Identity,
|
||||
lf: &LdapFilter,
|
||||
attrs: Option<BTreeSet<AttrString>>,
|
||||
attrs: Option<BTreeSet<Attribute>>,
|
||||
) -> Result<Self, OperationError> {
|
||||
// Kanidm Filter from LdapFilter
|
||||
let f = Filter::from_ldap_ro(&ident, lf, qs)?;
|
||||
|
|
|
@ -24,7 +24,6 @@ use hashbrown::HashSet;
|
|||
use kanidm_proto::constants::ATTR_UUID;
|
||||
use kanidm_proto::internal::{Filter as ProtoFilter, OperationError, SchemaError};
|
||||
use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter};
|
||||
// use smartstring::alias::String as AttrString;
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -48,20 +47,20 @@ pub type ResolveFilterCacheReadTxn<'a> = ARCacheReadTxn<
|
|||
|
||||
// This is &Value so we can lazy const then clone, but perhaps we can reconsider
|
||||
// later if this should just take Value.
|
||||
pub fn f_eq<'a>(a: Attribute, v: PartialValue) -> FC<'a> {
|
||||
FC::Eq(a.into(), v)
|
||||
pub fn f_eq(a: Attribute, v: PartialValue) -> FC {
|
||||
FC::Eq(a, v)
|
||||
}
|
||||
|
||||
pub fn f_sub<'a>(a: Attribute, v: PartialValue) -> FC<'a> {
|
||||
FC::Cnt(a.into(), v)
|
||||
pub fn f_sub(a: Attribute, v: PartialValue) -> FC {
|
||||
FC::Cnt(a, v)
|
||||
}
|
||||
|
||||
pub fn f_pres<'a>(a: Attribute) -> FC<'a> {
|
||||
FC::Pres(a.into())
|
||||
pub fn f_pres(a: Attribute) -> FC {
|
||||
FC::Pres(a)
|
||||
}
|
||||
|
||||
pub fn f_lt<'a>(a: Attribute, v: PartialValue) -> FC<'a> {
|
||||
FC::LessThan(a.into(), v)
|
||||
pub fn f_lt(a: Attribute, v: PartialValue) -> FC {
|
||||
FC::LessThan(a, v)
|
||||
}
|
||||
|
||||
pub fn f_or(vs: Vec<FC>) -> FC {
|
||||
|
@ -80,16 +79,16 @@ pub fn f_andnot(fc: FC) -> FC {
|
|||
FC::AndNot(Box::new(fc))
|
||||
}
|
||||
|
||||
pub fn f_self<'a>() -> FC<'a> {
|
||||
pub fn f_self() -> FC {
|
||||
FC::SelfUuid
|
||||
}
|
||||
|
||||
pub fn f_id(uuid: &str) -> FC<'static> {
|
||||
pub fn f_id(uuid: &str) -> FC {
|
||||
let uf = Uuid::parse_str(uuid)
|
||||
.ok()
|
||||
.map(|u| FC::Eq(Attribute::Uuid.as_ref(), PartialValue::Uuid(u)));
|
||||
let spnf = PartialValue::new_spn_s(uuid).map(|spn| FC::Eq(Attribute::Spn.as_ref(), spn));
|
||||
let nf = FC::Eq(Attribute::Name.as_ref(), PartialValue::new_iname(uuid));
|
||||
.map(|u| FC::Eq(Attribute::Uuid, PartialValue::Uuid(u)));
|
||||
let spnf = PartialValue::new_spn_s(uuid).map(|spn| FC::Eq(Attribute::Spn, spn));
|
||||
let nf = FC::Eq(Attribute::Name, PartialValue::new_iname(uuid));
|
||||
let f: Vec<_> = iter::once(uf)
|
||||
.chain(iter::once(spnf))
|
||||
.flatten()
|
||||
|
@ -98,9 +97,9 @@ pub fn f_id(uuid: &str) -> FC<'static> {
|
|||
FC::Or(f)
|
||||
}
|
||||
|
||||
pub fn f_spn_name(id: &str) -> FC<'static> {
|
||||
let spnf = PartialValue::new_spn_s(id).map(|spn| FC::Eq(Attribute::Spn.as_ref(), spn));
|
||||
let nf = FC::Eq(Attribute::Name.as_ref(), PartialValue::new_iname(id));
|
||||
pub fn f_spn_name(id: &str) -> FC {
|
||||
let spnf = PartialValue::new_spn_s(id).map(|spn| FC::Eq(Attribute::Spn, spn));
|
||||
let nf = FC::Eq(Attribute::Name, PartialValue::new_iname(id));
|
||||
let f: Vec<_> = iter::once(spnf).flatten().chain(iter::once(nf)).collect();
|
||||
FC::Or(f)
|
||||
}
|
||||
|
@ -108,15 +107,15 @@ pub fn f_spn_name(id: &str) -> FC<'static> {
|
|||
/// This is the short-form for tests and internal filters that can then
|
||||
/// be transformed into a filter for the server to use.
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub enum FC<'a> {
|
||||
Eq(&'a str, PartialValue),
|
||||
Cnt(&'a str, PartialValue),
|
||||
Pres(&'a str),
|
||||
LessThan(&'a str, PartialValue),
|
||||
Or(Vec<FC<'a>>),
|
||||
And(Vec<FC<'a>>),
|
||||
Inclusion(Vec<FC<'a>>),
|
||||
AndNot(Box<FC<'a>>),
|
||||
pub enum FC {
|
||||
Eq(Attribute, PartialValue),
|
||||
Cnt(Attribute, PartialValue),
|
||||
Pres(Attribute),
|
||||
LessThan(Attribute, PartialValue),
|
||||
Or(Vec<FC>),
|
||||
And(Vec<FC>),
|
||||
Inclusion(Vec<FC>),
|
||||
AndNot(Box<FC>),
|
||||
SelfUuid,
|
||||
// Not(Box<FC>),
|
||||
}
|
||||
|
@ -125,12 +124,12 @@ pub enum FC<'a> {
|
|||
#[derive(Clone, Hash, PartialEq, PartialOrd, Ord, Eq)]
|
||||
enum FilterComp {
|
||||
// This is attr - value
|
||||
Eq(AttrString, PartialValue),
|
||||
Cnt(AttrString, PartialValue),
|
||||
Stw(AttrString, PartialValue),
|
||||
Enw(AttrString, PartialValue),
|
||||
Pres(AttrString),
|
||||
LessThan(AttrString, PartialValue),
|
||||
Eq(Attribute, PartialValue),
|
||||
Cnt(Attribute, PartialValue),
|
||||
Stw(Attribute, PartialValue),
|
||||
Enw(Attribute, PartialValue),
|
||||
Pres(Attribute),
|
||||
LessThan(Attribute, PartialValue),
|
||||
Or(Vec<FilterComp>),
|
||||
And(Vec<FilterComp>),
|
||||
Inclusion(Vec<FilterComp>),
|
||||
|
@ -214,12 +213,12 @@ impl fmt::Debug for FilterComp {
|
|||
#[derive(Clone, Eq)]
|
||||
pub enum FilterResolved {
|
||||
// This is attr - value - indexed slope factor
|
||||
Eq(AttrString, PartialValue, Option<NonZeroU8>),
|
||||
Cnt(AttrString, PartialValue, Option<NonZeroU8>),
|
||||
Stw(AttrString, PartialValue, Option<NonZeroU8>),
|
||||
Enw(AttrString, PartialValue, Option<NonZeroU8>),
|
||||
Pres(AttrString, Option<NonZeroU8>),
|
||||
LessThan(AttrString, PartialValue, Option<NonZeroU8>),
|
||||
Eq(Attribute, PartialValue, Option<NonZeroU8>),
|
||||
Cnt(Attribute, PartialValue, Option<NonZeroU8>),
|
||||
Stw(Attribute, PartialValue, Option<NonZeroU8>),
|
||||
Enw(Attribute, PartialValue, Option<NonZeroU8>),
|
||||
Pres(Attribute, Option<NonZeroU8>),
|
||||
LessThan(Attribute, PartialValue, Option<NonZeroU8>),
|
||||
Or(Vec<FilterResolved>, Option<NonZeroU8>),
|
||||
And(Vec<FilterResolved>, Option<NonZeroU8>),
|
||||
// All terms must have 1 or more items, or the inclusion is false!
|
||||
|
@ -335,16 +334,16 @@ pub struct FilterValidResolved {
|
|||
#[derive(Debug)]
|
||||
pub enum FilterPlan {
|
||||
Invalid,
|
||||
EqIndexed(AttrString, String),
|
||||
EqUnindexed(AttrString),
|
||||
EqCorrupt(AttrString),
|
||||
SubIndexed(AttrString, String),
|
||||
SubUnindexed(AttrString),
|
||||
SubCorrupt(AttrString),
|
||||
PresIndexed(AttrString),
|
||||
PresUnindexed(AttrString),
|
||||
PresCorrupt(AttrString),
|
||||
LessThanUnindexed(AttrString),
|
||||
EqIndexed(Attribute, String),
|
||||
EqUnindexed(Attribute),
|
||||
EqCorrupt(Attribute),
|
||||
SubIndexed(Attribute, String),
|
||||
SubUnindexed(Attribute),
|
||||
SubCorrupt(Attribute),
|
||||
PresIndexed(Attribute),
|
||||
PresUnindexed(Attribute),
|
||||
PresCorrupt(Attribute),
|
||||
LessThanUnindexed(Attribute),
|
||||
OrUnindexed(Vec<FilterPlan>),
|
||||
OrIndexed(Vec<FilterPlan>),
|
||||
OrPartial(Vec<FilterPlan>),
|
||||
|
@ -520,7 +519,7 @@ impl Filter<FilterValid> {
|
|||
Ok(resolved_filt)
|
||||
}
|
||||
|
||||
pub fn get_attr_set(&self) -> BTreeSet<&str> {
|
||||
pub fn get_attr_set(&self) -> BTreeSet<Attribute> {
|
||||
// Recurse through the filter getting an attribute set.
|
||||
let mut r_set = BTreeSet::new();
|
||||
self.state.inner.get_attr_set(&mut r_set);
|
||||
|
@ -603,19 +602,19 @@ impl Filter<FilterInvalid> {
|
|||
// some core test idxs faster. This is never used in production, it's JUST for
|
||||
// test case speedups.
|
||||
let idxmeta = vec![
|
||||
(Attribute::Uuid.into(), IndexType::Equality),
|
||||
(Attribute::Uuid.into(), IndexType::Presence),
|
||||
(Attribute::Name.into(), IndexType::Equality),
|
||||
(Attribute::Name.into(), IndexType::SubString),
|
||||
(Attribute::Name.into(), IndexType::Presence),
|
||||
(Attribute::Class.into(), IndexType::Equality),
|
||||
(Attribute::Class.into(), IndexType::Presence),
|
||||
(Attribute::Member.into(), IndexType::Equality),
|
||||
(Attribute::Member.into(), IndexType::Presence),
|
||||
(Attribute::MemberOf.into(), IndexType::Equality),
|
||||
(Attribute::MemberOf.into(), IndexType::Presence),
|
||||
(Attribute::DirectMemberOf.into(), IndexType::Equality),
|
||||
(Attribute::DirectMemberOf.into(), IndexType::Presence),
|
||||
(Attribute::Uuid, IndexType::Equality),
|
||||
(Attribute::Uuid, IndexType::Presence),
|
||||
(Attribute::Name, IndexType::Equality),
|
||||
(Attribute::Name, IndexType::SubString),
|
||||
(Attribute::Name, IndexType::Presence),
|
||||
(Attribute::Class, IndexType::Equality),
|
||||
(Attribute::Class, IndexType::Presence),
|
||||
(Attribute::Member, IndexType::Equality),
|
||||
(Attribute::Member, IndexType::Presence),
|
||||
(Attribute::MemberOf, IndexType::Equality),
|
||||
(Attribute::MemberOf, IndexType::Presence),
|
||||
(Attribute::DirectMemberOf, IndexType::Equality),
|
||||
(Attribute::DirectMemberOf, IndexType::Presence),
|
||||
];
|
||||
|
||||
let idxmeta_ref = idxmeta.iter().map(|(attr, itype)| (attr, itype)).collect();
|
||||
|
@ -721,10 +720,10 @@ impl FromStr for Filter<FilterInvalid> {
|
|||
impl FilterComp {
|
||||
fn new(fc: FC) -> Self {
|
||||
match fc {
|
||||
FC::Eq(a, v) => FilterComp::Eq(AttrString::from(a), v),
|
||||
FC::Cnt(a, v) => FilterComp::Cnt(AttrString::from(a), v),
|
||||
FC::Pres(a) => FilterComp::Pres(AttrString::from(a)),
|
||||
FC::LessThan(a, v) => FilterComp::LessThan(AttrString::from(a), v),
|
||||
FC::Eq(a, v) => FilterComp::Eq(a, v),
|
||||
FC::Cnt(a, v) => FilterComp::Cnt(a, v),
|
||||
FC::Pres(a) => FilterComp::Pres(a),
|
||||
FC::LessThan(a, v) => FilterComp::LessThan(a, v),
|
||||
FC::Or(v) => FilterComp::Or(v.into_iter().map(FilterComp::new).collect()),
|
||||
FC::And(v) => FilterComp::And(v.into_iter().map(FilterComp::new).collect()),
|
||||
FC::Inclusion(v) => FilterComp::Inclusion(v.into_iter().map(FilterComp::new).collect()),
|
||||
|
@ -736,8 +735,8 @@ impl FilterComp {
|
|||
fn new_ignore_hidden(fc: FilterComp) -> Self {
|
||||
FilterComp::And(vec![
|
||||
FilterComp::AndNot(Box::new(FilterComp::Or(vec![
|
||||
FilterComp::Eq(Attribute::Class.into(), EntryClass::Tombstone.into()),
|
||||
FilterComp::Eq(Attribute::Class.into(), EntryClass::Recycled.into()),
|
||||
FilterComp::Eq(Attribute::Class, EntryClass::Tombstone.into()),
|
||||
FilterComp::Eq(Attribute::Class, EntryClass::Recycled.into()),
|
||||
]))),
|
||||
fc,
|
||||
])
|
||||
|
@ -745,12 +744,12 @@ impl FilterComp {
|
|||
|
||||
fn new_recycled(fc: FilterComp) -> Self {
|
||||
FilterComp::And(vec![
|
||||
FilterComp::Eq(Attribute::Class.into(), EntryClass::Recycled.into()),
|
||||
FilterComp::Eq(Attribute::Class, EntryClass::Recycled.into()),
|
||||
fc,
|
||||
])
|
||||
}
|
||||
|
||||
fn get_attr_set<'a>(&'a self, r_set: &mut BTreeSet<&'a str>) {
|
||||
fn get_attr_set(&self, r_set: &mut BTreeSet<Attribute>) {
|
||||
match self {
|
||||
FilterComp::Eq(attr, _)
|
||||
| FilterComp::Cnt(attr, _)
|
||||
|
@ -758,14 +757,14 @@ impl FilterComp {
|
|||
| FilterComp::Enw(attr, _)
|
||||
| FilterComp::Pres(attr)
|
||||
| FilterComp::LessThan(attr, _) => {
|
||||
r_set.insert(attr.as_str());
|
||||
r_set.insert(attr.clone());
|
||||
}
|
||||
FilterComp::Or(vs) => vs.iter().for_each(|f| f.get_attr_set(r_set)),
|
||||
FilterComp::And(vs) => vs.iter().for_each(|f| f.get_attr_set(r_set)),
|
||||
FilterComp::Inclusion(vs) => vs.iter().for_each(|f| f.get_attr_set(r_set)),
|
||||
FilterComp::AndNot(f) => f.get_attr_set(r_set),
|
||||
FilterComp::SelfUuid => {
|
||||
r_set.insert(ATTR_UUID);
|
||||
r_set.insert(Attribute::Uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -784,89 +783,74 @@ impl FilterComp {
|
|||
|
||||
match self {
|
||||
FilterComp::Eq(attr, value) => {
|
||||
// Validate/normalise the attr name.
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
// Now check it exists
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
// Check the requested attribute exists, and this PV type matches something
|
||||
// that can be queried of the attribute.
|
||||
match schema_attributes.get(attr) {
|
||||
Some(schema_a) => {
|
||||
schema_a
|
||||
.validate_partialvalue(attr_norm.as_str(), value)
|
||||
.validate_partialvalue(attr, value)
|
||||
// Okay, it worked, transform to a filter component
|
||||
.map(|_| FilterComp::Eq(attr_norm, value.clone()))
|
||||
.map(|_| FilterComp::Eq(attr.clone(), value.clone()))
|
||||
// On error, pass the error back out.
|
||||
}
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
}
|
||||
}
|
||||
FilterComp::Cnt(attr, value) => {
|
||||
// Validate/normalise the attr name.
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
// Now check it exists
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
match schema_attributes.get(attr) {
|
||||
Some(schema_a) => {
|
||||
schema_a
|
||||
.validate_partialvalue(attr_norm.as_str(), value)
|
||||
.validate_partialvalue(attr, value)
|
||||
// Okay, it worked, transform to a filter component
|
||||
.map(|_| FilterComp::Cnt(attr_norm, value.clone()))
|
||||
.map(|_| FilterComp::Cnt(attr.clone(), value.clone()))
|
||||
// On error, pass the error back out.
|
||||
}
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
}
|
||||
}
|
||||
FilterComp::Stw(attr, value) => {
|
||||
// Validate/normalise the attr name.
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
// Now check it exists
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
match schema_attributes.get(attr) {
|
||||
Some(schema_a) => {
|
||||
schema_a
|
||||
.validate_partialvalue(attr_norm.as_str(), value)
|
||||
.validate_partialvalue(attr, value)
|
||||
// Okay, it worked, transform to a filter component
|
||||
.map(|_| FilterComp::Stw(attr_norm, value.clone()))
|
||||
.map(|_| FilterComp::Stw(attr.clone(), value.clone()))
|
||||
// On error, pass the error back out.
|
||||
}
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
}
|
||||
}
|
||||
FilterComp::Enw(attr, value) => {
|
||||
// Validate/normalise the attr name.
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
// Now check it exists
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
match schema_attributes.get(attr) {
|
||||
Some(schema_a) => {
|
||||
schema_a
|
||||
.validate_partialvalue(attr_norm.as_str(), value)
|
||||
.validate_partialvalue(attr, value)
|
||||
// Okay, it worked, transform to a filter component
|
||||
.map(|_| FilterComp::Enw(attr_norm, value.clone()))
|
||||
.map(|_| FilterComp::Enw(attr.clone(), value.clone()))
|
||||
// On error, pass the error back out.
|
||||
}
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
}
|
||||
}
|
||||
FilterComp::Pres(attr) => {
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
// Now check it exists
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
match schema_attributes.get(attr) {
|
||||
Some(_attr_name) => {
|
||||
// Return our valid data
|
||||
Ok(FilterComp::Pres(attr_norm))
|
||||
Ok(FilterComp::Pres(attr.clone()))
|
||||
}
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
}
|
||||
}
|
||||
FilterComp::LessThan(attr, value) => {
|
||||
// Validate/normalise the attr name.
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
// Now check it exists
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
match schema_attributes.get(attr) {
|
||||
Some(schema_a) => {
|
||||
schema_a
|
||||
.validate_partialvalue(attr_norm.as_str(), value)
|
||||
.validate_partialvalue(attr, value)
|
||||
// Okay, it worked, transform to a filter component
|
||||
.map(|_| FilterComp::LessThan(attr_norm, value.clone()))
|
||||
.map(|_| FilterComp::LessThan(attr.clone(), value.clone()))
|
||||
// On error, pass the error back out.
|
||||
}
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
}
|
||||
}
|
||||
FilterComp::Or(filters) => {
|
||||
|
@ -932,17 +916,17 @@ impl FilterComp {
|
|||
let ndepth = depth.checked_sub(1).ok_or(OperationError::ResourceLimit)?;
|
||||
Ok(match f {
|
||||
ProtoFilter::Eq(a, v) => {
|
||||
let nk = qs.get_schema().normalise_attr_name(a);
|
||||
let v = qs.clone_partialvalue(nk.as_str(), v)?;
|
||||
let nk = Attribute::from(a.as_str());
|
||||
let v = qs.clone_partialvalue(&nk, v)?;
|
||||
FilterComp::Eq(nk, v)
|
||||
}
|
||||
ProtoFilter::Cnt(a, v) => {
|
||||
let nk = qs.get_schema().normalise_attr_name(a);
|
||||
let v = qs.clone_partialvalue(nk.as_str(), v)?;
|
||||
let nk = Attribute::from(a.as_str());
|
||||
let v = qs.clone_partialvalue(&nk, v)?;
|
||||
FilterComp::Cnt(nk, v)
|
||||
}
|
||||
ProtoFilter::Pres(a) => {
|
||||
let nk = qs.get_schema().normalise_attr_name(a);
|
||||
let nk = Attribute::from(a.as_str());
|
||||
FilterComp::Pres(nk)
|
||||
}
|
||||
ProtoFilter::Or(l) => {
|
||||
|
@ -984,17 +968,17 @@ impl FilterComp {
|
|||
let ndepth = depth.checked_sub(1).ok_or(OperationError::ResourceLimit)?;
|
||||
Ok(match f {
|
||||
ProtoFilter::Eq(a, v) => {
|
||||
let nk = qs.get_schema().normalise_attr_name(a);
|
||||
let v = qs.clone_partialvalue(nk.as_str(), v)?;
|
||||
let nk = Attribute::from(a.as_str());
|
||||
let v = qs.clone_partialvalue(&nk, v)?;
|
||||
FilterComp::Eq(nk, v)
|
||||
}
|
||||
ProtoFilter::Cnt(a, v) => {
|
||||
let nk = qs.get_schema().normalise_attr_name(a);
|
||||
let v = qs.clone_partialvalue(nk.as_str(), v)?;
|
||||
let nk = Attribute::from(a.as_str());
|
||||
let v = qs.clone_partialvalue(&nk, v)?;
|
||||
FilterComp::Cnt(nk, v)
|
||||
}
|
||||
ProtoFilter::Pres(a) => {
|
||||
let nk = qs.get_schema().normalise_attr_name(a);
|
||||
let nk = Attribute::from(a.as_str());
|
||||
FilterComp::Pres(nk)
|
||||
}
|
||||
ProtoFilter::Or(l) => {
|
||||
|
@ -1065,7 +1049,7 @@ impl FilterComp {
|
|||
}
|
||||
LdapFilter::Equality(a, v) => {
|
||||
let a = ldap_attr_filter_map(a);
|
||||
let v = qs.clone_partialvalue(a.as_str(), v)?;
|
||||
let v = qs.clone_partialvalue(&a, v)?;
|
||||
FilterComp::Eq(a, v)
|
||||
}
|
||||
LdapFilter::Present(a) => FilterComp::Pres(ldap_attr_filter_map(a)),
|
||||
|
@ -1081,17 +1065,17 @@ impl FilterComp {
|
|||
|
||||
let mut terms = Vec::with_capacity(any.len() + 2);
|
||||
if let Some(ini) = initial {
|
||||
let v = qs.clone_partialvalue(a.as_str(), ini)?;
|
||||
let v = qs.clone_partialvalue(&a, ini)?;
|
||||
terms.push(FilterComp::Stw(a.clone(), v));
|
||||
}
|
||||
|
||||
for term in any.iter() {
|
||||
let v = qs.clone_partialvalue(a.as_str(), term)?;
|
||||
let v = qs.clone_partialvalue(&a, term)?;
|
||||
terms.push(FilterComp::Cnt(a.clone(), v));
|
||||
}
|
||||
|
||||
if let Some(fin) = final_ {
|
||||
let v = qs.clone_partialvalue(a.as_str(), fin)?;
|
||||
let v = qs.clone_partialvalue(&a, fin)?;
|
||||
terms.push(FilterComp::Enw(a.clone(), v));
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1211,7 @@ impl FilterResolved {
|
|||
/// ⚠️ - Process a filter without verifying with schema.
|
||||
/// This is a TEST ONLY method and will never be exposed in production.
|
||||
#[cfg(test)]
|
||||
fn from_invalid(fc: FilterComp, idxmeta: &HashSet<(&AttrString, &IndexType)>) -> Self {
|
||||
fn from_invalid(fc: FilterComp, idxmeta: &HashSet<(&Attribute, &IndexType)>) -> Self {
|
||||
match fc {
|
||||
FilterComp::Eq(a, v) => {
|
||||
let idx = idxmeta.contains(&(&a, &IndexType::Equality));
|
||||
|
@ -1332,7 +1316,7 @@ impl FilterResolved {
|
|||
.get(&idxkref as &dyn IdxKeyToRef)
|
||||
.copied()
|
||||
.and_then(NonZeroU8::new);
|
||||
FilterResolved::Eq(Attribute::Uuid.into(), PartialValue::Uuid(uuid), idx)
|
||||
FilterResolved::Eq(Attribute::Uuid, PartialValue::Uuid(uuid), idx)
|
||||
}),
|
||||
FilterComp::Cnt(a, v) => {
|
||||
let idxkref = IdxKeyRef::new(&a, &IndexType::SubString);
|
||||
|
@ -1421,7 +1405,7 @@ impl FilterResolved {
|
|||
}
|
||||
FilterComp::SelfUuid => ev.get_uuid().map(|uuid| {
|
||||
FilterResolved::Eq(
|
||||
Attribute::Uuid.into(),
|
||||
Attribute::Uuid,
|
||||
PartialValue::Uuid(uuid),
|
||||
NonZeroU8::new(true as u8),
|
||||
)
|
||||
|
@ -2012,8 +1996,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_attr_set_filter() {
|
||||
let mut f_expect = BTreeSet::new();
|
||||
f_expect.insert("userid");
|
||||
f_expect.insert(Attribute::Class.as_ref());
|
||||
f_expect.insert(Attribute::from("userid"));
|
||||
f_expect.insert(Attribute::Class);
|
||||
// Given filters, get their expected attribute sets - this is used by access control profiles
|
||||
// to determine what attrs we are requesting regardless of the partialvalue.
|
||||
let f_t1a = filter_valid!(f_and!([
|
||||
|
|
|
@ -567,20 +567,20 @@ impl Account {
|
|||
|
||||
if let Some(ncred) = opt_ncred {
|
||||
let vcred = Value::new_credential("primary", ncred);
|
||||
ml.push(Modify::Purged(Attribute::PrimaryCredential.into()));
|
||||
ml.push(Modify::Present(Attribute::PrimaryCredential.into(), vcred));
|
||||
ml.push(Modify::Purged(Attribute::PrimaryCredential));
|
||||
ml.push(Modify::Present(Attribute::PrimaryCredential, vcred));
|
||||
}
|
||||
|
||||
// Is it a passkey?
|
||||
self.passkeys.iter_mut().for_each(|(u, (t, k))| {
|
||||
if let Some(true) = k.update_credential(auth_result) {
|
||||
ml.push(Modify::Removed(
|
||||
Attribute::PassKeys.into(),
|
||||
Attribute::PassKeys,
|
||||
PartialValue::Passkey(*u),
|
||||
));
|
||||
|
||||
ml.push(Modify::Present(
|
||||
Attribute::PassKeys.into(),
|
||||
Attribute::PassKeys,
|
||||
Value::Passkey(*u, t.clone(), k.clone()),
|
||||
));
|
||||
}
|
||||
|
@ -590,12 +590,12 @@ impl Account {
|
|||
self.attested_passkeys.iter_mut().for_each(|(u, (t, k))| {
|
||||
if let Some(true) = k.update_credential(auth_result) {
|
||||
ml.push(Modify::Removed(
|
||||
Attribute::AttestedPasskeys.into(),
|
||||
Attribute::AttestedPasskeys,
|
||||
PartialValue::AttestedPasskey(*u),
|
||||
));
|
||||
|
||||
ml.push(Modify::Present(
|
||||
Attribute::AttestedPasskeys.into(),
|
||||
Attribute::AttestedPasskeys,
|
||||
Value::AttestedPasskey(*u, t.clone(), k.clone()),
|
||||
));
|
||||
}
|
||||
|
@ -827,7 +827,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
) -> Result<(), OperationError> {
|
||||
// Delete the attribute with uuid.
|
||||
let modlist = ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::UserAuthTokenSession.into(),
|
||||
Attribute::UserAuthTokenSession,
|
||||
PartialValue::Refer(dte.token_id),
|
||||
)]);
|
||||
|
||||
|
@ -881,9 +881,9 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let prev_classes: BTreeSet<_> = account_entry
|
||||
.get_ava_as_iutf8_iter(Attribute::Class)
|
||||
.ok_or_else(|| {
|
||||
admin_error!(
|
||||
error!(
|
||||
"Invalid entry, {} attribute is not present or not iutf8",
|
||||
Attribute::Class.as_ref()
|
||||
Attribute::Class
|
||||
);
|
||||
OperationError::InvalidAccountState(format!(
|
||||
"Missing attribute: {}",
|
||||
|
@ -916,7 +916,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
);
|
||||
// add person
|
||||
modlist.push_mod(Modify::Present(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::Person.to_value(),
|
||||
));
|
||||
// purge the other attrs that are SA only.
|
||||
|
@ -1076,8 +1076,8 @@ mod tests {
|
|||
PartialValue::new_iname("testaccount")
|
||||
)),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::Class, EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(2001)),
|
||||
]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
|
||||
|
|
|
@ -518,11 +518,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
.effective_permission_check(
|
||||
ident,
|
||||
Some(btreeset![
|
||||
Attribute::PrimaryCredential.into(),
|
||||
Attribute::PassKeys.into(),
|
||||
Attribute::AttestedPasskeys.into(),
|
||||
Attribute::UnixPassword.into(),
|
||||
Attribute::SshPublicKey.into()
|
||||
Attribute::PrimaryCredential,
|
||||
Attribute::PassKeys,
|
||||
Attribute::AttestedPasskeys,
|
||||
Attribute::UnixPassword,
|
||||
Attribute::SshPublicKey
|
||||
]),
|
||||
&[entry],
|
||||
)?;
|
||||
|
@ -543,19 +543,19 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let eperm_search_primary_cred = match &eperm.search {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::PrimaryCredential.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::PrimaryCredential),
|
||||
};
|
||||
|
||||
let eperm_mod_primary_cred = match &eperm.modify_pres {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::PrimaryCredential.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::PrimaryCredential),
|
||||
};
|
||||
|
||||
let eperm_rem_primary_cred = match &eperm.modify_rem {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::PrimaryCredential.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::PrimaryCredential),
|
||||
};
|
||||
|
||||
let primary_can_edit =
|
||||
|
@ -564,19 +564,19 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let eperm_search_passkeys = match &eperm.search {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::PassKeys.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::PassKeys),
|
||||
};
|
||||
|
||||
let eperm_mod_passkeys = match &eperm.modify_pres {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::PassKeys.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::PassKeys),
|
||||
};
|
||||
|
||||
let eperm_rem_passkeys = match &eperm.modify_rem {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::PassKeys.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::PassKeys),
|
||||
};
|
||||
|
||||
let passkeys_can_edit = eperm_search_passkeys && eperm_mod_passkeys && eperm_rem_passkeys;
|
||||
|
@ -584,19 +584,19 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let eperm_search_attested_passkeys = match &eperm.search {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::AttestedPasskeys.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::AttestedPasskeys),
|
||||
};
|
||||
|
||||
let eperm_mod_attested_passkeys = match &eperm.modify_pres {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::AttestedPasskeys.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::AttestedPasskeys),
|
||||
};
|
||||
|
||||
let eperm_rem_attested_passkeys = match &eperm.modify_rem {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::AttestedPasskeys.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::AttestedPasskeys),
|
||||
};
|
||||
|
||||
let attested_passkeys_can_edit = eperm_search_attested_passkeys
|
||||
|
@ -606,19 +606,19 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let eperm_search_unixcred = match &eperm.search {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::UnixPassword.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::UnixPassword),
|
||||
};
|
||||
|
||||
let eperm_mod_unixcred = match &eperm.modify_pres {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::UnixPassword.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::UnixPassword),
|
||||
};
|
||||
|
||||
let eperm_rem_unixcred = match &eperm.modify_rem {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::UnixPassword.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::UnixPassword),
|
||||
};
|
||||
|
||||
let unixcred_can_edit = account.unix_extn().is_some()
|
||||
|
@ -629,19 +629,19 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let eperm_search_sshpubkey = match &eperm.search {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::SshPublicKey.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::SshPublicKey),
|
||||
};
|
||||
|
||||
let eperm_mod_sshpubkey = match &eperm.modify_pres {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::SshPublicKey.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::SshPublicKey),
|
||||
};
|
||||
|
||||
let eperm_rem_sshpubkey = match &eperm.modify_rem {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::SshPublicKey.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::SshPublicKey),
|
||||
};
|
||||
|
||||
let sshpubkey_can_edit = account.unix_extn().is_some()
|
||||
|
@ -658,7 +658,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
.get_accesscontrols()
|
||||
.effective_permission_check(
|
||||
ident,
|
||||
Some(btreeset![Attribute::SyncCredentialPortal.into()]),
|
||||
Some(btreeset![Attribute::SyncCredentialPortal]),
|
||||
&[entry],
|
||||
)?;
|
||||
|
||||
|
@ -670,7 +670,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
match &eperm.search {
|
||||
Access::Denied => false,
|
||||
Access::Grant => true,
|
||||
Access::Allow(attrs) => attrs.contains(Attribute::SyncCredentialPortal.as_ref()),
|
||||
Access::Allow(attrs) => attrs.contains(&Attribute::SyncCredentialPortal),
|
||||
}
|
||||
} else {
|
||||
false
|
||||
|
@ -940,7 +940,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
if ct >= max_ttl {
|
||||
modlist.push_mod(Modify::Removed(
|
||||
Attribute::CredentialUpdateIntentToken.into(),
|
||||
Attribute::CredentialUpdateIntentToken,
|
||||
PartialValue::IntentToken(existing_intent_id.clone()),
|
||||
));
|
||||
}
|
||||
|
@ -1113,11 +1113,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let mut modlist = ModifyList::new();
|
||||
|
||||
modlist.push_mod(Modify::Removed(
|
||||
Attribute::CredentialUpdateIntentToken.into(),
|
||||
Attribute::CredentialUpdateIntentToken,
|
||||
PartialValue::IntentToken(intent_id.clone()),
|
||||
));
|
||||
modlist.push_mod(Modify::Present(
|
||||
Attribute::CredentialUpdateIntentToken.into(),
|
||||
Attribute::CredentialUpdateIntentToken,
|
||||
Value::IntentToken(
|
||||
intent_id.clone(),
|
||||
IntentTokenState::InProgress {
|
||||
|
@ -1309,11 +1309,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
};
|
||||
|
||||
modlist.push_mod(Modify::Removed(
|
||||
Attribute::CredentialUpdateIntentToken.into(),
|
||||
Attribute::CredentialUpdateIntentToken,
|
||||
PartialValue::IntentToken(intent_token_id.clone()),
|
||||
));
|
||||
modlist.push_mod(Modify::Present(
|
||||
Attribute::CredentialUpdateIntentToken.into(),
|
||||
Attribute::CredentialUpdateIntentToken,
|
||||
Value::IntentToken(
|
||||
intent_token_id.clone(),
|
||||
IntentTokenState::Consumed { max_ttl },
|
||||
|
@ -1323,37 +1323,37 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
match session.primary_state {
|
||||
CredentialState::Modifiable => {
|
||||
modlist.push_mod(Modify::Purged(Attribute::PrimaryCredential.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::PrimaryCredential));
|
||||
if let Some(ncred) = &session.primary {
|
||||
let vcred = Value::new_credential("primary", ncred.clone());
|
||||
modlist.push_mod(Modify::Present(Attribute::PrimaryCredential.into(), vcred));
|
||||
modlist.push_mod(Modify::Present(Attribute::PrimaryCredential, vcred));
|
||||
};
|
||||
}
|
||||
CredentialState::DeleteOnly | CredentialState::PolicyDeny => {
|
||||
modlist.push_mod(Modify::Purged(Attribute::PrimaryCredential.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::PrimaryCredential));
|
||||
}
|
||||
CredentialState::AccessDeny => {}
|
||||
};
|
||||
|
||||
match session.passkeys_state {
|
||||
CredentialState::DeleteOnly | CredentialState::Modifiable => {
|
||||
modlist.push_mod(Modify::Purged(Attribute::PassKeys.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::PassKeys));
|
||||
// Add all the passkeys. If none, nothing will be added! This handles
|
||||
// the delete case quite cleanly :)
|
||||
session.passkeys.iter().for_each(|(uuid, (tag, pk))| {
|
||||
let v_pk = Value::Passkey(*uuid, tag.clone(), pk.clone());
|
||||
modlist.push_mod(Modify::Present(Attribute::PassKeys.into(), v_pk));
|
||||
modlist.push_mod(Modify::Present(Attribute::PassKeys, v_pk));
|
||||
});
|
||||
}
|
||||
CredentialState::PolicyDeny => {
|
||||
modlist.push_mod(Modify::Purged(Attribute::PassKeys.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::PassKeys));
|
||||
}
|
||||
CredentialState::AccessDeny => {}
|
||||
};
|
||||
|
||||
match session.attested_passkeys_state {
|
||||
CredentialState::DeleteOnly | CredentialState::Modifiable => {
|
||||
modlist.push_mod(Modify::Purged(Attribute::AttestedPasskeys.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::AttestedPasskeys));
|
||||
// Add all the passkeys. If none, nothing will be added! This handles
|
||||
// the delete case quite cleanly :)
|
||||
session
|
||||
|
@ -1361,29 +1361,29 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
.iter()
|
||||
.for_each(|(uuid, (tag, pk))| {
|
||||
let v_pk = Value::AttestedPasskey(*uuid, tag.clone(), pk.clone());
|
||||
modlist.push_mod(Modify::Present(Attribute::AttestedPasskeys.into(), v_pk));
|
||||
modlist.push_mod(Modify::Present(Attribute::AttestedPasskeys, v_pk));
|
||||
});
|
||||
}
|
||||
CredentialState::PolicyDeny => {
|
||||
modlist.push_mod(Modify::Purged(Attribute::AttestedPasskeys.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::AttestedPasskeys));
|
||||
}
|
||||
// CredentialState::Disabled |
|
||||
CredentialState::AccessDeny => {}
|
||||
};
|
||||
|
||||
if session.unixcred_can_edit {
|
||||
modlist.push_mod(Modify::Purged(Attribute::UnixPassword.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::UnixPassword));
|
||||
if let Some(ncred) = &session.unixcred {
|
||||
let vcred = Value::new_credential("unix", ncred.clone());
|
||||
modlist.push_mod(Modify::Present(Attribute::UnixPassword.into(), vcred));
|
||||
modlist.push_mod(Modify::Present(Attribute::UnixPassword, vcred));
|
||||
}
|
||||
}
|
||||
|
||||
if session.sshpubkey_can_edit {
|
||||
modlist.push_mod(Modify::Purged(Attribute::SshPublicKey.into()));
|
||||
modlist.push_mod(Modify::Purged(Attribute::SshPublicKey));
|
||||
for (tag, pk) in &session.sshkeys {
|
||||
let v_sk = Value::SshKey(tag.clone(), pk.clone());
|
||||
modlist.push_mod(Modify::Present(Attribute::SshPublicKey.into(), v_sk));
|
||||
modlist.push_mod(Modify::Present(Attribute::SshPublicKey, v_sk));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1452,11 +1452,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
};
|
||||
|
||||
modlist.push_mod(Modify::Removed(
|
||||
Attribute::CredentialUpdateIntentToken.into(),
|
||||
Attribute::CredentialUpdateIntentToken,
|
||||
PartialValue::IntentToken(intent_token_id.clone()),
|
||||
));
|
||||
modlist.push_mod(Modify::Present(
|
||||
Attribute::CredentialUpdateIntentToken.into(),
|
||||
Attribute::CredentialUpdateIntentToken,
|
||||
Value::IntentToken(
|
||||
intent_token_id.clone(),
|
||||
IntentTokenState::Valid { max_ttl, perms },
|
||||
|
|
|
@ -311,7 +311,7 @@ impl LdapServer {
|
|||
// NOTE: All req_attrs are lowercase at this point.
|
||||
let mapped_attrs: BTreeSet<_> = req_attrs
|
||||
.iter()
|
||||
.map(|a| AttrString::from(ldap_vattr_map(a).unwrap_or(a)))
|
||||
.map(|a| Attribute::from(ldap_vattr_map(a).unwrap_or(a)))
|
||||
.collect();
|
||||
|
||||
(Some(mapped_attrs), req_attrs)
|
||||
|
@ -833,9 +833,9 @@ pub(crate) fn ldap_vattr_map(input: &str) -> Option<&str> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn ldap_attr_filter_map(input: &str) -> AttrString {
|
||||
pub(crate) fn ldap_attr_filter_map(input: &str) -> Attribute {
|
||||
let a_lower = input.to_lowercase();
|
||||
AttrString::from(ldap_vattr_map(&a_lower).unwrap_or(a_lower.as_str()))
|
||||
Attribute::from(ldap_vattr_map(&a_lower).unwrap_or(a_lower.as_str()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -866,8 +866,8 @@ mod tests {
|
|||
let me_posix = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::Class, EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(2001)),
|
||||
]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
|
||||
|
@ -1507,8 +1507,8 @@ mod tests {
|
|||
let me = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(acct))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::AccountExpire.into(), v_expire),
|
||||
Modify::Present(Attribute::AccountValidFrom.into(), v_valid_from),
|
||||
Modify::Present(Attribute::AccountExpire, v_expire),
|
||||
Modify::Present(Attribute::AccountValidFrom, v_valid_from),
|
||||
]),
|
||||
);
|
||||
assert!(idms_write.qs_write.modify(&me).is_ok());
|
||||
|
@ -1896,7 +1896,7 @@ mod tests {
|
|||
PartialValue::new_iname(BUILTIN_GROUP_PEOPLE_PII_READ.name)
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::Refer(sa_uuid),
|
||||
)]),
|
||||
);
|
||||
|
@ -1984,12 +1984,9 @@ mod tests {
|
|||
assert_entry_contains!(
|
||||
lsre,
|
||||
"spn=testperson1@example.com,dc=example,dc=com",
|
||||
(Attribute::Name.as_ref(), "testperson1"),
|
||||
(Attribute::Mail.as_ref(), "testperson1@example.com"),
|
||||
(
|
||||
Attribute::Mail.as_ref(),
|
||||
"testperson1.alternative@example.com"
|
||||
),
|
||||
(Attribute::Name, "testperson1"),
|
||||
(Attribute::Mail, "testperson1@example.com"),
|
||||
(Attribute::Mail, "testperson1.alternative@example.com"),
|
||||
(LDAP_ATTR_MAIL_PRIMARY, "testperson1@example.com"),
|
||||
(
|
||||
LDAP_ATTR_MAIL_ALTERNATIVE,
|
||||
|
@ -2044,12 +2041,9 @@ mod tests {
|
|||
assert_entry_contains!(
|
||||
lsre,
|
||||
"spn=testperson1@example.com,dc=example,dc=com",
|
||||
(Attribute::Name.as_ref(), "testperson1"),
|
||||
(Attribute::Mail.as_ref(), "testperson1@example.com"),
|
||||
(
|
||||
Attribute::Mail.as_ref(),
|
||||
"testperson1.alternative@example.com"
|
||||
),
|
||||
(Attribute::Name, "testperson1"),
|
||||
(Attribute::Mail, "testperson1@example.com"),
|
||||
(Attribute::Mail, "testperson1.alternative@example.com"),
|
||||
(LDAP_ATTR_MAIL_PRIMARY, "testperson1@example.com"),
|
||||
(
|
||||
LDAP_ATTR_MAIL_ALTERNATIVE,
|
||||
|
@ -2125,10 +2119,7 @@ mod tests {
|
|||
(Attribute::Name, "testperson1"),
|
||||
(Attribute::DisplayName, "testperson1"),
|
||||
(Attribute::Uuid, "cc8e95b4-c24f-4d68-ba54-8bed76f63930"),
|
||||
(
|
||||
Attribute::EntryUuid.as_ref(),
|
||||
"cc8e95b4-c24f-4d68-ba54-8bed76f63930"
|
||||
)
|
||||
(Attribute::EntryUuid, "cc8e95b4-c24f-4d68-ba54-8bed76f63930")
|
||||
);
|
||||
}
|
||||
_ => panic!("Oh no"),
|
||||
|
@ -2218,10 +2209,7 @@ mod tests {
|
|||
assert_entry_contains!(
|
||||
lsre,
|
||||
"spn=testperson1@example.com,dc=example,dc=com",
|
||||
(
|
||||
Attribute::EntryUuid.as_ref(),
|
||||
"cc8e95b4-c24f-4d68-ba54-8bed76f63930"
|
||||
)
|
||||
(Attribute::EntryUuid, "cc8e95b4-c24f-4d68-ba54-8bed76f63930")
|
||||
);
|
||||
}
|
||||
_ => panic!("Oh no"),
|
||||
|
@ -2426,10 +2414,7 @@ mod tests {
|
|||
(Attribute::Gecos, "testperson1"),
|
||||
(Attribute::UidNumber, "12345"),
|
||||
(Attribute::GidNumber, "12345"),
|
||||
(
|
||||
Attribute::EntryUuid.as_ref(),
|
||||
"cc8e95b4-c24f-4d68-ba54-8bed76f63930"
|
||||
)
|
||||
(Attribute::EntryUuid, "cc8e95b4-c24f-4d68-ba54-8bed76f63930")
|
||||
);
|
||||
}
|
||||
_ => panic!("Oh no"),
|
||||
|
|
|
@ -588,7 +588,7 @@ impl<'a> Oauth2ResourceServersWriteTransaction<'a> {
|
|||
BTreeMap::default()
|
||||
};
|
||||
|
||||
trace!("{}", Attribute::OAuth2JwtLegacyCryptoEnable.as_ref());
|
||||
trace!("{}", Attribute::OAuth2JwtLegacyCryptoEnable);
|
||||
let jws_signer = if ent.get_ava_single_bool(Attribute::OAuth2JwtLegacyCryptoEnable).unwrap_or(false) {
|
||||
trace!("{}", Attribute::Rs256PrivateKeyDer);
|
||||
ent
|
||||
|
@ -819,7 +819,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
// and when replication converges the session is actually removed.
|
||||
|
||||
let modlist = ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::OAuth2Session.into(),
|
||||
Attribute::OAuth2Session,
|
||||
PartialValue::Refer(session_id),
|
||||
)]);
|
||||
|
||||
|
@ -1005,11 +1005,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
let modlist = ModifyList::new_list(vec![
|
||||
Modify::Removed(
|
||||
Attribute::OAuth2ConsentScopeMap.into(),
|
||||
Attribute::OAuth2ConsentScopeMap,
|
||||
PartialValue::Refer(o2rs.uuid),
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::OAuth2ConsentScopeMap.into(),
|
||||
Attribute::OAuth2ConsentScopeMap,
|
||||
Value::OauthScopeMap(o2rs.uuid, consent_req.scopes.iter().cloned().collect()),
|
||||
),
|
||||
]);
|
||||
|
@ -1219,7 +1219,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
// Revoke it
|
||||
let modlist = ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::OAuth2Session.into(),
|
||||
Attribute::OAuth2Session,
|
||||
PartialValue::Refer(session_id),
|
||||
)]);
|
||||
|
||||
|
@ -1352,10 +1352,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
);
|
||||
|
||||
// We need to create this session on the o2rs
|
||||
let modlist = ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::OAuth2Session.into(),
|
||||
session,
|
||||
)]);
|
||||
let modlist =
|
||||
ModifyList::new_list(vec![Modify::Present(Attribute::OAuth2Session, session)]);
|
||||
|
||||
self.qs_write
|
||||
.internal_modify(
|
||||
|
@ -1562,7 +1560,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
// NOTE: Oauth2_session has special handling that allows update in place without
|
||||
// the remove step needing to be carried out.
|
||||
// Modify::Removed("oauth2_session".into(), PartialValue::Refer(session_id)),
|
||||
Modify::Present(Attribute::OAuth2Session.into(), session),
|
||||
Modify::Present(Attribute::OAuth2Session, session),
|
||||
]);
|
||||
|
||||
self.qs_write
|
||||
|
@ -2900,9 +2898,9 @@ mod tests {
|
|||
|
||||
// Mod the user
|
||||
let modlist = ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::UserAuthTokenSession.into(), session),
|
||||
Modify::Present(Attribute::UserAuthTokenSession, session),
|
||||
Modify::Present(
|
||||
Attribute::PrimaryCredential.into(),
|
||||
Attribute::PrimaryCredential,
|
||||
Value::Cred("primary".to_string(), cred),
|
||||
),
|
||||
]);
|
||||
|
@ -3033,9 +3031,9 @@ mod tests {
|
|||
|
||||
// Mod the user
|
||||
let modlist = ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::UserAuthTokenSession.into(), session),
|
||||
Modify::Present(Attribute::UserAuthTokenSession, session),
|
||||
Modify::Present(
|
||||
Attribute::PrimaryCredential.into(),
|
||||
Attribute::PrimaryCredential,
|
||||
Value::Cred("primary".to_string(), cred),
|
||||
),
|
||||
]);
|
||||
|
@ -3222,7 +3220,7 @@ mod tests {
|
|||
let (_code_verifier, code_challenge) = create_code_verifier!("Whar Garble");
|
||||
|
||||
let pkce_request = Some(PkceRequest {
|
||||
code_challenge: code_challenge.into(),
|
||||
code_challenge: code_challenge,
|
||||
code_challenge_method: CodeChallengeMethod::S256,
|
||||
});
|
||||
|
||||
|
@ -3662,7 +3660,7 @@ mod tests {
|
|||
client_id: "test_resource_server".to_string(),
|
||||
state: "123".to_string(),
|
||||
pkce_request: Some(PkceRequest {
|
||||
code_challenge: code_challenge.clone().into(),
|
||||
code_challenge: code_challenge.clone(),
|
||||
code_challenge_method: CodeChallengeMethod::S256,
|
||||
}),
|
||||
redirect_uri: Url::parse("https://portal.example.com").unwrap(),
|
||||
|
@ -3731,7 +3729,7 @@ mod tests {
|
|||
client_id: "test_resource_server".to_string(),
|
||||
state: "123".to_string(),
|
||||
pkce_request: Some(PkceRequest {
|
||||
code_challenge: code_challenge.into(),
|
||||
code_challenge: code_challenge,
|
||||
code_challenge_method: CodeChallengeMethod::S256,
|
||||
}),
|
||||
redirect_uri: Url::parse("app://cheese").unwrap(),
|
||||
|
@ -3859,10 +3857,7 @@ mod tests {
|
|||
let v_expire = Value::new_datetime_epoch(Duration::from_secs(TEST_CURRENT_TIME - 1));
|
||||
let me_inv_m = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_TESTPERSON_1))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::AccountExpire.into(),
|
||||
v_expire,
|
||||
)]),
|
||||
ModifyList::new_list(vec![Modify::Present(Attribute::AccountExpire, v_expire)]),
|
||||
);
|
||||
// go!
|
||||
assert!(idms_prox_write.qs_write.modify(&me_inv_m).is_ok());
|
||||
|
@ -5061,7 +5056,7 @@ mod tests {
|
|||
PartialValue::new_iname("test_resource_server")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
AttrString::from(Attribute::OAuth2RsScopeMap.as_ref()),
|
||||
Attribute::OAuth2RsScopeMap,
|
||||
Value::new_oauthscopemap(
|
||||
UUID_IDM_ALL_ACCOUNTS,
|
||||
btreeset![
|
||||
|
@ -5092,7 +5087,7 @@ mod tests {
|
|||
client_id: "test_resource_server".to_string(),
|
||||
state: "123".to_string(),
|
||||
pkce_request: Some(PkceRequest {
|
||||
code_challenge: code_challenge.into(),
|
||||
code_challenge: code_challenge,
|
||||
code_challenge_method: CodeChallengeMethod::S256,
|
||||
}),
|
||||
redirect_uri: Url::parse("https://demo.example.com/oauth2/result").unwrap(),
|
||||
|
@ -5124,7 +5119,7 @@ mod tests {
|
|||
PartialValue::new_iname("test_resource_server")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::OAuth2RsSupScopeMap.into(),
|
||||
Attribute::OAuth2RsSupScopeMap,
|
||||
Value::new_oauthscopemap(UUID_IDM_ALL_ACCOUNTS, btreeset!["newscope".to_string()])
|
||||
.expect("invalid oauthscope"),
|
||||
)]),
|
||||
|
@ -5149,7 +5144,7 @@ mod tests {
|
|||
client_id: "test_resource_server".to_string(),
|
||||
state: "123".to_string(),
|
||||
pkce_request: Some(PkceRequest {
|
||||
code_challenge: code_challenge.into(),
|
||||
code_challenge: code_challenge,
|
||||
code_challenge_method: CodeChallengeMethod::S256,
|
||||
}),
|
||||
redirect_uri: Url::parse("https://demo.example.com/oauth2/result").unwrap(),
|
||||
|
@ -5364,7 +5359,7 @@ mod tests {
|
|||
client_id: "test_resource_server".to_string(),
|
||||
state: "123".to_string(),
|
||||
pkce_request: Some(PkceRequest {
|
||||
code_challenge: code_challenge.clone().into(),
|
||||
code_challenge: code_challenge.clone(),
|
||||
code_challenge_method: CodeChallengeMethod::S256,
|
||||
}),
|
||||
redirect_uri: Url::parse("http://demo.example.com/oauth2/result").unwrap(),
|
||||
|
@ -6057,14 +6052,14 @@ mod tests {
|
|||
let modlist = ModifyList::new_list(vec![
|
||||
// Member of a claim map.
|
||||
Modify::Present(
|
||||
Attribute::OAuth2RsClaimMap.into(),
|
||||
Attribute::OAuth2RsClaimMap,
|
||||
Value::OauthClaimMap(
|
||||
"custom_a".to_string(),
|
||||
OauthClaimMapJoin::CommaSeparatedValue,
|
||||
),
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::OAuth2RsClaimMap.into(),
|
||||
Attribute::OAuth2RsClaimMap,
|
||||
Value::OauthClaimValue(
|
||||
"custom_a".to_string(),
|
||||
UUID_TESTGROUP,
|
||||
|
@ -6073,7 +6068,7 @@ mod tests {
|
|||
),
|
||||
// If you are a member of two groups, the claim maps merge.
|
||||
Modify::Present(
|
||||
Attribute::OAuth2RsClaimMap.into(),
|
||||
Attribute::OAuth2RsClaimMap,
|
||||
Value::OauthClaimValue(
|
||||
"custom_a".to_string(),
|
||||
UUID_IDM_ALL_ACCOUNTS,
|
||||
|
@ -6082,14 +6077,14 @@ mod tests {
|
|||
),
|
||||
// Map with a different seperator
|
||||
Modify::Present(
|
||||
Attribute::OAuth2RsClaimMap.into(),
|
||||
Attribute::OAuth2RsClaimMap,
|
||||
Value::OauthClaimMap(
|
||||
"custom_b".to_string(),
|
||||
OauthClaimMapJoin::SpaceSeparatedValue,
|
||||
),
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::OAuth2RsClaimMap.into(),
|
||||
Attribute::OAuth2RsClaimMap,
|
||||
Value::OauthClaimValue(
|
||||
"custom_b".to_string(),
|
||||
UUID_TESTGROUP,
|
||||
|
@ -6097,7 +6092,7 @@ mod tests {
|
|||
),
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::OAuth2RsClaimMap.into(),
|
||||
Attribute::OAuth2RsClaimMap,
|
||||
Value::OauthClaimValue(
|
||||
"custom_b".to_string(),
|
||||
UUID_IDM_ALL_ACCOUNTS,
|
||||
|
@ -6106,7 +6101,7 @@ mod tests {
|
|||
),
|
||||
// Not a member of the claim map.
|
||||
Modify::Present(
|
||||
Attribute::OAuth2RsClaimMap.into(),
|
||||
Attribute::OAuth2RsClaimMap,
|
||||
Value::OauthClaimValue(
|
||||
"custom_b".to_string(),
|
||||
UUID_IDM_ADMINS,
|
||||
|
@ -6296,7 +6291,7 @@ mod tests {
|
|||
let mut idms_prox_write = idms.proxy_write(ct).await.unwrap();
|
||||
|
||||
let modlist = ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::OAuth2AllowLocalhostRedirect.into(),
|
||||
Attribute::OAuth2AllowLocalhostRedirect,
|
||||
Value::Bool(true),
|
||||
)]);
|
||||
|
||||
|
@ -6320,7 +6315,7 @@ mod tests {
|
|||
client_id: "test_resource_server".to_string(),
|
||||
state: "123".to_string(),
|
||||
pkce_request: Some(PkceRequest {
|
||||
code_challenge: code_challenge.into(),
|
||||
code_challenge: code_challenge,
|
||||
code_challenge_method: CodeChallengeMethod::S256,
|
||||
}),
|
||||
redirect_uri: Url::parse("http://localhost:8765/oauth2/result").unwrap(),
|
||||
|
|
|
@ -167,10 +167,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
OperationError::SerdeJsonError
|
||||
})?;
|
||||
|
||||
let modlist = ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::SyncTokenSession.into(),
|
||||
session,
|
||||
)]);
|
||||
let modlist =
|
||||
ModifyList::new_list(vec![Modify::Present(Attribute::SyncTokenSession, session)]);
|
||||
|
||||
self.qs_write
|
||||
.impersonate_modify(
|
||||
|
@ -216,8 +214,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
target: Uuid,
|
||||
_ct: Duration,
|
||||
) -> Result<(), OperationError> {
|
||||
let modlist =
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::SyncTokenSession.into())]);
|
||||
let modlist = ModifyList::new_list(vec![Modify::Purged(Attribute::SyncTokenSession)]);
|
||||
|
||||
self.qs_write
|
||||
.impersonate_modify(
|
||||
|
@ -339,7 +336,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
})?;
|
||||
|
||||
let modlist = std::iter::once(Modify::Removed(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::SyncObject.into(),
|
||||
))
|
||||
.chain(
|
||||
|
@ -438,9 +435,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let existing_entries = self
|
||||
.qs_write
|
||||
.internal_search(f_all_sync.clone())
|
||||
.map_err(|e| {
|
||||
error!("Failed to determine existing entries set");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to determine existing entries set");
|
||||
})?;
|
||||
|
||||
let delete_filter = if existing_entries.is_empty() {
|
||||
|
@ -467,7 +463,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
})?;
|
||||
|
||||
let modlist = std::iter::once(Modify::Removed(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::SyncObject.into(),
|
||||
))
|
||||
.chain(
|
||||
|
@ -481,9 +477,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
self.qs_write
|
||||
.internal_modify(&f_all_sync, &mods)
|
||||
.map_err(|e| {
|
||||
error!("Failed to modify sync objects to grant authority to kanidm");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(
|
||||
?err,
|
||||
"Failed to modify sync objects to grant authority to Kanidm"
|
||||
);
|
||||
})?;
|
||||
|
||||
filter!(f_or!([
|
||||
|
@ -570,10 +568,15 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
};
|
||||
|
||||
// Retrieve the related sync entry.
|
||||
let sync_entry = self.qs_write.internal_search_uuid(sync_uuid).map_err(|e| {
|
||||
error!("Failed to located sync entry related to {}", sync_uuid);
|
||||
e
|
||||
})?;
|
||||
let sync_entry = self
|
||||
.qs_write
|
||||
.internal_search_uuid(sync_uuid)
|
||||
.inspect_err(|err| {
|
||||
error!(
|
||||
?err,
|
||||
"Failed to located sync entry related to {}", sync_uuid
|
||||
);
|
||||
})?;
|
||||
|
||||
// Assert that the requested "from" state is consistent to this entry.
|
||||
// OperationError::InvalidSyncState
|
||||
|
@ -649,9 +652,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let existing_entries = self
|
||||
.qs_write
|
||||
.internal_search(filter_all!(f_or(filter_or)))
|
||||
.map_err(|e| {
|
||||
error!("Failed to determine existing entries set");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to determine existing entries set");
|
||||
})?;
|
||||
|
||||
// Refuse to proceed if any entries are in the recycled or tombstone state, since subsequent
|
||||
|
@ -703,10 +705,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
// We know that uuid won't conflict because it didn't exist in the previous search, so if we error
|
||||
// it has to be something bad.
|
||||
if !create_stubs.is_empty() {
|
||||
self.qs_write.internal_create(create_stubs).map_err(|e| {
|
||||
error!("Unable to create stub entries");
|
||||
e
|
||||
})?;
|
||||
self.qs_write
|
||||
.internal_create(create_stubs)
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Unable to create stub entries");
|
||||
})?;
|
||||
}
|
||||
|
||||
// We have to search again now, this way we can do the internal mod process for
|
||||
|
@ -727,18 +730,14 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
Attribute::SyncParentUuid,
|
||||
PartialValue::Refer(sync_uuid),
|
||||
),
|
||||
Modify::Purged(Attribute::SyncExternalId.into()),
|
||||
Modify::Present(
|
||||
Attribute::SyncExternalId.into(),
|
||||
Value::new_iutf8(ext_id),
|
||||
),
|
||||
Modify::Purged(Attribute::SyncExternalId),
|
||||
Modify::Present(Attribute::SyncExternalId, Value::new_iutf8(ext_id)),
|
||||
]),
|
||||
)
|
||||
})
|
||||
}))
|
||||
.map_err(|e| {
|
||||
error!("Unable to setup external ids from sync entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Unable to setup external ids from sync entries");
|
||||
})?;
|
||||
|
||||
// Ready to go.
|
||||
|
@ -805,7 +804,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
fn scim_attr_to_values(
|
||||
&mut self,
|
||||
scim_attr_name: &str,
|
||||
scim_attr_name: &Attribute,
|
||||
scim_attr: &ScimValue,
|
||||
) -> Result<Vec<Value>, OperationError> {
|
||||
let schema = self.qs_write.get_schema();
|
||||
|
@ -1154,11 +1153,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
for req_class in requested_classes.keys() {
|
||||
mods.push(Modify::Present(
|
||||
Attribute::SyncClass.into(),
|
||||
Attribute::SyncClass,
|
||||
Value::new_iutf8(req_class),
|
||||
));
|
||||
mods.push(Modify::Present(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
Value::new_iutf8(req_class),
|
||||
));
|
||||
}
|
||||
|
@ -1220,21 +1219,23 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
return Err(OperationError::InvalidEntryState);
|
||||
}
|
||||
|
||||
// Make it a native attribute name.
|
||||
let scim_attr_name = Attribute::from(scim_attr_name.as_str());
|
||||
|
||||
// Convert each scim_attr to a set of values.
|
||||
let values = self
|
||||
.scim_attr_to_values(scim_attr_name, scim_attr)
|
||||
.map_err(|e| {
|
||||
.scim_attr_to_values(&scim_attr_name, scim_attr)
|
||||
.inspect_err(|err| {
|
||||
error!(
|
||||
"Failed to convert {} for entry {}",
|
||||
scim_attr_name, scim_ent.id
|
||||
?err,
|
||||
"Failed to convert {} for entry {}", scim_attr_name, scim_ent.id
|
||||
);
|
||||
e
|
||||
})?;
|
||||
|
||||
mods.extend(
|
||||
values
|
||||
.into_iter()
|
||||
.map(|val| Modify::Present(scim_attr_name.into(), val)),
|
||||
.map(|val| Modify::Present(scim_attr_name.clone(), val)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1324,9 +1325,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
self.qs_write
|
||||
.internal_batch_modify(asserts.into_iter())
|
||||
.map_err(|e| {
|
||||
error!("Unable to apply modifications to sync entries.");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Unable to apply modifications to sync entries.");
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1380,9 +1380,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let delete_cands = self
|
||||
.qs_write
|
||||
.internal_search(filter_all!(f_or(filter_or)))
|
||||
.map_err(|e| {
|
||||
error!("Failed to determine existing entries set");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to determine existing entries set");
|
||||
})?;
|
||||
|
||||
let delete_filter = delete_cands
|
||||
|
@ -1456,9 +1455,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
self.qs_write
|
||||
.internal_modify_uuid(sync_uuid, &modlist)
|
||||
.map_err(|e| {
|
||||
error!("Failed to update sync entry state");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to update sync entry state");
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1639,7 +1637,7 @@ mod tests {
|
|||
Attribute::Name,
|
||||
PartialValue::new_iname("test_scim_sync")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::SyncTokenSession.into())]),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::SyncTokenSession)]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_inv_m).is_ok());
|
||||
assert!(idms_prox_write.commit().is_ok());
|
||||
|
@ -1762,7 +1760,7 @@ mod tests {
|
|||
|
||||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
to_state: ScimSyncState::Refresh,
|
||||
entries: Vec::with_capacity(0),
|
||||
|
@ -1791,7 +1789,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries: vec![ScimEntry {
|
||||
schemas: vec![SCIM_SCHEMA_SYNC_PERSON.to_string()],
|
||||
|
@ -1859,7 +1857,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries: vec![ScimEntry {
|
||||
schemas: vec![SCIM_SCHEMA_SYNC_PERSON.to_string()],
|
||||
|
@ -1899,7 +1897,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries,
|
||||
retain: ScimSyncRetentionMode::Ignore,
|
||||
|
@ -2102,7 +2100,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries: vec![ScimEntry {
|
||||
schemas: vec![SCIM_SCHEMA_SYNC_GROUP.to_string()],
|
||||
|
@ -2126,10 +2124,10 @@ mod tests {
|
|||
|
||||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![2, 3, 4, 5].into(),
|
||||
cookie: vec![2, 3, 4, 5],
|
||||
},
|
||||
entries: vec![],
|
||||
retain: ScimSyncRetentionMode::Delete(vec![user_sync_uuid]),
|
||||
|
@ -2169,7 +2167,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
// Doesn't exist. If it does, then bless rng.
|
||||
entries: Vec::with_capacity(0),
|
||||
|
@ -2208,7 +2206,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
// Doesn't exist. If it does, then bless rng.
|
||||
entries: Vec::with_capacity(0),
|
||||
|
@ -2250,7 +2248,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
// Doesn't exist. If it does, then bless rng.
|
||||
entries: Vec::with_capacity(0),
|
||||
|
@ -2285,7 +2283,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries: vec![
|
||||
ScimEntry {
|
||||
|
@ -2321,10 +2319,10 @@ mod tests {
|
|||
|
||||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![2, 3, 4, 5].into(),
|
||||
cookie: vec![2, 3, 4, 5],
|
||||
},
|
||||
entries: vec![],
|
||||
retain: ScimSyncRetentionMode::Retain(vec![sync_uuid_a]),
|
||||
|
@ -2369,7 +2367,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries: vec![
|
||||
ScimEntry {
|
||||
|
@ -2405,10 +2403,10 @@ mod tests {
|
|||
|
||||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![2, 3, 4, 5].into(),
|
||||
cookie: vec![2, 3, 4, 5],
|
||||
},
|
||||
entries: vec![],
|
||||
retain: ScimSyncRetentionMode::Retain(vec![]),
|
||||
|
@ -2467,7 +2465,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries: vec![ScimEntry {
|
||||
schemas: vec![SCIM_SCHEMA_SYNC_GROUP.to_string()],
|
||||
|
@ -2491,10 +2489,10 @@ mod tests {
|
|||
|
||||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![2, 3, 4, 5].into(),
|
||||
cookie: vec![2, 3, 4, 5],
|
||||
},
|
||||
entries: vec![],
|
||||
retain: ScimSyncRetentionMode::Retain(vec![sync_uuid_a]),
|
||||
|
@ -2529,7 +2527,7 @@ mod tests {
|
|||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Refresh,
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
entries: Vec::with_capacity(0),
|
||||
retain: ScimSyncRetentionMode::Ignore,
|
||||
|
@ -2544,10 +2542,10 @@ mod tests {
|
|||
|
||||
let changes = ScimSyncRequest {
|
||||
from_state: ScimSyncState::Active {
|
||||
cookie: vec![1, 2, 3, 4].into(),
|
||||
cookie: vec![1, 2, 3, 4],
|
||||
},
|
||||
to_state: ScimSyncState::Active {
|
||||
cookie: vec![2, 3, 4, 5].into(),
|
||||
cookie: vec![2, 3, 4, 5],
|
||||
},
|
||||
entries: vec![],
|
||||
retain: ScimSyncRetentionMode::Ignore,
|
||||
|
|
|
@ -1252,16 +1252,15 @@ impl<'a> IdmServerAuthTransaction<'a> {
|
|||
self.webauthn,
|
||||
self.qs_read.pw_badlist(),
|
||||
)
|
||||
.map(|aus| {
|
||||
.inspect(|aus| {
|
||||
// Inspect the result:
|
||||
// if it was a failure, we need to inc the softlock.
|
||||
if let AuthState::Denied(_) = &aus {
|
||||
if let AuthState::Denied(_) = aus {
|
||||
// Update it.
|
||||
if let Some(ref mut slock) = maybe_slock {
|
||||
slock.record_failure(ct);
|
||||
}
|
||||
};
|
||||
aus
|
||||
})
|
||||
} else {
|
||||
// Fail the session
|
||||
|
@ -1341,12 +1340,11 @@ impl<'a> IdmServerAuthTransaction<'a> {
|
|||
// Account is unlocked, can proceed.
|
||||
account
|
||||
.verify_unix_credential(uae.cleartext.as_str(), &self.async_tx, ct)
|
||||
.map(|res| {
|
||||
.inspect(|res| {
|
||||
if res.is_none() {
|
||||
// Update it.
|
||||
slock.record_failure(ct);
|
||||
};
|
||||
res
|
||||
})
|
||||
} else {
|
||||
// Account is slocked!
|
||||
|
@ -1671,9 +1669,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
.as_ref()
|
||||
.ok_or(OperationError::InvalidState)
|
||||
.cloned()
|
||||
.map_err(|e| {
|
||||
security_info!("zxcvbn returned no feedback when score < 3");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
security_info!(?err, "zxcvbn returned no feedback when score < 3");
|
||||
})?;
|
||||
|
||||
security_info!(?feedback, "pw quality feedback");
|
||||
|
@ -1881,7 +1878,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let modlist = ModifyList::new_list(vec![
|
||||
m_purge(Attribute::PassKeys),
|
||||
m_purge(Attribute::PrimaryCredential),
|
||||
Modify::Present(Attribute::PrimaryCredential.into(), vcred),
|
||||
Modify::Present(Attribute::PrimaryCredential, vcred),
|
||||
]);
|
||||
|
||||
trace!(?modlist, "processing change");
|
||||
|
@ -2386,10 +2383,7 @@ mod tests {
|
|||
// now modify and provide a primary credential.
|
||||
let me_inv_m = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_TESTPERSON_1))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::PrimaryCredential.into(),
|
||||
v_cred,
|
||||
)]),
|
||||
ModifyList::new_list(vec![Modify::Present(Attribute::PrimaryCredential, v_cred)]),
|
||||
);
|
||||
// go!
|
||||
assert!(idms_write.qs_write.modify(&me_inv_m).is_ok());
|
||||
|
@ -2684,8 +2678,8 @@ mod tests {
|
|||
let me_posix = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::Class, EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(2001)),
|
||||
]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
|
||||
|
@ -2766,8 +2760,8 @@ mod tests {
|
|||
let me_posix = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::Class, EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(2001)),
|
||||
]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
|
||||
|
@ -2803,7 +2797,7 @@ mod tests {
|
|||
let mut idms_prox_write = idms.proxy_write(duration_from_epoch_now()).await.unwrap();
|
||||
let me_purge_up = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::UnixPassword.into())]),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::UnixPassword)]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_purge_up).is_ok());
|
||||
assert!(idms_prox_write.commit().is_ok());
|
||||
|
@ -2843,7 +2837,7 @@ mod tests {
|
|||
ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_TESTPERSON_1))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::PasswordImport.into(),
|
||||
Attribute::PasswordImport,
|
||||
Value::from("{SSHA512}JwrSUHkI7FTAfHRVR6KoFlSN0E3dmaQWARjZ+/UsShYlENOqDtFVU77HJLLrY2MuSp0jve52+pwtdVl2QUAHukQ0XUf5LDtM")
|
||||
)]),
|
||||
);
|
||||
|
@ -2923,9 +2917,9 @@ mod tests {
|
|||
let me_posix = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::UnixPassword.into(), v_cred),
|
||||
Modify::Present(Attribute::Class, EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::UnixPassword, v_cred),
|
||||
]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
|
||||
|
@ -2978,8 +2972,8 @@ mod tests {
|
|||
let me_inv_m = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_TESTPERSON_1))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::AccountExpire.into(), v_expire),
|
||||
Modify::Present(Attribute::AccountValidFrom.into(), v_valid_from),
|
||||
Modify::Present(Attribute::AccountExpire, v_expire),
|
||||
Modify::Present(Attribute::AccountValidFrom, v_valid_from),
|
||||
]),
|
||||
);
|
||||
// go!
|
||||
|
@ -3068,8 +3062,8 @@ mod tests {
|
|||
let me_posix = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_TESTPERSON_1))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::Class, EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(2001)),
|
||||
]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
|
||||
|
@ -3434,8 +3428,8 @@ mod tests {
|
|||
let me_posix = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_TESTPERSON_1))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
|
||||
Modify::Present(Attribute::Class, EntryClass::PosixAccount.into()),
|
||||
Modify::Present(Attribute::GidNumber, Value::new_uint32(2001)),
|
||||
]),
|
||||
);
|
||||
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
|
||||
|
|
|
@ -235,10 +235,8 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
})?;
|
||||
|
||||
// modify the account to put the session onto it.
|
||||
let modlist = ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::ApiTokenSession.into(),
|
||||
session,
|
||||
)]);
|
||||
let modlist =
|
||||
ModifyList::new_list(vec![Modify::Present(Attribute::ApiTokenSession, session)]);
|
||||
|
||||
self.qs_write
|
||||
.impersonate_modify(
|
||||
|
@ -282,7 +280,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
) -> Result<(), OperationError> {
|
||||
// Delete the attribute with uuid.
|
||||
let modlist = ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::ApiTokenSession.into(),
|
||||
Attribute::ApiTokenSession,
|
||||
PartialValue::Refer(dte.token_id),
|
||||
)]);
|
||||
|
||||
|
@ -331,7 +329,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
let modlist = ModifyList::new_list(vec![
|
||||
m_purge(Attribute::PassKeys),
|
||||
m_purge(Attribute::PrimaryCredential),
|
||||
Modify::Present(Attribute::PrimaryCredential.into(), vcred),
|
||||
Modify::Present(Attribute::PrimaryCredential, vcred),
|
||||
]);
|
||||
|
||||
trace!(?modlist, "processing change");
|
||||
|
@ -395,9 +393,8 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
|
|||
issued_at: s.issued_at,
|
||||
purpose,
|
||||
})
|
||||
.map_err(|e| {
|
||||
admin_error!("Invalid api_token {}", u);
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
admin_error!(?err, "Invalid api_token {}", u);
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
|
|
|
@ -10,7 +10,6 @@ use kanidm_proto::internal::{
|
|||
use kanidm_proto::v1::Entry as ProtoEntry;
|
||||
// Should this be std?
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smartstring::alias::String as AttrString;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::schema::SchemaTransaction;
|
||||
|
@ -27,25 +26,25 @@ pub enum Modify {
|
|||
// This value *should* exist.
|
||||
// Clippy doesn't like value here, as value > pv. It could be an improvement to
|
||||
// box here, but not sure. ... TODO and thought needed.
|
||||
Present(AttrString, Value),
|
||||
Present(Attribute, Value),
|
||||
// This value *should not* exist.
|
||||
Removed(AttrString, PartialValue),
|
||||
Removed(Attribute, PartialValue),
|
||||
// This attr *should not* exist.
|
||||
Purged(AttrString),
|
||||
Purged(Attribute),
|
||||
// This attr and value must exist *in this state* for this change to proceed.
|
||||
Assert(Attribute, PartialValue),
|
||||
}
|
||||
|
||||
pub fn m_pres(attr: Attribute, v: &Value) -> Modify {
|
||||
Modify::Present(attr.into(), v.clone())
|
||||
Modify::Present(attr, v.clone())
|
||||
}
|
||||
|
||||
pub fn m_remove(attr: Attribute, v: &PartialValue) -> Modify {
|
||||
Modify::Removed(attr.into(), v.clone())
|
||||
Modify::Removed(attr, v.clone())
|
||||
}
|
||||
|
||||
pub fn m_purge(attr: Attribute) -> Modify {
|
||||
Modify::Purged(attr.into())
|
||||
Modify::Purged(attr)
|
||||
}
|
||||
|
||||
pub fn m_assert(attr: Attribute, v: &PartialValue) -> Modify {
|
||||
|
@ -58,9 +57,17 @@ impl Modify {
|
|||
qs: &mut QueryServerWriteTransaction,
|
||||
) -> Result<Self, OperationError> {
|
||||
Ok(match m {
|
||||
ProtoModify::Present(a, v) => Modify::Present(a.into(), qs.clone_value(a, v)?),
|
||||
ProtoModify::Removed(a, v) => Modify::Removed(a.into(), qs.clone_partialvalue(a, v)?),
|
||||
ProtoModify::Purged(a) => Modify::Purged(a.into()),
|
||||
ProtoModify::Present(a, v) => {
|
||||
let a = Attribute::from(a.as_str());
|
||||
let v = qs.clone_value(&a, v)?;
|
||||
Modify::Present(a, v)
|
||||
}
|
||||
ProtoModify::Removed(a, v) => {
|
||||
let a = Attribute::from(a.as_str());
|
||||
let v = qs.clone_partialvalue(&a, v)?;
|
||||
Modify::Removed(a, v)
|
||||
}
|
||||
ProtoModify::Purged(a) => Modify::Purged(Attribute::from(a.as_str())),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -99,15 +106,15 @@ impl ModifyList<ModifyInvalid> {
|
|||
}
|
||||
|
||||
pub fn new_purge_and_set(attr: Attribute, v: Value) -> Self {
|
||||
Self::new_list(vec![m_purge(attr), Modify::Present(attr.into(), v)])
|
||||
Self::new_list(vec![m_purge(attr.clone()), Modify::Present(attr, v)])
|
||||
}
|
||||
|
||||
pub fn new_append(attr: Attribute, v: Value) -> Self {
|
||||
Self::new_list(vec![Modify::Present(attr.into(), v)])
|
||||
Self::new_list(vec![Modify::Present(attr, v)])
|
||||
}
|
||||
|
||||
pub fn new_remove(attr: Attribute, pv: PartialValue) -> Self {
|
||||
Self::new_list(vec![Modify::Removed(attr.into(), pv)])
|
||||
Self::new_list(vec![Modify::Removed(attr, pv)])
|
||||
}
|
||||
|
||||
pub fn new_purge(attr: Attribute) -> Self {
|
||||
|
@ -141,13 +148,13 @@ impl ModifyList<ModifyInvalid> {
|
|||
|
||||
pe.attrs.iter().try_for_each(|(attr, vals)| {
|
||||
// Issue a purge to the attr.
|
||||
let attr: Attribute = attr.as_str().try_into()?;
|
||||
mods.push(m_purge(attr));
|
||||
let attr: Attribute = attr.as_str().into();
|
||||
mods.push(m_purge(attr.clone()));
|
||||
// Now if there are vals, push those too.
|
||||
// For each value we want to now be present.
|
||||
vals.iter().try_for_each(|val| {
|
||||
qs.clone_value(attr.as_ref(), val).map(|resolved_v| {
|
||||
mods.push(Modify::Present(attr.into(), resolved_v));
|
||||
qs.clone_value(&attr, val).map(|resolved_v| {
|
||||
mods.push(Modify::Present(attr.clone(), resolved_v));
|
||||
})
|
||||
})
|
||||
})?;
|
||||
|
@ -172,38 +179,28 @@ impl ModifyList<ModifyInvalid> {
|
|||
.mods
|
||||
.iter()
|
||||
.map(|m| match m {
|
||||
Modify::Present(attr, value) => {
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
Some(schema_a) => schema_a
|
||||
.validate_value(attr_norm.as_str(), value)
|
||||
.map(|_| Modify::Present(attr_norm, value.clone())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
}
|
||||
}
|
||||
Modify::Removed(attr, value) => {
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
Some(schema_a) => schema_a
|
||||
.validate_partialvalue(attr_norm.as_str(), value)
|
||||
.map(|_| Modify::Removed(attr_norm, value.clone())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
}
|
||||
}
|
||||
Modify::Assert(attr, value) => match schema_attributes.get(attr.as_ref()) {
|
||||
// TODO: given attr is an enum... you can't get this wrong anymore?
|
||||
Modify::Present(attr, value) => match schema_attributes.get(attr) {
|
||||
Some(schema_a) => schema_a
|
||||
.validate_partialvalue(attr.as_ref(), value)
|
||||
.map(|_| Modify::Assert(attr.to_owned(), value.clone())),
|
||||
.validate_value(attr, value)
|
||||
.map(|_| Modify::Present(attr.clone(), value.clone())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
},
|
||||
Modify::Removed(attr, value) => match schema_attributes.get(attr) {
|
||||
Some(schema_a) => schema_a
|
||||
.validate_partialvalue(attr, value)
|
||||
.map(|_| Modify::Removed(attr.clone(), value.clone())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
},
|
||||
Modify::Assert(attr, value) => match schema_attributes.get(attr) {
|
||||
Some(schema_a) => schema_a
|
||||
.validate_partialvalue(attr, value)
|
||||
.map(|_| Modify::Assert(attr.clone(), value.clone())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
},
|
||||
Modify::Purged(attr) => match schema_attributes.get(attr) {
|
||||
Some(_attr_name) => Ok(Modify::Purged(attr.clone())),
|
||||
None => Err(SchemaError::InvalidAttribute(attr.to_string())),
|
||||
},
|
||||
Modify::Purged(attr) => {
|
||||
let attr_norm = schema.normalise_attr_name(attr);
|
||||
match schema_attributes.get(&attr_norm) {
|
||||
Some(_attr_name) => Ok(Modify::Purged(attr_norm)),
|
||||
None => Err(SchemaError::InvalidAttribute(attr_norm.to_string())),
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -20,12 +20,12 @@ pub struct AttrUnique;
|
|||
fn get_cand_attr_set<'a, VALID: 'a, STATE: 'a, T>(
|
||||
// cand: &[Entry<VALID, STATE>],
|
||||
cand: T,
|
||||
uniqueattrs: &[AttrString],
|
||||
) -> Result<BTreeMap<(AttrString, PartialValue), Vec<Uuid>>, OperationError>
|
||||
uniqueattrs: &[Attribute],
|
||||
) -> Result<BTreeMap<(Attribute, PartialValue), Vec<Uuid>>, OperationError>
|
||||
where
|
||||
T: IntoIterator<Item = &'a Entry<VALID, STATE>>,
|
||||
{
|
||||
let mut cand_attr: BTreeMap<(AttrString, PartialValue), Vec<Uuid>> = BTreeMap::new();
|
||||
let mut cand_attr: BTreeMap<(Attribute, PartialValue), Vec<Uuid>> = BTreeMap::new();
|
||||
|
||||
cand.into_iter()
|
||||
// We don't need to consider recycled or tombstoned entries
|
||||
|
@ -39,16 +39,16 @@ where
|
|||
})?;
|
||||
|
||||
// Faster to iterate over the attr vec inside this loop.
|
||||
for attrstr in uniqueattrs.iter() {
|
||||
if let Some(vs) = e.get_ava_set(attrstr.try_into()?) {
|
||||
for attr in uniqueattrs.iter() {
|
||||
if let Some(vs) = e.get_ava_set(attr) {
|
||||
for pv in vs.to_partialvalue_iter() {
|
||||
let key = (attrstr.clone(), pv);
|
||||
let key = (attr.clone(), pv);
|
||||
cand_attr.entry(key)
|
||||
// Must have conflicted, lets append.
|
||||
.and_modify(|v| {
|
||||
warn!(
|
||||
"ava already exists -> {:?} on entry {:?} has conflicts within change set",
|
||||
attrstr,
|
||||
attr,
|
||||
e.get_display_id()
|
||||
);
|
||||
v.push(uuid)
|
||||
|
@ -120,8 +120,8 @@ fn enforce_unique<VALID, STATE>(
|
|||
// and[ attr eq k, andnot [ uuid eq v ]]
|
||||
// Basically this says where name but also not self.
|
||||
cand_filters.push(f_and(vec![
|
||||
FC::Eq(attr, v.clone()),
|
||||
f_andnot(FC::Eq(Attribute::Uuid.as_ref(), PartialValue::Uuid(*uuid))),
|
||||
FC::Eq(attr.clone(), v.clone()),
|
||||
f_andnot(FC::Eq(Attribute::Uuid, PartialValue::Uuid(*uuid))),
|
||||
]));
|
||||
}
|
||||
|
||||
|
@ -308,8 +308,8 @@ impl Plugin for AttrUnique {
|
|||
// and[ attr eq k, andnot [ uuid eq v ]]
|
||||
// Basically this says where name but also not self.
|
||||
f_and(vec![
|
||||
FC::Eq(attr, v.clone()),
|
||||
f_andnot(FC::Eq(Attribute::Uuid.as_ref(), PartialValue::Uuid(*uuid))),
|
||||
FC::Eq(attr.clone(), v.clone()),
|
||||
f_andnot(FC::Eq(Attribute::Uuid, PartialValue::Uuid(*uuid))),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
@ -364,8 +364,8 @@ impl Plugin for AttrUnique {
|
|||
.iter()
|
||||
.map(|(attr, pv)| {
|
||||
f_and(vec![
|
||||
FC::Eq(attr, pv.clone()),
|
||||
f_andnot(FC::Eq(Attribute::Uuid.as_ref(), PartialValue::Uuid(uuid))),
|
||||
FC::Eq(attr.clone(), pv.clone()),
|
||||
f_andnot(FC::Eq(Attribute::Uuid, PartialValue::Uuid(uuid))),
|
||||
])
|
||||
})
|
||||
.collect();
|
||||
|
@ -571,8 +571,8 @@ mod tests {
|
|||
PartialValue::new_iname("testgroup_b")
|
||||
),])),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::Name.into()),
|
||||
Modify::Present(Attribute::Name.into(), Value::new_iname("testgroup_a"))
|
||||
Modify::Purged(Attribute::Name),
|
||||
Modify::Present(Attribute::Name, Value::new_iname("testgroup_a"))
|
||||
]),
|
||||
None,
|
||||
|_| {},
|
||||
|
@ -606,8 +606,8 @@ mod tests {
|
|||
f_eq(Attribute::Name, PartialValue::new_iname("testgroup_b")),
|
||||
])),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::Name.into()),
|
||||
Modify::Present(Attribute::Name.into(), Value::new_iname("testgroup"))
|
||||
Modify::Purged(Attribute::Name),
|
||||
Modify::Present(Attribute::Name, Value::new_iname("testgroup"))
|
||||
]),
|
||||
None,
|
||||
|_| {},
|
||||
|
|
|
@ -45,7 +45,7 @@ impl Plugin for Base {
|
|||
// Generate
|
||||
let ava_uuid = Value::Uuid(Uuid::new_v4());
|
||||
trace!("Setting temporary UUID {:?} to entry", ava_uuid);
|
||||
entry.set_ava(Attribute::Uuid, once(ava_uuid));
|
||||
entry.set_ava(&Attribute::Uuid, once(ava_uuid));
|
||||
}
|
||||
Some(1) => {
|
||||
// Do nothing
|
||||
|
@ -124,7 +124,7 @@ impl Plugin for Base {
|
|||
let filt_in = filter_all!(FC::Or(
|
||||
cand_uuid
|
||||
.into_iter()
|
||||
.map(|u| FC::Eq(Attribute::Uuid.as_ref(), PartialValue::Uuid(u)))
|
||||
.map(|u| FC::Eq(Attribute::Uuid, PartialValue::Uuid(u)))
|
||||
.collect(),
|
||||
));
|
||||
|
||||
|
@ -169,7 +169,7 @@ impl Plugin for Base {
|
|||
Modify::Purged(a) => Some(a),
|
||||
Modify::Assert(_, _) => None,
|
||||
};
|
||||
if attr == Some(&AttrString::from(Attribute::Uuid)) {
|
||||
if attr == Some(&Attribute::Uuid) {
|
||||
debug!(?modify, "Modify in violation");
|
||||
request_error!("Modifications to UUID's are NOT ALLOWED");
|
||||
Err(OperationError::SystemProtectedAttribute)
|
||||
|
@ -196,7 +196,7 @@ impl Plugin for Base {
|
|||
Modify::Purged(a) => Some(a),
|
||||
Modify::Assert(_, _) => None,
|
||||
};
|
||||
if attr == Some(&AttrString::from(Attribute::Uuid)) {
|
||||
if attr == Some(&Attribute::Uuid) {
|
||||
debug!(?modify, "Modify in violation");
|
||||
request_error!("Modifications to UUID's are NOT ALLOWED");
|
||||
Err(OperationError::SystemProtectedAttribute)
|
||||
|
@ -616,7 +616,7 @@ mod tests {
|
|||
PartialValue::new_iname("testgroup_a")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Uuid.into(),
|
||||
Attribute::Uuid,
|
||||
Value::from("f15a7219-1d15-44e3-a7b4-bec899c07788")
|
||||
)]),
|
||||
None,
|
||||
|
@ -649,7 +649,7 @@ mod tests {
|
|||
PartialValue::new_iname("testgroup_a")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::Uuid.into(),
|
||||
Attribute::Uuid,
|
||||
PartialValue::Uuid(uuid!("f15a7219-1d15-44e3-a7b4-bec899c07788"))
|
||||
)]),
|
||||
None,
|
||||
|
@ -681,7 +681,7 @@ mod tests {
|
|||
Attribute::Name,
|
||||
PartialValue::new_iname("testgroup_a")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::Uuid.into())]),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::Uuid)]),
|
||||
None,
|
||||
|_| {},
|
||||
|_| {}
|
||||
|
|
|
@ -83,7 +83,7 @@ impl CredImport {
|
|||
Some(c) => {
|
||||
let c = c.update_password(pw);
|
||||
e.set_ava(
|
||||
Attribute::PrimaryCredential,
|
||||
&Attribute::PrimaryCredential,
|
||||
once(Value::new_credential("primary", c)),
|
||||
);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ impl CredImport {
|
|||
// just set it then!
|
||||
let c = Credential::new_from_password(pw);
|
||||
e.set_ava(
|
||||
Attribute::PrimaryCredential,
|
||||
&Attribute::PrimaryCredential,
|
||||
once(Value::new_credential("primary", c)),
|
||||
);
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ impl CredImport {
|
|||
acc.append_totp(label.clone(), totp.clone())
|
||||
});
|
||||
e.set_ava(
|
||||
Attribute::PrimaryCredential,
|
||||
&Attribute::PrimaryCredential,
|
||||
once(Value::new_credential("primary", c)),
|
||||
);
|
||||
} else {
|
||||
|
@ -153,7 +153,7 @@ impl CredImport {
|
|||
// Unix pw's aren't like primary, we can just splat them here.
|
||||
let c = Credential::new_from_password(pw);
|
||||
e.set_ava(
|
||||
Attribute::UnixPassword,
|
||||
&Attribute::UnixPassword,
|
||||
once(Value::new_credential("primary", c)),
|
||||
);
|
||||
};
|
||||
|
@ -235,7 +235,7 @@ mod tests {
|
|||
preload,
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::PasswordImport.into(),
|
||||
Attribute::PasswordImport,
|
||||
Value::from(IMPORT_HASH)
|
||||
)]),
|
||||
None,
|
||||
|
@ -278,7 +278,7 @@ mod tests {
|
|||
preload,
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::PasswordImport.into(),
|
||||
Attribute::PasswordImport,
|
||||
Value::from(IMPORT_HASH)
|
||||
)]),
|
||||
None,
|
||||
|
@ -324,7 +324,7 @@ mod tests {
|
|||
preload,
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::PasswordImport.into(),
|
||||
Attribute::PasswordImport,
|
||||
Value::from(IMPORT_HASH)
|
||||
)]),
|
||||
None,
|
||||
|
@ -378,15 +378,15 @@ mod tests {
|
|||
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(
|
||||
Attribute::PasswordImport.into(),
|
||||
Attribute::PasswordImport,
|
||||
Value::Utf8(IMPORT_HASH.to_string())
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::TotpImport.into(),
|
||||
Attribute::TotpImport,
|
||||
Value::TotpSecret("a".to_string(), totp_a.clone())
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::TotpImport.into(),
|
||||
Attribute::TotpImport,
|
||||
Value::TotpSecret("b".to_string(), totp_b.clone())
|
||||
)
|
||||
]),
|
||||
|
@ -443,7 +443,7 @@ mod tests {
|
|||
preload,
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::TotpImport.into(),
|
||||
Attribute::TotpImport,
|
||||
Value::TotpSecret("a".to_string(), totp_a)
|
||||
)]),
|
||||
None,
|
||||
|
@ -480,7 +480,7 @@ mod tests {
|
|||
preload,
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::UnixPasswordImport.into(),
|
||||
Attribute::UnixPasswordImport,
|
||||
Value::from(IMPORT_HASH)
|
||||
)]),
|
||||
None,
|
||||
|
|
|
@ -68,7 +68,7 @@ impl DefaultValues {
|
|||
e.add_ava(Attribute::Class, EntryClass::AccountPolicy.to_value());
|
||||
|
||||
if !e.attribute_pres(Attribute::AuthSessionExpiry) {
|
||||
e.set_ava(Attribute::AuthSessionExpiry, once(
|
||||
e.set_ava(&Attribute::AuthSessionExpiry, once(
|
||||
Value::Uint32(DEFAULT_AUTH_SESSION_EXPIRY),
|
||||
));
|
||||
debug!("default_values: idm_all_accounts - restore default auth_session_expiry");
|
||||
|
@ -76,7 +76,7 @@ impl DefaultValues {
|
|||
|
||||
// Setup the minimum functional level if one is not set already.
|
||||
if !e.attribute_pres(Attribute::PrivilegeExpiry) {
|
||||
e.set_ava(Attribute::PrivilegeExpiry, once(
|
||||
e.set_ava(&Attribute::PrivilegeExpiry, once(
|
||||
Value::Uint32(DEFAULT_AUTH_PRIVILEGE_EXPIRY),
|
||||
));
|
||||
debug!("default_values: idm_all_accounts - restore default privilege_session_expiry");
|
||||
|
@ -117,8 +117,8 @@ mod tests {
|
|||
.internal_modify_uuid(
|
||||
UUID_IDM_ALL_ACCOUNTS,
|
||||
&ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::AuthSessionExpiry.into()),
|
||||
Modify::Purged(Attribute::PrivilegeExpiry.into()),
|
||||
Modify::Purged(Attribute::AuthSessionExpiry),
|
||||
Modify::Purged(Attribute::PrivilegeExpiry),
|
||||
]),
|
||||
)
|
||||
.expect("failed to modify account");
|
||||
|
|
|
@ -91,20 +91,20 @@ impl Domain {
|
|||
|
||||
// We always set this, because the DB uuid is authoritative.
|
||||
let u = Value::Uuid(qs.get_domain_uuid());
|
||||
e.set_ava(Attribute::DomainUuid, once(u));
|
||||
e.set_ava(&Attribute::DomainUuid, once(u));
|
||||
trace!("plugin_domain: Applying uuid transform");
|
||||
|
||||
// We only apply this if one isn't provided.
|
||||
if !e.attribute_pres(Attribute::DomainName) {
|
||||
let n = Value::new_iname(qs.get_domain_name());
|
||||
e.set_ava(Attribute::DomainName, once(n));
|
||||
e.set_ava(&Attribute::DomainName, once(n));
|
||||
trace!("plugin_domain: Applying domain_name transform");
|
||||
}
|
||||
|
||||
// Setup the minimum functional level if one is not set already.
|
||||
if !e.attribute_pres(Attribute::Version) {
|
||||
let n = Value::Uint32(DOMAIN_LEVEL_0);
|
||||
e.set_ava(Attribute::Version, once(n));
|
||||
e.set_ava(&Attribute::Version, once(n));
|
||||
warn!("plugin_domain: Applying domain version transform");
|
||||
} else {
|
||||
debug!("plugin_domain: NOT Applying domain version transform");
|
||||
|
@ -115,7 +115,7 @@ impl Domain {
|
|||
let domain_display_name = Value::new_utf8(format!("Kanidm {}", qs.get_domain_name()));
|
||||
security_info!("plugin_domain: setting default domain_display_name to {:?}", domain_display_name);
|
||||
|
||||
e.set_ava(Attribute::DomainDisplayName, once(domain_display_name));
|
||||
e.set_ava(&Attribute::DomainDisplayName, once(domain_display_name));
|
||||
}
|
||||
|
||||
if qs.get_domain_version() < DOMAIN_LEVEL_6 && !e.attribute_pres(Attribute::FernetPrivateKeyStr) {
|
||||
|
|
|
@ -103,7 +103,7 @@ impl DynGroup {
|
|||
|
||||
if let Some(members) = members {
|
||||
// Only set something if there is actually something to do!
|
||||
nd_group.set_ava_set(Attribute::DynMember, members);
|
||||
nd_group.set_ava_set(&Attribute::DynMember, members);
|
||||
// push the entries to pre/cand
|
||||
} else {
|
||||
nd_group.purge_ava(Attribute::DynMember);
|
||||
|
@ -659,7 +659,7 @@ mod tests {
|
|||
ModifyList::new_list(vec![
|
||||
Modify::Purged("dyngroup_filter".into()),
|
||||
Modify::Present(
|
||||
Attribute::DynGroupFilter.into(),
|
||||
Attribute::DynGroupFilter,
|
||||
Value::JsonFilt(ProtoFilter::Eq(
|
||||
Attribute::Name.to_string(),
|
||||
"testgroup".to_string()
|
||||
|
@ -720,7 +720,7 @@ mod tests {
|
|||
ModifyList::new_list(vec![
|
||||
Modify::Purged("dyngroup_filter".into()),
|
||||
Modify::Present(
|
||||
Attribute::DynGroupFilter.into(),
|
||||
Attribute::DynGroupFilter,
|
||||
Value::JsonFilt(ProtoFilter::Eq(
|
||||
Attribute::Name.to_string(),
|
||||
"no_such_entry_exists".to_string()
|
||||
|
@ -775,7 +775,7 @@ mod tests {
|
|||
PartialValue::new_iname("test_dyngroup")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::DynMember.into(),
|
||||
Attribute::DynMember,
|
||||
Value::Refer(UUID_ADMIN)
|
||||
)]),
|
||||
None,
|
||||
|
@ -830,7 +830,7 @@ mod tests {
|
|||
Attribute::Name,
|
||||
PartialValue::new_iname("test_dyngroup")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::DynMember.into(),)]),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::DynMember,)]),
|
||||
None,
|
||||
|_| {},
|
||||
|qs: &mut QueryServerWriteTransaction| {
|
||||
|
@ -883,8 +883,8 @@ mod tests {
|
|||
PartialValue::new_iname("not_testgroup")
|
||||
)),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::Name.into(),),
|
||||
Modify::Present(Attribute::Name.into(), Value::new_iname("testgroup"))
|
||||
Modify::Purged(Attribute::Name,),
|
||||
Modify::Present(Attribute::Name, Value::new_iname("testgroup"))
|
||||
]),
|
||||
None,
|
||||
|_| {},
|
||||
|
@ -935,8 +935,8 @@ mod tests {
|
|||
preload,
|
||||
filter!(f_eq(Attribute::Name, PartialValue::new_iname("testgroup"))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::Name.into(),),
|
||||
Modify::Present(Attribute::Name.into(), Value::new_iname("not_testgroup"))
|
||||
Modify::Purged(Attribute::Name,),
|
||||
Modify::Present(Attribute::Name, Value::new_iname("not_testgroup"))
|
||||
]),
|
||||
None,
|
||||
|_| {},
|
||||
|
|
|
@ -86,7 +86,7 @@ fn apply_gidnumber<T: Clone>(
|
|||
|
||||
let gid_v = Value::new_uint32(gid);
|
||||
admin_info!("Generated {} for {:?}", gid, u_ref);
|
||||
e.set_ava(Attribute::GidNumber, once(gid_v));
|
||||
e.set_ava(&Attribute::GidNumber, once(gid_v));
|
||||
Ok(())
|
||||
} else if let Some(gid) = e.get_ava_single_uint32(Attribute::GidNumber) {
|
||||
if domain_version <= DOMAIN_LEVEL_6 {
|
||||
|
|
|
@ -211,8 +211,8 @@ mod tests {
|
|||
preload,
|
||||
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(uuid))),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::OAuth2RsBasicSecret.into(),),
|
||||
Modify::Purged(Attribute::OAuth2RsTokenKey.into(),)
|
||||
Modify::Purged(Attribute::OAuth2RsBasicSecret,),
|
||||
Modify::Purged(Attribute::OAuth2RsTokenKey,)
|
||||
]),
|
||||
None,
|
||||
|_| {},
|
||||
|
|
|
@ -220,7 +220,7 @@ impl KeyObjectManagement {
|
|||
.as_valuesets()?
|
||||
.into_iter()
|
||||
.try_for_each(|(attribute, valueset)| {
|
||||
entry.merge_ava_set(attribute, valueset)
|
||||
entry.merge_ava_set(&attribute, valueset)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -65,7 +65,7 @@ fn do_group_memberof(
|
|||
// Add all the direct mo's and mos.
|
||||
if let Some(dmo) = dmo {
|
||||
// We need to clone this else type checker gets real sad.
|
||||
tgte.set_ava_set(Attribute::DirectMemberOf, dmo.clone());
|
||||
tgte.set_ava_set(&Attribute::DirectMemberOf, dmo.clone());
|
||||
|
||||
if let Some(mo) = &mut mo {
|
||||
let dmo = dmo as ValueSet;
|
||||
|
@ -78,7 +78,7 @@ fn do_group_memberof(
|
|||
};
|
||||
|
||||
if let Some(mo) = mo {
|
||||
tgte.set_ava_set(Attribute::MemberOf, mo);
|
||||
tgte.set_ava_set(&Attribute::MemberOf, mo);
|
||||
}
|
||||
|
||||
trace!(
|
||||
|
@ -205,7 +205,7 @@ fn do_leaf_memberof(
|
|||
dmo_set.insert(group_uuid);
|
||||
} else {
|
||||
let dmo = ValueSetRefer::new(group_uuid);
|
||||
tgte.set_ava_set(Attribute::DirectMemberOf, dmo);
|
||||
tgte.set_ava_set(&Attribute::DirectMemberOf, dmo);
|
||||
}
|
||||
|
||||
// We're also in member of this group.
|
||||
|
@ -213,7 +213,7 @@ fn do_leaf_memberof(
|
|||
mo_set.insert(group_uuid);
|
||||
} else {
|
||||
let mo = ValueSetRefer::new(group_uuid);
|
||||
tgte.set_ava_set(Attribute::MemberOf, mo);
|
||||
tgte.set_ava_set(&Attribute::MemberOf, mo);
|
||||
}
|
||||
|
||||
// If the group has memberOf attributes, we propogate these to
|
||||
|
@ -510,7 +510,7 @@ impl Plugin for MemberOf {
|
|||
|
||||
for entry in cand.iter_mut() {
|
||||
if let Some(direct_mo_vs) = entry.pop_ava(Attribute::DirectMemberOf) {
|
||||
entry.set_ava_set(Attribute::RecycledDirectMemberOf, direct_mo_vs);
|
||||
entry.set_ava_set(&Attribute::RecycledDirectMemberOf, direct_mo_vs);
|
||||
} else {
|
||||
// Ensure it's empty
|
||||
entry.purge_ava(Attribute::RecycledDirectMemberOf);
|
||||
|
@ -1074,7 +1074,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_A).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(UUID_B).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1113,7 +1113,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_A).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(UUID_B).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1170,7 +1170,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_B).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(UUID_C).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1230,7 +1230,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_C).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(UUID_A).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1297,7 +1297,7 @@ mod tests {
|
|||
f_eq(Attribute::Uuid, PartialValue::new_uuid_s(UUID_D).unwrap()),
|
||||
])),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(UUID_A).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1369,7 +1369,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_A).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
PartialValue::new_refer_s(UUID_B).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1411,7 +1411,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_A).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
PartialValue::new_refer_s(UUID_B).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1472,7 +1472,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_B).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
PartialValue::new_refer_s(UUID_C).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1543,7 +1543,7 @@ mod tests {
|
|||
PartialValue::new_uuid_s(UUID_C).unwrap()
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
PartialValue::new_refer_s(UUID_A).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -1633,11 +1633,11 @@ mod tests {
|
|||
)),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Removed(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
PartialValue::new_refer_s(UUID_A).unwrap()
|
||||
),
|
||||
Modify::Removed(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
PartialValue::new_refer_s(UUID_D).unwrap()
|
||||
),
|
||||
]),
|
||||
|
|
|
@ -13,25 +13,12 @@ pub struct NameHistory {}
|
|||
lazy_static! {
|
||||
// it contains all the partialvalues used to match against an Entry's class,
|
||||
// we just need a partialvalue to match in order to target the entry
|
||||
static ref CLASSES_TO_UPDATE: [PartialValue; 1] = [PartialValue::new_iutf8(EntryClass::Account.into())];
|
||||
}
|
||||
|
||||
const HISTORY_ATTRIBUTES: [Attribute; 1] = [Attribute::Name];
|
||||
|
||||
#[test]
|
||||
fn test_history_attribute() {
|
||||
assert_eq!(NameHistory::get_ava_name(Attribute::Name), "name_history");
|
||||
static ref CLASS_TO_UPDATE: PartialValue = PartialValue::new_iutf8(EntryClass::Account.into());
|
||||
}
|
||||
|
||||
impl NameHistory {
|
||||
fn is_entry_to_update<VALUE, STATE>(entry: &mut Entry<VALUE, STATE>) -> bool {
|
||||
CLASSES_TO_UPDATE
|
||||
.iter()
|
||||
.any(|pv| entry.attribute_equality(Attribute::Class, pv))
|
||||
}
|
||||
|
||||
fn get_ava_name(history_attr: Attribute) -> String {
|
||||
format!("{}_history", history_attr)
|
||||
entry.attribute_equality(Attribute::Class, &CLASS_TO_UPDATE)
|
||||
}
|
||||
|
||||
fn handle_name_updates(
|
||||
|
@ -42,22 +29,16 @@ impl NameHistory {
|
|||
for (pre, post) in pre_cand.iter().zip(cand) {
|
||||
// here we check if the current entry has at least one of the classes we intend to target
|
||||
if Self::is_entry_to_update(post) {
|
||||
for history_attr in HISTORY_ATTRIBUTES.into_iter() {
|
||||
let pre_name_option = pre.get_ava_single(history_attr);
|
||||
let post_name_option = post.get_ava_single(history_attr);
|
||||
if let (Some(pre_name), Some(post_name)) = (pre_name_option, post_name_option) {
|
||||
if pre_name != post_name {
|
||||
let ava_name = Self::get_ava_name(history_attr);
|
||||
//// WARNING!!! this match will have to be adjusted based on what kind of attribute
|
||||
//// we are matching on, for example for displayname we would have to use Value::utf8 instead!!
|
||||
// as of now we're interested just in the name so we use Iname
|
||||
match post_name {
|
||||
Value::Iname(n) => post.add_ava_if_not_exist(
|
||||
ava_name.as_str().try_into()?,
|
||||
Value::AuditLogString(cid.clone(), n),
|
||||
),
|
||||
_ => return Err(OperationError::InvalidValueState),
|
||||
}
|
||||
let pre_name_option = pre.get_ava_single(Attribute::Name);
|
||||
let post_name_option = post.get_ava_single(Attribute::Name);
|
||||
if let (Some(pre_name), Some(post_name)) = (pre_name_option, post_name_option) {
|
||||
if pre_name != post_name {
|
||||
match post_name {
|
||||
Value::Iname(n) => post.add_ava_if_not_exist(
|
||||
Attribute::NameHistory,
|
||||
Value::AuditLogString(cid.clone(), n),
|
||||
),
|
||||
_ => return Err(OperationError::InvalidValueState),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,16 +53,13 @@ impl NameHistory {
|
|||
) -> Result<(), OperationError> {
|
||||
for cand in cands.iter_mut() {
|
||||
if Self::is_entry_to_update(cand) {
|
||||
for history_attr in HISTORY_ATTRIBUTES.into_iter() {
|
||||
if let Some(name) = cand.get_ava_single(history_attr) {
|
||||
let ava_name = Self::get_ava_name(history_attr);
|
||||
match name {
|
||||
Value::Iname(n) => cand.add_ava_if_not_exist(
|
||||
ava_name.as_str().try_into()?,
|
||||
Value::AuditLogString(cid.clone(), n),
|
||||
),
|
||||
_ => return Err(OperationError::InvalidValueState),
|
||||
}
|
||||
if let Some(name) = cand.get_ava_single(Attribute::Name) {
|
||||
match name {
|
||||
Value::Iname(n) => cand.add_ava_if_not_exist(
|
||||
Attribute::NameHistory,
|
||||
Value::AuditLogString(cid.clone(), n),
|
||||
),
|
||||
_ => return Err(OperationError::InvalidValueState),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,9 +149,8 @@ impl Plugin for Protected {
|
|||
Modify::Present(a, _) | Modify::Removed(a, _) | Modify::Purged(a) => Some(a),
|
||||
Modify::Assert(_, _) => None,
|
||||
};
|
||||
if let Some(a) = a {
|
||||
let attr: Attribute = a.try_into()?;
|
||||
match ALLOWED_ATTRS.contains(&attr) {
|
||||
if let Some(attr) = a {
|
||||
match ALLOWED_ATTRS.contains(attr) {
|
||||
true => Ok(()),
|
||||
false => {
|
||||
trace!("If you're getting this, you need to modify the ALLOWED_ATTRS list");
|
||||
|
@ -229,9 +228,8 @@ impl Plugin for Protected {
|
|||
Modify::Present(a, _) | Modify::Removed(a, _) | Modify::Purged(a) => Some(a),
|
||||
Modify::Assert(_, _) => None,
|
||||
};
|
||||
if let Some(a) = a {
|
||||
let attr: Attribute = a.try_into()?;
|
||||
match ALLOWED_ATTRS.contains(&attr) {
|
||||
if let Some(attr) = a {
|
||||
match ALLOWED_ATTRS.contains(attr) {
|
||||
true => Ok(()),
|
||||
false => {
|
||||
|
||||
|
|
|
@ -103,24 +103,9 @@ impl ReferentialIntegrity {
|
|||
let filt = filter_all!(FC::Or(
|
||||
uuids
|
||||
.into_iter()
|
||||
.flat_map(|u| ref_types.values().filter_map(move |r_type| {
|
||||
let value_attribute = r_type.name.to_string();
|
||||
// For everything that references the uuid's in the deleted set.
|
||||
let val: Result<Attribute, OperationError> = value_attribute.as_str().try_into();
|
||||
// error!("{:?}", val);
|
||||
let res = match val {
|
||||
Ok(val) => {
|
||||
let res = f_eq(val, PartialValue::Refer(u));
|
||||
Some(res)
|
||||
}
|
||||
Err(err) => {
|
||||
// we shouldn't be able to get here...
|
||||
admin_error!("post_delete invalid attribute specified - please log this as a bug! {:?}", err);
|
||||
None
|
||||
}
|
||||
};
|
||||
res
|
||||
}))
|
||||
.flat_map(|u| ref_types
|
||||
.values()
|
||||
.map(move |r_type| { f_eq(r_type.name.clone(), PartialValue::Refer(u)) }))
|
||||
.collect(),
|
||||
));
|
||||
|
||||
|
@ -130,8 +115,7 @@ impl ReferentialIntegrity {
|
|||
|
||||
for (_, post) in work_set.iter_mut() {
|
||||
for schema_attribute in ref_types.values() {
|
||||
let attribute = (&schema_attribute.name).try_into()?;
|
||||
post.remove_avas(attribute, &removed_ids);
|
||||
post.remove_avas(&schema_attribute.name, &removed_ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,19 +308,8 @@ impl Plugin for ReferentialIntegrity {
|
|||
for c in &all_cand {
|
||||
// For all reference in each cand.
|
||||
for rtype in ref_types.values() {
|
||||
let attr: Attribute = match (&rtype.name).try_into() {
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
// we shouldn't be able to get here...
|
||||
admin_error!("verify referential integrity invalid attribute {} specified - please log this as a bug! {:?}", &rtype.name, err);
|
||||
res.push(Err(ConsistencyError::InvalidAttributeType(
|
||||
rtype.name.to_string(),
|
||||
)));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// If the attribute is present
|
||||
if let Some(vs) = c.get_ava_set(attr) {
|
||||
if let Some(vs) = c.get_ava_set(&rtype.name) {
|
||||
// For each value in the set.
|
||||
match vs.as_ref_uuid_iter() {
|
||||
Some(uuid_iter) => {
|
||||
|
@ -359,7 +332,7 @@ impl Plugin for ReferentialIntegrity {
|
|||
}
|
||||
|
||||
fn update_reference_set<'a, I>(
|
||||
ref_types: &HashMap<AttrString, SchemaAttribute>,
|
||||
ref_types: &HashMap<Attribute, SchemaAttribute>,
|
||||
entry_iter: I,
|
||||
reference_set: &mut BTreeSet<Uuid>,
|
||||
) -> Result<(), OperationError>
|
||||
|
@ -374,23 +347,14 @@ where
|
|||
// For all reference types that exist in the schema.
|
||||
let cand_ref_valuesets = ref_types.values().filter_map(|rtype| {
|
||||
// If the entry is a dyn-group, skip dyn member.
|
||||
let skip_mb = dyn_group && rtype.name == Attribute::DynMember.as_ref();
|
||||
let skip_mb = dyn_group && rtype.name == Attribute::DynMember;
|
||||
// MemberOf is always recalculated, so it can be skipped
|
||||
let skip_mo = rtype.name == Attribute::MemberOf.as_ref();
|
||||
let skip_mo = rtype.name == Attribute::MemberOf;
|
||||
|
||||
if skip_mb || skip_mo {
|
||||
None
|
||||
} else {
|
||||
trace!(rtype_name = ?rtype.name, "examining");
|
||||
cand.get_ava_set(
|
||||
(&rtype.name)
|
||||
.try_into()
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "invalid attribute type {}", &rtype.name);
|
||||
None::<Attribute>
|
||||
})
|
||||
.ok()?,
|
||||
)
|
||||
cand.get_ava_set(&rtype.name)
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -399,8 +363,8 @@ where
|
|||
reference_set.extend(uuid_iter);
|
||||
Ok(())
|
||||
} else {
|
||||
admin_error!(?vs, "reference value could not convert to reference uuid.");
|
||||
admin_error!("If you are sure the name/uuid/spn exist, and that this is in error, you should run a verify task.");
|
||||
error!(?vs, "reference value could not convert to reference uuid.");
|
||||
error!("If you are sure the name/uuid/spn exist, and that this is in error, you should run a verify task.");
|
||||
Err(OperationError::InvalidAttribute(
|
||||
"uuid could not become reference value".to_string(),
|
||||
))
|
||||
|
@ -623,7 +587,7 @@ mod tests {
|
|||
PartialValue::new_iname("testgroup_b")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(TEST_TESTGROUP_A_UUID).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -657,7 +621,7 @@ mod tests {
|
|||
PartialValue::new_iname("testgroup_b")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(TEST_TESTGROUP_A_UUID).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -704,10 +668,10 @@ mod tests {
|
|||
)),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::Refer(Uuid::parse_str(TEST_TESTGROUP_A_UUID).unwrap())
|
||||
),
|
||||
Modify::Present(Attribute::Member.into(), Value::Refer(UUID_DOES_NOT_EXIST)),
|
||||
Modify::Present(Attribute::Member, Value::Refer(UUID_DOES_NOT_EXIST)),
|
||||
]),
|
||||
None,
|
||||
|_| {},
|
||||
|
@ -749,7 +713,7 @@ mod tests {
|
|||
Attribute::Name,
|
||||
PartialValue::new_iname("testgroup_b")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::Member.into())]),
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::Member)]),
|
||||
None,
|
||||
|_| {},
|
||||
|_| {}
|
||||
|
@ -780,7 +744,7 @@ mod tests {
|
|||
PartialValue::new_iname("testgroup_a")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(TEST_TESTGROUP_A_UUID).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -825,7 +789,7 @@ mod tests {
|
|||
PartialValue::new_iname("testgroup_b")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Member.into(),
|
||||
Attribute::Member,
|
||||
Value::new_refer_s(TEST_TESTGROUP_A_UUID).unwrap()
|
||||
)]),
|
||||
None,
|
||||
|
@ -927,7 +891,7 @@ mod tests {
|
|||
|
||||
run_delete_test!(
|
||||
Err(OperationError::SchemaViolation(
|
||||
SchemaError::MissingMustAttribute(vec!["acp_receiver_group".to_string()])
|
||||
SchemaError::MissingMustAttribute(vec![Attribute::AcpReceiverGroup])
|
||||
)),
|
||||
preload,
|
||||
filter!(f_eq(
|
||||
|
@ -1143,7 +1107,7 @@ mod tests {
|
|||
// Mod the user
|
||||
let modlist = modlist!([
|
||||
Modify::Present(
|
||||
Attribute::OAuth2Session.into(),
|
||||
Attribute::OAuth2Session,
|
||||
Value::Oauth2Session(
|
||||
session_id,
|
||||
Oauth2Session {
|
||||
|
@ -1156,7 +1120,7 @@ mod tests {
|
|||
)
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::UserAuthTokenSession.into(),
|
||||
Attribute::UserAuthTokenSession,
|
||||
Value::Session(
|
||||
parent_id,
|
||||
Session {
|
||||
|
|
|
@ -403,7 +403,7 @@ mod tests {
|
|||
)
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::UserAuthTokenSession.into(),
|
||||
Attribute::UserAuthTokenSession,
|
||||
Value::Session(
|
||||
parent_id,
|
||||
Session {
|
||||
|
@ -576,7 +576,7 @@ mod tests {
|
|||
)
|
||||
),
|
||||
Modify::Present(
|
||||
Attribute::UserAuthTokenSession.into(),
|
||||
Attribute::UserAuthTokenSession,
|
||||
Value::Session(
|
||||
parent_id,
|
||||
Session {
|
||||
|
|
|
@ -166,7 +166,7 @@ impl Spn {
|
|||
Attribute::Spn,
|
||||
spn
|
||||
);
|
||||
ent.set_ava(Attribute::Spn, once(spn));
|
||||
ent.set_ava(&Attribute::Spn, once(spn));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -118,7 +118,7 @@ mod tests {
|
|||
let me_inv_m = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_eq(Attribute::Uuid, PVUUID_SYSTEM_CONFIG.clone())),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::DeniedName.into(),
|
||||
Attribute::DeniedName,
|
||||
Value::new_iname("tobias"),
|
||||
)]),
|
||||
);
|
||||
|
|
|
@ -41,10 +41,12 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
|
||||
trace!(?ctx_entries);
|
||||
|
||||
let db_entries = self.be_txn.incremental_prepare(&ctx_entries).map_err(|e| {
|
||||
error!("Failed to access entries from db");
|
||||
e
|
||||
})?;
|
||||
let db_entries = self
|
||||
.be_txn
|
||||
.incremental_prepare(&ctx_entries)
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to access entries from db");
|
||||
})?;
|
||||
|
||||
trace!(?db_entries);
|
||||
|
||||
|
@ -366,9 +368,11 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
let ruv = self.be_txn.get_ruv_write();
|
||||
|
||||
ruv.incremental_preflight_validate_ruv(ctx_ranges, &txn_cid)
|
||||
.map_err(|e| {
|
||||
error!("Incoming RUV failed preflight checks, unable to proceed.");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(
|
||||
?err,
|
||||
"Incoming RUV failed preflight checks, unable to proceed."
|
||||
);
|
||||
})?;
|
||||
|
||||
// == ⚠️ Below this point we begin to make changes! ==
|
||||
|
@ -383,16 +387,14 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
// Apply the schema entries first.
|
||||
let schema_changed = self
|
||||
.consumer_incremental_apply_entries(ctx_schema_entries)
|
||||
.map_err(|e| {
|
||||
error!("Failed to apply incremental schema entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to apply incremental schema entries");
|
||||
})?;
|
||||
|
||||
if schema_changed {
|
||||
// We need to reload schema now!
|
||||
self.reload_schema().map_err(|e| {
|
||||
error!("Failed to reload schema");
|
||||
e
|
||||
self.reload_schema().inspect_err(|err| {
|
||||
error!(?err, "Failed to reload schema");
|
||||
})?;
|
||||
}
|
||||
|
||||
|
@ -400,29 +402,25 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
// Apply meta entries now.
|
||||
let meta_changed = self
|
||||
.consumer_incremental_apply_entries(ctx_meta_entries)
|
||||
.map_err(|e| {
|
||||
error!("Failed to apply incremental schema entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to apply incremental schema entries");
|
||||
})?;
|
||||
|
||||
// This is re-loaded in case the domain name changed on the remote
|
||||
if meta_changed {
|
||||
self.reload_domain_info().map_err(|e| {
|
||||
error!("Failed to reload domain info");
|
||||
e
|
||||
self.reload_domain_info().inspect_err(|err| {
|
||||
error!(?err, "Failed to reload domain info");
|
||||
})?;
|
||||
self.reload_system_config().map_err(|e| {
|
||||
error!("Failed to reload system configuration");
|
||||
e
|
||||
self.reload_system_config().inspect_err(|err| {
|
||||
error!(?err, "Failed to reload system configuration");
|
||||
})?;
|
||||
}
|
||||
|
||||
debug!("Applying all context entries");
|
||||
// Update all other entries now.
|
||||
self.consumer_incremental_apply_entries(ctx_entries)
|
||||
.map_err(|e| {
|
||||
error!("Failed to apply incremental schema entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to apply incremental schema entries");
|
||||
})?;
|
||||
|
||||
// Reload the domain version, doing any needed migrations.
|
||||
|
@ -432,9 +430,8 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
// was just migrated. As a result, we only need to apply the migrations to entries
|
||||
// that were not on the supplier, and therefore need updates here.
|
||||
if meta_changed {
|
||||
self.reload_domain_info_version().map_err(|e| {
|
||||
error!("Failed to reload domain info version");
|
||||
e
|
||||
self.reload_domain_info_version().inspect_err(|err| {
|
||||
error!(?err, "Failed to reload domain info version");
|
||||
})?;
|
||||
}
|
||||
|
||||
|
@ -442,14 +439,12 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
// context. Note that we get this in a writeable form!
|
||||
let ruv = self.be_txn.get_ruv_write();
|
||||
|
||||
ruv.refresh_validate_ruv(ctx_ranges).map_err(|e| {
|
||||
error!("RUV ranges were not rebuilt correctly.");
|
||||
e
|
||||
ruv.refresh_validate_ruv(ctx_ranges).inspect_err(|err| {
|
||||
error!(?err, "RUV ranges were not rebuilt correctly.");
|
||||
})?;
|
||||
|
||||
ruv.refresh_update_ruv(ctx_ranges).map_err(|e| {
|
||||
error!("Unable to update RUV with supplier ranges.");
|
||||
e
|
||||
ruv.refresh_update_ruv(ctx_ranges).inspect_err(|err| {
|
||||
error!(?err, "Unable to update RUV with supplier ranges.");
|
||||
})?;
|
||||
|
||||
Ok(ConsumerState::Ok)
|
||||
|
@ -488,9 +483,8 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
.iter()
|
||||
.map(EntryRefreshNew::from_repl_entry_v1)
|
||||
.collect::<Result<Vec<EntryRefreshNew>, _>>()
|
||||
.map_err(|e| {
|
||||
error!("Failed to convert entries from supplier");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to convert entries from supplier");
|
||||
})?;
|
||||
|
||||
Plugins::run_pre_repl_refresh(self, candidates.as_slice()).map_err(|e| {
|
||||
|
@ -573,10 +567,11 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
// == ⚠️ Below this point we begin to make changes! ==
|
||||
|
||||
// Update the d_uuid. This is what defines us as being part of this repl topology!
|
||||
self.be_txn.set_db_d_uuid(ctx_domain_uuid).map_err(|e| {
|
||||
error!("Failed to reset domain uuid");
|
||||
e
|
||||
})?;
|
||||
self.be_txn
|
||||
.set_db_d_uuid(ctx_domain_uuid)
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to reset domain uuid");
|
||||
})?;
|
||||
|
||||
// We need to reset our server uuid now. This is so that any other servers
|
||||
// which had our former server_uuid in their RUV, is able to start to age it
|
||||
|
@ -585,51 +580,46 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
|
||||
// Delete all entries - *proper delete, not just tombstone!*
|
||||
|
||||
self.be_txn.danger_delete_all_db_content().map_err(|e| {
|
||||
error!("Failed to clear existing server database content");
|
||||
e
|
||||
})?;
|
||||
self.be_txn
|
||||
.danger_delete_all_db_content()
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to clear existing server database content");
|
||||
})?;
|
||||
|
||||
// Reset this transactions schema to a completely clean slate.
|
||||
self.schema.generate_in_memory().map_err(|e| {
|
||||
error!("Failed to reset in memory schema to clean state");
|
||||
e
|
||||
self.schema.generate_in_memory().inspect_err(|err| {
|
||||
error!(?err, "Failed to reset in memory schema to clean state");
|
||||
})?;
|
||||
|
||||
// Apply the schema entries first. This is the foundation that everything
|
||||
// else will build upon!
|
||||
self.consumer_refresh_create_entries(ctx_schema_entries)
|
||||
.map_err(|e| {
|
||||
error!("Failed to refresh schema entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to refresh schema entries");
|
||||
})?;
|
||||
|
||||
// We need to reload schema now!
|
||||
self.reload_schema().map_err(|e| {
|
||||
error!("Failed to reload schema");
|
||||
e
|
||||
self.reload_schema().inspect_err(|err| {
|
||||
error!(?err, "Failed to reload schema");
|
||||
})?;
|
||||
|
||||
// We have to reindex to force all the existing indexes to be dumped
|
||||
// and recreated before we start to import.
|
||||
self.reindex().map_err(|e| {
|
||||
error!("Failed to reload schema");
|
||||
e
|
||||
self.reindex().inspect_err(|err| {
|
||||
error!(?err, "Failed to reload schema");
|
||||
})?;
|
||||
|
||||
// Apply the domain info entry / system info / system config entry?
|
||||
self.consumer_refresh_create_entries(ctx_meta_entries)
|
||||
.map_err(|e| {
|
||||
error!("Failed to refresh meta entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to refresh meta entries");
|
||||
})?;
|
||||
|
||||
// NOTE: The domain info we receive here will have the domain version populated!
|
||||
// That's okay though, because all the incoming data is already at the right
|
||||
// version!
|
||||
self.reload_domain_info().map_err(|e| {
|
||||
error!("Failed to reload domain info");
|
||||
e
|
||||
self.reload_domain_info().inspect_err(|err| {
|
||||
error!(?err, "Failed to reload domain info");
|
||||
})?;
|
||||
|
||||
// Mark that everything changed so that post commit hooks function as expected.
|
||||
|
@ -648,23 +638,20 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
|
||||
// Create all the entries. Note we don't hit plugins here beside post repl plugs.
|
||||
self.consumer_refresh_create_entries(ctx_entries)
|
||||
.map_err(|e| {
|
||||
error!("Failed to refresh schema entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to refresh schema entries");
|
||||
})?;
|
||||
|
||||
// Finally, confirm that the ranges that we have recreated match the ranges from our
|
||||
// context. Note that we get this in a writeable form!
|
||||
let ruv = self.be_txn.get_ruv_write();
|
||||
|
||||
ruv.refresh_validate_ruv(ctx_ranges).map_err(|e| {
|
||||
error!("RUV ranges were not rebuilt correctly.");
|
||||
e
|
||||
ruv.refresh_validate_ruv(ctx_ranges).inspect_err(|err| {
|
||||
error!(?err, "RUV ranges were not rebuilt correctly.");
|
||||
})?;
|
||||
|
||||
ruv.refresh_update_ruv(ctx_ranges).map_err(|e| {
|
||||
error!("Unable to update RUV with supplier ranges.");
|
||||
e
|
||||
ruv.refresh_update_ruv(ctx_ranges).inspect_err(|err| {
|
||||
error!(?err, "Unable to update RUV with supplier ranges.");
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::collections::BTreeMap;
|
|||
pub enum State {
|
||||
Live {
|
||||
at: Cid,
|
||||
changes: BTreeMap<AttrString, Cid>,
|
||||
changes: BTreeMap<Attribute, Cid>,
|
||||
},
|
||||
Tombstone {
|
||||
at: Cid,
|
||||
|
@ -40,7 +40,7 @@ impl EntryChangeState {
|
|||
}
|
||||
|
||||
pub fn new_without_schema(cid: &Cid, attrs: &Eattrs) -> Self {
|
||||
let class = attrs.get(Attribute::Class.as_ref());
|
||||
let class = attrs.get(&Attribute::Class);
|
||||
let st = if class
|
||||
.as_ref()
|
||||
.map(|c| c.contains(&EntryClass::Tombstone.to_partialvalue()))
|
||||
|
@ -75,7 +75,7 @@ impl EntryChangeState {
|
|||
.iter()
|
||||
.map(|(attr, cid)| {
|
||||
(
|
||||
attr.to_string(),
|
||||
attr.clone(),
|
||||
DbCidV1 {
|
||||
server_id: cid.s_uuid,
|
||||
timestamp: cid.ts,
|
||||
|
@ -109,7 +109,7 @@ impl EntryChangeState {
|
|||
.iter()
|
||||
.map(|(attr, cid)| {
|
||||
(
|
||||
attr.into(),
|
||||
attr.clone(),
|
||||
Cid {
|
||||
s_uuid: cid.server_id,
|
||||
ts: cid.timestamp,
|
||||
|
@ -159,19 +159,19 @@ impl EntryChangeState {
|
|||
EntryChangeState { st }
|
||||
}
|
||||
|
||||
pub fn change_ava(&mut self, cid: &Cid, attr: Attribute) {
|
||||
pub fn change_ava(&mut self, cid: &Cid, attr: &Attribute) {
|
||||
match &mut self.st {
|
||||
State::Live {
|
||||
at: _,
|
||||
ref mut changes,
|
||||
} => {
|
||||
if let Some(change) = changes.get_mut(attr.as_ref()) {
|
||||
if let Some(change) = changes.get_mut(attr) {
|
||||
// Update the cid.
|
||||
if change != cid {
|
||||
*change = cid.clone()
|
||||
}
|
||||
} else {
|
||||
changes.insert(attr.into(), cid.clone());
|
||||
changes.insert(attr.clone(), cid.clone());
|
||||
}
|
||||
}
|
||||
State::Tombstone { .. } => {
|
||||
|
@ -221,7 +221,7 @@ impl EntryChangeState {
|
|||
#[cfg(test)]
|
||||
pub(crate) fn get_attr_cid(&self, attr: Attribute) -> Option<&Cid> {
|
||||
match &self.st {
|
||||
State::Live { at: _, changes } => changes.get(attr.as_ref()),
|
||||
State::Live { at: _, changes } => changes.get(&attr),
|
||||
State::Tombstone { at: _ } => None,
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ impl EntryChangeState {
|
|||
|
||||
pub fn retain<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnMut(&AttrString, &mut Cid) -> bool,
|
||||
F: FnMut(&Attribute, &mut Cid) -> bool,
|
||||
{
|
||||
match &mut self.st {
|
||||
State::Live { at: _, changes } => changes.retain(f),
|
||||
|
@ -256,7 +256,7 @@ impl EntryChangeState {
|
|||
entry_id: u64,
|
||||
results: &mut Vec<Result<(), ConsistencyError>>,
|
||||
) {
|
||||
let class = expected_attrs.get(Attribute::Class.as_ref());
|
||||
let class = expected_attrs.get(&Attribute::Class);
|
||||
let is_ts = class
|
||||
.as_ref()
|
||||
.map(|c| c.contains(&EntryClass::Tombstone.to_partialvalue()))
|
||||
|
|
|
@ -460,7 +460,7 @@ pub enum ReplStateV1 {
|
|||
Live {
|
||||
at: ReplCidV1,
|
||||
// Also add AT here for breaking entry origin on conflict.
|
||||
attrs: BTreeMap<String, ReplAttrStateV1>,
|
||||
attrs: BTreeMap<Attribute, ReplAttrStateV1>,
|
||||
},
|
||||
Tombstone {
|
||||
at: ReplCidV1,
|
||||
|
@ -489,7 +489,7 @@ impl ReplEntryV1 {
|
|||
.iter()
|
||||
.filter_map(|(attr_name, cid)| {
|
||||
if schema.is_replicated(attr_name) {
|
||||
let live_attr = live_attrs.get(attr_name.as_str());
|
||||
let live_attr = live_attrs.get(attr_name);
|
||||
|
||||
let cid = cid.into();
|
||||
let attr = live_attr.and_then(|maybe|
|
||||
|
@ -507,7 +507,7 @@ impl ReplEntryV1 {
|
|||
}
|
||||
);
|
||||
|
||||
Some((attr_name.to_string(), ReplAttrStateV1 { cid, attr }))
|
||||
Some((attr_name.clone(), ReplAttrStateV1 { cid, attr }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -535,15 +535,13 @@ impl ReplEntryV1 {
|
|||
let mut eattrs = Eattrs::default();
|
||||
|
||||
for (attr_name, ReplAttrStateV1 { cid, attr }) in attrs.iter() {
|
||||
let astring: AttrString = attr_name.as_str().into();
|
||||
let cid: Cid = cid.into();
|
||||
|
||||
if let Some(attr_value) = attr {
|
||||
let v = valueset::from_repl_v1(attr_value).map_err(|e| {
|
||||
error!("Unable to restore valueset for {}", attr_name);
|
||||
e
|
||||
let v = valueset::from_repl_v1(attr_value).inspect_err(|err| {
|
||||
error!(?err, "Unable to restore valueset for {}", attr_name);
|
||||
})?;
|
||||
if eattrs.insert(astring.clone(), v).is_some() {
|
||||
if eattrs.insert(attr_name.clone(), v).is_some() {
|
||||
error!(
|
||||
"Impossible eattrs state, attribute {} appears to be duplicated!",
|
||||
attr_name
|
||||
|
@ -552,7 +550,7 @@ impl ReplEntryV1 {
|
|||
}
|
||||
}
|
||||
|
||||
if changes.insert(astring, cid).is_some() {
|
||||
if changes.insert(attr_name.clone(), cid).is_some() {
|
||||
error!(
|
||||
"Impossible changes state, attribute {} appears to be duplicated!",
|
||||
attr_name
|
||||
|
@ -576,9 +574,9 @@ impl ReplEntryV1 {
|
|||
let class_ava = vs_iutf8![EntryClass::Object.into(), EntryClass::Tombstone.into()];
|
||||
let last_mod_ava = vs_cid![at.clone()];
|
||||
|
||||
eattrs.insert(Attribute::Uuid.into(), vs_uuid![self.uuid]);
|
||||
eattrs.insert(Attribute::Class.into(), class_ava);
|
||||
eattrs.insert(Attribute::LastModifiedCid.into(), last_mod_ava);
|
||||
eattrs.insert(Attribute::Uuid, vs_uuid![self.uuid]);
|
||||
eattrs.insert(Attribute::Class, class_ava);
|
||||
eattrs.insert(Attribute::LastModifiedCid, last_mod_ava);
|
||||
|
||||
let ecstate = EntryChangeState {
|
||||
st: State::Tombstone { at },
|
||||
|
@ -632,7 +630,7 @@ impl ReplIncrementalEntryV1 {
|
|||
|
||||
// Then setup to supply it.
|
||||
if within {
|
||||
let live_attr = live_attrs.get(attr_name.as_str());
|
||||
let live_attr = live_attrs.get(attr_name);
|
||||
let cid = cid.into();
|
||||
let attr = live_attr.and_then(|maybe| {
|
||||
if maybe.len() > 0 {
|
||||
|
@ -642,7 +640,7 @@ impl ReplIncrementalEntryV1 {
|
|||
}
|
||||
});
|
||||
|
||||
Some((attr_name.to_string(), ReplAttrStateV1 { cid, attr }))
|
||||
Some((attr_name.clone(), ReplAttrStateV1 { cid, attr }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -669,15 +667,13 @@ impl ReplIncrementalEntryV1 {
|
|||
let mut eattrs = Eattrs::default();
|
||||
|
||||
for (attr_name, ReplAttrStateV1 { cid, attr }) in attrs.iter() {
|
||||
let astring: AttrString = attr_name.as_str().into();
|
||||
let cid: Cid = cid.into();
|
||||
|
||||
if let Some(attr_value) = attr {
|
||||
let v = valueset::from_repl_v1(attr_value).map_err(|e| {
|
||||
error!("Unable to restore valueset for {}", attr_name);
|
||||
e
|
||||
let v = valueset::from_repl_v1(attr_value).inspect_err(|err| {
|
||||
error!(?err, "Unable to restore valueset for {}", attr_name);
|
||||
})?;
|
||||
if eattrs.insert(astring.clone(), v).is_some() {
|
||||
if eattrs.insert(attr_name.clone(), v).is_some() {
|
||||
error!(
|
||||
"Impossible eattrs state, attribute {} appears to be duplicated!",
|
||||
attr_name
|
||||
|
@ -686,7 +682,7 @@ impl ReplIncrementalEntryV1 {
|
|||
}
|
||||
}
|
||||
|
||||
if changes.insert(astring, cid).is_some() {
|
||||
if changes.insert(attr_name.clone(), cid).is_some() {
|
||||
error!(
|
||||
"Impossible changes state, attribute {} appears to be duplicated!",
|
||||
attr_name
|
||||
|
|
|
@ -327,9 +327,8 @@ impl<'a> QueryServerReadTransaction<'a> {
|
|||
.map(|e| ReplEntryV1::new(e.as_ref(), schema))
|
||||
.collect()
|
||||
})
|
||||
.map_err(|e| {
|
||||
error!("Failed to access schema entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to access schema entries");
|
||||
})?;
|
||||
|
||||
let meta_entries = self
|
||||
|
@ -339,9 +338,8 @@ impl<'a> QueryServerReadTransaction<'a> {
|
|||
.map(|e| ReplEntryV1::new(e.as_ref(), schema))
|
||||
.collect()
|
||||
})
|
||||
.map_err(|e| {
|
||||
error!("Failed to access meta entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to access meta entries");
|
||||
})?;
|
||||
|
||||
let entries = self
|
||||
|
@ -351,9 +349,8 @@ impl<'a> QueryServerReadTransaction<'a> {
|
|||
.map(|e| ReplEntryV1::new(e.as_ref(), schema))
|
||||
.collect()
|
||||
})
|
||||
.map_err(|e| {
|
||||
error!("Failed to access entries");
|
||||
e
|
||||
.inspect_err(|err| {
|
||||
error!(?err, "Failed to access entries");
|
||||
})?;
|
||||
|
||||
// Finally, populate the ranges with anchors from the RUV
|
||||
|
|
|
@ -1075,8 +1075,8 @@ async fn test_repl_increment_basic_bidirectional_recycle(
|
|||
changes: changes_right,
|
||||
},
|
||||
) => match (
|
||||
changes_left.get(Attribute::Class.into()),
|
||||
changes_right.get(Attribute::Class.into()),
|
||||
changes_left.get(&Attribute::Class),
|
||||
changes_right.get(&Attribute::Class),
|
||||
) {
|
||||
(Some(cid_left), Some(cid_right)) => cid_left < cid_right,
|
||||
_ => false,
|
||||
|
@ -1647,12 +1647,12 @@ async fn test_repl_increment_schema_conflict(server_a: &QueryServer, server_b: &
|
|||
let ct = ct + Duration::from_secs(1);
|
||||
let mut server_b_txn = server_b.write(ct).await.unwrap();
|
||||
let modlist = ModifyList::new_list(vec![
|
||||
Modify::Removed(Attribute::Class.into(), EntryClass::Person.into()),
|
||||
Modify::Removed(Attribute::Class.into(), EntryClass::Account.into()),
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::Group.into()),
|
||||
Modify::Purged(Attribute::IdVerificationEcKey.into()),
|
||||
Modify::Purged(Attribute::NameHistory.into()),
|
||||
Modify::Purged(Attribute::DisplayName.into()),
|
||||
Modify::Removed(Attribute::Class, EntryClass::Person.into()),
|
||||
Modify::Removed(Attribute::Class, EntryClass::Account.into()),
|
||||
Modify::Present(Attribute::Class, EntryClass::Group.into()),
|
||||
Modify::Purged(Attribute::IdVerificationEcKey),
|
||||
Modify::Purged(Attribute::NameHistory),
|
||||
Modify::Purged(Attribute::DisplayName),
|
||||
]);
|
||||
assert!(server_b_txn.internal_modify_uuid(t_uuid, &modlist).is_ok());
|
||||
server_b_txn.commit().expect("Failed to commit");
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -52,6 +52,13 @@ mod search;
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Access {
|
||||
Grant,
|
||||
Denied,
|
||||
Allow(BTreeSet<Attribute>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum AccessClass {
|
||||
Grant,
|
||||
Denied,
|
||||
Allow(BTreeSet<AttrString>),
|
||||
|
@ -66,17 +73,33 @@ pub struct AccessEffectivePermission {
|
|||
pub search: Access,
|
||||
pub modify_pres: Access,
|
||||
pub modify_rem: Access,
|
||||
pub modify_class: Access,
|
||||
pub modify_class: AccessClass,
|
||||
}
|
||||
|
||||
pub enum AccessResult<'a> {
|
||||
pub enum AccessResult {
|
||||
// Deny this operation unconditionally.
|
||||
Denied,
|
||||
// Unbounded allow, provided no denied exists.
|
||||
Grant,
|
||||
// This module makes no decisions about this entry.
|
||||
Ignore,
|
||||
// Limit the allowed attr set to this.
|
||||
// Limit the allowed attr set to this - this doesn't
|
||||
// allow anything, it constrains what might be allowed.
|
||||
Constrain(BTreeSet<Attribute>),
|
||||
// Allow these attributes within constraints.
|
||||
Allow(BTreeSet<Attribute>),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum AccessResultClass<'a> {
|
||||
// Deny this operation unconditionally.
|
||||
Denied,
|
||||
// Unbounded allow, provided no denied exists.
|
||||
Grant,
|
||||
// This module makes no decisions about this entry.
|
||||
Ignore,
|
||||
// Limit the allowed attr set to this - this doesn't
|
||||
// allow anything, it constrains what might be allowed.
|
||||
Constrain(BTreeSet<&'a str>),
|
||||
// Allow these attributes within constraints.
|
||||
Allow(BTreeSet<&'a str>),
|
||||
|
@ -92,7 +115,7 @@ struct AccessControlsInner {
|
|||
acps_create: Vec<AccessControlCreate>,
|
||||
acps_modify: Vec<AccessControlModify>,
|
||||
acps_delete: Vec<AccessControlDelete>,
|
||||
sync_agreements: HashMap<Uuid, BTreeSet<String>>,
|
||||
sync_agreements: HashMap<Uuid, BTreeSet<Attribute>>,
|
||||
// Oauth2
|
||||
// Sync prov
|
||||
}
|
||||
|
@ -149,7 +172,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
fn get_create(&self) -> &Vec<AccessControlCreate>;
|
||||
fn get_modify(&self) -> &Vec<AccessControlModify>;
|
||||
fn get_delete(&self) -> &Vec<AccessControlDelete>;
|
||||
fn get_sync_agreements(&self) -> &HashMap<Uuid, BTreeSet<String>>;
|
||||
fn get_sync_agreements(&self) -> &HashMap<Uuid, BTreeSet<Attribute>>;
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
fn get_acp_resolve_filter_cache(&self) -> &mut ResolveFilterCacheReadTxn<'a>;
|
||||
|
@ -238,7 +261,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
|
||||
// Get the set of attributes requested by this se filter. This is what we are
|
||||
// going to access check.
|
||||
let requested_attrs: BTreeSet<&str> = filter_orig.get_attr_set();
|
||||
let requested_attrs: BTreeSet<Attribute> = filter_orig.get_attr_set();
|
||||
|
||||
// First get the set of acps that apply to this receiver
|
||||
let related_acp = self.search_related_acp(ident);
|
||||
|
@ -299,10 +322,6 @@ pub trait AccessControlsTransaction<'a> {
|
|||
) -> Result<Vec<Entry<EntryReduced, EntryCommitted>>, OperationError> {
|
||||
// Build a reference set from the req_attrs. This is what we test against
|
||||
// to see if the attribute is something we currently want.
|
||||
let requested_attrs: Option<BTreeSet<_>> = se
|
||||
.attrs
|
||||
.as_ref()
|
||||
.map(|vs| vs.iter().map(|s| s.as_str()).collect());
|
||||
|
||||
// Get the relevant acps for this receiver.
|
||||
let related_acp = self.search_related_acp(&se.ident);
|
||||
|
@ -331,13 +350,13 @@ pub trait AccessControlsTransaction<'a> {
|
|||
SearchResult::Allow(allowed_attrs) => {
|
||||
// The allow set constrained.
|
||||
debug!(
|
||||
requested = ?requested_attrs,
|
||||
requested = ?se.attrs,
|
||||
allowed = ?allowed_attrs,
|
||||
"reduction",
|
||||
);
|
||||
|
||||
// Reduce requested by allowed.
|
||||
let reduced_attrs = if let Some(requested) = requested_attrs.as_ref() {
|
||||
let reduced_attrs = if let Some(requested) = se.attrs.as_ref() {
|
||||
requested & &allowed_attrs
|
||||
} else {
|
||||
allowed_attrs
|
||||
|
@ -423,21 +442,21 @@ pub trait AccessControlsTransaction<'a> {
|
|||
let related_acp: Vec<_> = self.modify_related_acp(&me.ident);
|
||||
|
||||
// build two sets of "requested pres" and "requested rem"
|
||||
let requested_pres: BTreeSet<&str> = me
|
||||
let requested_pres: BTreeSet<Attribute> = me
|
||||
.modlist
|
||||
.iter()
|
||||
.filter_map(|m| match m {
|
||||
Modify::Present(a, _) => Some(a.as_str()),
|
||||
Modify::Present(a, _) => Some(a.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let requested_rem: BTreeSet<&str> = me
|
||||
let requested_rem: BTreeSet<Attribute> = me
|
||||
.modlist
|
||||
.iter()
|
||||
.filter_map(|m| match m {
|
||||
Modify::Removed(a, _) => Some(a.as_str()),
|
||||
Modify::Purged(a) => Some(a.as_str()),
|
||||
Modify::Removed(a, _) => Some(a.clone()),
|
||||
Modify::Purged(a) => Some(a.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
@ -556,19 +575,19 @@ pub trait AccessControlsTransaction<'a> {
|
|||
}
|
||||
|
||||
// build two sets of "requested pres" and "requested rem"
|
||||
let requested_pres: BTreeSet<&str> = modlist
|
||||
let requested_pres: BTreeSet<Attribute> = modlist
|
||||
.iter()
|
||||
.filter_map(|m| match m {
|
||||
Modify::Present(a, _) => Some(a.as_str()),
|
||||
Modify::Present(a, _) => Some(a.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let requested_rem: BTreeSet<&str> = modlist
|
||||
let requested_rem: BTreeSet<Attribute> = modlist
|
||||
.iter()
|
||||
.filter_map(|m| match m {
|
||||
Modify::Removed(a, _) => Some(a.as_str()),
|
||||
Modify::Purged(a) => Some(a.as_str()),
|
||||
Modify::Removed(a, _) => Some(a.clone()),
|
||||
Modify::Purged(a) => Some(a.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
@ -756,7 +775,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
fn effective_permission_check(
|
||||
&self,
|
||||
ident: &Identity,
|
||||
attrs: Option<BTreeSet<AttrString>>,
|
||||
attrs: Option<BTreeSet<Attribute>>,
|
||||
entries: &[Arc<EntrySealedCommitted>],
|
||||
) -> Result<Vec<AccessEffectivePermission>, OperationError> {
|
||||
// I think we need a structure like " CheckResult, which is in the order of the
|
||||
|
@ -816,7 +835,7 @@ pub trait AccessControlsTransaction<'a> {
|
|||
SearchResult::Grant => Access::Grant,
|
||||
SearchResult::Allow(allowed_attrs) => {
|
||||
// Bound by requested attrs?
|
||||
Access::Allow(allowed_attrs.into_iter().map(|s| s.into()).collect())
|
||||
Access::Allow(allowed_attrs.into_iter().collect())
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -827,12 +846,12 @@ pub trait AccessControlsTransaction<'a> {
|
|||
sync_agmts,
|
||||
e,
|
||||
) {
|
||||
ModifyResult::Denied => (Access::Denied, Access::Denied, Access::Denied),
|
||||
ModifyResult::Grant => (Access::Grant, Access::Grant, Access::Grant),
|
||||
ModifyResult::Denied => (Access::Denied, Access::Denied, AccessClass::Denied),
|
||||
ModifyResult::Grant => (Access::Grant, Access::Grant, AccessClass::Grant),
|
||||
ModifyResult::Allow { pres, rem, cls } => (
|
||||
Access::Allow(pres.into_iter().map(|s| s.into()).collect()),
|
||||
Access::Allow(rem.into_iter().map(|s| s.into()).collect()),
|
||||
Access::Allow(cls.into_iter().map(|s| s.into()).collect()),
|
||||
Access::Allow(pres.into_iter().collect()),
|
||||
Access::Allow(rem.into_iter().collect()),
|
||||
AccessClass::Allow(cls.into_iter().map(|s| s.into()).collect()),
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -904,7 +923,10 @@ impl<'a> AccessControlsWriteTransaction<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_sync_agreements(&mut self, mut sync_agreements: HashMap<Uuid, BTreeSet<String>>) {
|
||||
pub fn update_sync_agreements(
|
||||
&mut self,
|
||||
mut sync_agreements: HashMap<Uuid, BTreeSet<Attribute>>,
|
||||
) {
|
||||
std::mem::swap(
|
||||
&mut sync_agreements,
|
||||
&mut self.inner.deref_mut().sync_agreements,
|
||||
|
@ -935,7 +957,7 @@ impl<'a> AccessControlsTransaction<'a> for AccessControlsWriteTransaction<'a> {
|
|||
&self.inner.acps_delete
|
||||
}
|
||||
|
||||
fn get_sync_agreements(&self) -> &HashMap<Uuid, BTreeSet<String>> {
|
||||
fn get_sync_agreements(&self) -> &HashMap<Uuid, BTreeSet<Attribute>> {
|
||||
&self.inner.sync_agreements
|
||||
}
|
||||
|
||||
|
@ -978,7 +1000,7 @@ impl<'a> AccessControlsTransaction<'a> for AccessControlsReadTransaction<'a> {
|
|||
&self.inner.acps_delete
|
||||
}
|
||||
|
||||
fn get_sync_agreements(&self) -> &HashMap<Uuid, BTreeSet<String>> {
|
||||
fn get_sync_agreements(&self) -> &HashMap<Uuid, BTreeSet<Attribute>> {
|
||||
&self.inner.sync_agreements
|
||||
}
|
||||
|
||||
|
@ -1052,7 +1074,7 @@ mod tests {
|
|||
AccessControlCreate, AccessControlDelete, AccessControlModify, AccessControlProfile,
|
||||
AccessControlSearch, AccessControlTarget,
|
||||
},
|
||||
Access, AccessControls, AccessControlsTransaction, AccessEffectivePermission,
|
||||
Access, AccessClass, AccessControls, AccessControlsTransaction, AccessEffectivePermission,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
|
||||
|
@ -1797,7 +1819,7 @@ mod tests {
|
|||
)),
|
||||
);
|
||||
// the requested attrs here.
|
||||
se_anon.attrs = Some(btreeset![Attribute::Name.into()]);
|
||||
se_anon.attrs = Some(btreeset![Attribute::Name]);
|
||||
|
||||
let acp = AccessControlSearch::from_raw(
|
||||
"test_acp",
|
||||
|
@ -1852,7 +1874,7 @@ mod tests {
|
|||
acw.update_modify($controls).expect("Failed to update");
|
||||
let mut sync_agmt = HashMap::new();
|
||||
let mut set = BTreeSet::new();
|
||||
set.insert($sync_yield_attr.to_string());
|
||||
set.insert($sync_yield_attr);
|
||||
sync_agmt.insert($sync_uuid, set);
|
||||
acw.update_sync_agreements(sync_agmt);
|
||||
let acw = acw;
|
||||
|
@ -2381,10 +2403,10 @@ mod tests {
|
|||
vec![AccessEffectivePermission {
|
||||
delete: false,
|
||||
target: uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"),
|
||||
search: Access::Allow(btreeset![Attribute::Name.into()]),
|
||||
search: Access::Allow(btreeset![Attribute::Name]),
|
||||
modify_pres: Access::Allow(BTreeSet::new()),
|
||||
modify_rem: Access::Allow(BTreeSet::new()),
|
||||
modify_class: Access::Allow(BTreeSet::new()),
|
||||
modify_class: AccessClass::Allow(BTreeSet::new()),
|
||||
}]
|
||||
)
|
||||
}
|
||||
|
@ -2423,9 +2445,9 @@ mod tests {
|
|||
delete: false,
|
||||
target: uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"),
|
||||
search: Access::Allow(BTreeSet::new()),
|
||||
modify_pres: Access::Allow(btreeset![Attribute::Name.into()]),
|
||||
modify_rem: Access::Allow(btreeset![Attribute::Name.into()]),
|
||||
modify_class: Access::Allow(btreeset![EntryClass::Object.into()]),
|
||||
modify_pres: Access::Allow(btreeset![Attribute::Name]),
|
||||
modify_rem: Access::Allow(btreeset![Attribute::Name]),
|
||||
modify_class: AccessClass::Allow(btreeset![EntryClass::Object.into()]),
|
||||
}]
|
||||
)
|
||||
}
|
||||
|
@ -2660,7 +2682,7 @@ mod tests {
|
|||
&me_pres,
|
||||
vec![acp_allow.clone()],
|
||||
sync_uuid,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
&r2_set,
|
||||
true
|
||||
);
|
||||
|
@ -2669,7 +2691,7 @@ mod tests {
|
|||
&me_rem,
|
||||
vec![acp_allow.clone()],
|
||||
sync_uuid,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
&r2_set,
|
||||
true
|
||||
);
|
||||
|
@ -2678,7 +2700,7 @@ mod tests {
|
|||
&me_purge,
|
||||
vec![acp_allow],
|
||||
sync_uuid,
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::Name,
|
||||
&r2_set,
|
||||
true
|
||||
);
|
||||
|
|
|
@ -6,15 +6,15 @@ use super::profiles::{
|
|||
AccessControlModify, AccessControlModifyResolved, AccessControlReceiverCondition,
|
||||
AccessControlTargetCondition,
|
||||
};
|
||||
use super::AccessResult;
|
||||
use super::{AccessResult, AccessResultClass};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(super) enum ModifyResult<'a> {
|
||||
Denied,
|
||||
Grant,
|
||||
Allow {
|
||||
pres: BTreeSet<&'a str>,
|
||||
rem: BTreeSet<&'a str>,
|
||||
pres: BTreeSet<Attribute>,
|
||||
rem: BTreeSet<Attribute>,
|
||||
cls: BTreeSet<&'a str>,
|
||||
},
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ pub(super) enum ModifyResult<'a> {
|
|||
pub(super) fn apply_modify_access<'a>(
|
||||
ident: &Identity,
|
||||
related_acp: &'a [AccessControlModifyResolved],
|
||||
sync_agreements: &'a HashMap<Uuid, BTreeSet<String>>,
|
||||
entry: &'a Arc<EntrySealedCommitted>,
|
||||
sync_agreements: &HashMap<Uuid, BTreeSet<Attribute>>,
|
||||
entry: &Arc<EntrySealedCommitted>,
|
||||
) -> ModifyResult<'a> {
|
||||
let mut denied = false;
|
||||
let mut grant = false;
|
||||
|
@ -57,7 +57,7 @@ pub(super) fn apply_modify_access<'a>(
|
|||
match modify_sync_constrain(ident, entry, sync_agreements) {
|
||||
AccessResult::Denied => denied = true,
|
||||
AccessResult::Constrain(mut set) => {
|
||||
constrain_rem.extend(set.iter().copied());
|
||||
constrain_rem.extend(set.iter().cloned());
|
||||
constrain_pres.append(&mut set)
|
||||
}
|
||||
// Can't grant.
|
||||
|
@ -140,12 +140,12 @@ pub(super) fn apply_modify_access<'a>(
|
|||
}
|
||||
|
||||
match modify_cls_test(scoped_acp.as_slice()) {
|
||||
AccessResult::Denied => denied = true,
|
||||
AccessResultClass::Denied => denied = true,
|
||||
// Can never return a unilateral grant.
|
||||
AccessResult::Grant => {}
|
||||
AccessResult::Ignore => {}
|
||||
AccessResult::Constrain(mut set) => constrain_cls.append(&mut set),
|
||||
AccessResult::Allow(mut set) => allow_cls.append(&mut set),
|
||||
AccessResultClass::Grant => {}
|
||||
AccessResultClass::Ignore => {}
|
||||
AccessResultClass::Constrain(mut set) => constrain_cls.append(&mut set),
|
||||
AccessResultClass::Allow(mut set) => allow_cls.append(&mut set),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ pub(super) fn apply_modify_access<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn modify_ident_test<'a>(ident: &Identity) -> AccessResult<'a> {
|
||||
fn modify_ident_test(ident: &Identity) -> AccessResult {
|
||||
match &ident.origin {
|
||||
IdentType::Internal => {
|
||||
trace!("Internal operation, bypassing access check");
|
||||
|
@ -211,35 +211,37 @@ fn modify_ident_test<'a>(ident: &Identity) -> AccessResult<'a> {
|
|||
AccessResult::Ignore
|
||||
}
|
||||
|
||||
fn modify_pres_test<'a>(scoped_acp: &[&'a AccessControlModify]) -> AccessResult<'a> {
|
||||
let allowed_pres: BTreeSet<&str> = scoped_acp
|
||||
fn modify_pres_test(scoped_acp: &[&AccessControlModify]) -> AccessResult {
|
||||
let allowed_pres: BTreeSet<Attribute> = scoped_acp
|
||||
.iter()
|
||||
.flat_map(|acp| acp.presattrs.iter().map(|v| v.as_str()))
|
||||
.flat_map(|acp| acp.presattrs.iter().cloned())
|
||||
.collect();
|
||||
AccessResult::Allow(allowed_pres)
|
||||
}
|
||||
|
||||
fn modify_rem_test<'a>(scoped_acp: &[&'a AccessControlModify]) -> AccessResult<'a> {
|
||||
let allowed_rem: BTreeSet<&str> = scoped_acp
|
||||
fn modify_rem_test(scoped_acp: &[&AccessControlModify]) -> AccessResult {
|
||||
let allowed_rem: BTreeSet<Attribute> = scoped_acp
|
||||
.iter()
|
||||
.flat_map(|acp| acp.remattrs.iter().map(|v| v.as_str()))
|
||||
.flat_map(|acp| acp.remattrs.iter().cloned())
|
||||
.collect();
|
||||
AccessResult::Allow(allowed_rem)
|
||||
}
|
||||
|
||||
fn modify_cls_test<'a>(scoped_acp: &[&'a AccessControlModify]) -> AccessResult<'a> {
|
||||
let allowed_classes: BTreeSet<&str> = scoped_acp
|
||||
// TODO: Should this be reverted to the Str borrow method? Or do we try to change
|
||||
// to EntryClass?
|
||||
fn modify_cls_test<'a>(scoped_acp: &[&'a AccessControlModify]) -> AccessResultClass<'a> {
|
||||
let allowed_classes: BTreeSet<&'a str> = scoped_acp
|
||||
.iter()
|
||||
.flat_map(|acp| acp.classes.iter().map(|v| v.as_str()))
|
||||
.flat_map(|acp| acp.classes.iter().map(|s| s.as_str()))
|
||||
.collect();
|
||||
AccessResult::Allow(allowed_classes)
|
||||
AccessResultClass::Allow(allowed_classes)
|
||||
}
|
||||
|
||||
fn modify_sync_constrain<'a>(
|
||||
fn modify_sync_constrain(
|
||||
ident: &Identity,
|
||||
entry: &'a Arc<EntrySealedCommitted>,
|
||||
sync_agreements: &'a HashMap<Uuid, BTreeSet<String>>,
|
||||
) -> AccessResult<'a> {
|
||||
entry: &Arc<EntrySealedCommitted>,
|
||||
sync_agreements: &HashMap<Uuid, BTreeSet<Attribute>>,
|
||||
) -> AccessResult {
|
||||
match &ident.origin {
|
||||
IdentType::Internal => AccessResult::Ignore,
|
||||
IdentType::Synch(_) => {
|
||||
|
@ -262,14 +264,14 @@ fn modify_sync_constrain<'a>(
|
|||
|
||||
if let Some(sync_uuid) = entry.get_ava_single_refer(Attribute::SyncParentUuid) {
|
||||
let mut set = btreeset![
|
||||
Attribute::UserAuthTokenSession.as_ref(),
|
||||
Attribute::OAuth2Session.as_ref(),
|
||||
Attribute::OAuth2ConsentScopeMap.as_ref(),
|
||||
Attribute::CredentialUpdateIntentToken.as_ref()
|
||||
Attribute::UserAuthTokenSession,
|
||||
Attribute::OAuth2Session,
|
||||
Attribute::OAuth2ConsentScopeMap,
|
||||
Attribute::CredentialUpdateIntentToken
|
||||
];
|
||||
|
||||
if let Some(sync_yield_authority) = sync_agreements.get(&sync_uuid) {
|
||||
set.extend(sync_yield_authority.iter().map(|s| s.as_str()))
|
||||
set.extend(sync_yield_authority.iter().cloned())
|
||||
}
|
||||
|
||||
AccessResult::Constrain(set)
|
||||
|
|
|
@ -19,7 +19,7 @@ pub struct AccessControlSearchResolved<'a> {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct AccessControlSearch {
|
||||
pub acp: AccessControlProfile,
|
||||
pub attrs: BTreeSet<AttrString>,
|
||||
pub attrs: BTreeSet<Attribute>,
|
||||
}
|
||||
|
||||
impl AccessControlSearch {
|
||||
|
@ -41,12 +41,12 @@ impl AccessControlSearch {
|
|||
admin_error!("Missing {}", Attribute::AcpSearchAttr);
|
||||
OperationError::InvalidAcpState(format!("Missing {}", Attribute::AcpSearchAttr))
|
||||
})?
|
||||
.map(AttrString::from)
|
||||
.map(Attribute::from)
|
||||
.collect();
|
||||
|
||||
// Ability to search memberof, implies the ability to read directmemberof
|
||||
if attrs.contains(Attribute::MemberOf.as_ref()) {
|
||||
attrs.insert(Attribute::DirectMemberOf.into());
|
||||
if attrs.contains(&Attribute::MemberOf) {
|
||||
attrs.insert(Attribute::DirectMemberOf);
|
||||
}
|
||||
|
||||
let acp = AccessControlProfile::try_from(qs, value)?;
|
||||
|
@ -64,11 +64,11 @@ impl AccessControlSearch {
|
|||
targetscope: Filter<FilterValid>,
|
||||
attrs: &str,
|
||||
) -> Self {
|
||||
let mut attrs: BTreeSet<_> = attrs.split_whitespace().map(AttrString::from).collect();
|
||||
let mut attrs: BTreeSet<_> = attrs.split_whitespace().map(Attribute::from).collect();
|
||||
|
||||
// Ability to search memberof, implies the ability to read directmemberof
|
||||
if attrs.contains(Attribute::MemberOf.as_ref()) {
|
||||
attrs.insert(Attribute::DirectMemberOf.into());
|
||||
if attrs.contains(&Attribute::MemberOf) {
|
||||
attrs.insert(Attribute::DirectMemberOf);
|
||||
}
|
||||
|
||||
AccessControlSearch {
|
||||
|
@ -98,7 +98,7 @@ impl AccessControlSearch {
|
|||
receiver: AccessControlReceiver::EntryManager,
|
||||
target,
|
||||
},
|
||||
attrs: attrs.split_whitespace().map(AttrString::from).collect(),
|
||||
attrs: attrs.split_whitespace().map(Attribute::from).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ pub struct AccessControlCreateResolved<'a> {
|
|||
pub struct AccessControlCreate {
|
||||
pub acp: AccessControlProfile,
|
||||
pub classes: Vec<AttrString>,
|
||||
pub attrs: Vec<AttrString>,
|
||||
pub attrs: Vec<Attribute>,
|
||||
}
|
||||
|
||||
impl AccessControlCreate {
|
||||
|
@ -195,7 +195,7 @@ impl AccessControlCreate {
|
|||
|
||||
let attrs = value
|
||||
.get_ava_iter_iutf8(Attribute::AcpCreateAttr)
|
||||
.map(|i| i.map(AttrString::from).collect())
|
||||
.map(|i| i.map(Attribute::from).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
let classes = value
|
||||
|
@ -229,7 +229,7 @@ impl AccessControlCreate {
|
|||
target: AccessControlTarget::Scope(targetscope),
|
||||
},
|
||||
classes: classes.split_whitespace().map(AttrString::from).collect(),
|
||||
attrs: attrs.split_whitespace().map(AttrString::from).collect(),
|
||||
attrs: attrs.split_whitespace().map(Attribute::from).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ impl AccessControlCreate {
|
|||
target,
|
||||
},
|
||||
classes: classes.split_whitespace().map(AttrString::from).collect(),
|
||||
attrs: attrs.split_whitespace().map(AttrString::from).collect(),
|
||||
attrs: attrs.split_whitespace().map(Attribute::from).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,8 +267,8 @@ pub struct AccessControlModifyResolved<'a> {
|
|||
pub struct AccessControlModify {
|
||||
pub acp: AccessControlProfile,
|
||||
pub classes: Vec<AttrString>,
|
||||
pub presattrs: Vec<AttrString>,
|
||||
pub remattrs: Vec<AttrString>,
|
||||
pub presattrs: Vec<Attribute>,
|
||||
pub remattrs: Vec<Attribute>,
|
||||
}
|
||||
|
||||
impl AccessControlModify {
|
||||
|
@ -285,12 +285,12 @@ impl AccessControlModify {
|
|||
|
||||
let presattrs = value
|
||||
.get_ava_iter_iutf8(Attribute::AcpModifyPresentAttr)
|
||||
.map(|i| i.map(AttrString::from).collect())
|
||||
.map(|i| i.map(Attribute::from).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
let remattrs = value
|
||||
.get_ava_iter_iutf8(Attribute::AcpModifyRemovedAttr)
|
||||
.map(|i| i.map(AttrString::from).collect())
|
||||
.map(|i| i.map(Attribute::from).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
let classes = value
|
||||
|
@ -326,8 +326,8 @@ impl AccessControlModify {
|
|||
target: AccessControlTarget::Scope(targetscope),
|
||||
},
|
||||
classes: classes.split_whitespace().map(AttrString::from).collect(),
|
||||
presattrs: presattrs.split_whitespace().map(AttrString::from).collect(),
|
||||
remattrs: remattrs.split_whitespace().map(AttrString::from).collect(),
|
||||
presattrs: presattrs.split_whitespace().map(Attribute::from).collect(),
|
||||
remattrs: remattrs.split_whitespace().map(Attribute::from).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,8 +350,8 @@ impl AccessControlModify {
|
|||
target,
|
||||
},
|
||||
classes: classes.split_whitespace().map(AttrString::from).collect(),
|
||||
presattrs: presattrs.split_whitespace().map(AttrString::from).collect(),
|
||||
remattrs: remattrs.split_whitespace().map(AttrString::from).collect(),
|
||||
presattrs: presattrs.split_whitespace().map(Attribute::from).collect(),
|
||||
remattrs: remattrs.split_whitespace().map(Attribute::from).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,17 @@ use super::profiles::{
|
|||
use super::AccessResult;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(super) enum SearchResult<'a> {
|
||||
pub(super) enum SearchResult {
|
||||
Denied,
|
||||
Grant,
|
||||
Allow(BTreeSet<&'a str>),
|
||||
Allow(BTreeSet<Attribute>),
|
||||
}
|
||||
|
||||
pub(super) fn apply_search_access<'a>(
|
||||
pub(super) fn apply_search_access(
|
||||
ident: &Identity,
|
||||
related_acp: &'a [AccessControlSearchResolved],
|
||||
entry: &'a Arc<EntrySealedCommitted>,
|
||||
) -> SearchResult<'a> {
|
||||
related_acp: &[AccessControlSearchResolved],
|
||||
entry: &Arc<EntrySealedCommitted>,
|
||||
) -> SearchResult {
|
||||
// This could be considered "slow" due to allocs each iter with the entry. We
|
||||
// could move these out of the loop and reuse, but there are likely risks to
|
||||
// that.
|
||||
|
@ -70,11 +70,11 @@ pub(super) fn apply_search_access<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn search_filter_entry<'a>(
|
||||
fn search_filter_entry(
|
||||
ident: &Identity,
|
||||
related_acp: &'a [AccessControlSearchResolved],
|
||||
entry: &'a Arc<EntrySealedCommitted>,
|
||||
) -> AccessResult<'a> {
|
||||
related_acp: &[AccessControlSearchResolved],
|
||||
entry: &Arc<EntrySealedCommitted>,
|
||||
) -> AccessResult {
|
||||
// If this is an internal search, return our working set.
|
||||
match &ident.origin {
|
||||
IdentType::Internal => {
|
||||
|
@ -106,7 +106,7 @@ fn search_filter_entry<'a>(
|
|||
let ident_memberof = ident.get_memberof();
|
||||
let ident_uuid = ident.get_uuid();
|
||||
|
||||
let allowed_attrs: BTreeSet<&str> = related_acp
|
||||
let allowed_attrs: BTreeSet<Attribute> = related_acp
|
||||
.iter()
|
||||
.filter_map(|acs| {
|
||||
// Assert that the receiver condition applies.
|
||||
|
@ -156,7 +156,7 @@ fn search_filter_entry<'a>(
|
|||
|
||||
security_debug!(entry = ?entry.get_display_id(), acs = %acs.acp.acp.name, "acs applied to entry");
|
||||
// add search_attrs to allowed.
|
||||
Some(acs.acp.attrs.iter().map(|s| s.as_str()))
|
||||
Some(acs.acp.attrs.iter().cloned())
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
|
@ -164,10 +164,7 @@ fn search_filter_entry<'a>(
|
|||
AccessResult::Allow(allowed_attrs)
|
||||
}
|
||||
|
||||
fn search_oauth2_filter_entry<'a>(
|
||||
ident: &Identity,
|
||||
entry: &'a Arc<EntrySealedCommitted>,
|
||||
) -> AccessResult<'a> {
|
||||
fn search_oauth2_filter_entry(ident: &Identity, entry: &Arc<EntrySealedCommitted>) -> AccessResult {
|
||||
match &ident.origin {
|
||||
IdentType::Internal | IdentType::Synch(_) => AccessResult::Ignore,
|
||||
IdentType::User(iuser) => {
|
||||
|
@ -189,12 +186,12 @@ fn search_oauth2_filter_entry<'a>(
|
|||
security_debug!(entry = ?entry.get_uuid(), ident = ?iuser.entry.get_uuid2rdn(), "ident is a memberof a group granted an oauth2 scope by this entry");
|
||||
|
||||
return AccessResult::Allow(btreeset!(
|
||||
Attribute::Class.as_ref(),
|
||||
Attribute::DisplayName.as_ref(),
|
||||
Attribute::Uuid.as_ref(),
|
||||
Attribute::Name.as_ref(),
|
||||
Attribute::OAuth2RsOriginLanding.as_ref(),
|
||||
Attribute::Image.as_ref()
|
||||
Attribute::Class,
|
||||
Attribute::DisplayName,
|
||||
Attribute::Uuid,
|
||||
Attribute::Name,
|
||||
Attribute::OAuth2RsOriginLanding,
|
||||
Attribute::Image
|
||||
));
|
||||
}
|
||||
AccessResult::Ignore
|
||||
|
@ -202,10 +199,10 @@ fn search_oauth2_filter_entry<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn search_sync_account_filter_entry<'a>(
|
||||
fn search_sync_account_filter_entry(
|
||||
ident: &Identity,
|
||||
entry: &'a Arc<EntrySealedCommitted>,
|
||||
) -> AccessResult<'a> {
|
||||
entry: &Arc<EntrySealedCommitted>,
|
||||
) -> AccessResult {
|
||||
match &ident.origin {
|
||||
IdentType::Internal | IdentType::Synch(_) => AccessResult::Ignore,
|
||||
IdentType::User(iuser) => {
|
||||
|
@ -243,9 +240,9 @@ fn search_sync_account_filter_entry<'a>(
|
|||
security_debug!(entry = ?entry.get_uuid(), ident = ?iuser.entry.get_uuid2rdn(), "ident is a synchronised account from this sync account");
|
||||
|
||||
return AccessResult::Allow(btreeset!(
|
||||
Attribute::Class.as_ref(),
|
||||
Attribute::Uuid.as_ref(),
|
||||
Attribute::SyncCredentialPortal.as_ref()
|
||||
Attribute::Class,
|
||||
Attribute::Uuid,
|
||||
Attribute::SyncCredentialPortal
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
) -> Result<(), OperationError> {
|
||||
trace!("operating on {:?}", e.get_uuid());
|
||||
|
||||
let Some(filt) = e.filter_from_attrs(&[Attribute::Uuid.into()]) else {
|
||||
let Some(filt) = e.filter_from_attrs(&[Attribute::Uuid]) else {
|
||||
return Err(OperationError::FilterGeneration);
|
||||
};
|
||||
|
||||
|
@ -277,7 +277,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
} else if results.len() == 1 {
|
||||
// For each ignored attr, we remove it from entry.
|
||||
for attr in attrs.iter() {
|
||||
e.remove_ava(*attr);
|
||||
e.remove_ava(attr);
|
||||
}
|
||||
|
||||
// If the thing is subset, pass
|
||||
|
@ -412,7 +412,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
.map(|origin_url| {
|
||||
// Copy the origin url to the landing.
|
||||
let modlist = vec![Modify::Present(
|
||||
Attribute::OAuth2RsOriginLanding.into(),
|
||||
Attribute::OAuth2RsOriginLanding,
|
||||
Value::Url(origin_url.clone()),
|
||||
)];
|
||||
|
||||
|
@ -431,9 +431,9 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
//
|
||||
// Domain info should have the attribute private cookie key removed.
|
||||
let modlist = ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::PrivateCookieKey.into()),
|
||||
Modify::Purged(Attribute::Es256PrivateKeyDer.into()),
|
||||
Modify::Purged(Attribute::FernetPrivateKeyStr.into()),
|
||||
Modify::Purged(Attribute::PrivateCookieKey),
|
||||
Modify::Purged(Attribute::Es256PrivateKeyDer),
|
||||
Modify::Purged(Attribute::FernetPrivateKeyStr),
|
||||
]);
|
||||
|
||||
self.internal_modify_uuid(UUID_DOMAIN_INFO, &modlist)?;
|
||||
|
@ -443,8 +443,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
f_eq(Attribute::Class, EntryClass::SyncAccount.into())
|
||||
]));
|
||||
|
||||
let modlist =
|
||||
ModifyList::new_list(vec![Modify::Purged(Attribute::JwsEs256PrivateKey.into())]);
|
||||
let modlist = ModifyList::new_list(vec![Modify::Purged(Attribute::JwsEs256PrivateKey)]);
|
||||
|
||||
self.internal_modify(&filter, &modlist)?;
|
||||
|
||||
|
|
|
@ -608,7 +608,7 @@ pub trait QueryServerTransaction<'a> {
|
|||
|
||||
/// Do a schema aware conversion from a String:String to String:Value for modification
|
||||
/// present.
|
||||
fn clone_value(&mut self, attr: &str, value: &str) -> Result<Value, OperationError> {
|
||||
fn clone_value(&mut self, attr: &Attribute, value: &str) -> Result<Value, OperationError> {
|
||||
let schema = self.get_schema();
|
||||
|
||||
// Should this actually be a fn of Value - no - I think that introduces issues with the
|
||||
|
@ -702,7 +702,7 @@ pub trait QueryServerTransaction<'a> {
|
|||
|
||||
fn clone_partialvalue(
|
||||
&mut self,
|
||||
attr: &str,
|
||||
attr: &Attribute,
|
||||
value: &str,
|
||||
) -> Result<PartialValue, OperationError> {
|
||||
let schema = self.get_schema();
|
||||
|
@ -1652,6 +1652,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
// load them.
|
||||
let attributetypes: Result<Vec<_>, _> =
|
||||
res.iter().map(|e| SchemaAttribute::try_from(e)).collect();
|
||||
|
||||
let attributetypes = attributetypes.map_err(|e| {
|
||||
admin_error!("reload schema attributetypes {:?}", e);
|
||||
e
|
||||
|
@ -1736,12 +1737,15 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
e
|
||||
})?;
|
||||
|
||||
let sync_agreement_map: HashMap<Uuid, BTreeSet<String>> = res
|
||||
let sync_agreement_map: HashMap<Uuid, BTreeSet<Attribute>> = res
|
||||
.iter()
|
||||
.filter_map(|e| {
|
||||
e.get_ava_as_iutf8(Attribute::SyncYieldAuthority)
|
||||
.cloned()
|
||||
.map(|set| (e.get_uuid(), set))
|
||||
.map(|set| {
|
||||
let set: BTreeSet<_> =
|
||||
set.iter().map(|s| Attribute::from(s.as_str())).collect();
|
||||
(e.get_uuid(), set)
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -2416,18 +2420,18 @@ mod tests {
|
|||
assert!(cr.is_ok());
|
||||
|
||||
// test attr not exist
|
||||
let r1 = server_txn.clone_value("tausau", "naoeutnhaou");
|
||||
let r1 = server_txn.clone_value(&Attribute::from("tausau"), "naoeutnhaou");
|
||||
|
||||
assert!(r1.is_err());
|
||||
|
||||
// test attr not-normalised (error)
|
||||
// test attr not-reference
|
||||
let r2 = server_txn.clone_value("NaMe", "NaMe");
|
||||
let r2 = server_txn.clone_value(&Attribute::Custom("NaMe".into()), "NaMe");
|
||||
|
||||
assert!(r2.is_err());
|
||||
|
||||
// test attr reference
|
||||
let r3 = server_txn.clone_value("member", "testperson1");
|
||||
let r3 = server_txn.clone_value(&Attribute::from("member"), "testperson1");
|
||||
|
||||
assert_eq!(
|
||||
r3,
|
||||
|
@ -2435,7 +2439,10 @@ mod tests {
|
|||
);
|
||||
|
||||
// test attr reference already resolved.
|
||||
let r4 = server_txn.clone_value("member", "cc8e95b4-c24f-4d68-ba54-8bed76f63930");
|
||||
let r4 = server_txn.clone_value(
|
||||
&Attribute::from("member"),
|
||||
"cc8e95b4-c24f-4d68-ba54-8bed76f63930",
|
||||
);
|
||||
|
||||
debug!("{:?}", r4);
|
||||
assert_eq!(
|
||||
|
|
|
@ -623,7 +623,7 @@ mod tests {
|
|||
PartialValue::new_iname("flarbalgarble")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Description.into(),
|
||||
Attribute::Description,
|
||||
Value::from("anusaosu"),
|
||||
)]),
|
||||
);
|
||||
|
@ -658,7 +658,7 @@ mod tests {
|
|||
let me_inv_m = ModifyEvent::new_internal_invalid(
|
||||
filter!(f_pres(Attribute::Class)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::NonExist.into(),
|
||||
Attribute::NonExist,
|
||||
Value::from("anusaosu"),
|
||||
)]),
|
||||
);
|
||||
|
@ -676,8 +676,8 @@ mod tests {
|
|||
PartialValue::new_iname("testperson2")
|
||||
)),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::Description.into()),
|
||||
Modify::Present(Attribute::Description.into(), Value::from("anusaosu")),
|
||||
Modify::Purged(Attribute::Description),
|
||||
Modify::Present(Attribute::Description, Value::from("anusaosu")),
|
||||
]),
|
||||
);
|
||||
assert!(server_txn.modify(&me_sin).is_ok());
|
||||
|
@ -689,8 +689,8 @@ mod tests {
|
|||
f_eq(Attribute::Name, PartialValue::new_iname("testperson2")),
|
||||
])),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::Description.into()),
|
||||
Modify::Present(Attribute::Description.into(), Value::from("anusaosu")),
|
||||
Modify::Purged(Attribute::Description),
|
||||
Modify::Present(Attribute::Description, Value::from("anusaosu")),
|
||||
]),
|
||||
);
|
||||
assert!(server_txn.modify(&me_mult).is_ok());
|
||||
|
@ -767,7 +767,7 @@ mod tests {
|
|||
PartialValue::new_iname("testperson1")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::SystemInfo.to_value(),
|
||||
)]),
|
||||
);
|
||||
|
@ -780,7 +780,7 @@ mod tests {
|
|||
PartialValue::new_iname("testperson1")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Name.into(),
|
||||
Attribute::Name,
|
||||
Value::new_iname("testpersonx"),
|
||||
)]),
|
||||
);
|
||||
|
@ -793,9 +793,9 @@ mod tests {
|
|||
PartialValue::new_iname("testperson1")
|
||||
)),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Present(Attribute::Class.into(), EntryClass::SystemInfo.to_value()),
|
||||
Modify::Present(Attribute::Class, EntryClass::SystemInfo.to_value()),
|
||||
// Modify::Present(Attribute::Domain.into(), Value::new_iutf8("domain.name")),
|
||||
Modify::Present(Attribute::Version.into(), Value::new_uint32(1)),
|
||||
Modify::Present(Attribute::Version, Value::new_uint32(1)),
|
||||
]),
|
||||
);
|
||||
assert!(server_txn.modify(&me_sin).is_ok());
|
||||
|
@ -807,8 +807,8 @@ mod tests {
|
|||
PartialValue::new_iname("testperson1")
|
||||
)),
|
||||
ModifyList::new_list(vec![
|
||||
Modify::Purged(Attribute::Name.into()),
|
||||
Modify::Present(Attribute::Name.into(), Value::new_iname("testpersonx")),
|
||||
Modify::Purged(Attribute::Name),
|
||||
Modify::Present(Attribute::Name, Value::new_iname("testpersonx")),
|
||||
]),
|
||||
);
|
||||
assert!(server_txn.modify(&me_sin).is_ok());
|
||||
|
@ -847,10 +847,7 @@ mod tests {
|
|||
Attribute::Name,
|
||||
PartialValue::new_iname("testperson1")
|
||||
)),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::PrimaryCredential.into(),
|
||||
v_cred,
|
||||
)]),
|
||||
ModifyList::new_list(vec![Modify::Present(Attribute::PrimaryCredential, v_cred)]),
|
||||
);
|
||||
// go!
|
||||
assert!(server_txn.modify(&me_inv_m).is_ok());
|
||||
|
|
|
@ -110,7 +110,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
|
||||
// Check access against a "fake" modify.
|
||||
let modlist = ModifyList::new_list(vec![Modify::Removed(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::Recycled.into(),
|
||||
)]);
|
||||
|
||||
|
@ -152,11 +152,11 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
dm_mods
|
||||
.entry(g_uuid)
|
||||
.and_modify(|mlist| {
|
||||
let m = Modify::Present(Attribute::Member.into(), Value::Refer(u));
|
||||
let m = Modify::Present(Attribute::Member, Value::Refer(u));
|
||||
mlist.push_mod(m);
|
||||
})
|
||||
.or_insert({
|
||||
let m = Modify::Present(Attribute::Member.into(), Value::Refer(u));
|
||||
let m = Modify::Present(Attribute::Member, Value::Refer(u));
|
||||
ModifyList::new_list(vec![m])
|
||||
});
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ mod tests {
|
|||
admin.clone(),
|
||||
filt_i_rc.clone(),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::Recycled.into(),
|
||||
)]),
|
||||
);
|
||||
|
@ -529,7 +529,7 @@ mod tests {
|
|||
admin.clone(),
|
||||
filt_i_ts.clone(),
|
||||
ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::Class.into(),
|
||||
Attribute::Class,
|
||||
EntryClass::Tombstone.into(),
|
||||
)]),
|
||||
);
|
||||
|
@ -625,8 +625,7 @@ mod tests {
|
|||
(
|
||||
Attribute::Uuid,
|
||||
#[allow(clippy::panic)]
|
||||
Value::new_uuid_s(uuid)
|
||||
.unwrap_or_else(|| { panic!("{}", Attribute::Uuid.as_ref().to_string()) })
|
||||
Value::new_uuid_s(uuid).unwrap_or_else(|| { panic!("{}", Attribute::Uuid) })
|
||||
),
|
||||
(Attribute::Description, Value::new_utf8s("testperson-entry")),
|
||||
(Attribute::DisplayName, Value::new_utf8s(name))
|
||||
|
@ -641,8 +640,7 @@ mod tests {
|
|||
(Attribute::Name, Value::new_iname(name)),
|
||||
(
|
||||
Attribute::Uuid,
|
||||
Value::new_uuid_s(uuid)
|
||||
.unwrap_or_else(|| { panic!("{}", Attribute::Uuid.as_ref().to_string()) })
|
||||
Value::new_uuid_s(uuid).unwrap_or_else(|| { panic!("{}", Attribute::Uuid) })
|
||||
),
|
||||
(Attribute::Description, Value::new_utf8s("testgroup-entry"))
|
||||
);
|
||||
|
|
|
@ -449,14 +449,14 @@ impl From<CredentialType> for PartialValue {
|
|||
|
||||
impl From<Attribute> for Value {
|
||||
fn from(attr: Attribute) -> Value {
|
||||
let s: &str = attr.into();
|
||||
let s: &str = attr.as_str();
|
||||
Value::new_iutf8(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Attribute> for PartialValue {
|
||||
fn from(attr: Attribute) -> PartialValue {
|
||||
let s: &str = attr.into();
|
||||
let s: &str = attr.as_str();
|
||||
PartialValue::new_iutf8(s)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -551,7 +551,7 @@ mod tests {
|
|||
let res = image.validate_image();
|
||||
trace!("SVG Validation result of {}: {:?}", filename, &res);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(image.hash_imagevalue().is_empty(), false);
|
||||
assert!(!image.hash_imagevalue().is_empty());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -242,7 +242,7 @@ pub async fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: Attribute
|
|||
.await
|
||||
.is_ok(),
|
||||
),
|
||||
entry => {
|
||||
ref entry => {
|
||||
let new_value = match entry {
|
||||
Attribute::AcpReceiverGroup => "00000000-0000-0000-0000-000000000011".to_string(),
|
||||
Attribute::AcpTargetScope => "{\"and\": [{\"eq\": [\"class\",\"access_control_profile\"]}, {\"andnot\": {\"or\": [{\"eq\": [\"class\", \"tombstone\"]}, {\"eq\": [\"class\", \"recycled\"]}]}}]}".to_string(),
|
||||
|
@ -320,7 +320,7 @@ pub async fn test_read_attrs(
|
|||
.await
|
||||
.unwrap()
|
||||
.is_some(),
|
||||
_ => e.attrs.contains_key(attr.as_ref()),
|
||||
_ => e.attrs.contains_key(attr.as_str()),
|
||||
};
|
||||
trace!("is_ok: {}, is_readable: {}", is_ok, is_readable);
|
||||
assert_eq!(is_ok, is_readable)
|
||||
|
@ -337,7 +337,7 @@ pub async fn test_write_attrs(
|
|||
for attr in attrs.iter() {
|
||||
println!("Writing to {} - ex {}", attr, is_writeable);
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let is_ok = is_attr_writable(rsclient, id, *attr).await.unwrap();
|
||||
let is_ok = is_attr_writable(rsclient, id, attr.clone()).await.unwrap();
|
||||
assert_eq!(is_ok, is_writeable)
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +352,9 @@ pub async fn test_modify_group(
|
|||
println!("Testing group: {}", group);
|
||||
for attr in [Attribute::Description, Attribute::Name].into_iter() {
|
||||
#[allow(clippy::unwrap_used)]
|
||||
let is_writable = is_attr_writable(rsclient, group, attr).await.unwrap();
|
||||
let is_writable = is_attr_writable(rsclient, group, attr.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
dbg!(group, attr, is_writable, can_be_modified);
|
||||
assert_eq!(is_writable, can_be_modified)
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ async fn test_server_search(rsclient: KanidmClient) {
|
|||
let e = rset.first().unwrap();
|
||||
// Check it's admin.
|
||||
println!("{:?}", e);
|
||||
let name = e.attrs.get(Attribute::Name.as_ref()).unwrap();
|
||||
let name = e.attrs.get(Attribute::Name.as_str()).unwrap();
|
||||
assert_eq!(name, &vec!["admin".to_string()]);
|
||||
}
|
||||
|
||||
|
@ -537,7 +537,7 @@ async fn test_server_rest_domain_lifecycle(rsclient: KanidmClient) {
|
|||
assert!(
|
||||
dlocal
|
||||
.attrs
|
||||
.get(Attribute::DomainDisplayName.as_ref())
|
||||
.get(Attribute::DomainDisplayName.as_str())
|
||||
.and_then(|v| v.first())
|
||||
== Some(&"Super Cool Crabz".to_string())
|
||||
);
|
||||
|
@ -870,11 +870,11 @@ async fn test_server_rest_oauth2_basic_lifecycle(rsclient: KanidmClient) {
|
|||
// What can we see?
|
||||
assert!(oauth2_config
|
||||
.attrs
|
||||
.contains_key(Attribute::OAuth2RsBasicSecret.as_ref()));
|
||||
.contains_key(Attribute::OAuth2RsBasicSecret.as_str()));
|
||||
// This is present, but redacted.
|
||||
assert!(oauth2_config
|
||||
.attrs
|
||||
.contains_key(Attribute::OAuth2RsTokenKey.as_ref()));
|
||||
.contains_key(Attribute::OAuth2RsTokenKey.as_str()));
|
||||
|
||||
// Mod delete the secret/key and check them again.
|
||||
// Check we can patch the oauth2_rs_name / oauth2_rs_origin
|
||||
|
|
Loading…
Reference in a new issue