Schema dooby doo part two ()

* scim strings!
* mapmapmap
* mapmapmap -comments and map
* updating delete teest
* fixing some tests
This commit is contained in:
James Hodgkinson 2023-09-05 16:58:42 +10:00 committed by GitHub
parent 436a3f0307
commit d5d76d1a3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 934 additions and 662 deletions

View file

@ -24,6 +24,7 @@ pub const ATTR_ACP_TARGET_SCOPE: &str = "acp_targetscope";
pub const ATTR_API_TOKEN_SESSION: &str = "api_token_session";
pub const ATTR_ATTR: &str = "attr";
pub const ATTR_ATTRIBUTENAME: &str = "attributename";
pub const ATTR_ATTRIBUTETYPE: &str = "attributetype";
pub const ATTR_AUTH_SESSION_EXPIRY: &str = "authsession_expiry";
pub const ATTR_BADLIST_PASSWORD: &str = "badlist_password";
pub const ATTR_CLAIM: &str = "claim";
@ -36,6 +37,7 @@ pub const ATTR_DESCRIPTION: &str = "description";
pub const ATTR_DEVICEKEYS: &str = "devicekeys";
pub const ATTR_DIRECTMEMBEROF: &str = "directmemberof";
pub const ATTR_DISPLAYNAME: &str = "displayname";
pub const ATTR_DN: &str = "dn";
pub const ATTR_DOMAIN_DISPLAY_NAME: &str = "domain_display_name";
pub const ATTR_DOMAIN_LDAP_BASEDN: &str = "domain_ldap_basedn";
pub const ATTR_DOMAIN_NAME: &str = "domain_name";
@ -46,9 +48,14 @@ pub const ATTR_DOMAIN: &str = "domain";
pub const ATTR_DYNGROUP_FILTER: &str = "dyngroup_filter";
pub const ATTR_DYNGROUP: &str = "dyngroup";
pub const ATTR_DYNMEMBER: &str = "dynmember";
pub const ATTR_LDAP_EMAIL_ADDRESS: &str = "emailaddress";
pub const ATTR_EMAIL_ALTERNATIVE: &str = "emailalternative";
pub const ATTR_EMAIL_PRIMARY: &str = "emailprimary";
pub const ATTR_EMAIL: &str = "email";
pub const ATTR_ENTRYDN: &str = "entrydn";
pub const ATTR_ENTRYUUID: &str = "entryuuid";
pub const ATTR_LDAP_KEYS: &str = "keys";
pub const ATTR_EXCLUDES: &str = "excludes";
pub const ATTR_ES256_PRIVATE_KEY_DER: &str = "es256_private_key_der";
pub const ATTR_FERNET_PRIVATE_KEY_STR: &str = "fernet_private_key_str";
pub const ATTR_GIDNUMBER: &str = "gidnumber";
@ -71,6 +78,7 @@ pub const ATTR_NAME_HISTORY: &str = "name_history";
pub const ATTR_NAME: &str = "name";
pub const ATTR_NO_INDEX: &str = "no-index";
pub const ATTR_NSUNIQUEID: &str = "nsuniqueid";
pub const ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE: &str =
"oauth2_allow_insecure_client_disable_pkce";
pub const ATTR_OAUTH2_CONSENT_SCOPE_MAP: &str = "oauth2_consent_scope_map";
@ -91,26 +99,34 @@ pub const ATTR_PASSKEYS: &str = "passkeys";
pub const ATTR_PASSWORD_IMPORT: &str = "password_import";
pub const ATTR_PHANTOM: &str = "phantom";
pub const ATTR_PRIMARY_CREDENTIAL: &str = "primary_credential";
pub const ATTR_TOTP_IMPORT: &str = "totp_import";
pub const ATTR_PRIVATE_COOKIE_KEY: &str = "private_cookie_key";
pub const ATTR_PRIVILEGE_EXPIRY: &str = "privilege_expiry";
pub const ATTR_RADIUS_SECRET: &str = "radius_secret";
pub const ATTR_RECYCLED: &str = "recycled";
pub const ATTR_REPLICATED: &str = "replicated";
pub const ATTR_RS256_PRIVATE_KEY_DER: &str = "rs256_private_key_der";
pub const ATTR_SCOPE: &str = "scope";
pub const ATTR_SELF: &str = "self";
pub const ATTR_SOURCE_UUID: &str = "source_uuid";
pub const ATTR_SPN: &str = "spn";
pub const ATTR_SUPPLEMENTS: &str = "supplements";
pub const ATTR_LDAP_SSH_PUBLICKEY: &str = "ssh_publickey";
pub const ATTR_SSHPUBLICKEY: &str = "sshpublickey";
pub const ATTR_SYNC_ALLOWED: &str = "sync_allowed";
pub const ATTR_SYNC_CLASS: &str = "sync_class";
pub const ATTR_SYNC_COOKIE: &str = "sync_cookie";
pub const ATTR_SYNC_CREDENTIAL_PORTAL: &str = "sync_credential_portal";
pub const ATTR_SYNC_EXTERNAL_ID: &str = "sync_external_id";
pub const ATTR_SYNC_EXTERNAL_UUID: &str = "sync_external_uuid";
pub const ATTR_SYNC_PARENT_UUID: &str = "sync_parent_uuid";
pub const ATTR_SYNC_TOKEN_SESSION: &str = "sync_token_session";
pub const ATTR_SYNC_YIELD_AUTHORITY: &str = "sync_yield_authority";
pub const ATTR_SYNTAX: &str = "syntax";
pub const ATTR_SYSTEMEXCLUDES: &str = "systemexcludes";
pub const ATTR_SYSTEMMAY: &str = "systemmay";
pub const ATTR_SYSTEMMUST: &str = "systemmust";
pub const ATTR_SYSTEMSUPPLEMENTS: &str = "systemsupplements";
pub const ATTR_TERM: &str = "term";
pub const ATTR_UID: &str = "uid";
pub const ATTR_UIDNUMBER: &str = "uidnumber";
@ -126,6 +142,8 @@ pub const ATTR_VERSION: &str = "version";
pub const TEST_ATTR_NON_EXIST: &str = "non-exist";
pub const TEST_ATTR_TEST_ATTR: &str = "testattr";
pub const TEST_ATTR_EXTRA: &str = "extra";
pub const TEST_ATTR_NUMBER: &str = "testattrnumber";
pub const TEST_ATTR_NOTALLOWED: &str = "notallowed";
pub const OAUTH2_SCOPE_EMAIL: &str = ATTR_EMAIL;
pub const OAUTH2_SCOPE_GROUPS: &str = "groups";

View file

@ -53,6 +53,11 @@ impl ScimSyncRequest {
}
}
pub const SCIM_ALGO: &str = "algo";
pub const SCIM_DIGITS: &str = "digits";
pub const SCIM_SECRET: &str = "secret";
pub const SCIM_STEP: &str = "step";
pub const SCIM_SCHEMA_SYNC: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:";
pub const SCIM_SCHEMA_SYNC_PERSON: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:person";
pub const SCIM_SCHEMA_SYNC_ACCOUNT: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:account";
@ -88,13 +93,16 @@ impl Into<ScimComplexAttr> for ScimTotp {
ScimSimpleAttr::String(external_id),
);
attrs.insert("secret".to_string(), ScimSimpleAttr::String(secret));
attrs.insert(SCIM_SECRET.to_string(), ScimSimpleAttr::String(secret));
attrs.insert("algo".to_string(), ScimSimpleAttr::String(algo));
attrs.insert(SCIM_ALGO.to_string(), ScimSimpleAttr::String(algo));
attrs.insert("step".to_string(), ScimSimpleAttr::Number(step.into()));
attrs.insert(SCIM_STEP.to_string(), ScimSimpleAttr::Number(step.into()));
attrs.insert("digits".to_string(), ScimSimpleAttr::Number(digits.into()));
attrs.insert(
SCIM_DIGITS.to_string(),
ScimSimpleAttr::Number(digits.into()),
);
ScimComplexAttr { attrs }
}

View file

@ -1242,7 +1242,7 @@ pub async fn recycle_bin_get(
State(state): State<ServerState>,
Extension(kopid): Extension<KOpId>,
) -> impl IntoResponse {
let filter = filter_all!(f_pres(Attribute::Class.as_ref()));
let filter = filter_all!(f_pres(Attribute::Class));
let attrs = None;
let res = state
.qe_r_ref
@ -1434,7 +1434,7 @@ pub async fn debug_ipinfo(
#[instrument(skip(state))]
pub fn router(state: ServerState) -> Router<ServerState> {
let router = Router::new()
Router::new()
.route("/v1/oauth2", get(super::oauth2::oauth2_get))
.route("/v1/oauth2/_basic", post(super::oauth2::oauth2_basic_post))
.route(
@ -1735,15 +1735,6 @@ pub fn router(state: ServerState) -> Router<ServerState> {
post(sync_account_token_post).delete(sync_account_token_delete),
)
.with_state(state)
.layer(from_fn(dont_cache_me));
if cfg!(debug_assertions) || cfg!(test) {
add_debug_info(router)
} else {
router
}
}
// #[cfg(any(debug_assertions, test))]
fn add_debug_info(router: Router<ServerState>) -> Router<ServerState> {
router.route("/v1/debug/ipinfo", get(debug_ipinfo))
.layer(from_fn(dont_cache_me))
.route("/v1/debug/ipinfo", get(debug_ipinfo))
}

View file

@ -7,6 +7,7 @@ use smartstring::alias::String as AttrString;
use uuid::Uuid;
use crate::be::dbvalue::{DbValueEmailAddressV1, DbValuePhoneNumberV1, DbValueSetV2, DbValueV1};
use crate::prelude::entries::Attribute;
use crate::prelude::OperationError;
#[derive(Serialize, Deserialize, Debug)]
@ -446,12 +447,12 @@ impl std::fmt::Display for DbEntry {
}
None => write!(f, "Uuid(INVALID), ")?,
};
if let Some(names) = dbe_v1.attrs.get("name") {
if let Some(names) = dbe_v1.attrs.get(Attribute::Name.as_ref()) {
for name in names {
write!(f, "{name:?}, ")?;
}
}
if let Some(names) = dbe_v1.attrs.get("attributename") {
if let Some(names) = dbe_v1.attrs.get(Attribute::AttributeName.as_ref()) {
for name in names {
write!(f, "{name:?}, ")?;
}
@ -471,10 +472,10 @@ impl std::fmt::Display for DbEntry {
}
None => write!(f, "Uuid(INVALID), ")?,
};
if let Some(names) = dbe_v2.attrs.get("name") {
if let Some(names) = dbe_v2.attrs.get(Attribute::Name.as_ref()) {
write!(f, "{names:?}, ")?;
}
if let Some(names) = dbe_v2.attrs.get("attributename") {
if let Some(names) = dbe_v2.attrs.get(Attribute::AttributeName.as_ref()) {
write!(f, "{names:?}, ")?;
}
if let Some(names) = dbe_v2.attrs.get("classname") {

View file

@ -2046,31 +2046,31 @@ mod tests {
// This is a demo idxmeta, purely for testing.
let idxmeta = vec![
IdxKey {
attr: AttrString::from("name"),
attr: Attribute::Name.into(),
itype: IndexType::Equality,
},
IdxKey {
attr: AttrString::from("name"),
attr: Attribute::Name.into(),
itype: IndexType::Presence,
},
IdxKey {
attr: AttrString::from("name"),
attr: Attribute::Name.into(),
itype: IndexType::SubString,
},
IdxKey {
attr: AttrString::from("uuid"),
attr: Attribute::Uuid.into(),
itype: IndexType::Equality,
},
IdxKey {
attr: AttrString::from("uuid"),
attr: Attribute::Uuid.into(),
itype: IndexType::Presence,
},
IdxKey {
attr: AttrString::from("ta"),
attr: Attribute::TestAttr.into(),
itype: IndexType::Equality,
},
IdxKey {
attr: AttrString::from("tb"),
attr: Attribute::TestNumber.into(),
itype: IndexType::Equality,
},
];
@ -2091,7 +2091,7 @@ mod tests {
($be:expr, $ent:expr) => {{
let ei = $ent.clone().into_sealed_committed();
let filt = ei
.filter_from_attrs(&vec![AttrString::from("uuid")])
.filter_from_attrs(&vec![Attribute::Uuid.into()])
.expect("failed to generate filter")
.into_valid_resolved();
let lims = Limits::unlimited();
@ -2104,7 +2104,7 @@ mod tests {
($be:expr, $ent:expr, $attr:expr) => {{
let ei = $ent.clone().into_sealed_committed();
let filt = ei
.filter_from_attrs(&vec![AttrString::from("userid")])
.filter_from_attrs(&vec![Attribute::UserId.into()])
.expect("failed to generate filter")
.into_valid_resolved();
let lims = Limits::unlimited();
@ -2136,8 +2136,11 @@ mod tests {
assert_eq!(empty_result, Err(OperationError::EmptyRequest));
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("userid", Value::from("william"));
e.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let e = e.into_sealed_new();
let single_result = be.create(&CID_ZERO, vec![e.clone()]);
@ -2155,8 +2158,11 @@ mod tests {
trace!("Simple Search");
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("userid", Value::from("claire"));
e.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e.add_ava(Attribute::UserId.as_ref(), Value::from("claire"));
e.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let e = e.into_sealed_new();
let single_result = be.create(&CID_ZERO, vec![e]);
@ -2185,12 +2191,18 @@ mod tests {
let lims = Limits::unlimited();
// First create some entries (3?)
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("userid", Value::from("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("userid", Value::from("alice"));
e2.add_ava("uuid", Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"));
e2.add_ava(Attribute::UserId.as_ref(), Value::from("alice"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"),
);
let ve1 = e1.clone().into_sealed_new();
let ve2 = e2.clone().into_sealed_new();
@ -2201,7 +2213,7 @@ mod tests {
// You need to now retrieve the entries back out to get the entry id's
let mut results = be
.search(&lims, &filter_resolved!(f_pres("userid")))
.search(&lims, &filter_resolved!(f_pres(Attribute::UserId)))
.expect("Failed to search");
// Get these out to usable entries.
@ -2224,8 +2236,8 @@ mod tests {
// Make some changes to r1, r2.
let pre1 = Arc::new(r1.clone().into_sealed_committed());
let pre2 = Arc::new(r2.clone().into_sealed_committed());
r1.add_ava("desc", Value::from("modified"));
r2.add_ava("desc", Value::from("modified"));
r1.add_ava("testattr", Value::from("modified"));
r2.add_ava("testattr", Value::from("modified"));
// Now ... cheat.
@ -2235,8 +2247,8 @@ mod tests {
// Modify single
assert!(be.modify(&CID_ZERO, &[pre1], &[vr1.clone()]).is_ok());
// Assert no other changes
assert!(entry_attr_pres!(be, vr1, "desc"));
assert!(!entry_attr_pres!(be, vr2, "desc"));
assert!(entry_attr_pres!(be, vr1, "testattr"));
assert!(!entry_attr_pres!(be, vr2, "testattr"));
// Modify both
assert!(be
@ -2247,8 +2259,8 @@ mod tests {
)
.is_ok());
assert!(entry_attr_pres!(be, vr1, "desc"));
assert!(entry_attr_pres!(be, vr2, "desc"));
assert!(entry_attr_pres!(be, vr1, "testattr"));
assert!(entry_attr_pres!(be, vr2, "testattr"));
});
}
@ -2260,16 +2272,25 @@ mod tests {
// First create some entries (3?)
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("userid", Value::from("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("userid", Value::from("alice"));
e2.add_ava("uuid", Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"));
e2.add_ava(Attribute::UserId.as_ref(), Value::from("alice"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"),
);
let mut e3: Entry<EntryInit, EntryNew> = Entry::new();
e3.add_ava("userid", Value::from("lucy"));
e3.add_ava("uuid", Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"));
e3.add_ava(Attribute::UserId.as_ref(), Value::from("lucy"));
e3.add_ava(
Attribute::Uuid.as_ref(),
Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"),
);
let ve1 = e1.clone().into_sealed_new();
let ve2 = e2.clone().into_sealed_new();
@ -2282,7 +2303,7 @@ mod tests {
// You need to now retrieve the entries back out to get the entry id's
let mut results = be
.search(&lims, &filter_resolved!(f_pres("userid")))
.search(&lims, &filter_resolved!(f_pres(Attribute::UserId)))
.expect("Failed to search");
// Get these out to usable entries.
@ -2356,16 +2377,25 @@ mod tests {
// First create some entries (3?)
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("userid", Value::from("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("userid", Value::from("alice"));
e2.add_ava("uuid", Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"));
e2.add_ava(Attribute::UserId.as_ref(), Value::from("alice"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"),
);
let mut e3: Entry<EntryInit, EntryNew> = Entry::new();
e3.add_ava("userid", Value::from("lucy"));
e3.add_ava("uuid", Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"));
e3.add_ava(Attribute::UserId.as_ref(), Value::from("lucy"));
e3.add_ava(
Attribute::Uuid.as_ref(),
Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"),
);
let ve1 = e1.clone().into_sealed_new();
let ve2 = e2.clone().into_sealed_new();
@ -2411,16 +2441,25 @@ mod tests {
be.set_db_ts_max(Duration::from_secs(1)).unwrap();
// First create some entries (3?)
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("userid", Value::from("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("userid", Value::from("alice"));
e2.add_ava("uuid", Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"));
e2.add_ava(Attribute::UserId.as_ref(), Value::from("alice"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("4b6228ab-1dbe-42a4-a9f5-f6368222438e"),
);
let mut e3: Entry<EntryInit, EntryNew> = Entry::new();
e3.add_ava("userid", Value::from("lucy"));
e3.add_ava("uuid", Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"));
e3.add_ava(Attribute::UserId.as_ref(), Value::from("lucy"));
e3.add_ava(
Attribute::Uuid.as_ref(),
Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"),
);
let ve1 = e1.clone().into_sealed_new();
let ve2 = e2.clone().into_sealed_new();
@ -2506,13 +2545,19 @@ mod tests {
run_test!(|be: &mut BackendWriteTransaction| {
// Add some test data?
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::new_iname("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::Name.as_ref(), Value::new_iname("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let e1 = e1.into_sealed_new();
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("name", Value::new_iname("claire"));
e2.add_ava("uuid", Value::from("bd651620-00dd-426b-aaa0-4494f7b7906f"));
e2.add_ava(Attribute::Name.as_ref(), Value::new_iname("claire"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("bd651620-00dd-426b-aaa0-4494f7b7906f"),
);
let e2 = e2.into_sealed_new();
be.create(&CID_ZERO, vec![e1, e2]).unwrap();
@ -2603,8 +2648,11 @@ mod tests {
// Test that on entry create, the indexes are made correctly.
// this is a similar case to reindex.
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::from("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::Name.as_ref(), Value::from("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let e1 = e1.into_sealed_new();
let rset = be.create(&CID_ZERO, vec![e1]).unwrap();
@ -2664,18 +2712,27 @@ mod tests {
// Test that on entry create, the indexes are made correctly.
// this is a similar case to reindex.
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::new_iname("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::Name.as_ref(), Value::new_iname("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let e1 = e1.into_sealed_new();
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("name", Value::new_iname("claire"));
e2.add_ava("uuid", Value::from("bd651620-00dd-426b-aaa0-4494f7b7906f"));
e2.add_ava(Attribute::Name.as_ref(), Value::new_iname("claire"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("bd651620-00dd-426b-aaa0-4494f7b7906f"),
);
let e2 = e2.into_sealed_new();
let mut e3: Entry<EntryInit, EntryNew> = Entry::new();
e3.add_ava("userid", Value::new_iname("lucy"));
e3.add_ava("uuid", Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"));
e3.add_ava(Attribute::UserId.as_ref(), Value::new_iname("lucy"));
e3.add_ava(
Attribute::Uuid.as_ref(),
Value::from("7b23c99d-c06b-4a9a-a958-3afa56383e1d"),
);
let e3 = e3.into_sealed_new();
let mut rset = be.create(&CID_ZERO, vec![e1, e2, e3]).unwrap();
@ -2732,9 +2789,12 @@ mod tests {
// us. For the test to be "accurate" we must add one attr, remove one attr
// and change one attr.
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::new_iname("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava("ta", Value::from("test"));
e1.add_ava(Attribute::Name.as_ref(), Value::new_iname("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
e1.add_ava("testattr", Value::from("test"));
let e1 = e1.into_sealed_new();
let rset = be.create(&CID_ZERO, vec![e1]).unwrap();
@ -2742,12 +2802,12 @@ mod tests {
// Now, alter the new entry.
let mut ce1 = rset[0].as_ref().clone().into_invalid();
// add something.
ce1.add_ava("tb", Value::from("test"));
ce1.add_ava("testattrnumber", Value::from("test"));
// remove something.
ce1.purge_ava("ta");
ce1.purge_ava("testattr");
// mod something.
ce1.purge_ava("name");
ce1.add_ava("name", Value::new_iname("claire"));
ce1.add_ava(Attribute::Name.as_ref(), Value::new_iname("claire"));
let ce1 = ce1.into_sealed_committed();
@ -2758,9 +2818,15 @@ mod tests {
idl_state!(be, "name", IndexType::Presence, "_", Some(vec![1]));
idl_state!(be, "tb", IndexType::Equality, "test", Some(vec![1]));
idl_state!(
be,
"testattrnumber",
IndexType::Equality,
"test",
Some(vec![1])
);
idl_state!(be, "ta", IndexType::Equality, "test", Some(vec![]));
idl_state!(be, "testattr", IndexType::Equality, "test", Some(vec![]));
let william_uuid = uuid!("db237e8a-0079-4b8c-8a56-593b22aa44d1");
assert!(be.name2uuid("william") == Ok(None));
@ -2778,8 +2844,11 @@ mod tests {
// This will be needing to be correct for conflicts when we add
// replication support!
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::new_iname("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::Name.as_ref(), Value::new_iname("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let e1 = e1.into_sealed_new();
let rset = be.create(&CID_ZERO, vec![e1]).unwrap();
@ -2788,8 +2857,11 @@ mod tests {
let mut ce1 = rset[0].as_ref().clone().into_invalid();
ce1.purge_ava("name");
ce1.purge_ava("uuid");
ce1.add_ava("name", Value::new_iname("claire"));
ce1.add_ava("uuid", Value::from("04091a7a-6ce4-42d2-abf5-c2ce244ac9e8"));
ce1.add_ava(Attribute::Name.as_ref(), Value::new_iname("claire"));
ce1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("04091a7a-6ce4-42d2-abf5-c2ce244ac9e8"),
);
let ce1 = ce1.into_sealed_committed();
be.modify(&CID_ZERO, &rset, &[ce1]).unwrap();
@ -2834,15 +2906,21 @@ mod tests {
// Create a test entry with some indexed / unindexed values.
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::new_iname("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava(Attribute::Name.as_ref(), Value::new_iname("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
e1.add_ava("no-index", Value::from("william"));
e1.add_ava("other-no-index", Value::from("william"));
let e1 = e1.into_sealed_new();
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("name", Value::new_iname("claire"));
e2.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d2"));
e2.add_ava(Attribute::Name.as_ref(), Value::new_iname("claire"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d2"),
);
let e2 = e2.into_sealed_new();
let _rset = be.create(&CID_ZERO, vec![e1, e2]).unwrap();
@ -3015,7 +3093,7 @@ mod tests {
// test andnot in and (first) with name
let f_and_andnot = filter_resolved!(f_and!([
f_andnot(f_eq(Attribute::Name, PartialValue::new_utf8s("claire"))),
f_pres("name")
f_pres(Attribute::Name)
]));
let (r, _plan) = be.filter2idl(f_and_andnot.to_inner(), 0).unwrap();
@ -3030,7 +3108,7 @@ mod tests {
}
// test andnot in and (last) with name
let f_and_andnot = filter_resolved!(f_and!([
f_pres("name"),
f_pres(Attribute::Name),
f_andnot(f_eq(Attribute::Name, PartialValue::new_utf8s("claire")))
]));
@ -3046,7 +3124,7 @@ mod tests {
// test andnot in and (first) with no-index
let f_and_andnot = filter_resolved!(f_and!([
f_andnot(f_eq(Attribute::Name, PartialValue::new_utf8s("claire"))),
f_pres("no-index")
f_pres(Attribute::NoIndex)
]));
let (r, _plan) = be.filter2idl(f_and_andnot.to_inner(), 0).unwrap();
@ -3058,7 +3136,7 @@ mod tests {
}
// test andnot in and (last) with no-index
let f_and_andnot = filter_resolved!(f_and!([
f_pres("no-index"),
f_pres(Attribute::NoIndex),
f_andnot(f_eq(Attribute::Name, PartialValue::new_utf8s("claire")))
]));
@ -3121,24 +3199,33 @@ mod tests {
run_test!(|be: &mut BackendWriteTransaction| {
// Create some test entry with some indexed / unindexed values.
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("name", Value::new_iname("william"));
e1.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e1.add_ava("ta", Value::from("dupe"));
e1.add_ava("tb", Value::from("1"));
e1.add_ava(Attribute::Name.as_ref(), Value::new_iname("william"));
e1.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
e1.add_ava("testattr", Value::from("dupe"));
e1.add_ava("testattrnumber", Value::from("1"));
let e1 = e1.into_sealed_new();
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("name", Value::new_iname("claire"));
e2.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d2"));
e2.add_ava("ta", Value::from("dupe"));
e2.add_ava("tb", Value::from("1"));
e2.add_ava(Attribute::Name.as_ref(), Value::new_iname("claire"));
e2.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d2"),
);
e2.add_ava("testattr", Value::from("dupe"));
e2.add_ava("testattrnumber", Value::from("1"));
let e2 = e2.into_sealed_new();
let mut e3: Entry<EntryInit, EntryNew> = Entry::new();
e3.add_ava("name", Value::new_iname("benny"));
e3.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d3"));
e3.add_ava("ta", Value::from("dupe"));
e3.add_ava("tb", Value::from("2"));
e3.add_ava(Attribute::Name.as_ref(), Value::new_iname("benny"));
e3.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d3"),
);
e3.add_ava("testattr", Value::from("dupe"));
e3.add_ava("testattrnumber", Value::from("2"));
let e3 = e3.into_sealed_new();
let _rset = be.create(&CID_ZERO, vec![e1, e2, e3]).unwrap();
@ -3148,12 +3235,12 @@ mod tests {
assert!(!be.is_idx_slopeyness_generated().unwrap());
let ta_eq_slope = be
.get_idx_slope(&IdxKey::new("ta", IndexType::Equality))
.get_idx_slope(&IdxKey::new("testattr", IndexType::Equality))
.unwrap();
assert_eq!(ta_eq_slope, 45);
let tb_eq_slope = be
.get_idx_slope(&IdxKey::new("tb", IndexType::Equality))
.get_idx_slope(&IdxKey::new("testattrnumber", IndexType::Equality))
.unwrap();
assert_eq!(tb_eq_slope, 45);
@ -3182,12 +3269,12 @@ mod tests {
assert!(be.is_idx_slopeyness_generated().unwrap());
let ta_eq_slope = be
.get_idx_slope(&IdxKey::new("ta", IndexType::Equality))
.get_idx_slope(&IdxKey::new("testattr", IndexType::Equality))
.unwrap();
assert_eq!(ta_eq_slope, 200);
let tb_eq_slope = be
.get_idx_slope(&IdxKey::new("tb", IndexType::Equality))
.get_idx_slope(&IdxKey::new("testattrnumber", IndexType::Equality))
.unwrap();
assert_eq!(tb_eq_slope, 133);
@ -3221,15 +3308,18 @@ mod tests {
lim_deny_allids.unindexed_allow = false;
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("userid", Value::from("william"));
e.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e.add_ava("nonexist", Value::from("x"));
e.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
e.add_ava(Attribute::NonExist.as_ref(), Value::from("x"));
let e = e.into_sealed_new();
let single_result = be.create(&CID_ZERO, vec![e.clone()]);
assert!(single_result.is_ok());
let filt = e
.filter_from_attrs(&[AttrString::from("nonexist")])
.filter_from_attrs(&[Attribute::NonExist.into()])
.expect("failed to generate filter")
.into_valid_resolved();
// check allow on allids
@ -3256,15 +3346,18 @@ mod tests {
lim_deny.search_max_results = 0;
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("userid", Value::from("william"));
e.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e.add_ava("nonexist", Value::from("x"));
e.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
e.add_ava(Attribute::NonExist.as_ref(), Value::from("x"));
let e = e.into_sealed_new();
let single_result = be.create(&CID_ZERO, vec![e.clone()]);
assert!(single_result.is_ok());
let filt = e
.filter_from_attrs(&[AttrString::from("nonexist")])
.filter_from_attrs(&[Attribute::NonExist.into()])
.expect("failed to generate filter")
.into_valid_resolved();
@ -3312,10 +3405,13 @@ mod tests {
lim_deny.search_max_filter_test = 0;
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("name", Value::new_iname("william"));
e.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e.add_ava("nonexist", Value::from("x"));
e.add_ava("nonexist", Value::from("y"));
e.add_ava(Attribute::Name.as_ref(), Value::new_iname("william"));
e.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
e.add_ava(Attribute::NonExist.as_ref(), Value::from("x"));
e.add_ava(Attribute::NonExist.as_ref(), Value::from("y"));
let e = e.into_sealed_new();
let single_result = be.create(&CID_ZERO, vec![e]);
assert!(single_result.is_ok());
@ -3364,7 +3460,7 @@ mod tests {
// This is a demo idxmeta, purely for testing.
let idxmeta = vec![IdxKey {
attr: AttrString::from("uuid"),
attr: Attribute::Uuid.into(),
itype: IndexType::Equality,
}];
@ -3381,8 +3477,11 @@ mod tests {
// Create into A
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("userid", Value::from("william"));
e.add_ava("uuid", Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"));
e.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
e.add_ava(
Attribute::Uuid.as_ref(),
Value::from("db237e8a-0079-4b8c-8a56-593b22aa44d1"),
);
let e = e.into_sealed_new();
let single_result = be_a_txn.create(&CID_ZERO, vec![e]);
@ -3402,8 +3501,11 @@ mod tests {
// Create into B
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("userid", Value::from("claire"));
e.add_ava("uuid", Value::from("0c680959-0944-47d6-9dea-53304d124266"));
e.add_ava(Attribute::UserId.as_ref(), Value::from("claire"));
e.add_ava(
Attribute::Uuid.as_ref(),
Value::from("0c680959-0944-47d6-9dea-53304d124266"),
);
let e = e.into_sealed_new();
let single_result = be_b_txn.create(&CID_ZERO, vec![e]);

View file

@ -44,12 +44,14 @@ pub enum Attribute {
AcpModifyClass,
AcpModifyPresentAttr,
AcpModifyRemovedAttr,
AcpReceiver,
AcpReceiverGroup,
AcpSearchAttr,
AcpTargetScope,
ApiTokenSession,
Attr,
AttributeName,
AttributeType,
AuthSessionExpiry,
BadlistPassword,
Claim,
@ -62,6 +64,8 @@ pub enum Attribute {
DeviceKeys,
DirectMemberOf,
DisplayName,
Dn,
Domain,
DomainDisplayName,
DomainLdapBasedn,
DomainName,
@ -74,7 +78,10 @@ pub enum Attribute {
Email,
EmailAlternative,
EmailPrimary,
EntryDn,
EntryUuid,
Es256PrivateKeyDer,
Excludes,
FernetPrivateKeyStr,
GidNumber,
GrantUiHint,
@ -84,6 +91,10 @@ pub enum Attribute {
IpaNtHash,
JwsEs256PrivateKey,
LastModifiedCid,
/// An LDAP Compatible emailAddress
LdapEmailAddress,
/// An LDAP Compatible sshkeys virtual attribute
LdapKeys,
LegalName,
LoginShell,
Mail,
@ -120,22 +131,29 @@ pub enum Attribute {
RadiusSecret,
Replicated,
Rs256PrivateKeyDer,
Scope,
SourceUuid,
Spn,
/// An LDAP-compatible sshpublickey
LdapSshPublicKey,
/// The Kanidm-local ssh_publickey
SshPublicKey,
Supplements,
SystemSupplements,
SyncAllowed,
SyncClass,
SyncCookie,
SyncCredentialPortal,
SyncExternalId,
SyncParentUuid,
SyncTokenSession,
SyncYieldAuthority,
Syntax,
SystemExcludes,
SystemMay,
SystemMust,
Term,
TotpImport,
Uid,
UidNumber,
Unique,
@ -151,7 +169,11 @@ pub enum Attribute {
#[cfg(any(debug_assertions, test))]
TestAttr,
#[cfg(any(debug_assertions, test))]
TestNumber,
#[cfg(any(debug_assertions, test))]
Extra,
#[cfg(any(debug_assertions, test))]
TestNotAllowed,
}
impl AsRef<str> for Attribute {
@ -160,18 +182,20 @@ impl AsRef<str> for Attribute {
}
}
// impl Attribute {
// pub fn as_str(self) -> &'static str {
// self.into()
// }
// }
impl From<&Attribute> for &'static str {
fn from(value: &Attribute) -> Self {
(*value).into()
}
}
impl TryFrom<&str> for Attribute {
type Error = OperationError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Attribute::try_from(value.to_string())
}
}
impl TryFrom<String> for Attribute {
type Error = OperationError;
fn try_from(val: String) -> Result<Self, OperationError> {
@ -185,12 +209,14 @@ impl TryFrom<String> for Attribute {
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_ATTR => Attribute::Attr,
ATTR_ATTRIBUTENAME => Attribute::AttributeName,
ATTR_ATTRIBUTETYPE => Attribute::AttributeType,
ATTR_AUTH_SESSION_EXPIRY => Attribute::AuthSessionExpiry,
ATTR_BADLIST_PASSWORD => Attribute::BadlistPassword,
ATTR_CLAIM => Attribute::Claim,
@ -203,6 +229,8 @@ impl TryFrom<String> for Attribute {
ATTR_DEVICEKEYS => Attribute::DeviceKeys,
ATTR_DIRECTMEMBEROF => Attribute::DirectMemberOf,
ATTR_DISPLAYNAME => Attribute::DisplayName,
ATTR_DN => Attribute::Dn,
ATTR_DOMAIN => Attribute::Domain,
ATTR_DOMAIN_DISPLAY_NAME => Attribute::DomainDisplayName,
ATTR_DOMAIN_LDAP_BASEDN => Attribute::DomainLdapBasedn,
ATTR_DOMAIN_NAME => Attribute::DomainName,
@ -215,16 +243,22 @@ impl TryFrom<String> for Attribute {
ATTR_EMAIL => Attribute::Email,
ATTR_EMAIL_ALTERNATIVE => Attribute::EmailAlternative,
ATTR_EMAIL_PRIMARY => Attribute::EmailPrimary,
ATTR_ENTRYDN => Attribute::EntryDn,
ATTR_ENTRYUUID => Attribute::EntryUuid,
ATTR_ES256_PRIVATE_KEY_DER => Attribute::Es256PrivateKeyDer,
ATTR_EXCLUDES => Attribute::Excludes,
ATTR_FERNET_PRIVATE_KEY_STR => Attribute::FernetPrivateKeyStr,
ATTR_GROUP => Attribute::Group,
ATTR_GIDNUMBER => Attribute::GidNumber,
ATTR_GRANT_UI_HINT => Attribute::GrantUiHint,
ATTR_GROUP => Attribute::Group,
ATTR_ID_VERIFICATION_ECKEY => Attribute::IdVerificationEcKey,
ATTR_INDEX => Attribute::Index,
ATTR_IPANTHASH => Attribute::IpaNtHash,
ATTR_JWS_ES256_PRIVATE_KEY => Attribute::JwsEs256PrivateKey,
ATTR_LAST_MODIFIED_CID => Attribute::LastModifiedCid,
ATTR_LDAP_EMAIL_ADDRESS => Attribute::LdapEmailAddress,
ATTR_LDAP_KEYS => Attribute::LdapKeys,
ATTR_LDAP_SSH_PUBLICKEY => Attribute::SshPublicKey,
ATTR_LEGALNAME => Attribute::LegalName,
ATTR_LOGINSHELL => Attribute::LoginShell,
ATTR_MAIL => Attribute::Mail,
@ -263,20 +297,26 @@ impl TryFrom<String> for Attribute {
ATTR_RADIUS_SECRET => Attribute::RadiusSecret,
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_SSH_PUBLICKEY => Attribute::SshPublicKey,
ATTR_SSHPUBLICKEY => Attribute::LdapSshPublicKey,
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,
@ -293,6 +333,10 @@ impl TryFrom<String> for Attribute {
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,
_ => return Err(OperationError::InvalidAttributeName(val)),
};
Ok(res)
@ -303,76 +347,76 @@ impl From<Attribute> for &'static str {
fn from(val: Attribute) -> Self {
match val {
Attribute::Account => ATTR_ACCOUNT,
Attribute::SystemMay => ATTR_SYSTEMMAY,
Attribute::DynGroup => ATTR_DYNGROUP,
Attribute::May => ATTR_MAY,
Attribute::DomainDisplayName => ATTR_DOMAIN_DISPLAY_NAME,
Attribute::SyncCredentialPortal => ATTR_SYNC_CREDENTIAL_PORTAL,
Attribute::SyncCookie => ATTR_SYNC_COOKIE,
Attribute::SyncYieldAuthority => ATTR_SYNC_YIELD_AUTHORITY,
Attribute::SyncTokenSession => ATTR_SYNC_TOKEN_SESSION,
Attribute::Es256PrivateKeyDer => ATTR_ES256_PRIVATE_KEY_DER,
Attribute::Rs256PrivateKeyDer => ATTR_RS256_PRIVATE_KEY_DER,
Attribute::SystemMust => ATTR_SYSTEMMUST,
Attribute::AccountExpire => ATTR_ACCOUNT_EXPIRE,
Attribute::AccountValidFrom => ATTR_ACCOUNT_VALID_FROM,
Attribute::LegalName => ATTR_LEGALNAME,
Attribute::DeviceKeys => ATTR_DEVICEKEYS,
Attribute::DynGroupFilter => ATTR_DYNGROUP_FILTER,
Attribute::UnixPassword => ATTR_UNIX_PASSWORD,
Attribute::RadiusSecret => ATTR_RADIUS_SECRET,
Attribute::NameHistory => ATTR_NAME_HISTORY,
Attribute::Must => ATTR_MUST,
Attribute::AcpCreateAttr => ATTR_ACP_CREATE_ATTR,
Attribute::AcpCreateClass => ATTR_ACP_CREATE_CLASS,
Attribute::AcpEnable => ATTR_ACP_ENABLE,
Attribute::AcpModifyClass => ATTR_ACP_MODIFY_CLASS,
Attribute::AcpModifyPresentAttr => ATTR_ACP_MODIFY_PRESENTATTR,
Attribute::AcpModifyRemovedAttr => ATTR_ACP_MODIFY_REMOVEDATTR,
Attribute::AcpReceiver => ATTR_ACP_RECEIVER,
Attribute::AcpReceiverGroup => ATTR_ACP_RECEIVER_GROUP,
Attribute::AcpSearchAttr => ATTR_ACP_SEARCH_ATTR,
Attribute::AcpTargetScope => ATTR_ACP_TARGET_SCOPE,
Attribute::ApiTokenSession => ATTR_API_TOKEN_SESSION,
Attribute::Attr => ATTR_ATTR,
Attribute::Group => ATTR_GROUP,
Attribute::DomainLdapBasedn => ATTR_DOMAIN_LDAP_BASEDN,
Attribute::FernetPrivateKeyStr => ATTR_FERNET_PRIVATE_KEY_STR,
Attribute::CookiePrivateKey => ATTR_COOKIE_PRIVATE_KEY,
Attribute::NsUniqueId => ATTR_NSUNIQUEID,
Attribute::IdVerificationEcKey => ATTR_ID_VERIFICATION_ECKEY,
Attribute::DomainSsid => ATTR_DOMAIN_SSID,
Attribute::AttributeName => ATTR_ATTRIBUTENAME,
Attribute::AttributeType => ATTR_ATTRIBUTETYPE,
Attribute::AuthSessionExpiry => ATTR_AUTH_SESSION_EXPIRY,
Attribute::BadlistPassword => ATTR_BADLIST_PASSWORD,
Attribute::Claim => ATTR_CLAIM,
Attribute::Class => ATTR_CLASS,
Attribute::ClassName => ATTR_CLASSNAME,
Attribute::Cn => ATTR_CN,
Attribute::CookiePrivateKey => ATTR_COOKIE_PRIVATE_KEY,
Attribute::CredentialUpdateIntentToken => ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN,
Attribute::Description => ATTR_DESCRIPTION,
Attribute::DeviceKeys => ATTR_DEVICEKEYS,
Attribute::DirectMemberOf => ATTR_DIRECTMEMBEROF,
Attribute::DisplayName => ATTR_DISPLAYNAME,
Attribute::Dn => ATTR_DN,
Attribute::Domain => ATTR_DOMAIN,
Attribute::DomainDisplayName => ATTR_DOMAIN_DISPLAY_NAME,
Attribute::DomainLdapBasedn => ATTR_DOMAIN_LDAP_BASEDN,
Attribute::DomainName => ATTR_DOMAIN_NAME,
Attribute::DomainUuid => ATTR_DOMAIN_UUID,
Attribute::DomainSsid => ATTR_DOMAIN_SSID,
Attribute::DomainTokenKey => ATTR_DOMAIN_TOKEN_KEY,
Attribute::DomainUuid => ATTR_DOMAIN_UUID,
Attribute::DynGroup => ATTR_DYNGROUP,
Attribute::DynGroupFilter => ATTR_DYNGROUP_FILTER,
Attribute::DynMember => ATTR_DYNMEMBER,
Attribute::Email => ATTR_EMAIL,
Attribute::EmailAlternative => ATTR_EMAIL_ALTERNATIVE,
Attribute::EmailPrimary => ATTR_EMAIL_PRIMARY,
Attribute::EntryDn => ATTR_ENTRYDN,
Attribute::EntryUuid => ATTR_ENTRYUUID,
Attribute::Es256PrivateKeyDer => ATTR_ES256_PRIVATE_KEY_DER,
Attribute::Excludes => ATTR_EXCLUDES,
Attribute::FernetPrivateKeyStr => ATTR_FERNET_PRIVATE_KEY_STR,
Attribute::GidNumber => ATTR_GIDNUMBER,
Attribute::GrantUiHint => ATTR_GRANT_UI_HINT,
Attribute::Group => ATTR_GROUP,
Attribute::IdVerificationEcKey => ATTR_ID_VERIFICATION_ECKEY,
Attribute::Index => ATTR_INDEX,
Attribute::IpaNtHash => ATTR_IPANTHASH,
Attribute::JwsEs256PrivateKey => ATTR_JWS_ES256_PRIVATE_KEY,
Attribute::LastModifiedCid => ATTR_LAST_MODIFIED_CID,
Attribute::LdapEmailAddress => ATTR_LDAP_EMAIL_ADDRESS,
Attribute::LdapKeys => ATTR_LDAP_KEYS,
Attribute::LdapSshPublicKey => ATTR_SSHPUBLICKEY,
Attribute::LegalName => ATTR_LEGALNAME,
Attribute::LoginShell => ATTR_LOGINSHELL,
Attribute::Mail => ATTR_MAIL,
Attribute::May => ATTR_MAY,
Attribute::Member => ATTR_MEMBER,
Attribute::MemberOf => ATTR_MEMBEROF,
Attribute::MultiValue => ATTR_MULTIVALUE,
Attribute::Must => ATTR_MUST,
Attribute::Name => ATTR_NAME,
Attribute::NameHistory => ATTR_NAME_HISTORY,
Attribute::NoIndex => ATTR_NO_INDEX,
Attribute::NsUniqueId => ATTR_NSUNIQUEID,
Attribute::OAuth2AllowInsecureClientDisablePkce => {
ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE
}
@ -391,23 +435,38 @@ impl From<Attribute> for &'static str {
Attribute::ObjectClass => ATTR_OBJECTCLASS,
Attribute::OtherNoIndex => ATTR_OTHER_NO_INDEX,
Attribute::PassKeys => ATTR_PASSKEYS,
Attribute::PasswordImport => ATTR_PASSWORD_IMPORT,
Attribute::Phantom => ATTR_PHANTOM,
Attribute::PrimaryCredential => ATTR_PRIMARY_CREDENTIAL,
Attribute::PrivateCookieKey => ATTR_PRIVATE_COOKIE_KEY,
Attribute::PrivilegeExpiry => ATTR_PRIVILEGE_EXPIRY,
Attribute::RadiusSecret => ATTR_RADIUS_SECRET,
Attribute::Replicated => ATTR_REPLICATED,
Attribute::Rs256PrivateKeyDer => ATTR_RS256_PRIVATE_KEY_DER,
Attribute::Scope => ATTR_SCOPE,
Attribute::SourceUuid => ATTR_SOURCE_UUID,
Attribute::Spn => ATTR_SPN,
Attribute::LdapSshPublicKey => ATTR_SSHPUBLICKEY,
Attribute::SshPublicKey => ATTR_LDAP_SSH_PUBLICKEY,
Attribute::Supplements => ATTR_SUPPLEMENTS,
Attribute::SyncAllowed => ATTR_SYNC_ALLOWED,
Attribute::SyncClass => ATTR_SYNC_CLASS,
Attribute::SyncCookie => ATTR_SYNC_COOKIE,
Attribute::SyncCredentialPortal => ATTR_SYNC_CREDENTIAL_PORTAL,
Attribute::SyncExternalId => ATTR_SYNC_EXTERNAL_ID,
Attribute::SyncParentUuid => ATTR_SYNC_PARENT_UUID,
Attribute::SyncTokenSession => ATTR_SYNC_TOKEN_SESSION,
Attribute::SyncYieldAuthority => ATTR_SYNC_YIELD_AUTHORITY,
Attribute::Syntax => ATTR_SYNTAX,
Attribute::SystemExcludes => ATTR_SYSTEMEXCLUDES,
Attribute::SystemMay => ATTR_SYSTEMMAY,
Attribute::SystemMust => ATTR_SYSTEMMUST,
Attribute::SystemSupplements => ATTR_SYSTEMSUPPLEMENTS,
Attribute::Term => ATTR_TERM,
Attribute::TotpImport => ATTR_TOTP_IMPORT,
Attribute::Uid => ATTR_UID,
Attribute::UidNumber => ATTR_UIDNUMBER,
Attribute::Unique => ATTR_UNIQUE,
Attribute::UnixPassword => ATTR_UNIX_PASSWORD,
Attribute::UserAuthTokenSession => ATTR_USER_AUTH_TOKEN_SESSION,
Attribute::UserId => ATTR_USERID,
Attribute::UserPassword => ATTR_USERPASSWORD,
@ -420,8 +479,10 @@ impl From<Attribute> for &'static str {
Attribute::TestAttr => TEST_ATTR_TEST_ATTR,
#[cfg(any(debug_assertions, test))]
Attribute::Extra => TEST_ATTR_EXTRA,
Attribute::AuthSessionExpiry => ATTR_AUTH_SESSION_EXPIRY,
Attribute::PrivilegeExpiry => ATTR_PRIVILEGE_EXPIRY,
#[cfg(any(debug_assertions, test))]
Attribute::TestNumber => TEST_ATTR_NUMBER,
#[cfg(any(debug_assertions, test))]
Attribute::TestNotAllowed => TEST_ATTR_NOTALLOWED,
}
}
}

View file

@ -255,7 +255,9 @@ where
{
/// Get the uuid of this entry.
pub(crate) fn get_uuid(&self) -> Option<Uuid> {
self.attrs.get("uuid").and_then(|vs| vs.to_uuid_single())
self.attrs
.get(Attribute::Uuid.as_ref())
.and_then(|vs| vs.to_uuid_single())
}
}
@ -352,6 +354,7 @@ impl Entry<EntryInit, EntryNew> {
if vs.is_empty() {
None
} else {
// TODO: this should be an "Attribute::from(k)"
let attr = AttrString::from(k.to_lowercase());
let vv: ValueSet = match attr.as_str() {
kanidm_proto::constants::ATTR_ATTRIBUTENAME | kanidm_proto::constants::ATTR_CLASSNAME | kanidm_proto::constants::ATTR_DOMAIN => {
@ -618,6 +621,10 @@ impl Entry<EntryInit, EntryNew> {
// event for the attribute.
/// Add an attribute-value-assertion to this Entry.
pub fn add_ava(&mut self, attr: &str, value: Value) {
// TODO: attr can be replaced with Attribute and this can go away
#[allow(clippy::panic)]
let attr =
Attribute::try_from(attr).unwrap_or_else(|_| panic!("Invalid attribute {}", attr));
self.add_ava_int(attr, value);
}
@ -794,7 +801,7 @@ impl Entry<EntryIncremental, EntryNew> {
// We need to make a random uuid in the conflict gen process.
let new_uuid = Uuid::new_v4();
cnf_ent.purge_ava("uuid");
cnf_ent.add_ava("uuid", Value::Uuid(new_uuid));
cnf_ent.add_ava(Attribute::Uuid.as_ref(), Value::Uuid(new_uuid));
cnf_ent.add_ava(Attribute::Class.as_ref(), EntryClass::Recycled.into());
cnf_ent.add_ava(Attribute::Class.as_ref(), EntryClass::Conflict.into());
@ -1075,9 +1082,9 @@ impl Entry<EntryIncremental, EntryCommitted> {
if let Err(e) = ne.validate(schema) {
warn!(uuid = ?self.valid.uuid, err = ?e, "Entry failed schema check, moving to a conflict state");
ne.add_ava_int(Attribute::Class.as_ref(), EntryClass::Recycled.into());
ne.add_ava_int(Attribute::Class.as_ref(), EntryClass::Conflict.into());
ne.add_ava_int(Attribute::SourceUuid.as_ref(), Value::Uuid(self.valid.uuid));
ne.add_ava_int(Attribute::Class, EntryClass::Recycled.into());
ne.add_ava_int(Attribute::Class, EntryClass::Conflict.into());
ne.add_ava_int(Attribute::SourceUuid, Value::Uuid(self.valid.uuid));
}
ne
}
@ -1330,7 +1337,7 @@ impl Entry<EntrySealed, EntryCommitted> {
/// Insert a claim to this entry. This claim can NOT be persisted to disk, this is only
/// used during a single Event session.
pub fn insert_claim(&mut self, value: &str) {
self.add_ava_int("claim", Value::new_iutf8(value));
self.add_ava_int(Attribute::Claim, Value::new_iutf8(value));
}
pub fn compare(&self, rhs: &Entry<EntrySealed, EntryCommitted>) -> bool {
@ -1370,7 +1377,11 @@ impl Entry<EntrySealed, EntryCommitted> {
// * name
// * gidnumber
let cands = ["spn", "name", "gidnumber"];
let cands = [
Attribute::Spn.as_ref(),
Attribute::Name.as_ref(),
Attribute::GidNumber.as_ref(),
];
cands
.iter()
.filter_map(|c| self.attrs.get(*c).map(|vs| vs.to_proto_string_clone_iter()))
@ -1394,7 +1405,11 @@ impl Entry<EntrySealed, EntryCommitted> {
self.attrs
.get("spn")
.and_then(|vs| vs.to_value_single())
.or_else(|| self.attrs.get("name").and_then(|vs| vs.to_value_single()))
.or_else(|| {
self.attrs
.get(Attribute::Name.as_ref())
.and_then(|vs| vs.to_value_single())
})
.unwrap_or_else(|| Value::Uuid(self.get_uuid()))
}
@ -1406,7 +1421,7 @@ impl Entry<EntrySealed, EntryCommitted> {
.and_then(|vs| vs.to_proto_string_single().map(|v| format!("spn={v}")))
.or_else(|| {
self.attrs
.get("name")
.get(Attribute::Name.as_ref())
.and_then(|vs| vs.to_proto_string_single().map(|v| format!("name={v}")))
})
.unwrap_or_else(|| format!("uuid={}", self.get_uuid().as_hyphenated()))
@ -2345,8 +2360,8 @@ impl<VALID, STATE> Entry<VALID, STATE> {
/// If the value already existed, or was unable to be added, false is returned. Alternately,
/// you can think of this boolean as "if a write occurred to the structure", true indicating that
/// a change occurred.
fn add_ava_int(&mut self, attr: &str, value: Value) -> bool {
if let Some(vs) = self.attrs.get_mut(attr) {
fn add_ava_int(&mut self, attr: Attribute, value: Value) -> bool {
if let Some(vs) = self.attrs.get_mut(attr.as_ref()) {
let r = vs.insert_checked(value);
debug_assert!(r.is_ok());
// Default to the value not being present if wrong typed.
@ -2355,7 +2370,7 @@ impl<VALID, STATE> Entry<VALID, STATE> {
#[allow(clippy::expect_used)]
let vs = valueset::from_value_iter(std::iter::once(value))
.expect("Unable to fail - non-zero iter, and single value type!");
self.attrs.insert(AttrString::from(attr), vs);
self.attrs.insert(attr.into(), vs);
// The attribute did not exist before.
true
}
@ -2393,10 +2408,18 @@ impl<VALID, STATE> Entry<VALID, STATE> {
pub(crate) fn get_display_id(&self) -> String {
self.attrs
.get("spn")
.get(Attribute::Spn.as_ref())
.and_then(|vs| vs.to_value_single())
.or_else(|| self.attrs.get("name").and_then(|vs| vs.to_value_single()))
.or_else(|| self.attrs.get("uuid").and_then(|vs| vs.to_value_single()))
.or_else(|| {
self.attrs
.get(Attribute::Name.as_ref())
.and_then(|vs| vs.to_value_single())
})
.or_else(|| {
self.attrs
.get(Attribute::Uuid.as_ref())
.and_then(|vs| vs.to_value_single())
})
.map(|value| value.to_proto_string_clone())
.unwrap_or_else(|| "no entry id available".to_string())
}
@ -2922,14 +2945,25 @@ where
// we need this to be *state* based where we assert presence.
pub fn add_ava(&mut self, attr: &str, value: Value) {
self.valid.ecstate.change_ava(&self.valid.cid, attr);
// TODO: attr can be replaced with Attribute and this can go away
#[allow(clippy::panic)]
let attr =
Attribute::try_from(attr).unwrap_or_else(|_| panic!("Invalid attribute {}", attr));
self.add_ava_int(attr, value);
}
pub fn add_ava_if_not_exist(&mut self, attr: &str, value: Value) {
// This returns true if the value WAS changed! See add_ava_int.
// TODO: attr can be replaced with Attribute and this can go away
#[allow(clippy::panic)]
let attr =
Attribute::try_from(attr).unwrap_or_else(|_| panic!("Invalid attribute {}", attr));
if self.add_ava_int(attr, value) {
// In this case, we ONLY update the changestate if the value was already present!
self.valid.ecstate.change_ava(&self.valid.cid, attr);
self.valid
.ecstate
.change_ava(&self.valid.cid, attr.as_ref());
}
}
@ -3095,18 +3129,18 @@ impl From<&SchemaAttribute> for Entry<EntryInit, EntryNew> {
// Build the Map of the attributes relevant
// let mut attrs: Map<AttrString, Set<Value>> = Map::with_capacity(8);
let mut attrs: Map<AttrString, ValueSet> = Map::new();
attrs.insert(AttrString::from("attributename"), name_v);
attrs.insert(AttrString::from(Attribute::Description.as_ref()), desc_v);
attrs.insert(Attribute::AttributeName.into(), name_v);
attrs.insert(Attribute::Description.into(), desc_v);
attrs.insert(Attribute::Uuid.into(), uuid_v);
attrs.insert(AttrString::from("multivalue"), multivalue_v);
attrs.insert(AttrString::from("phantom"), phantom_v);
attrs.insert(AttrString::from("sync_allowed"), sync_allowed_v);
attrs.insert(AttrString::from("replicated"), replicated_v);
attrs.insert(AttrString::from("unique"), unique_v);
attrs.insert(Attribute::MultiValue.into(), multivalue_v);
attrs.insert(Attribute::Phantom.into(), phantom_v);
attrs.insert(Attribute::SyncAllowed.into(), sync_allowed_v);
attrs.insert(Attribute::Replicated.into(), replicated_v);
attrs.insert(Attribute::Unique.into(), unique_v);
if let Some(vs) = index_v {
attrs.insert(AttrString::from("index"), vs);
attrs.insert(Attribute::Index.into(), vs);
}
attrs.insert(AttrString::from("syntax"), syntax_v);
attrs.insert(Attribute::Syntax.into(), syntax_v);
attrs.insert(
Attribute::Class.into(),
vs_iutf8!["object", "system", "attributetype"],
@ -3131,24 +3165,28 @@ impl From<&SchemaClass> for Entry<EntryInit, EntryNew> {
// let mut attrs: Map<AttrString, Set<Value>> = Map::with_capacity(8);
let mut attrs: Map<AttrString, ValueSet> = Map::new();
attrs.insert(AttrString::from("classname"), name_v);
attrs.insert(AttrString::from(Attribute::Description.as_ref()), desc_v);
attrs.insert(AttrString::from("sync_allowed"), sync_allowed_v);
attrs.insert(Attribute::ClassName.into(), name_v);
attrs.insert(Attribute::Description.into(), desc_v);
attrs.insert(Attribute::SyncAllowed.into(), sync_allowed_v);
attrs.insert(Attribute::Uuid.into(), uuid_v);
attrs.insert(
Attribute::Class.into(),
vs_iutf8!["object", "system", "classtype"],
vs_iutf8![
EntryClass::Object.into(),
EntryClass::System.into(),
EntryClass::ClassType.into()
],
);
let vs_systemmay = ValueSetIutf8::from_iter(s.systemmay.iter().map(|sm| sm.as_str()));
if let Some(vs) = vs_systemmay {
attrs.insert(AttrString::from("systemmay"), vs);
attrs.insert(Attribute::SystemMay.into(), vs);
}
let vs_systemmust = ValueSetIutf8::from_iter(s.systemmust.iter().map(|sm| sm.as_str()));
if let Some(vs) = vs_systemmust {
attrs.insert(AttrString::from("systemmust"), vs);
attrs.insert(Attribute::SystemMust.into(), vs);
}
Entry {
@ -3165,7 +3203,6 @@ mod tests {
use std::collections::BTreeSet as Set;
use hashbrown::HashMap;
use smartstring::alias::String as AttrString;
use crate::be::{IdxKey, IdxSlope};
use crate::entry::{Entry, EntryInit, EntryInvalid, EntryNew};
@ -3176,7 +3213,7 @@ mod tests {
fn test_entry_basic() {
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava("userid", Value::from("william"));
e.add_ava(Attribute::UserId.as_ref(), Value::from("william"));
}
#[test]
@ -3256,19 +3293,19 @@ mod tests {
let pv10 = PartialValue::new_uint32(10);
let pv15 = PartialValue::new_uint32(15);
e1.add_ava("a", Value::new_uint32(10));
e1.add_ava("testattr", Value::new_uint32(10));
assert!(!e1.attribute_lessthan("a", &pv2));
assert!(!e1.attribute_lessthan("a", &pv8));
assert!(!e1.attribute_lessthan("a", &pv10));
assert!(e1.attribute_lessthan("a", &pv15));
assert!(!e1.attribute_lessthan("testattr", &pv2));
assert!(!e1.attribute_lessthan("testattr", &pv8));
assert!(!e1.attribute_lessthan("testattr", &pv10));
assert!(e1.attribute_lessthan("testattr", &pv15));
e1.add_ava("a", Value::new_uint32(8));
e1.add_ava("testattr", Value::new_uint32(8));
assert!(!e1.attribute_lessthan("a", &pv2));
assert!(!e1.attribute_lessthan("a", &pv8));
assert!(e1.attribute_lessthan("a", &pv10));
assert!(e1.attribute_lessthan("a", &pv15));
assert!(!e1.attribute_lessthan("testattr", &pv2));
assert!(!e1.attribute_lessthan("testattr", &pv8));
assert!(e1.attribute_lessthan("testattr", &pv10));
assert!(e1.attribute_lessthan("testattr", &pv15));
}
#[test]
@ -3374,7 +3411,7 @@ mod tests {
);
idxmeta.insert(
IdxKey {
attr: AttrString::from("extra"),
attr: Attribute::Extra.into(),
itype: IndexType::Equality,
},
IdxSlope::MAX,
@ -3438,7 +3475,7 @@ mod tests {
assert!(
add_a_r[0]
== Ok((
&AttrString::from("extra"),
&Attribute::Extra.into(),
IndexType::Equality,
"test".to_string()
))
@ -3449,7 +3486,7 @@ mod tests {
assert!(
del_a_r[0]
== Err((
&AttrString::from("extra"),
&Attribute::Extra.into(),
IndexType::Equality,
"test".to_string()
))
@ -3515,11 +3552,14 @@ mod tests {
{
let mut e: Entry<EntryInit, EntryNew> = Entry::new();
e.add_ava(Attribute::Class.as_ref(), EntryClass::Person.to_value());
e.add_ava("gidnumber", Value::new_uint32(1300));
e.add_ava("name", Value::new_iname("testperson"));
e.add_ava("spn", Value::new_spn_str("testperson", "example.com"));
e.add_ava(Attribute::GidNumber.as_ref(), Value::new_uint32(1300));
e.add_ava(Attribute::Name.as_ref(), Value::new_iname("testperson"));
e.add_ava(
"uuid",
Attribute::Spn.as_ref(),
Value::new_spn_str("testperson", "example.com"),
);
e.add_ava(
Attribute::Uuid.as_ref(),
Value::Uuid(uuid!("9fec0398-c46c-4df4-9df5-b0016f7d563f")),
);
let e = e.into_sealed_committed();
@ -3561,13 +3601,19 @@ mod tests {
{
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava(Attribute::Class.as_ref(), EntryClass::Person.to_value());
e1.add_ava("spn", Value::new_spn_str("testperson", "example.com"));
e1.add_ava(
Attribute::Spn.as_ref(),
Value::new_spn_str("testperson", "example.com"),
);
let e1 = e1.into_sealed_committed();
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava(Attribute::Class.as_ref(), EntryClass::Person.to_value());
e2.add_ava("name", Value::new_iname("testperson"));
e2.add_ava("spn", Value::new_spn_str("testperson", "example.com"));
e2.add_ava(Attribute::Name.as_ref(), Value::new_iname("testperson"));
e2.add_ava(
Attribute::Spn.as_ref(),
Value::new_spn_str("testperson", "example.com"),
);
let e2 = e2.into_sealed_committed();
// One attr added
@ -3587,12 +3633,18 @@ mod tests {
{
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava(Attribute::Class.as_ref(), EntryClass::Person.to_value());
e1.add_ava("spn", Value::new_spn_str("testperson", "example.com"));
e1.add_ava(
Attribute::Spn.as_ref(),
Value::new_spn_str("testperson", "example.com"),
);
let e1 = e1.into_sealed_committed();
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava(Attribute::Class.as_ref(), EntryClass::Person.to_value());
e2.add_ava("spn", Value::new_spn_str("renameperson", "example.com"));
e2.add_ava(
Attribute::Spn.as_ref(),
Value::new_spn_str("renameperson", "example.com"),
);
let e2 = e2.into_sealed_committed();
assert!(
@ -3610,11 +3662,17 @@ mod tests {
assert!(Entry::idx_uuid2spn_diff(None, None).is_none());
let mut e1: Entry<EntryInit, EntryNew> = Entry::new();
e1.add_ava("spn", Value::new_spn_str("testperson", "example.com"));
e1.add_ava(
Attribute::Spn.as_ref(),
Value::new_spn_str("testperson", "example.com"),
);
let e1 = e1.into_sealed_committed();
let mut e2: Entry<EntryInit, EntryNew> = Entry::new();
e2.add_ava("spn", Value::new_spn_str("renameperson", "example.com"));
e2.add_ava(
Attribute::Spn.as_ref(),
Value::new_spn_str("renameperson", "example.com"),
);
let e2 = e2.into_sealed_committed();
assert!(

View file

@ -38,8 +38,7 @@ const FILTER_DEPTH_MAX: usize = 16;
// 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> {
let a: &'static str = a.into();
FC::Eq(a, v)
FC::Eq(a.into(), v)
}
#[allow(dead_code)]
@ -48,8 +47,8 @@ pub fn f_sub(a: &str, v: PartialValue) -> FC {
}
#[allow(dead_code)]
pub fn f_pres(a: &str) -> FC {
FC::Pres(a)
pub fn f_pres<'a>(a: Attribute) -> FC<'a> {
FC::Pres(a.into())
}
#[allow(dead_code)]
@ -86,9 +85,9 @@ pub fn f_self<'a>() -> FC<'a> {
pub fn f_id(id: &str) -> FC<'static> {
let uf = Uuid::parse_str(id)
.ok()
.map(|u| FC::Eq("uuid", PartialValue::Uuid(u)));
.map(|u| FC::Eq(Attribute::Uuid.as_ref(), PartialValue::Uuid(u)));
let spnf = PartialValue::new_spn_s(id).map(|spn| FC::Eq("spn", spn));
let nf = FC::Eq("name", PartialValue::new_iname(id));
let nf = FC::Eq(Attribute::Name.as_ref(), PartialValue::new_iname(id));
let f: Vec<_> = iter::once(uf)
.chain(iter::once(spnf))
.flatten()
@ -99,8 +98,8 @@ pub fn f_id(id: &str) -> FC<'static> {
#[allow(dead_code)]
pub fn f_spn_name(id: &str) -> FC<'static> {
let spnf = PartialValue::new_spn_s(id).map(|spn| FC::Eq("spn", spn));
let nf = FC::Eq("name", PartialValue::new_iname(id));
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));
let f: Vec<_> = iter::once(spnf).flatten().chain(iter::once(nf)).collect();
FC::Or(f)
}
@ -1152,7 +1151,7 @@ impl FilterResolved {
// Since we have no index data, we manually configure a reasonable
// slope and indicate the presence of some expected basic
// indexes.
let idx = matches!(a.as_str(), "name" | "uuid");
let idx = matches!(a.as_str(), ATTR_NAME | ATTR_UUID);
let idx = NonZeroU8::new(idx as u8);
Some(FilterResolved::Eq(a, v, idx))
}
@ -1424,12 +1423,12 @@ mod tests {
EntryClass::TestClass.to_partialvalue()
)]),
f_sub(Attribute::Class.as_ref(), PartialValue::new_class("te")),
f_pres(Attribute::Class.as_ref()),
f_pres(Attribute::Class),
f_eq(Attribute::Class, EntryClass::TestClass.to_partialvalue())
]),
f_and(vec![
f_eq(Attribute::Class, EntryClass::TestClass.to_partialvalue()),
f_pres(Attribute::Class.as_ref()),
f_pres(Attribute::Class),
f_sub(Attribute::Class.as_ref(), PartialValue::new_class("te")),
])
);
@ -1443,13 +1442,13 @@ mod tests {
f_eq(Attribute::Uid, PartialValue::new_class("bar")),
]),
f_sub(Attribute::Class.as_ref(), PartialValue::new_class("te")),
f_pres(Attribute::Class.as_ref()),
f_pres(Attribute::Class),
f_eq(Attribute::Class, EntryClass::TestClass.to_partialvalue())
]),
f_and(vec![
f_eq(Attribute::Class, PartialValue::new_class("foo")),
f_eq(Attribute::Class, EntryClass::TestClass.to_partialvalue()),
f_pres(Attribute::Class.as_ref()),
f_pres(Attribute::Class),
f_eq(Attribute::Uid, PartialValue::new_class("bar")),
f_sub(Attribute::Class.as_ref(), PartialValue::new_class("te")),
])
@ -1458,7 +1457,7 @@ mod tests {
filter_optimise_assert!(
f_or(vec![
f_eq(Attribute::Class, EntryClass::TestClass.to_partialvalue()),
f_pres(Attribute::Class.as_ref()),
f_pres(Attribute::Class),
f_sub(Attribute::Class.as_ref(), PartialValue::new_class("te")),
f_or(vec![f_eq(
Attribute::Class,
@ -1467,7 +1466,7 @@ mod tests {
]),
f_or(vec![
f_sub(Attribute::Class.as_ref(), PartialValue::new_class("te")),
f_pres(Attribute::Class.as_ref()),
f_pres(Attribute::Class),
f_eq(Attribute::Class, EntryClass::TestClass.to_partialvalue())
])
);
@ -1497,17 +1496,17 @@ mod tests {
#[test]
fn test_filter_eq() {
let f_t1a = filter!(f_pres("userid"));
let f_t1b = filter!(f_pres("userid"));
let f_t1c = filter!(f_pres("zzzz"));
let f_t1a = filter!(f_pres(Attribute::UserId));
let f_t1b = filter!(f_pres(Attribute::UserId));
let f_t1c = filter!(f_pres(Attribute::NonExist));
assert!(f_t1a == f_t1b);
assert!(f_t1a != f_t1c);
assert!(f_t1b != f_t1c);
let f_t2a = filter!(f_and!([f_pres("userid")]));
let f_t2b = filter!(f_and!([f_pres("userid")]));
let f_t2c = filter!(f_and!([f_pres("zzzz")]));
let f_t2a = filter!(f_and!([f_pres(Attribute::UserId)]));
let f_t2b = filter!(f_and!([f_pres(Attribute::UserId)]));
let f_t2c = filter!(f_and!([f_pres(Attribute::NonExist)]));
assert!(f_t2a == f_t2b);
assert!(f_t2a != f_t2c);
assert!(f_t2b != f_t2c);
@ -1521,8 +1520,8 @@ mod tests {
// Test that we uphold the rules of partialOrd
// Basic equality
// Test the two major paths here (str vs list)
let f_t1a = filter_resolved!(f_pres("userid"));
let f_t1b = filter_resolved!(f_pres("userid"));
let f_t1a = filter_resolved!(f_pres(Attribute::UserId));
let f_t1b = filter_resolved!(f_pres(Attribute::UserId));
assert_eq!(f_t1a.partial_cmp(&f_t1b), Some(Ordering::Equal));
assert_eq!(f_t1b.partial_cmp(&f_t1a), Some(Ordering::Equal));
@ -1551,16 +1550,16 @@ mod tests {
fn test_filter_clone() {
// Test that cloning filters yields the same result regardless of
// complexity.
let f_t1a = filter_resolved!(f_pres("userid"));
let f_t1a = filter_resolved!(f_pres(Attribute::UserId));
let f_t1b = f_t1a.clone();
let f_t1c = filter_resolved!(f_pres("zzzz"));
let f_t1c = filter_resolved!(f_pres(Attribute::NonExist));
assert!(f_t1a == f_t1b);
assert!(f_t1a != f_t1c);
let f_t2a = filter_resolved!(f_and!([f_pres("userid")]));
let f_t2a = filter_resolved!(f_and!([f_pres(Attribute::UserId)]));
let f_t2b = f_t2a.clone();
let f_t2c = filter_resolved!(f_and!([f_pres("zzzz")]));
let f_t2c = filter_resolved!(f_and!([f_pres(Attribute::NonExist)]));
assert!(f_t2a == f_t2b);
assert!(f_t2a != f_t2c);

View file

@ -628,7 +628,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
) -> Result<(), OperationError> {
// Delete the attribute with uuid.
let modlist = ModifyList::new_list(vec![Modify::Removed(
AttrString::from("user_auth_token_session"),
Attribute::UserAuthTokenSession.into(),
PartialValue::Refer(dte.token_id),
)]);
@ -870,7 +870,7 @@ mod tests {
)),
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
Modify::Present(AttrString::from("gidnumber"), Value::new_uint32(2001)),
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());

View file

@ -419,7 +419,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
.get_accesscontrols()
.effective_permission_check(
ident,
Some(btreeset![AttrString::from("sync_credential_portal")]),
Some(btreeset![Attribute::SyncCredentialPortal.into()]),
&[entry],
)?;
@ -607,7 +607,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
if ct >= max_ttl {
modlist.push_mod(Modify::Removed(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
PartialValue::IntentToken(existing_intent_id.clone()),
));
}
@ -665,7 +665,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
let mut modlist = ModifyList::new();
modlist.push_mod(Modify::Removed(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
PartialValue::IntentToken(intent_id.clone()),
));
@ -779,11 +779,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
let mut modlist = ModifyList::new();
modlist.push_mod(Modify::Removed(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
PartialValue::IntentToken(intent_id.clone()),
));
modlist.push_mod(Modify::Present(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
Value::IntentToken(
intent_id.clone(),
IntentTokenState::InProgress {
@ -949,11 +949,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
};
modlist.push_mod(Modify::Removed(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
PartialValue::IntentToken(intent_token_id.clone()),
));
modlist.push_mod(Modify::Present(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
Value::IntentToken(
intent_token_id.clone(),
IntentTokenState::Consumed { max_ttl },
@ -1050,11 +1050,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
};
modlist.push_mod(Modify::Removed(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
PartialValue::IntentToken(intent_token_id.clone()),
));
modlist.push_mod(Modify::Present(
AttrString::from("credential_update_intent_token"),
Attribute::CredentialUpdateIntentToken.into(),
Value::IntentToken(
intent_token_id.clone(),
IntentTokenState::Valid { max_ttl, perms },

View file

@ -635,7 +635,7 @@ mod tests {
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
Modify::Present(AttrString::from("gidnumber"), Value::new_uint32(2001)),
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
@ -1057,7 +1057,7 @@ mod tests {
PartialValue::new_iname("idm_people_read_priv")
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::Refer(sa_uuid),
)]),
);

View file

@ -558,7 +558,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
// and when replication converges the session is actually removed.
let modlist = ModifyList::new_list(vec![Modify::Removed(
AttrString::from("oauth2_session"),
Attribute::OAuth2Session.into(),
PartialValue::Refer(session_id),
)]);
@ -729,11 +729,11 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
let modlist = ModifyList::new_list(vec![
Modify::Removed(
AttrString::from("oauth2_consent_scope_map"),
Attribute::OAuth2ConsentScopeMap.into(),
PartialValue::Refer(o2rs.uuid),
),
Modify::Present(
AttrString::from("oauth2_consent_scope_map"),
Attribute::OAuth2ConsentScopeMap.into(),
Value::OauthScopeMap(o2rs.uuid, consent_req.scopes.iter().cloned().collect()),
),
]);
@ -931,7 +931,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
// Revoke it
let modlist = ModifyList::new_list(vec![Modify::Removed(
AttrString::from("oauth2_session"),
Attribute::OAuth2Session.into(),
PartialValue::Refer(session_id),
)]);
@ -2955,7 +2955,7 @@ mod tests {
let me_inv_m = ModifyEvent::new_internal_invalid(
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("account_expire"),
Attribute::AccountExpire.into(),
v_expire,
)]),
);

View file

@ -161,7 +161,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
});
let modlist = ModifyList::new_list(vec![Modify::Present(
AttrString::from("sync_token_session"),
Attribute::SyncTokenSession.into(),
session,
)]);
@ -199,7 +199,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
_ct: Duration,
) -> Result<(), OperationError> {
let modlist =
ModifyList::new_list(vec![Modify::Purged(AttrString::from("sync_token_session"))]);
ModifyList::new_list(vec![Modify::Purged(Attribute::SyncTokenSession.into())]);
self.qs_write
.impersonate_modify(
@ -894,9 +894,9 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
let secret = complex
.attrs
.get("secret")
.get(SCIM_SECRET)
.ok_or_else(|| {
error!("Invalid scim complex attr - missing required key secret");
error!("Invalid SCIM complex attr - missing required key secret");
OperationError::InvalidAttribute(format!(
"missing required key secret - {scim_attr_name}"
))
@ -920,7 +920,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
}
})?;
let algo = complex.attrs.get("algo")
let algo = complex.attrs.get(SCIM_ALGO)
.ok_or_else(|| {
error!("Invalid scim complex attr - missing required key algo");
OperationError::InvalidAttribute(format!(
@ -951,7 +951,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
}
})?;
let step = complex.attrs.get("step").ok_or_else(|| {
let step = complex.attrs.get(SCIM_STEP).ok_or_else(|| {
error!("Invalid scim complex attr - missing required key step");
OperationError::InvalidAttribute(format!(
"missing required key step - {scim_attr_name}"
@ -978,7 +978,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
let digits = complex
.attrs
.get("digits")
.get(SCIM_DIGITS)
.ok_or_else(|| {
error!("Invalid scim complex attr - missing required key digits");
OperationError::InvalidAttribute(format!(
@ -1627,7 +1627,7 @@ mod tests {
Attribute::Name,
PartialValue::new_iname("test_scim_sync")
)),
ModifyList::new_list(vec![Modify::Purged(AttrString::from("sync_token_session"))]),
ModifyList::new_list(vec![Modify::Purged(Attribute::SyncTokenSession.into())]),
);
assert!(idms_prox_write.qs_write.modify(&me_inv_m).is_ok());
assert!(idms_prox_write.commit().is_ok());

View file

@ -2112,7 +2112,6 @@ mod tests {
use std::time::Duration;
use kanidm_proto::v1::{AuthAllowed, AuthIssueSession, AuthMech, OperationError};
use smartstring::alias::String as AttrString;
use time::OffsetDateTime;
use uuid::Uuid;
@ -2666,7 +2665,7 @@ mod tests {
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
Modify::Present(AttrString::from("gidnumber"), Value::new_uint32(2001)),
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
@ -2751,7 +2750,7 @@ mod tests {
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
Modify::Present(AttrString::from("gidnumber"), Value::new_uint32(2001)),
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
@ -2787,7 +2786,7 @@ mod tests {
let mut idms_prox_write = idms.proxy_write(duration_from_epoch_now()).await;
let me_purge_up = ModifyEvent::new_internal_invalid(
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![Modify::Purged(AttrString::from("unix_password"))]),
ModifyList::new_list(vec![Modify::Purged(Attribute::UnixPassword.into())]),
);
assert!(idms_prox_write.qs_write.modify(&me_purge_up).is_ok());
assert!(idms_prox_write.commit().is_ok());
@ -2820,7 +2819,7 @@ mod tests {
ModifyEvent::new_internal_invalid(
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("password_import"),
Attribute::PasswordImport.into(),
Value::from("{SSHA512}JwrSUHkI7FTAfHRVR6KoFlSN0E3dmaQWARjZ+/UsShYlENOqDtFVU77HJLLrY2MuSp0jve52+pwtdVl2QUAHukQ0XUf5LDtM")
)]),
);
@ -2901,8 +2900,8 @@ mod tests {
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
Modify::Present(AttrString::from("gidnumber"), Value::new_uint32(2001)),
Modify::Present(AttrString::from("unix_password"), v_cred),
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
Modify::Present(Attribute::UnixPassword.into(), v_cred),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
@ -2955,8 +2954,8 @@ mod tests {
let me_inv_m = ModifyEvent::new_internal_invalid(
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![
Modify::Present(AttrString::from("account_expire"), v_expire),
Modify::Present(AttrString::from("account_valid_from"), v_valid_from),
Modify::Present(Attribute::AccountExpire.into(), v_expire),
Modify::Present(Attribute::AccountValidFrom.into(), v_valid_from),
]),
);
// go!
@ -3046,7 +3045,7 @@ mod tests {
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
Modify::Present(AttrString::from("gidnumber"), Value::new_uint32(2001)),
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
@ -3409,7 +3408,7 @@ mod tests {
filter!(f_eq(Attribute::Name, PartialValue::new_iname("admin"))),
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::PosixAccount.into()),
Modify::Present(AttrString::from("gidnumber"), Value::new_uint32(2001)),
Modify::Present(Attribute::GidNumber.into(), Value::new_uint32(2001)),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_posix).is_ok());
@ -3947,9 +3946,9 @@ mod tests {
let me_reset_tokens = ModifyEvent::new_internal_invalid(
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_DOMAIN_INFO))),
ModifyList::new_list(vec![
Modify::Purged(AttrString::from("fernet_private_key_str")),
Modify::Purged(AttrString::from("es256_private_key_der")),
Modify::Purged(AttrString::from("domain_token_key")),
Modify::Purged(Attribute::FernetPrivateKeyStr.into()),
Modify::Purged(Attribute::Es256PrivateKeyDer.into()),
Modify::Purged(Attribute::DomainTokenKey.into()),
]),
);
assert!(idms_prox_write.qs_write.modify(&me_reset_tokens).is_ok());

View file

@ -249,7 +249,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
// modify the account to put the session onto it.
let modlist = ModifyList::new_list(vec![Modify::Present(
AttrString::from("api_token_session"),
Attribute::ApiTokenSession.into(),
session,
)]);
@ -286,7 +286,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
) -> Result<(), OperationError> {
// Delete the attribute with uuid.
let modlist = ModifyList::new_list(vec![Modify::Removed(
AttrString::from("api_token_session"),
Attribute::ApiTokenSession.into(),
PartialValue::Refer(dte.token_id),
)]);

View file

@ -170,7 +170,7 @@ impl ModifyList<ModifyInvalid> {
let schema_attributes = schema.get_attributes();
/*
let schema_name = schema_attributes
.get("name")
.get(Attribute::Name.as_ref()")
.expect("Critical: Core schema corrupt or missing. To initiate a core transfer, please deposit substitute core in receptacle.");
*/

View file

@ -259,7 +259,7 @@ impl Plugin for AttrUnique {
#[instrument(level = "debug", name = "attrunique::verify", skip_all)]
fn verify(qs: &mut QueryServerReadTransaction) -> Vec<Result<(), ConsistencyError>> {
// Only check live entries, not recycled.
let filt_in = filter!(f_pres(Attribute::Class.as_ref()));
let filt_in = filter!(f_pres(Attribute::Class));
let all_cand = match qs
.internal_search(filt_in)

View file

@ -206,7 +206,7 @@ impl Plugin for Base {
#[instrument(level = "debug", name = "base::verify", skip_all)]
fn verify(qs: &mut QueryServerReadTransaction) -> Vec<Result<(), ConsistencyError>> {
// Search for class = *
let entries = match qs.internal_search(filter!(f_pres(Attribute::Class.as_ref()))) {
let entries = match qs.internal_search(filter!(f_pres(Attribute::Class))) {
Ok(v) => v,
Err(e) => {
admin_error!("Internal Search Failure: {:?}", e);

View file

@ -193,7 +193,7 @@ mod tests {
preload,
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("password_import"),
Attribute::PasswordImport.into(),
Value::from(IMPORT_HASH)
)]),
None,
@ -228,7 +228,7 @@ mod tests {
preload,
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("password_import"),
Attribute::PasswordImport.into(),
Value::from(IMPORT_HASH)
)]),
None,
@ -266,7 +266,7 @@ mod tests {
preload,
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("password_import"),
Attribute::PasswordImport.into(),
Value::from(IMPORT_HASH)
)]),
None,
@ -320,15 +320,15 @@ mod tests {
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![
Modify::Present(
AttrString::from("password_import"),
Attribute::PasswordImport.into(),
Value::Utf8(IMPORT_HASH.to_string())
),
Modify::Present(
AttrString::from("totp_import"),
Attribute::TotpImport.into(),
Value::TotpSecret("a".to_string(), totp_a.clone())
),
Modify::Present(
AttrString::from("totp_import"),
Attribute::TotpImport.into(),
Value::TotpSecret("b".to_string(), totp_b.clone())
)
]),
@ -385,7 +385,7 @@ mod tests {
preload,
filter!(f_eq(Attribute::Name, PartialValue::new_iutf8("testperson"))),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("totp_import"),
Attribute::TotpImport.into(),
Value::TotpSecret("a".to_string(), totp_a)
)]),
None,

View file

@ -582,7 +582,7 @@ mod tests {
ModifyList::new_list(vec![
Modify::Purged("dyngroup_filter".into()),
Modify::Present(
AttrString::from("dyngroup_filter"),
Attribute::DynGroupFilter.into(),
Value::JsonFilt(ProtoFilter::Eq("name".to_string(), "testgroup".to_string()))
)
]),
@ -637,7 +637,7 @@ mod tests {
ModifyList::new_list(vec![
Modify::Purged("dyngroup_filter".into()),
Modify::Present(
AttrString::from("dyngroup_filter"),
Attribute::DynGroupFilter.into(),
Value::JsonFilt(ProtoFilter::Eq(
"name".to_string(),
"no_such_entry_exists".to_string()
@ -689,7 +689,7 @@ mod tests {
PartialValue::new_iname("test_dyngroup")
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("dynmember"),
Attribute::DynMember.into(),
Value::Refer(UUID_ADMIN)
)]),
None,
@ -741,7 +741,7 @@ mod tests {
Attribute::Name,
PartialValue::new_iname("test_dyngroup")
)),
ModifyList::new_list(vec![Modify::Purged(AttrString::from("dynmember"),)]),
ModifyList::new_list(vec![Modify::Purged(Attribute::DynMember.into(),)]),
None,
|_| {},
|qs: &mut QueryServerWriteTransaction| {

View file

@ -214,8 +214,8 @@ mod tests {
preload,
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(uuid))),
ModifyList::new_list(vec![
Modify::Purged(AttrString::from("oauth2_rs_basic_secret"),),
Modify::Purged(AttrString::from("oauth2_rs_token_key"),)
Modify::Purged(Attribute::OAuth2RsBasicSecret.into(),),
Modify::Purged(Attribute::OAuth2RsTokenKey.into(),)
]),
None,
|_| {},

View file

@ -305,7 +305,7 @@ impl Plugin for MemberOf {
fn verify(qs: &mut QueryServerReadTransaction) -> Vec<Result<(), ConsistencyError>> {
let mut r = Vec::new();
let filt_in = filter!(f_pres(Attribute::Class.as_ref()));
let filt_in = filter!(f_pres(Attribute::Class));
let all_cand = match qs
.internal_search(filt_in)
@ -797,7 +797,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_A).unwrap()
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s(UUID_B).unwrap()
)]),
None,
@ -836,7 +836,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_A).unwrap()
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s(UUID_B).unwrap()
)]),
None,
@ -893,7 +893,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_B).unwrap()
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s(UUID_C).unwrap()
)]),
None,
@ -953,7 +953,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_C).unwrap()
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s(UUID_A).unwrap()
)]),
None,
@ -1020,7 +1020,7 @@ mod tests {
f_eq(Attribute::Uuid, PartialValue::new_uuid_s(UUID_D).unwrap()),
])),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s(UUID_A).unwrap()
)]),
None,
@ -1092,7 +1092,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_A).unwrap()
)),
ModifyList::new_list(vec![Modify::Removed(
AttrString::from("member"),
Attribute::Member.into(),
PartialValue::new_refer_s(UUID_B).unwrap()
)]),
None,
@ -1134,7 +1134,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_A).unwrap()
)),
ModifyList::new_list(vec![Modify::Removed(
AttrString::from("member"),
Attribute::Member.into(),
PartialValue::new_refer_s(UUID_B).unwrap()
)]),
None,
@ -1195,7 +1195,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_B).unwrap()
)),
ModifyList::new_list(vec![Modify::Removed(
AttrString::from("member"),
Attribute::Member.into(),
PartialValue::new_refer_s(UUID_C).unwrap()
)]),
None,
@ -1266,7 +1266,7 @@ mod tests {
PartialValue::new_uuid_s(UUID_C).unwrap()
)),
ModifyList::new_list(vec![Modify::Removed(
AttrString::from("member"),
Attribute::Member.into(),
PartialValue::new_refer_s(UUID_A).unwrap()
)]),
None,
@ -1356,11 +1356,11 @@ mod tests {
)),
ModifyList::new_list(vec![
Modify::Removed(
AttrString::from("member"),
Attribute::Member.into(),
PartialValue::new_refer_s(UUID_A).unwrap()
),
Modify::Removed(
AttrString::from("member"),
Attribute::Member.into(),
PartialValue::new_refer_s(UUID_D).unwrap()
),
]),

View file

@ -339,7 +339,7 @@ mod tests {
),
(
Attribute::AcpSearchAttr.as_ref(),
Value::new_iutf8("attributename")
Value::new_iutf8(Attribute::AttributeName.as_ref())
),
(
Attribute::AcpModifyClass.as_ref(),

View file

@ -184,7 +184,7 @@ impl Plugin for ReferentialIntegrity {
fn verify(qs: &mut QueryServerReadTransaction) -> Vec<Result<(), ConsistencyError>> {
// Get all entries as cand
// build a cand-uuid set
let filt_in = filter_all!(f_pres(Attribute::Class.as_ref()));
let filt_in = filter_all!(f_pres(Attribute::Class));
let all_cand = match qs
.internal_search(filt_in)
@ -433,7 +433,7 @@ mod tests {
PartialValue::new_iname("testgroup_b")
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s("d2b496bd-8493-47b7-8142-f568b5cf47ee").unwrap()
)]),
None,
@ -467,7 +467,7 @@ mod tests {
PartialValue::new_iname("testgroup_b")
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s("d2b496bd-8493-47b7-8142-f568b5cf47ee").unwrap()
)]),
None,
@ -514,13 +514,10 @@ mod tests {
)),
ModifyList::new_list(vec![
Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::Refer(uuid!("d2b496bd-8493-47b7-8142-f568b5cf47ee"))
),
Modify::Present(
AttrString::from("member"),
Value::Refer(UUID_DOES_NOT_EXIST)
),
Modify::Present(Attribute::Member.into(), Value::Refer(UUID_DOES_NOT_EXIST)),
]),
None,
|_| {},
@ -562,7 +559,7 @@ mod tests {
Attribute::Name,
PartialValue::new_iname("testgroup_b")
)),
ModifyList::new_list(vec![Modify::Purged(AttrString::from("member"))]),
ModifyList::new_list(vec![Modify::Purged(Attribute::Member.into())]),
None,
|_| {},
|_| {}
@ -593,7 +590,7 @@ mod tests {
PartialValue::new_iname("testgroup_a")
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s("d2b496bd-8493-47b7-8142-f568b5cf47ee").unwrap()
)]),
None,
@ -638,7 +635,7 @@ mod tests {
PartialValue::new_iname("testgroup_b")
)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("member"),
Attribute::Member.into(),
Value::new_refer_s("d2b496bd-8493-47b7-8142-f568b5cf47ee").unwrap()
)]),
None,

View file

@ -174,7 +174,7 @@ impl<'a> QueryServerReadTransaction<'a> {
let entry_filter = filter_all!(f_or!([
f_and!([
f_pres(Attribute::Class.as_ref()),
f_pres(Attribute::Class),
f_andnot(f_or(vec![
// These are from above!
f_eq(Attribute::Class, EntryClass::AttributeType.into()),

View file

@ -154,7 +154,7 @@ async fn test_repl_refresh_basic(server_a: &QueryServer, server_b: &QueryServer)
// Now assert everything else in the db matches.
let entries_a = server_a_txn
.internal_search(filter_all!(f_pres(Attribute::Class.as_ref())))
.internal_search(filter_all!(f_pres(Attribute::Class)))
.map(|ents| {
ents.into_iter()
.map(|e| (e.get_uuid(), e))
@ -163,7 +163,7 @@ async fn test_repl_refresh_basic(server_a: &QueryServer, server_b: &QueryServer)
.expect("Failed to access all entries");
let entries_b = server_a_txn
.internal_search(filter_all!(f_pres(Attribute::Class.as_ref())))
.internal_search(filter_all!(f_pres(Attribute::Class)))
.map(|ents| {
ents.into_iter()
.map(|e| (e.get_uuid(), e))

File diff suppressed because it is too large Load diff

View file

@ -1627,7 +1627,7 @@ mod tests {
#[test]
fn test_access_internal_search() {
// Test that an internal search bypasses ACS
let se = SearchEvent::new_internal_invalid(filter!(f_pres(Attribute::Class.as_ref())));
let se = SearchEvent::new_internal_invalid(filter!(f_pres(Attribute::Class)));
let expect = vec![E_TEST_ACCOUNT_1.clone()];
let entries = vec![E_TEST_ACCOUNT_1.clone()];
@ -1639,8 +1639,8 @@ mod tests {
"test_acp",
Uuid::new_v4(),
UUID_TEST_GROUP_1,
filter_valid!(f_pres("nomatchy")), // apply to none - ie no allowed results
"name", // allow to this attr, but we don't eval this.
filter_valid!(f_pres(Attribute::NonExist)), // apply to none - ie no allowed results
"name", // allow to this attr, but we don't eval this.
)],
entries,
expect
@ -1657,13 +1657,13 @@ mod tests {
let se_a = SearchEvent::new_impersonate_entry(
E_TEST_ACCOUNT_1.clone(),
filter_all!(f_pres("name")),
filter_all!(f_pres(Attribute::Name)),
);
let ex_a = vec![Arc::new(ev1)];
let se_b = SearchEvent::new_impersonate_entry(
E_TEST_ACCOUNT_2.clone(),
filter_all!(f_pres("name")),
filter_all!(f_pres(Attribute::Name)),
);
let ex_b = vec![];
@ -1701,12 +1701,12 @@ mod tests {
let se_ro = SearchEvent::new_impersonate_identity(
Identity::from_impersonate_entry_readonly(E_TEST_ACCOUNT_1.clone()),
filter_all!(f_pres("name")),
filter_all!(f_pres(Attribute::Name)),
);
let se_rw = SearchEvent::new_impersonate_identity(
Identity::from_impersonate_entry_readwrite(E_TEST_ACCOUNT_1.clone()),
filter_all!(f_pres("name")),
filter_all!(f_pres(Attribute::Name)),
);
let acp = AccessControlSearch::from_raw(
@ -1744,7 +1744,7 @@ mod tests {
let se_anon_ro = SearchEvent::new_impersonate_identity(
Identity::from_impersonate_entry_readonly(E_TEST_ACCOUNT_1.clone()),
filter_all!(f_pres("name")),
filter_all!(f_pres(Attribute::Name)),
);
let acp = AccessControlSearch::from_raw(
@ -1829,7 +1829,7 @@ mod tests {
)),
);
// the requested attrs here.
se_anon.attrs = Some(btreeset![AttrString::from("name")]);
se_anon.attrs = Some(btreeset![Attribute::Name.into()]);
let acp = AccessControlSearch::from_raw(
"test_acp",
@ -2122,15 +2122,18 @@ mod tests {
fn test_access_enforce_create() {
let ev1 = entry_init!(
(Attribute::Class.as_ref(), EntryClass::Account.to_value()),
("name", Value::new_iname("testperson1")),
(Attribute::Name.as_ref(), Value::new_iname("testperson1")),
(Attribute::Uuid.as_ref(), Value::Uuid(UUID_TEST_ACCOUNT_1))
);
let r1_set = vec![ev1];
let ev2 = entry_init!(
(Attribute::Class.as_ref(), EntryClass::Account.to_value()),
("notallowed", Value::new_class("notallowed")),
("name", Value::new_iname("testperson1")),
(
Attribute::TestNotAllowed.as_ref(),
Value::new_class("notallowed")
),
(Attribute::Name.as_ref(), Value::new_iname("testperson1")),
(Attribute::Uuid.as_ref(), Value::Uuid(UUID_TEST_ACCOUNT_1))
);
@ -2138,8 +2141,8 @@ mod tests {
let ev3 = entry_init!(
(Attribute::Class.as_ref(), EntryClass::Account.to_value()),
("class", Value::new_class("notallowed")),
("name", Value::new_iname("testperson1")),
(Attribute::Class.as_ref(), Value::new_class("notallowed")),
(Attribute::Name.as_ref(), Value::new_iname("testperson1")),
(Attribute::Uuid.as_ref(), Value::Uuid(UUID_TEST_ACCOUNT_1))
);
let r3_set = vec![ev3];
@ -2147,7 +2150,7 @@ mod tests {
let ev4 = entry_init!(
(Attribute::Class.as_ref(), EntryClass::Account.to_value()),
(Attribute::Class.as_ref(), EntryClass::Group.to_value()),
("name", Value::new_iname("testperson1")),
(Attribute::Name.as_ref(), Value::new_iname("testperson1")),
(Attribute::Uuid.as_ref(), Value::Uuid(UUID_TEST_ACCOUNT_1))
);
let r4_set = vec![ev4];
@ -2411,7 +2414,7 @@ mod tests {
vec![AccessEffectivePermission {
delete: false,
target: uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"),
search: Access::Allow(btreeset![AttrString::from("name")]),
search: Access::Allow(btreeset![Attribute::Name.into()]),
modify_pres: Access::Allow(BTreeSet::new()),
modify_rem: Access::Allow(BTreeSet::new()),
modify_class: Access::Allow(BTreeSet::new()),
@ -2454,9 +2457,9 @@ mod tests {
delete: false,
target: uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"),
search: Access::Allow(BTreeSet::new()),
modify_pres: Access::Allow(btreeset![AttrString::from("name")]),
modify_rem: Access::Allow(btreeset![AttrString::from("name")]),
modify_class: Access::Allow(btreeset![AttrString::from("object")]),
modify_pres: Access::Allow(btreeset![Attribute::Name.into()]),
modify_rem: Access::Allow(btreeset![Attribute::Name.into()]),
modify_class: Access::Allow(btreeset![EntryClass::Object.into()]),
}]
)
}
@ -2814,14 +2817,14 @@ mod tests {
let se_a = SearchEvent::new_impersonate_entry(
E_TEST_ACCOUNT_1.clone(),
filter_all!(f_pres("oauth2_rs_name")),
filter_all!(f_pres(Attribute::OAuth2RsName)),
);
let ex_a = vec![Arc::new(ev1)];
let ex_a_reduced = vec![ev1_reduced];
let se_b = SearchEvent::new_impersonate_entry(
E_TEST_ACCOUNT_2.clone(),
filter_all!(f_pres("oauth2_rs_name")),
filter_all!(f_pres(Attribute::OAuth2RsName)),
);
let ex_b = vec![];
@ -2896,7 +2899,7 @@ mod tests {
let se_a = SearchEvent::new_impersonate_entry(
sync_test_account,
filter_all!(f_pres("sync_credential_portal")),
filter_all!(f_pres(Attribute::SyncCredentialPortal)),
);
let ex_a = vec![Arc::new(ev1)];
let ex_a_reduced = vec![ev1_reduced];
@ -2907,7 +2910,7 @@ mod tests {
// Test a non-synced account aka the deny case
let se_b = SearchEvent::new_impersonate_entry(
E_TEST_ACCOUNT_2.clone(),
filter_all!(f_pres("sync_credential_portal")),
filter_all!(f_pres(Attribute::SyncCredentialPortal)),
);
let ex_b = vec![];

View file

@ -206,7 +206,7 @@ mod tests {
(Attribute::Class.as_ref(), EntryClass::Person.to_value()),
(Attribute::Name.as_ref(), Value::new_iname("testperson1")),
(
"uuid",
Attribute::Uuid.as_ref(),
Value::Uuid(uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"))
),
(
@ -224,7 +224,7 @@ mod tests {
(Attribute::Class.as_ref(), EntryClass::Person.to_value()),
(Attribute::Name.as_ref(), Value::new_iname("testperson2")),
(
"uuid",
Attribute::Uuid.as_ref(),
Value::Uuid(uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63932"))
),
(
@ -242,7 +242,7 @@ mod tests {
(Attribute::Class.as_ref(), EntryClass::Person.to_value()),
(Attribute::Name.as_ref(), Value::new_iname("testperson3")),
(
"uuid",
Attribute::Uuid.as_ref(),
Value::Uuid(uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63933"))
),
(
@ -261,7 +261,7 @@ mod tests {
assert!(cr.is_ok());
// Delete filter is syntax invalid
let de_inv = DeleteEvent::new_internal_invalid(filter!(f_pres("nhtoaunaoehtnu")));
let de_inv = DeleteEvent::new_internal_invalid(filter!(f_pres(Attribute::NonExist)));
assert!(server_txn.delete(&de_inv).is_err());
// Delete deletes nothing

View file

@ -289,8 +289,8 @@ impl<'a> QueryServerWriteTransaction<'a> {
pub fn migrate_9_to_10(&mut self) -> Result<(), OperationError> {
admin_warn!("starting 9 to 10 migration.");
let filter = filter!(f_or!([
f_pres("primary_credential"),
f_pres("unix_password"),
f_pres(Attribute::PrimaryCredential),
f_pres(Attribute::UnixPassword),
]));
// This "does nothing" since everything has object anyway, but it forces the entry to be
// loaded and rewritten.
@ -309,7 +309,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
#[instrument(level = "debug", skip_all)]
pub fn migrate_10_to_11(&mut self) -> Result<(), OperationError> {
admin_warn!("starting 9 to 10 migration.");
let filter = filter!(f_pres("primary_credential"));
let filter = filter!(f_pres(Attribute::PrimaryCredential));
let pre_candidates = self.internal_search(filter).map_err(|e| {
admin_error!(err = ?e, "migrate_10_to_11 internal search failure");
@ -358,8 +358,8 @@ impl<'a> QueryServerWriteTransaction<'a> {
admin_warn!("starting 11 to 12 migration.");
// sync_token_session
let filter = filter!(f_or!([
f_pres("api_token_session"),
f_pres("sync_token_session"),
f_pres(Attribute::ApiTokenSession),
f_pres(Attribute::SyncTokenSession),
]));
let mut mod_candidates = self.internal_search_writeable(&filter).map_err(|e| {
@ -838,10 +838,10 @@ mod tests {
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_DOMAIN_INFO))),
ModifyList::new_list(vec![
Modify::Purged(Attribute::Name.into()),
Modify::Purged(AttrString::from("domain_name")),
Modify::Purged(Attribute::DomainName.into()),
Modify::Present(Attribute::Name.into(), Value::new_iutf8("domain_local")),
Modify::Present(
AttrString::from("domain_name"),
Attribute::DomainName.into(),
Value::new_iutf8("example.com"),
),
]),

View file

@ -991,7 +991,7 @@ impl<'a> QueryServerReadTransaction<'a> {
// the entry changelogs are consistent to their entries.
let schema = self.get_schema();
let filt_all = filter!(f_pres(Attribute::Class.as_ref()));
let filt_all = filter!(f_pres(Attribute::Class));
let all_entries = match self.internal_search(filt_all) {
Ok(a) => a,
Err(_e) => return vec![Err(ConsistencyError::QueryServerSearchFailure)],
@ -1930,7 +1930,10 @@ mod tests {
"uuid",
Value::Uuid(uuid!("cfcae205-31c3-484b-8ced-667d1709c5e3"))
),
("attributename", Value::new_iutf8("testattr")),
(
Attribute::AttributeName.as_ref(),
Value::new_iutf8("testattr")
),
("description", Value::new_utf8s("Test Attribute")),
("multivalue", Value::new_bool(false)),
("unique", Value::new_bool(false)),

View file

@ -512,7 +512,7 @@ mod tests {
(Attribute::Class.as_ref(), EntryClass::Person.to_value()),
(Attribute::Name.as_ref(), Value::new_iname("testperson1")),
(
"uuid",
Attribute::Uuid.as_ref(),
Value::Uuid(uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"))
),
(
@ -530,7 +530,7 @@ mod tests {
(Attribute::Class.as_ref(), EntryClass::Person.to_value()),
(Attribute::Name.as_ref(), Value::new_iname("testperson2")),
(
"uuid",
Attribute::Uuid.as_ref(),
Value::Uuid(uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63932"))
),
(
@ -550,7 +550,7 @@ mod tests {
// Empty Modlist (filter is valid)
let me_emp = ModifyEvent::new_internal_invalid(
filter!(f_pres(Attribute::Class.as_ref())),
filter!(f_pres(Attribute::Class)),
ModifyList::new_list(vec![]),
);
assert!(server_txn.modify(&me_emp) == Err(OperationError::EmptyRequest));
@ -580,7 +580,7 @@ mod tests {
// PartialValue::new_iname("Flarbalgarble")
// )),
// &ModifyList::new_list(vec![Modify::Present(
// AttrString::from("description"),
// Attribute::Description.into(),
// Value::from("anusaosu"),
// )]),
// );
@ -593,16 +593,16 @@ mod tests {
// Mod is invalid to schema
let me_inv_m = ModifyEvent::new_internal_invalid(
filter!(f_pres(Attribute::Class.as_ref())),
filter!(f_pres(Attribute::Class)),
ModifyList::new_list(vec![Modify::Present(
AttrString::from("htnaonu"),
Attribute::NonExist.into(),
Value::from("anusaosu"),
)]),
);
assert!(
server_txn.modify(&me_inv_m)
== Err(OperationError::SchemaViolation(
SchemaError::InvalidAttribute("htnaonu".to_string())
SchemaError::InvalidAttribute(Attribute::NonExist.to_string())
))
);
@ -737,7 +737,7 @@ mod tests {
ModifyList::new_list(vec![
Modify::Present(Attribute::Class.into(), EntryClass::SystemInfo.to_value()),
// Modify::Present("domain".to_string(), Value::new_iutf8("domain.name")),
Modify::Present(AttrString::from("version"), Value::new_uint32(1)),
Modify::Present(Attribute::Version.into(), Value::new_uint32(1)),
]),
);
assert!(server_txn.modify(&me_sin).is_ok());

View file

@ -150,11 +150,11 @@ impl<'a> QueryServerWriteTransaction<'a> {
dm_mods
.entry(g_uuid)
.and_modify(|mlist| {
let m = Modify::Present(AttrString::from("member"), Value::Refer(u));
let m = Modify::Present(Attribute::Member.into(), Value::Refer(u));
mlist.push_mod(m);
})
.or_insert({
let m = Modify::Present(AttrString::from("member"), Value::Refer(u));
let m = Modify::Present(Attribute::Member.into(), Value::Refer(u));
ModifyList::new_list(vec![m])
});
}

View file

@ -561,7 +561,7 @@ impl PartialValue {
pub fn new_spn_s(s: &str) -> Option<Self> {
SPN_RE.captures(s).and_then(|caps| {
let name = match caps.name("name") {
let name = match caps.name(Attribute::Name.as_ref()) {
Some(v) => v.as_str().to_string(),
None => return None,
};
@ -1222,7 +1222,7 @@ impl Value {
pub fn new_spn_parse(s: &str) -> Option<Self> {
SPN_RE.captures(s).and_then(|caps| {
let name = match caps.name("name") {
let name = match caps.name(Attribute::Name.as_ref()) {
Some(v) => v.as_str().to_string(),
None => return None,
};

View file

@ -6,6 +6,7 @@ use kanidm_proto::constants::{
APPLICATION_JSON, ATTR_ACP_RECEIVER_GROUP, ATTR_ACP_TARGET_SCOPE, ATTR_DESCRIPTION,
ATTR_LDAP_SSH_PUBLICKEY, ATTR_NAME,
};
use kanidmd_lib::prelude::Attribute;
use kanidmd_testkit::*;
use reqwest::header::CONTENT_TYPE;
@ -270,74 +271,89 @@ async fn test_default_entries_rbac_admins_schema_entries(rsclient: KanidmClient)
let classtype_entries = rsclient.idm_schema_classtype_list().await.unwrap();
let classnames: HashSet<String> = classtype_entries
.iter()
.map(|entry| entry.attrs.get("classname").unwrap().first().unwrap())
.map(|entry| {
entry
.attrs
.get(Attribute::ClassName.as_ref())
.unwrap()
.first()
.unwrap()
})
.cloned()
.collect();
println!("{:?}", classnames);
assert!(default_classnames.is_subset(&classnames));
// TODO: this could probably just iterate on the enum?
let default_attributenames: HashSet<String> = [
"acp_create_attr",
"acp_create_class",
"acp_enable",
"acp_modify_class",
"acp_modify_presentattr",
"acp_modify_removedattr",
"acp_receiver_group",
"acp_search_attr",
"acp_targetscope",
"attributename",
"claim",
"class",
"classname",
ATTR_DESCRIPTION,
"directmemberof",
"domain",
"index",
"last_modified_cid",
"may",
"member",
"memberof",
"multivalue",
"must",
ATTR_NAME,
"password_import",
"phantom",
"spn",
"syntax",
"systemmay",
"systemmust",
"unique",
"uuid",
"version",
"displayname",
"legalname",
"mail",
ATTR_LDAP_SSH_PUBLICKEY,
"primary_credential",
"radius_secret",
"domain_name",
"domain_display_name",
"domain_uuid",
"domain_ssid",
"gidnumber",
"badlist_password",
"authsession_expiry",
"privilege_expiry",
"loginshell",
"unix_password",
"nsuniqueid",
Attribute::AcpCreateAttr,
Attribute::AcpCreateClass,
Attribute::AcpEnable,
Attribute::AcpModifyClass,
Attribute::AcpModifyPresentAttr,
Attribute::AcpModifyRemovedAttr,
Attribute::AcpReceiverGroup,
Attribute::AcpSearchAttr,
Attribute::AcpTargetScope,
Attribute::AttributeName,
Attribute::Claim,
Attribute::Class,
Attribute::ClassName,
Attribute::Description,
Attribute::DirectMemberOf,
Attribute::Domain,
Attribute::Index,
Attribute::LastModifiedCid,
Attribute::May,
Attribute::Member,
Attribute::MemberOf,
Attribute::MultiValue,
Attribute::Must,
Attribute::Name,
Attribute::PasswordImport,
Attribute::Phantom,
Attribute::Spn,
Attribute::Syntax,
Attribute::SystemMay,
Attribute::SystemMust,
Attribute::Unique,
Attribute::Uuid,
Attribute::Version,
Attribute::DisplayName,
Attribute::LegalName,
Attribute::Mail,
Attribute::LdapSshPublicKey,
Attribute::PrimaryCredential,
Attribute::RadiusSecret,
Attribute::DomainName,
Attribute::DomainDisplayName,
Attribute::DomainUuid,
Attribute::DomainSsid,
Attribute::GidNumber,
Attribute::BadlistPassword,
Attribute::AuthSessionExpiry,
Attribute::PrivilegeExpiry,
Attribute::LoginShell,
Attribute::UnixPassword,
Attribute::NsUniqueId,
]
.iter()
.map(ToString::to_string)
.map(|a| a.as_ref().to_string())
.collect();
let attributename_entries = rsclient.idm_schema_attributetype_list().await.unwrap();
println!("{:?}", attributename_entries);
let attributenames = attributename_entries
.iter()
.map(|entry| entry.attrs.get("attributename").unwrap().first().unwrap())
.map(|entry| {
entry
.attrs
.get(Attribute::AttributeName.as_ref())
.unwrap()
.first()
.unwrap()
})
.cloned()
.collect();

View file

@ -47,11 +47,14 @@ async fn dont_trust_xff_dont_send_header(rsclient: KanidmClient) {
.send()
.await
.unwrap();
let ip_res: Vec<IpAddr> = res
.json()
.await
.expect("Failed to parse response as Vec<IpAddr>");
let body = res.bytes().await.unwrap();
let ip_res: Vec<IpAddr> = serde_json::from_slice(&body).unwrap_or_else(|op| {
panic!(
"Failed to parse response as Vec<IpAddr>: {:?} body: {:?}",
op, body,
)
});
eprintln!("Body: {:?}", body);
assert_eq!(ip_res[0], DEFAULT_IP_ADDRESS);
}