mirror of
https://github.com/kanidm/kanidm.git
synced 2025-05-30 12:53:54 +02:00
Compare commits
3 commits
7fa6d737e6
...
90445d54d9
Author | SHA1 | Date | |
---|---|---|---|
|
90445d54d9 | ||
|
be4818e121 | ||
|
588012a8e8 |
Cargo.lockCargo.toml
libs
server
core/static
lib/src
testkit-macros/src
testkit/tests/testkit
tools
cli/src/cli/system_config
orca/src
unix_integration
common/src
nss_kanidm/src
pam_kanidm/src
resolver/tests
779
Cargo.lock
generated
779
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
49
Cargo.toml
49
Cargo.toml
|
@ -118,15 +118,12 @@ codegen-units = 256
|
|||
# webauthn-rs-proto = { path = "../webauthn-rs/webauthn-rs-proto" }
|
||||
# sshkey-attest = { path = "../webauthn-rs/sshkey-attest" }
|
||||
|
||||
# kanidm-hsm-crypto = { path = "../hsm-crypto" }
|
||||
|
||||
# For BSD nss support
|
||||
libnss = { git = "https://github.com/Firstyear/libnss-rs.git", branch = "20250207-freebsd" }
|
||||
# Allow ssh keys to have comments with spaces.
|
||||
sshkeys = { git = "https://github.com/Firstyear/rust-sshkeys.git", rev = "3a081cbf7480628223bcb96fc8aaa8c19109d007" }
|
||||
|
||||
|
||||
|
||||
[workspace.dependencies]
|
||||
kanidmd_core = { path = "./server/core", version = "=1.6.0-dev" }
|
||||
kanidmd_lib = { path = "./server/lib", version = "=1.6.0-dev" }
|
||||
|
@ -143,7 +140,7 @@ kanidm_utils_users = { path = "./libs/users", version = "=1.6.0-dev" }
|
|||
scim_proto = { path = "./libs/scim_proto", version = "=1.6.0-dev" }
|
||||
sketching = { path = "./libs/sketching", version = "=1.6.0-dev" }
|
||||
|
||||
anyhow = { version = "1.0.95" }
|
||||
anyhow = { version = "1.0.98" }
|
||||
argon2 = { version = "0.5.3", features = ["alloc"] }
|
||||
askama = { version = "0.12.1", features = ["serde", "with-axum"] }
|
||||
askama_axum = { version = "0.4.0" }
|
||||
|
@ -164,7 +161,7 @@ base64 = "^0.22.1"
|
|||
base64urlsafedata = "0.5.1"
|
||||
bitflags = "^2.8.0"
|
||||
bytes = "^1.9.0"
|
||||
clap = { version = "^4.5.34", features = ["derive", "env"] }
|
||||
clap = { version = "4.5.37", features = ["derive", "env"] }
|
||||
clap_complete = "^4.5.42"
|
||||
# Forced by saffron/cron
|
||||
chrono = "^0.4.39"
|
||||
|
@ -181,9 +178,9 @@ filetime = "^0.2.24"
|
|||
fs4 = "^0.13.0"
|
||||
futures = "^0.3.31"
|
||||
futures-util = { version = "^0.3.30", features = ["sink"] }
|
||||
gix = { version = "0.64.0", default-features = false }
|
||||
gix = { version = "0.71.0", default-features = false }
|
||||
haproxy-protocol = { version = "0.0.1" }
|
||||
hashbrown = { version = "0.14.3", features = ["serde", "inline-more", "ahash"] }
|
||||
hashbrown = { version = "0.15.2", features = ["serde", "inline-more"] }
|
||||
hex = "^0.4.3"
|
||||
http = "1.2.0"
|
||||
http-body-util = "0.1"
|
||||
|
@ -192,7 +189,7 @@ hyper = { version = "1.5.1", features = [
|
|||
] } # hyper full includes client/server/http2
|
||||
hyper-util = { version = "0.1.10", features = ["server", "tokio"] }
|
||||
idlset = "^0.2.5"
|
||||
image = { version = "0.24.9", default-features = false, features = [
|
||||
image = { version = "0.25.6", default-features = false, features = [
|
||||
"gif",
|
||||
"jpeg",
|
||||
"webp",
|
||||
|
@ -205,16 +202,16 @@ lazy_static = "^1.5.0"
|
|||
ldap3_client = "^0.5.2"
|
||||
ldap3_proto = { version = "^0.5.2", features = ["serde"] }
|
||||
|
||||
libc = "^0.2.168"
|
||||
libc = "0.2.172"
|
||||
libnss = "^0.8.0"
|
||||
libsqlite3-sys = "^0.25.2"
|
||||
lodepng = "3.11.0"
|
||||
lru = "^0.13.0"
|
||||
mathru = "^0.13.0"
|
||||
lru = "0.14.0"
|
||||
mathru = "0.15.5"
|
||||
md-5 = "0.10.6"
|
||||
mimalloc = "0.1.43"
|
||||
mimalloc = "0.1.46"
|
||||
notify-debouncer-full = { version = "0.5" }
|
||||
num_enum = "^0.5.11"
|
||||
num_enum = "0.7.3"
|
||||
oauth2_ext = { version = "^4.4.2", package = "oauth2", default-features = false }
|
||||
openssl-sys = "^0.9"
|
||||
openssl = "^0.10.72"
|
||||
|
@ -236,11 +233,11 @@ tracing-core = "0.1.33"
|
|||
peg = "0.8"
|
||||
pkg-config = "^0.3.31"
|
||||
prctl = "1.0.0"
|
||||
proc-macro2 = "1.0.93"
|
||||
qrcode = "^0.12.0"
|
||||
proc-macro2 = "1.0.95"
|
||||
qrcode = "0.14.1"
|
||||
quote = "1"
|
||||
rand = "^0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
rand = "0.9.1"
|
||||
rand_chacha = "0.9.0"
|
||||
regex = "1.11.0"
|
||||
reqwest = { version = "0.12.12", default-features = false, features = [
|
||||
"cookies",
|
||||
|
@ -250,13 +247,13 @@ reqwest = { version = "0.12.12", default-features = false, features = [
|
|||
"rustls-tls-native-roots",
|
||||
"rustls-tls-native-roots-no-provider",
|
||||
] }
|
||||
rusqlite = { version = "^0.28.0", features = ["array", "bundled"] }
|
||||
rustls = { version = "0.23.21", default-features = false, features = [
|
||||
rusqlite = { version = "0.35.0", features = ["array", "bundled"] }
|
||||
rustls = { version = "0.23.26", default-features = false, features = [
|
||||
"aws_lc_rs",
|
||||
] }
|
||||
|
||||
sd-notify = "^0.4.5"
|
||||
selinux = "^0.4.6"
|
||||
selinux = "^0.5.1"
|
||||
serde = "^1.0.217"
|
||||
serde_cbor = { version = "0.12.0-dev", package = "serde_cbor_2" }
|
||||
serde_json = "^1.0.137"
|
||||
|
@ -264,13 +261,13 @@ serde_urlencoded = "^0.7.1"
|
|||
serde_with = "3.12.0"
|
||||
sha-crypt = "0.5.0"
|
||||
sha2 = "0.10.8"
|
||||
shellexpand = "^2.1.2"
|
||||
shellexpand = "3.1.1"
|
||||
smartstring = "^1.0.1"
|
||||
smolset = "^1.3.1"
|
||||
sshkey-attest = "^0.5.0"
|
||||
sshkeys = "0.3.3"
|
||||
svg = "0.13.1"
|
||||
syn = { version = "2.0.96", features = ["full"] }
|
||||
svg = "0.18.0"
|
||||
syn = { version = "2.0.100", features = ["full"] }
|
||||
tempfile = "3.15.0"
|
||||
testkit-macros = { path = "./server/testkit-macros" }
|
||||
time = { version = "^0.3.36", features = ["formatting", "local-offset"] }
|
||||
|
@ -279,7 +276,7 @@ tokio = "^1.44.2"
|
|||
tokio-openssl = "^0.6.5"
|
||||
tokio-util = "^0.7.13"
|
||||
|
||||
toml = "^0.5.11"
|
||||
toml = "^0.8.20"
|
||||
tracing = { version = "^0.1.41", features = [
|
||||
"max_level_trace",
|
||||
"release_max_level_debug",
|
||||
|
@ -306,6 +303,6 @@ walkdir = "2"
|
|||
|
||||
x509-cert = "0.2.5"
|
||||
|
||||
zxcvbn = "^2.2.2"
|
||||
zxcvbn = "3.1.0"
|
||||
|
||||
nonempty = "0.8.1"
|
||||
nonempty = "0.11.0"
|
||||
|
|
|
@ -834,9 +834,9 @@ impl TryFrom<&str> for Password {
|
|||
|
||||
impl Password {
|
||||
fn bench_pbkdf2(pbkdf2_cost: usize) -> Option<Duration> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let salt: Vec<u8> = (0..PBKDF2_SALT_LEN).map(|_| rng.gen()).collect();
|
||||
let input: Vec<u8> = (0..PBKDF2_SALT_LEN).map(|_| rng.gen()).collect();
|
||||
let mut rng = rand::rng();
|
||||
let salt: Vec<u8> = (0..PBKDF2_SALT_LEN).map(|_| rng.random()).collect();
|
||||
let input: Vec<u8> = (0..PBKDF2_SALT_LEN).map(|_| rng.random()).collect();
|
||||
// This is 512 bits of output
|
||||
let mut key: Vec<u8> = (0..PBKDF2_KEY_LEN).map(|_| 0).collect();
|
||||
|
||||
|
@ -855,9 +855,9 @@ impl Password {
|
|||
}
|
||||
|
||||
fn bench_argon2id(params: Params) -> Option<Duration> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let salt: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.gen()).collect();
|
||||
let input: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.gen()).collect();
|
||||
let mut rng = rand::rng();
|
||||
let salt: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.random()).collect();
|
||||
let input: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.random()).collect();
|
||||
let mut key: Vec<u8> = (0..ARGON2_KEY_LEN).map(|_| 0).collect();
|
||||
|
||||
let argon = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
|
||||
|
@ -873,8 +873,8 @@ impl Password {
|
|||
|
||||
pub fn new_pbkdf2(policy: &CryptoPolicy, cleartext: &str) -> Result<Self, CryptoError> {
|
||||
let pbkdf2_cost = policy.pbkdf2_cost;
|
||||
let mut rng = rand::thread_rng();
|
||||
let salt: Vec<u8> = (0..PBKDF2_SALT_LEN).map(|_| rng.gen()).collect();
|
||||
let mut rng = rand::rng();
|
||||
let salt: Vec<u8> = (0..PBKDF2_SALT_LEN).map(|_| rng.random()).collect();
|
||||
let mut key: Vec<u8> = (0..PBKDF2_KEY_LEN).map(|_| 0).collect();
|
||||
|
||||
pbkdf2_hmac(
|
||||
|
@ -897,8 +897,8 @@ impl Password {
|
|||
|
||||
let argon = Argon2::new(Algorithm::Argon2id, version, policy.argon2id_params.clone());
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let salt: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.gen()).collect();
|
||||
let mut rng = rand::rng();
|
||||
let salt: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.random()).collect();
|
||||
let mut key: Vec<u8> = (0..ARGON2_KEY_LEN).map(|_| 0).collect();
|
||||
|
||||
argon
|
||||
|
@ -925,8 +925,8 @@ impl Password {
|
|||
|
||||
let argon = Argon2::new(Algorithm::Argon2id, version, policy.argon2id_params.clone());
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let salt: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.gen()).collect();
|
||||
let mut rng = rand::rng();
|
||||
let salt: Vec<u8> = (0..ARGON2_SALT_LEN).map(|_| rng.random()).collect();
|
||||
let mut check_key: Vec<u8> = (0..ARGON2_KEY_LEN).map(|_| 0).collect();
|
||||
|
||||
argon
|
||||
|
|
|
@ -77,7 +77,10 @@ pub fn apply_profile() {
|
|||
.decode(contents)
|
||||
.unwrap_or_else(|_| panic!("Failed to parse profile - {} - {}", profile, contents));
|
||||
|
||||
let profile_cfg: ProfileConfig = toml::from_slice(&data)
|
||||
let data_str = String::from_utf8(data)
|
||||
.unwrap_or_else(|_| panic!("Failed to read profile data to UTF-8 string - {}", profile));
|
||||
|
||||
let profile_cfg: ProfileConfig = toml::from_str(&data_str)
|
||||
.unwrap_or_else(|_| panic!("Failed to parse profile - {} - {}", profile, contents));
|
||||
|
||||
// We have to setup for our pkg version to be passed into things correctly
|
||||
|
|
3
server/core/static/overrides.css
Normal file
3
server/core/static/overrides.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
/* Custom stylesheet overrides */
|
||||
/* Administrators can add custom styles here */
|
||||
/* This file will be loaded after the main stylesheet */
|
|
@ -2417,7 +2417,7 @@ mod tests {
|
|||
let lims = Limits::unlimited();
|
||||
|
||||
let r = be.search(&lims, &filt);
|
||||
assert!(r.expect("Search failed!").len() == 0);
|
||||
assert!(r.expect("Search failed!").is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -145,8 +145,8 @@ impl Totp {
|
|||
|
||||
// Create a new token with secure key and algo.
|
||||
pub fn generate_secure(step: u64) -> Self {
|
||||
let mut rng = rand::thread_rng();
|
||||
let secret: Vec<u8> = (0..SECRET_SIZE_BYTES).map(|_| rng.gen()).collect();
|
||||
let mut rng = rand::rng();
|
||||
let secret: Vec<u8> = (0..SECRET_SIZE_BYTES).map(|_| rng.random()).collect();
|
||||
let algo = TotpAlgo::Sha256;
|
||||
let digits = TotpDigits::Six;
|
||||
Totp {
|
||||
|
|
|
@ -17,6 +17,7 @@ use webauthn_rs::prelude::{
|
|||
AttestedPasskey as AttestedPasskeyV4, AttestedPasskeyRegistration, CreationChallengeResponse,
|
||||
Passkey as PasskeyV4, PasskeyRegistration, RegisterPublicKeyCredential, WebauthnError,
|
||||
};
|
||||
use zxcvbn::{zxcvbn, Score};
|
||||
|
||||
use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP};
|
||||
use crate::credential::{BackupCodes, Credential};
|
||||
|
@ -1663,23 +1664,14 @@ impl IdmServerCredUpdateTransaction<'_> {
|
|||
}
|
||||
|
||||
// does the password pass zxcvbn?
|
||||
let entropy = zxcvbn::zxcvbn(cleartext, related_inputs).map_err(|e| {
|
||||
admin_error!("zxcvbn check failure (password empty?) {:?}", e);
|
||||
// Return some generic feedback when the password is this bad.
|
||||
PasswordQuality::Feedback(vec![
|
||||
PasswordFeedback::UseAFewWordsAvoidCommonPhrases,
|
||||
PasswordFeedback::AddAnotherWordOrTwo,
|
||||
PasswordFeedback::NoNeedForSymbolsDigitsOrUppercaseLetters,
|
||||
])
|
||||
})?;
|
||||
let entropy = zxcvbn(cleartext, related_inputs);
|
||||
|
||||
// PW's should always be enforced as strong as possible.
|
||||
if entropy.score() < 4 {
|
||||
if entropy.score() < Score::Four {
|
||||
// The password is too week as per:
|
||||
// https://docs.rs/zxcvbn/2.0.0/zxcvbn/struct.Entropy.html
|
||||
let feedback: zxcvbn::feedback::Feedback = entropy
|
||||
.feedback()
|
||||
.as_ref()
|
||||
.ok_or(OperationError::InvalidState)
|
||||
.cloned()
|
||||
.map_err(|e| {
|
||||
|
@ -3405,7 +3397,7 @@ mod tests {
|
|||
assert!(
|
||||
matches!(
|
||||
c_status.mfaregstate,
|
||||
MfaRegStateStatus::TotpNameTryAgain(ref val) if val == ""
|
||||
MfaRegStateStatus::TotpNameTryAgain(ref val) if val.is_empty()
|
||||
),
|
||||
"{:?}",
|
||||
c_status.mfaregstate
|
||||
|
|
|
@ -1209,7 +1209,7 @@ mod tests {
|
|||
// Searching a malformed spn shouldn't cause the query to fail
|
||||
let sr = SearchRequest {
|
||||
msgid: 1,
|
||||
base: format!("dc=example,dc=com"),
|
||||
base: "dc=example,dc=com".to_string(),
|
||||
scope: LdapSearchScope::Subtree,
|
||||
filter: LdapFilter::Or(vec![
|
||||
LdapFilter::Equality(Attribute::Name.to_string(), usr_name.to_string()),
|
||||
|
@ -1232,7 +1232,7 @@ mod tests {
|
|||
|
||||
let sr = SearchRequest {
|
||||
msgid: 1,
|
||||
base: format!("dc=example,dc=com"),
|
||||
base: "dc=example,dc=com".to_string(),
|
||||
scope: LdapSearchScope::Subtree,
|
||||
filter: LdapFilter::And(vec![
|
||||
LdapFilter::Equality(Attribute::Name.to_string(), usr_name.to_string()),
|
||||
|
|
|
@ -2992,11 +2992,12 @@ fn validate_scopes(req_scopes: &BTreeSet<String>) -> Result<(), Oauth2Error> {
|
|||
#[cfg(any(feature = "dev-oauth2-device-flow", test))]
|
||||
#[allow(dead_code)]
|
||||
fn gen_device_code() -> Result<[u8; 16], Oauth2Error> {
|
||||
let mut rng = rand::thread_rng();
|
||||
use rand::TryRngCore;
|
||||
|
||||
let mut rng = rand::rng();
|
||||
let mut result = [0u8; 16];
|
||||
// doing it here because of feature-shenanigans.
|
||||
use rand::Rng;
|
||||
if let Err(err) = rng.try_fill(&mut result) {
|
||||
if let Err(err) = rng.try_fill_bytes(&mut result) {
|
||||
error!("Failed to generate device code! {:?}", err);
|
||||
return Err(Oauth2Error::ServerError(OperationError::Backend));
|
||||
}
|
||||
|
@ -3009,8 +3010,8 @@ fn gen_device_code() -> Result<[u8; 16], Oauth2Error> {
|
|||
/// Returns (xxx-yyy-zzz, digits) where one's the human-facing code, the other is what we store in the DB.
|
||||
fn gen_user_code() -> (String, u32) {
|
||||
use rand::Rng;
|
||||
let mut rng = rand::thread_rng();
|
||||
let num: u32 = rng.gen_range(0..=999999999);
|
||||
let mut rng = rand::rng();
|
||||
let num: u32 = rng.random_range(0..=999999999);
|
||||
let result = format!("{:09}", num);
|
||||
(
|
||||
format!("{}-{}-{}", &result[0..3], &result[3..6], &result[6..9]),
|
||||
|
@ -3100,6 +3101,7 @@ mod tests {
|
|||
$code_challenge:expr,
|
||||
$scope:expr
|
||||
) => {{
|
||||
#[allow(clippy::unnecessary_to_owned)]
|
||||
let scope: BTreeSet<String> = $scope.split(" ").map(|s| s.to_string()).collect();
|
||||
|
||||
let auth_req = AuthorisationRequest {
|
||||
|
@ -7312,10 +7314,7 @@ mod tests {
|
|||
&Url::parse(example_is_not_local)
|
||||
.expect("Failed to parse example.com as a host?")
|
||||
.host()
|
||||
.expect(&format!(
|
||||
"Couldn't get a host from {}",
|
||||
example_is_not_local
|
||||
))
|
||||
.unwrap_or_else(|| panic!("Couldn't get a host from {}", example_is_not_local))
|
||||
));
|
||||
|
||||
let test_urls = [
|
||||
|
|
|
@ -21,6 +21,7 @@ use tokio::sync::{Mutex, Semaphore};
|
|||
use tracing::trace;
|
||||
use url::Url;
|
||||
use webauthn_rs::prelude::{Webauthn, WebauthnBuilder};
|
||||
use zxcvbn::{zxcvbn, Score};
|
||||
|
||||
use super::event::ReadBackupCodeEvent;
|
||||
use super::ldap::{LdapBoundToken, LdapSession};
|
||||
|
@ -235,7 +236,7 @@ impl IdmServer {
|
|||
let qs_read = self.qs.read().await?;
|
||||
|
||||
let mut sid = [0; 4];
|
||||
let mut rng = StdRng::from_entropy();
|
||||
let mut rng = StdRng::from_os_rng();
|
||||
rng.fill(&mut sid);
|
||||
|
||||
Ok(IdmServerAuthTransaction {
|
||||
|
@ -278,7 +279,7 @@ impl IdmServer {
|
|||
let qs_write = self.qs.write(ts).await?;
|
||||
|
||||
let mut sid = [0; 4];
|
||||
let mut rng = StdRng::from_entropy();
|
||||
let mut rng = StdRng::from_os_rng();
|
||||
rng.fill(&mut sid);
|
||||
|
||||
Ok(IdmServerProxyWriteTransaction {
|
||||
|
@ -1657,18 +1658,14 @@ impl IdmServerProxyWriteTransaction<'_> {
|
|||
|
||||
// does the password pass zxcvbn?
|
||||
|
||||
let entropy = zxcvbn::zxcvbn(cleartext, related_inputs).map_err(|e| {
|
||||
admin_error!("zxcvbn check failure (password empty?) {:?}", e);
|
||||
OperationError::PasswordQuality(vec![PasswordFeedback::TooShort(PW_MIN_LENGTH)])
|
||||
})?;
|
||||
let entropy = zxcvbn(cleartext, related_inputs);
|
||||
|
||||
// Unix PW's are a single factor, so we enforce good pws
|
||||
if entropy.score() < 4 {
|
||||
if entropy.score() < Score::Four {
|
||||
// The password is too week as per:
|
||||
// https://docs.rs/zxcvbn/2.0.0/zxcvbn/struct.Entropy.html
|
||||
let feedback: zxcvbn::feedback::Feedback = entropy
|
||||
.feedback()
|
||||
.as_ref()
|
||||
.ok_or(OperationError::InvalidState)
|
||||
.cloned()
|
||||
.inspect_err(|err| {
|
||||
|
|
|
@ -217,9 +217,9 @@ impl EntryChangeState {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn get_attr_cid(&self, attr: Attribute) -> Option<&Cid> {
|
||||
pub(crate) fn get_attr_cid(&self, attr: &Attribute) -> Option<&Cid> {
|
||||
match &self.st {
|
||||
State::Live { at: _, changes } => changes.get(&attr),
|
||||
State::Live { at: _, changes } => changes.get(attr),
|
||||
State::Tombstone { at: _ } => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -705,7 +705,7 @@ async fn test_repl_increment_basic_deleted_attr(server_a: &QueryServer, server_b
|
|||
let e1_cs = e1.get_changestate();
|
||||
let e2_cs = e2.get_changestate();
|
||||
assert_eq!(e1_cs, e2_cs);
|
||||
assert!(e1_cs.get_attr_cid(Attribute::Description).is_some());
|
||||
assert!(e1_cs.get_attr_cid(&Attribute::Description).is_some());
|
||||
|
||||
server_b_txn.commit().expect("Failed to commit");
|
||||
drop(server_a_txn);
|
||||
|
|
|
@ -186,7 +186,7 @@ mod tests {
|
|||
|
||||
match desc {
|
||||
ScimValueKanidm::String(gdesc) if gdesc == "Group Description" => {}
|
||||
_ => assert!(false),
|
||||
_ => unreachable!("Expected a string"),
|
||||
};
|
||||
|
||||
// null removes attr
|
||||
|
@ -201,7 +201,7 @@ mod tests {
|
|||
.expect("Failed to resolve data type");
|
||||
|
||||
let updated_entry = server_txn.scim_put(put_event).expect("Failed to put");
|
||||
assert!(updated_entry.attrs.get(&Attribute::Description).is_none());
|
||||
assert!(!updated_entry.attrs.contains_key(&Attribute::Description));
|
||||
|
||||
// set one
|
||||
let put = ScimEntryPutKanidm {
|
||||
|
@ -234,7 +234,7 @@ mod tests {
|
|||
value: "extra_1@example.com".to_string(),
|
||||
}));
|
||||
}
|
||||
_ => assert!(false),
|
||||
_ => unreachable!("Expected 1 member"),
|
||||
};
|
||||
|
||||
// set many
|
||||
|
@ -285,7 +285,7 @@ mod tests {
|
|||
value: "extra_3@example.com".to_string(),
|
||||
}));
|
||||
}
|
||||
_ => assert!(false),
|
||||
_ => unreachable!("Expected 3 members"),
|
||||
};
|
||||
|
||||
// set many with a removal
|
||||
|
@ -333,7 +333,7 @@ mod tests {
|
|||
value: "extra_2@example.com".to_string(),
|
||||
}));
|
||||
}
|
||||
_ => assert!(false),
|
||||
_ => unreachable!("Expected 2 members"),
|
||||
};
|
||||
|
||||
// empty set removes attr
|
||||
|
@ -348,6 +348,6 @@ mod tests {
|
|||
.expect("Failed to resolve data type");
|
||||
|
||||
let updated_entry = server_txn.scim_put(put_event).expect("Failed to put");
|
||||
assert!(updated_entry.attrs.get(&Attribute::Member).is_none());
|
||||
assert!(!updated_entry.attrs.contains_key(&Attribute::Member));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,19 @@ use crate::schema::Schema;
|
|||
|
||||
pub struct TestConfiguration {
|
||||
pub domain_level: DomainVersion,
|
||||
// This is literally here to make clippy happy, just leave it alone!
|
||||
// if you don't believe me then remove it and run 'cargo clippy --all-targets' it'll complain
|
||||
// about "struct update has no effect, all the fields in the struct have already been specified"
|
||||
// because the domain_level was set, then we ..Default::default() the "rest"
|
||||
#[allow(dead_code)]
|
||||
pub ignore_this_field: bool,
|
||||
}
|
||||
|
||||
impl Default for TestConfiguration {
|
||||
fn default() -> Self {
|
||||
TestConfiguration {
|
||||
domain_level: DOMAIN_TGT_LEVEL,
|
||||
ignore_this_field: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
use crate::prelude::*;
|
||||
use hashbrown::HashSet;
|
||||
use rand::distributions::{Distribution, Uniform};
|
||||
use rand::{thread_rng, Rng};
|
||||
use rand::distr::{Distribution, Uniform};
|
||||
use rand::{rng, Rng};
|
||||
use std::ops::Range;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -35,7 +35,7 @@ pub fn uuid_from_duration(d: Duration, sid: Sid) -> Uuid {
|
|||
}
|
||||
|
||||
pub(crate) fn password_from_random_len(len: u32) -> String {
|
||||
thread_rng()
|
||||
rng()
|
||||
.sample_iter(&DistinctAlpha)
|
||||
.take(len as usize)
|
||||
.collect::<String>()
|
||||
|
@ -52,7 +52,7 @@ pub fn backup_code_from_random() -> HashSet<String> {
|
|||
pub fn readable_password_from_random() -> String {
|
||||
// 2^112 bits, means we need at least 55^20 to have as many bits of entropy.
|
||||
// this leads us to 4 groups of 5 to create 55^20
|
||||
let mut trng = thread_rng();
|
||||
let mut trng = rng();
|
||||
format!(
|
||||
"{}-{}-{}-{}",
|
||||
(&mut trng)
|
||||
|
@ -80,8 +80,9 @@ impl Distribution<char> for DistinctAlpha {
|
|||
const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHJKLMNPQRSTUVWXYZ\
|
||||
abcdefghjkpqrstuvwxyz\
|
||||
0123456789";
|
||||
|
||||
let range = Uniform::new(0, RANGE);
|
||||
// TODO: this needs to handle the error, maybe?
|
||||
#[allow(clippy::expect_used)]
|
||||
let range = Uniform::new(0, RANGE).expect("Failed to get a uniform range");
|
||||
|
||||
let n = range.sample(rng);
|
||||
GEN_ASCII_STR_CHARSET[n as usize] as char
|
||||
|
|
|
@ -683,10 +683,10 @@ mod tests {
|
|||
"value": "claire@example.com"
|
||||
}
|
||||
]"#;
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetEmailAddress>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetEmailAddress>(&vs, &[])
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -711,9 +711,9 @@ mod tests {
|
|||
}
|
||||
]"#;
|
||||
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetAddress>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetAddress>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -381,6 +381,6 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -400,6 +400,6 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,9 +185,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_boolean() {
|
||||
let vs: ValueSet = ValueSetBool::new(true);
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), "true");
|
||||
crate::valueset::scim_json_reflexive(&vs, "true");
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetBool>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetBool>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,6 +352,6 @@ raBy6edj7W0EIH+yQxkDEwIhAI0nVKaI6duHLAvtKW6CfEQFG6jKg7dyk37YYiRD
|
|||
assert_eq!(cert.s256, expect_s256);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetCertificate>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetCertificate>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,6 +193,6 @@ mod tests {
|
|||
let vs: ValueSet = ValueSetCid::new(Cid::new_zero());
|
||||
|
||||
let data = r#""00000000000000000000000000000000-00000000-0000-0000-0000-000000000000""#;
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1183,15 +1183,15 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scim_credential_type() {
|
||||
let vs: ValueSet = ValueSetCredentialType::new(CredentialType::Mfa);
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#""mfa""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""mfa""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetCredentialType>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetCredentialType>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,9 +210,9 @@ mod tests {
|
|||
let odt = OffsetDateTime::UNIX_EPOCH + Duration::from_secs(69_420);
|
||||
let vs: ValueSet = ValueSetDateTime::new(odt);
|
||||
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#""1970-01-01T19:17:00Z""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""1970-01-01T19:17:00Z""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetDateTime>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetDateTime>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,9 +183,6 @@ mod tests {
|
|||
fn test_scim_hexstring() {
|
||||
let vs: ValueSet =
|
||||
ValueSetHexString::new("D68475C760A7A0F6A924C28F095573A967F600D6".to_string());
|
||||
crate::valueset::scim_json_reflexive(
|
||||
vs.clone(),
|
||||
r#""D68475C760A7A0F6A924C28F095573A967F600D6""#,
|
||||
);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""D68475C760A7A0F6A924C28F095573A967F600D6""#);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::io::Cursor;
|
||||
|
||||
use image::codecs::jpeg::JpegDecoder;
|
||||
use image::ImageDecoder;
|
||||
use sketching::*;
|
||||
|
@ -79,9 +81,9 @@ pub fn has_trailer(contents: &Vec<u8>) -> Result<bool, ImageValidationError> {
|
|||
pub fn validate_decoding(
|
||||
filename: &str,
|
||||
contents: &[u8],
|
||||
limits: image::io::Limits,
|
||||
limits: image::Limits,
|
||||
) -> Result<(), ImageValidationError> {
|
||||
let mut decoder = match JpegDecoder::new(contents) {
|
||||
let mut decoder = match JpegDecoder::new(Cursor::new(contents)) {
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
return Err(ImageValidationError::InvalidImage(format!(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![allow(dead_code)]
|
||||
use crate::valueset::ScimResolveStatus;
|
||||
use std::fmt::Display;
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::be::dbvalue::DbValueImage;
|
||||
use crate::prelude::*;
|
||||
|
@ -37,8 +38,8 @@ pub trait ImageValueThings {
|
|||
/// A sha256 of the filename/type/contents
|
||||
fn hash_imagevalue(&self) -> String;
|
||||
|
||||
fn get_limits(&self) -> image::io::Limits {
|
||||
let mut limits = image::io::Limits::default();
|
||||
fn get_limits(&self) -> image::Limits {
|
||||
let mut limits = image::Limits::default();
|
||||
limits.max_image_height = Some(MAX_IMAGE_HEIGHT);
|
||||
limits.max_image_width = Some(MAX_IMAGE_WIDTH);
|
||||
limits
|
||||
|
@ -148,7 +149,7 @@ impl ImageValueThings for ImageValue {
|
|||
|
||||
/// validate the GIF file contents, and that it's actually a GIF
|
||||
fn validate_is_gif(&self) -> Result<(), ImageValidationError> {
|
||||
let Ok(mut decoder) = GifDecoder::new(&self.contents[..]) else {
|
||||
let Ok(mut decoder) = GifDecoder::new(Cursor::new(&self.contents[..])) else {
|
||||
return Err(ImageValidationError::InvalidImage(
|
||||
"Failed to parse GIF".to_string(),
|
||||
));
|
||||
|
@ -189,7 +190,7 @@ impl ImageValueThings for ImageValue {
|
|||
));
|
||||
}
|
||||
|
||||
let Ok(mut decoder) = WebPDecoder::new(&self.contents[..]) else {
|
||||
let Ok(mut decoder) = WebPDecoder::new(Cursor::new(&self.contents[..])) else {
|
||||
return Err(ImageValidationError::InvalidImage(
|
||||
"Failed to parse WebP file".to_string(),
|
||||
));
|
||||
|
@ -532,7 +533,7 @@ mod tests {
|
|||
"142dc7984dd548dd5dacfe2ad30f8473e3217e39b3b6c8d17a0cf6e4e24b02e0"
|
||||
]"#;
|
||||
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -226,9 +226,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_iname() {
|
||||
let vs: ValueSet = ValueSetIname::new("stevo");
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#""stevo""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""stevo""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetIname>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetIname>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,9 +183,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_index() {
|
||||
let vs: ValueSet = ValueSetIndex::new(IndexType::Equality);
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#"["EQUALITY"]"#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#"["EQUALITY"]"#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetIndex>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetIndex>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,9 +227,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_iutf8() {
|
||||
let vs: ValueSet = ValueSetIutf8::new("lowercase string");
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#""lowercase string""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""lowercase string""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetIutf8>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetIutf8>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,9 +205,9 @@ mod tests {
|
|||
"{\"pres\":\"class\"}"
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
// crate::valueset::scim_json_put_reflexive::<ValueSetJsonFilter>(vs, &[])
|
||||
// crate::valueset::scim_json_put_reflexive::<ValueSetJsonFilter>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -649,6 +649,6 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -995,7 +995,7 @@ pub fn from_db_valueset_v2(dbvs: DbValueSetV2) -> Result<ValueSet, OperationErro
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn scim_json_reflexive(vs: ValueSet, data: &str) {
|
||||
pub(crate) fn scim_json_reflexive(vs: &ValueSet, data: &str) {
|
||||
let scim_value = vs.to_scim_value().unwrap().assume_resolved();
|
||||
|
||||
let strout = serde_json::to_string_pretty(&scim_value).unwrap();
|
||||
|
@ -1012,25 +1012,27 @@ pub(crate) fn scim_json_reflexive(vs: ValueSet, data: &str) {
|
|||
#[cfg(test)]
|
||||
pub(crate) fn scim_json_reflexive_unresolved(
|
||||
write_txn: &mut QueryServerWriteTransaction,
|
||||
vs: ValueSet,
|
||||
vs: &ValueSet,
|
||||
data: &str,
|
||||
) {
|
||||
let scim_int_value = vs.to_scim_value().unwrap().assume_unresolved();
|
||||
let scim_value = write_txn.resolve_scim_interim(scim_int_value).unwrap();
|
||||
|
||||
let strout = serde_json::to_string_pretty(&scim_value).unwrap();
|
||||
let strout = serde_json::to_string_pretty(&scim_value).expect("Failed to serialize");
|
||||
eprintln!("{}", strout);
|
||||
|
||||
let json_value: serde_json::Value = serde_json::to_value(&scim_value).unwrap();
|
||||
let json_value: serde_json::Value =
|
||||
serde_json::to_value(&scim_value).expect("Failed to convert to JSON");
|
||||
|
||||
let expect: serde_json::Value = serde_json::from_str(data).unwrap();
|
||||
let expect: serde_json::Value =
|
||||
serde_json::from_str(data).expect("Failed to parse expected JSON");
|
||||
|
||||
assert_eq!(json_value, expect);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn scim_json_put_reflexive<T: ValueSetScimPut>(
|
||||
expect_vs: ValueSet,
|
||||
expect_vs: &ValueSet,
|
||||
additional_tests: &[(JsonValue, ValueSet)],
|
||||
) {
|
||||
let scim_value = expect_vs.to_scim_value().unwrap().assume_resolved();
|
||||
|
@ -1041,7 +1043,7 @@ pub(crate) fn scim_json_put_reflexive<T: ValueSetScimPut>(
|
|||
let generic = serde_json::to_value(scim_value).unwrap();
|
||||
// Check that we can turn back into a vs from the generic version.
|
||||
let vs = T::from_scim_json_put(generic).unwrap().assume_resolved();
|
||||
assert_eq!(&vs, &expect_vs);
|
||||
assert_eq!(&vs, expect_vs);
|
||||
|
||||
// For each additional check, assert they work as expected.
|
||||
for (jv, expect_vs) in additional_tests {
|
||||
|
@ -1053,7 +1055,7 @@ pub(crate) fn scim_json_put_reflexive<T: ValueSetScimPut>(
|
|||
#[cfg(test)]
|
||||
pub(crate) fn scim_json_put_reflexive_unresolved<T: ValueSetScimPut>(
|
||||
write_txn: &mut QueryServerWriteTransaction,
|
||||
expect_vs: ValueSet,
|
||||
expect_vs: &ValueSet,
|
||||
additional_tests: &[(JsonValue, ValueSet)],
|
||||
) {
|
||||
let scim_int_value = expect_vs.to_scim_value().unwrap().assume_unresolved();
|
||||
|
@ -1063,7 +1065,7 @@ pub(crate) fn scim_json_put_reflexive_unresolved<T: ValueSetScimPut>(
|
|||
// Check that we can turn back into a vs from the generic version.
|
||||
let vs_inter = T::from_scim_json_put(generic).unwrap().assume_unresolved();
|
||||
let vs = write_txn.resolve_valueset_intermediate(vs_inter).unwrap();
|
||||
assert_eq!(&vs, &expect_vs);
|
||||
assert_eq!(&vs, expect_vs);
|
||||
|
||||
// For each additional check, assert they work as expected.
|
||||
for (jv, expect_vs) in additional_tests {
|
||||
|
|
|
@ -189,12 +189,9 @@ mod tests {
|
|||
fn test_scim_nsuniqueid() {
|
||||
let vs: ValueSet =
|
||||
ValueSetNsUniqueId::new("3a163ca0-47624620-a18806b7-50c84c86".to_string());
|
||||
crate::valueset::scim_json_reflexive(
|
||||
vs.clone(),
|
||||
r#""3a163ca0-47624620-a18806b7-50c84c86""#,
|
||||
);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""3a163ca0-47624620-a18806b7-50c84c86""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetNsUniqueId>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetNsUniqueId>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -898,10 +898,10 @@ mod tests {
|
|||
fn test_scim_oauth2_scope() {
|
||||
let vs: ValueSet = ValueSetOauthScope::new("fully_sick_scope_m8".to_string());
|
||||
let data = r#"["fully_sick_scope_m8"]"#;
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetOauthScope>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetOauthScope>(&vs, &[])
|
||||
}
|
||||
|
||||
#[qs_test]
|
||||
|
@ -930,12 +930,12 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive_unresolved(&mut write_txn, vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive_unresolved(&mut write_txn, &vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive_unresolved::<ValueSetOauthScopeMap>(
|
||||
&mut write_txn,
|
||||
vs,
|
||||
&vs,
|
||||
&[],
|
||||
);
|
||||
|
||||
|
@ -970,12 +970,12 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive_unresolved(&mut write_txn, vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive_unresolved(&mut write_txn, &vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive_unresolved::<ValueSetOauthClaimMap>(
|
||||
&mut write_txn,
|
||||
vs,
|
||||
&vs,
|
||||
&[],
|
||||
);
|
||||
|
||||
|
|
|
@ -205,6 +205,6 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_restricted() {
|
||||
let vs: ValueSet = ValueSetRestricted::new("Test".to_string());
|
||||
crate::valueset::scim_json_reflexive(vs, r#""Test""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""Test""#);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1920,7 +1920,7 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1948,6 +1948,6 @@ mod tests {
|
|||
]
|
||||
"#;
|
||||
|
||||
crate::valueset::scim_json_reflexive(vs, data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,6 +188,6 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_spn() {
|
||||
let vs: ValueSet = ValueSetSpn::new(("claire".to_string(), "example.com".to_string()));
|
||||
crate::valueset::scim_json_reflexive(vs, r#""claire@example.com""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""claire@example.com""#);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -247,9 +247,9 @@ mod tests {
|
|||
}
|
||||
]
|
||||
"#;
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetSshKey>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetSshKey>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,9 +188,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_syntax() {
|
||||
let vs: ValueSet = ValueSetSyntax::new(SyntaxType::Uuid);
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#""UUID""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""UUID""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetSyntax>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetSyntax>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,9 +163,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_uihint() {
|
||||
let vs: ValueSet = ValueSetUiHint::new(UiHint::PosixAccount);
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#"["posixaccount"]"#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#"["posixaccount"]"#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUiHint>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUiHint>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,9 +196,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_scim_uint32() {
|
||||
let vs: ValueSet = ValueSetUint32::new(69);
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), "69");
|
||||
crate::valueset::scim_json_reflexive(&vs, "69");
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUint32>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUint32>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,9 +183,9 @@ mod tests {
|
|||
fn test_scim_url() {
|
||||
let u = Url::parse("https://idm.example.com").unwrap();
|
||||
let vs: ValueSet = ValueSetUrl::new(u);
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#""https://idm.example.com/""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""https://idm.example.com/""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUrl>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUrl>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -246,9 +246,9 @@ mod tests {
|
|||
fn test_scim_utf8() {
|
||||
let vs: ValueSet = ValueSetUtf8::new("Test".to_string());
|
||||
// Test that the output json matches some known str
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), r#""Test""#);
|
||||
crate::valueset::scim_json_reflexive(&vs, r#""Test""#);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUtf8>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUtf8>(&vs, &[])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -422,10 +422,10 @@ mod tests {
|
|||
|
||||
let data = r#""4d21d04a-dc0e-42eb-b850-34dd180b107f""#;
|
||||
|
||||
crate::valueset::scim_json_reflexive(vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive(&vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUuid>(vs, &[])
|
||||
crate::valueset::scim_json_put_reflexive::<ValueSetUuid>(&vs, &[])
|
||||
}
|
||||
|
||||
#[qs_test]
|
||||
|
@ -449,12 +449,12 @@ mod tests {
|
|||
|
||||
let data = r#"[{"uuid": "4d21d04a-dc0e-42eb-b850-34dd180b107f", "value": "testperson1@example.com"}]"#;
|
||||
|
||||
crate::valueset::scim_json_reflexive_unresolved(&mut write_txn, vs.clone(), data);
|
||||
crate::valueset::scim_json_reflexive_unresolved(&mut write_txn, &vs, data);
|
||||
|
||||
// Test that we can parse json values into a valueset.
|
||||
crate::valueset::scim_json_put_reflexive_unresolved::<ValueSetRefer>(
|
||||
&mut write_txn,
|
||||
vs,
|
||||
&vs,
|
||||
&[],
|
||||
);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ pub fn cli_kanidm(_input: TokenStream) -> TokenStream {
|
|||
.run()
|
||||
.unwrap();
|
||||
let mut kanidm = kanidm.command();
|
||||
kanidm.env("KANIDM_URL", &rsclient.get_url().to_string());
|
||||
kanidm.env("KANIDM_URL", rsclient.get_url().to_string());
|
||||
kanidm.env("KANIDM_TOKEN_CACHE_PATH", &token_cache_path);
|
||||
kanidm
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ async fn test_v1_group_id_patch(rsclient: &KanidmClient) {
|
|||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
create_user(&rsclient, "foo", "foogroup").await;
|
||||
create_user(rsclient, "foo", "foogroup").await;
|
||||
|
||||
let post_body = serde_json::json!({"attrs": { ATTR_DESCRIPTION : ["Fancy group change"]}});
|
||||
|
||||
|
@ -31,7 +31,7 @@ async fn test_v1_group_id_attr_post(rsclient: &KanidmClient) {
|
|||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
create_user(&rsclient, "foo", "foogroup").await;
|
||||
create_user(rsclient, "foo", "foogroup").await;
|
||||
|
||||
let post_body = serde_json::json!(["foo"]);
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ static USER_B_NAME: &str = "valid_user_b";
|
|||
#[kanidmd_testkit::test]
|
||||
async fn test_not_authenticated(rsclient: &KanidmClient) {
|
||||
// basically here we try a bit of all the possible combinations while unauthenticated to check it's not working
|
||||
setup_server(&rsclient).await;
|
||||
create_user(&rsclient, USER_A_NAME).await;
|
||||
setup_server(rsclient).await;
|
||||
create_user(rsclient, USER_A_NAME).await;
|
||||
let _ = rsclient.logout().await;
|
||||
let res = rsclient
|
||||
.idm_person_identify_user(USER_A_NAME, IdentifyUserRequest::Start)
|
||||
|
@ -47,11 +47,11 @@ async fn test_not_authenticated(rsclient: &KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_non_existing_user_id(rsclient: &KanidmClient) {
|
||||
setup_server(&rsclient).await;
|
||||
create_user(&rsclient, USER_A_NAME).await;
|
||||
create_user(&rsclient, USER_B_NAME).await;
|
||||
setup_server(rsclient).await;
|
||||
create_user(rsclient, USER_A_NAME).await;
|
||||
create_user(rsclient, USER_B_NAME).await;
|
||||
let non_existing_user = "non_existing_user";
|
||||
login_with_user(&rsclient, USER_A_NAME).await;
|
||||
login_with_user(rsclient, USER_A_NAME).await;
|
||||
let res: Result<IdentifyUserResponse, kanidm_client::ClientError> = rsclient
|
||||
.idm_person_identify_user(non_existing_user, IdentifyUserRequest::Start)
|
||||
.await;
|
||||
|
@ -87,9 +87,9 @@ async fn test_non_existing_user_id(rsclient: &KanidmClient) {
|
|||
// Each tests is named like `test_{api input}_response_{expected api output}_or_{expected api output}`
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_start_response_identity_verification_available(rsclient: &KanidmClient) {
|
||||
setup_server(&rsclient).await;
|
||||
create_user(&rsclient, USER_A_NAME).await;
|
||||
login_with_user(&rsclient, USER_A_NAME).await;
|
||||
setup_server(rsclient).await;
|
||||
create_user(rsclient, USER_A_NAME).await;
|
||||
login_with_user(rsclient, USER_A_NAME).await;
|
||||
|
||||
let response = rsclient
|
||||
.idm_person_identify_user(USER_A_NAME, IdentifyUserRequest::Start)
|
||||
|
@ -106,10 +106,10 @@ async fn test_start_response_identity_verification_available(rsclient: &KanidmCl
|
|||
// `Start`, that is WaitForCode or ProvideCode
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_start_response_wait_for_code_or_provide_code(rsclient: &KanidmClient) {
|
||||
setup_server(&rsclient).await;
|
||||
let user_a_uuid = create_user(&rsclient, USER_A_NAME).await;
|
||||
let user_b_uuid = create_user(&rsclient, USER_B_NAME).await;
|
||||
login_with_user(&rsclient, USER_A_NAME).await;
|
||||
setup_server(rsclient).await;
|
||||
let user_a_uuid = create_user(rsclient, USER_A_NAME).await;
|
||||
let user_b_uuid = create_user(rsclient, USER_B_NAME).await;
|
||||
login_with_user(rsclient, USER_A_NAME).await;
|
||||
let response = rsclient
|
||||
.idm_person_identify_user(USER_B_NAME, IdentifyUserRequest::Start)
|
||||
.await;
|
||||
|
@ -130,10 +130,10 @@ async fn test_start_response_wait_for_code_or_provide_code(rsclient: &KanidmClie
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_provide_code_response_code_failure_or_provide_code(rsclient: &KanidmClient) {
|
||||
setup_server(&rsclient).await;
|
||||
let user_a_uuid = create_user(&rsclient, USER_A_NAME).await;
|
||||
let user_b_uuid = create_user(&rsclient, USER_B_NAME).await;
|
||||
login_with_user(&rsclient, USER_A_NAME).await;
|
||||
setup_server(rsclient).await;
|
||||
let user_a_uuid = create_user(rsclient, USER_A_NAME).await;
|
||||
let user_b_uuid = create_user(rsclient, USER_B_NAME).await;
|
||||
login_with_user(rsclient, USER_A_NAME).await;
|
||||
let response = rsclient
|
||||
.idm_person_identify_user(
|
||||
USER_B_NAME,
|
||||
|
@ -158,12 +158,12 @@ async fn test_provide_code_response_code_failure_or_provide_code(rsclient: &Kani
|
|||
// here we actually test the full idm flow by duplicating the server
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_full_identification_flow(rsclient: &KanidmClient) {
|
||||
setup_server(&rsclient).await;
|
||||
let user_a_uuid = create_user(&rsclient, USER_A_NAME).await;
|
||||
let user_b_uuid = create_user(&rsclient, USER_B_NAME).await;
|
||||
setup_server(rsclient).await;
|
||||
let user_a_uuid = create_user(rsclient, USER_A_NAME).await;
|
||||
let user_b_uuid = create_user(rsclient, USER_B_NAME).await;
|
||||
//user A session
|
||||
let valid_user_a_client = rsclient;
|
||||
login_with_user(&valid_user_a_client, USER_A_NAME).await;
|
||||
login_with_user(valid_user_a_client, USER_A_NAME).await;
|
||||
//user B session
|
||||
let valid_user_b_client = valid_user_a_client.new_session().unwrap();
|
||||
login_with_user(&valid_user_b_client, USER_B_NAME).await;
|
||||
|
|
|
@ -76,10 +76,10 @@ async fn test_webdriver_user_login(rsclient: &KanidmClient) {
|
|||
use fantoccini::Locator;
|
||||
use kanidmd_testkit::*;
|
||||
use std::time::Duration;
|
||||
login_put_admin_idm_admins(&rsclient).await;
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
|
||||
create_user_with_all_attrs(
|
||||
&rsclient,
|
||||
rsclient,
|
||||
NOT_ADMIN_TEST_USERNAME,
|
||||
Some(NOT_ADMIN_TEST_PASSWORD),
|
||||
)
|
||||
|
@ -89,7 +89,7 @@ async fn test_webdriver_user_login(rsclient: &KanidmClient) {
|
|||
|
||||
handle_error!(
|
||||
c,
|
||||
c.goto(&rsclient.get_url().to_string()).await,
|
||||
c.goto(rsclient.get_url().to_string()).await,
|
||||
"Couldn't get URL"
|
||||
);
|
||||
|
||||
|
@ -207,7 +207,7 @@ async fn test_webdriver_user_login(rsclient: &KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_domain_reset_token_key(rsclient: &KanidmClient) {
|
||||
login_put_admin_idm_admins(&rsclient).await;
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
|
||||
let token = rsclient.get_token().await.expect("No bearer token present");
|
||||
|
||||
|
@ -220,7 +220,7 @@ async fn test_domain_reset_token_key(rsclient: &KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_idm_domain_set_ldap_basedn(rsclient: &KanidmClient) {
|
||||
login_put_admin_idm_admins(&rsclient).await;
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
assert!(rsclient
|
||||
.idm_domain_set_ldap_basedn("dc=krabsarekool,dc=example,dc=com")
|
||||
.await
|
||||
|
@ -233,7 +233,7 @@ async fn test_idm_domain_set_ldap_basedn(rsclient: &KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_idm_domain_set_ldap_max_queryable_attrs(rsclient: &KanidmClient) {
|
||||
login_put_admin_idm_admins(&rsclient).await;
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
assert!(rsclient
|
||||
.idm_domain_set_ldap_max_queryable_attrs(20)
|
||||
.await
|
||||
|
@ -247,7 +247,7 @@ async fn test_idm_domain_set_ldap_max_queryable_attrs(rsclient: &KanidmClient) {
|
|||
#[kanidmd_testkit::test]
|
||||
/// Checks that a built-in group idm_all_persons has the "builtin" class as expected.
|
||||
async fn test_all_persons_has_builtin_class(rsclient: &KanidmClient) {
|
||||
login_put_admin_idm_admins(&rsclient).await;
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
let res = rsclient
|
||||
.idm_group_get("idm_all_persons")
|
||||
.await
|
||||
|
@ -306,7 +306,7 @@ async fn test_all_persons_has_builtin_class(rsclient: &KanidmClient) {
|
|||
/// Testing the CLI doing things.
|
||||
async fn test_integration_with_assert_cmd(rsclient: KanidmClient) {
|
||||
// setup the admin things
|
||||
login_put_admin_idm_admins(&rsclient).await;
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
|
||||
rsclient
|
||||
.idm_person_account_primary_credential_set_password(
|
||||
|
@ -334,13 +334,13 @@ async fn test_integration_with_assert_cmd(rsclient: KanidmClient) {
|
|||
assert!(anon_whoami.status.success());
|
||||
println!("Output: {:?}", anon_whoami);
|
||||
|
||||
test_cmd_admin(&token_cache_path, &rsclient, "login -D admin");
|
||||
test_cmd_admin(&token_cache_path, rsclient, "login -D admin");
|
||||
|
||||
// login as idm_admin
|
||||
test_cmd_idm_admin(&token_cache_path, &rsclient, "login -D idm_admin");
|
||||
test_cmd_idm_admin(&token_cache_path, rsclient, "login -D idm_admin");
|
||||
test_cmd_admin_split(
|
||||
&token_cache_path,
|
||||
&rsclient,
|
||||
rsclient,
|
||||
&[
|
||||
"service-account",
|
||||
"create",
|
||||
|
@ -355,13 +355,13 @@ async fn test_integration_with_assert_cmd(rsclient: KanidmClient) {
|
|||
|
||||
test_cmd_admin(
|
||||
&token_cache_path,
|
||||
&rsclient,
|
||||
rsclient,
|
||||
&format!("service-account get -D admin {}", NOT_ADMIN_TEST_USERNAME),
|
||||
);
|
||||
// updating the display name
|
||||
test_cmd_admin(
|
||||
&token_cache_path,
|
||||
&rsclient,
|
||||
rsclient,
|
||||
&format!(
|
||||
"service-account update -D admin {} --displayname cheeseballs",
|
||||
NOT_ADMIN_TEST_USERNAME
|
||||
|
@ -370,7 +370,7 @@ async fn test_integration_with_assert_cmd(rsclient: KanidmClient) {
|
|||
// updating the email
|
||||
test_cmd_admin(
|
||||
&token_cache_path,
|
||||
&rsclient,
|
||||
rsclient,
|
||||
&format!(
|
||||
"service-account update -D admin {} --mail foo@bar.com",
|
||||
NOT_ADMIN_TEST_USERNAME
|
||||
|
@ -380,7 +380,7 @@ async fn test_integration_with_assert_cmd(rsclient: KanidmClient) {
|
|||
// checking the email was changed
|
||||
let sad = test_cmd_admin(
|
||||
&token_cache_path,
|
||||
&rsclient,
|
||||
rsclient,
|
||||
&format!(
|
||||
"service-account get -D admin -o json {}",
|
||||
NOT_ADMIN_TEST_USERNAME
|
||||
|
|
|
@ -10,7 +10,7 @@ async fn test_v1_person_id_patch(rsclient: &KanidmClient) {
|
|||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
create_user(&rsclient, "foo", "foogroup").await;
|
||||
create_user(rsclient, "foo", "foogroup").await;
|
||||
|
||||
let post_body = serde_json::json!({"attrs": { ATTR_MAIL : ["crab@example.com"]}});
|
||||
|
||||
|
@ -31,7 +31,7 @@ async fn test_v1_person_id_ssh_pubkeys_post(rsclient: &KanidmClient) {
|
|||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
create_user(&rsclient, "foo", "foogroup").await;
|
||||
create_user(rsclient, "foo", "foogroup").await;
|
||||
|
||||
let post_body = serde_json::json!([
|
||||
"ssh-key-tag-goes-here",
|
||||
|
|
|
@ -1366,7 +1366,7 @@ async fn setup_demo_account_password(
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_server_credential_update_session_passkey(rsclient: &KanidmClient) {
|
||||
let mut wa = setup_demo_account_passkey(&rsclient).await;
|
||||
let mut wa = setup_demo_account_passkey(rsclient).await;
|
||||
|
||||
let res = rsclient
|
||||
.auth_passkey_begin("demo_account")
|
||||
|
@ -1690,7 +1690,7 @@ async fn test_server_user_auth_token_lifecycle(rsclient: &KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_server_user_auth_reauthentication(rsclient: &KanidmClient) {
|
||||
let mut wa = setup_demo_account_passkey(&rsclient).await;
|
||||
let mut wa = setup_demo_account_passkey(rsclient).await;
|
||||
|
||||
let res = rsclient
|
||||
.auth_passkey_begin("demo_account")
|
||||
|
@ -1869,12 +1869,12 @@ async fn start_password_session(
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_server_user_auth_unprivileged(rsclient: &KanidmClient) {
|
||||
let (account_name, account_pass) = setup_demo_account_password(&rsclient)
|
||||
let (account_name, account_pass) = setup_demo_account_password(rsclient)
|
||||
.await
|
||||
.expect("Failed to setup demo_account");
|
||||
|
||||
let uat = start_password_session(
|
||||
&rsclient,
|
||||
rsclient,
|
||||
account_name.as_str(),
|
||||
account_pass.as_str(),
|
||||
false,
|
||||
|
@ -1892,18 +1892,13 @@ async fn test_server_user_auth_unprivileged(rsclient: &KanidmClient) {
|
|||
|
||||
#[kanidmd_testkit::test]
|
||||
async fn test_server_user_auth_privileged_shortcut(rsclient: &KanidmClient) {
|
||||
let (account_name, account_pass) = setup_demo_account_password(&rsclient)
|
||||
let (account_name, account_pass) = setup_demo_account_password(rsclient)
|
||||
.await
|
||||
.expect("Failed to setup demo_account");
|
||||
|
||||
let uat = start_password_session(
|
||||
&rsclient,
|
||||
account_name.as_str(),
|
||||
account_pass.as_str(),
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.expect("Failed to start session");
|
||||
let uat = start_password_session(rsclient, account_name.as_str(), account_pass.as_str(), true)
|
||||
.await
|
||||
.expect("Failed to start session");
|
||||
|
||||
match uat.purpose {
|
||||
UatPurpose::ReadOnly => panic!("Unexpected uat purpose"),
|
||||
|
|
|
@ -6,10 +6,10 @@ use kanidmd_testkit::*;
|
|||
async fn account_id_unix_token(rsclient: &KanidmClient) {
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
|
||||
create_user(&rsclient, "group_manager", "idm_group_manage_priv").await;
|
||||
create_user(rsclient, "group_manager", "idm_group_manage_priv").await;
|
||||
// create test user without creating new groups
|
||||
create_user(&rsclient, NOT_ADMIN_TEST_USERNAME, NAME_IDM_ADMINS).await;
|
||||
login_account(&rsclient, "group_manager").await;
|
||||
create_user(rsclient, NOT_ADMIN_TEST_USERNAME, NAME_IDM_ADMINS).await;
|
||||
login_account(rsclient, "group_manager").await;
|
||||
|
||||
let response = rsclient
|
||||
.idm_account_unix_token_get(NOT_ADMIN_TEST_USERNAME)
|
||||
|
@ -32,7 +32,7 @@ async fn account_id_unix_token(rsclient: &KanidmClient) {
|
|||
assert!(format!("{:?}", val).contains("400"));
|
||||
}
|
||||
|
||||
login_put_admin_idm_admins(&rsclient).await;
|
||||
login_put_admin_idm_admins(rsclient).await;
|
||||
|
||||
rsclient
|
||||
.idm_person_account_unix_extend(NOT_ADMIN_TEST_USERNAME, None, None)
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::{handle_client_error, PwBadlistOpt};
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use tokio::task;
|
||||
use zxcvbn::Score;
|
||||
|
||||
const CHUNK_SIZE: usize = 1000;
|
||||
|
||||
|
@ -67,10 +68,6 @@ impl PwBadlistOpt {
|
|||
info!("Have {} unique passwords to process", pwset.len());
|
||||
|
||||
// Break the list into chunks per thread availability
|
||||
// let par_count = thread::available_parallelism()
|
||||
// .expect("Failed to determine available parallelism")
|
||||
// .get();
|
||||
|
||||
let task_handles: Vec<_> = pwset
|
||||
.chunks(CHUNK_SIZE)
|
||||
.map(|chunk| chunk.to_vec())
|
||||
|
@ -82,18 +79,7 @@ impl PwBadlistOpt {
|
|||
if v.len() < 10 {
|
||||
return false;
|
||||
}
|
||||
match zxcvbn::zxcvbn(v.as_str(), &[]) {
|
||||
Ok(r) => r.score() >= 4,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"zxcvbn unable to process '{}' - {:?}",
|
||||
v.as_str(),
|
||||
e
|
||||
);
|
||||
error!("adding to badlist anyway ...");
|
||||
true
|
||||
}
|
||||
}
|
||||
zxcvbn::zxcvbn(v.as_str(), &[]).score() >= Score::Four
|
||||
})
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
|
|
|
@ -8,4 +8,6 @@ pub enum Error {
|
|||
Interrupt,
|
||||
Crossbeam,
|
||||
InvalidState,
|
||||
#[allow(dead_code)]
|
||||
RandomNumber(String),
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@ use crate::model::ActorRole;
|
|||
use crate::profile::Profile;
|
||||
use crate::state::{Credential, Flag, Group, GroupName, Person, PreflightState, State};
|
||||
use hashbrown::HashMap;
|
||||
use rand::distributions::{Alphanumeric, DistString, Uniform};
|
||||
use rand::seq::{index, SliceRandom};
|
||||
use rand::distr::{Alphanumeric, SampleString, Uniform};
|
||||
use rand::seq::{index, IndexedRandom};
|
||||
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
|
@ -171,7 +172,8 @@ pub async fn populate(_client: &KanidmOrcaClient, profile: Profile) -> Result<St
|
|||
let baseline = persons.len() / 3;
|
||||
let inverse = persons.len() - baseline;
|
||||
// Randomly add extra from the inverse
|
||||
let extra = Uniform::new(0, inverse);
|
||||
let extra =
|
||||
Uniform::new(0, inverse).map_err(|err| Error::RandomNumber(err.to_string()))?;
|
||||
baseline + seeded_rng.sample(extra)
|
||||
}
|
||||
};
|
||||
|
|
|
@ -27,7 +27,7 @@ impl ActorBasic {
|
|||
pub fn new(mut cha_rng: ChaCha8Rng, warmup_time_ms: u64) -> Self {
|
||||
let max_backoff_time_in_ms = 2 * warmup_time_ms / 3;
|
||||
let randomised_backoff_time =
|
||||
Duration::from_millis(cha_rng.gen_range(0..max_backoff_time_in_ms));
|
||||
Duration::from_millis(cha_rng.random_range(0..max_backoff_time_in_ms));
|
||||
ActorBasic {
|
||||
state: State::Unauthenticated,
|
||||
randomised_backoff_time,
|
||||
|
|
|
@ -76,7 +76,7 @@ impl ActorLatencyMeasurer {
|
|||
|
||||
let max_backoff_time_in_ms = 2 * warmup_time_ms / 3;
|
||||
let randomised_backoff_time =
|
||||
Duration::from_millis(cha_rng.gen_range(0..max_backoff_time_in_ms));
|
||||
Duration::from_millis(cha_rng.random_range(0..max_backoff_time_in_ms));
|
||||
Ok(ActorLatencyMeasurer {
|
||||
state: State::Unauthenticated,
|
||||
randomised_backoff_time,
|
||||
|
|
|
@ -25,7 +25,7 @@ impl ActorReader {
|
|||
pub fn new(mut cha_rng: ChaCha8Rng, warmup_time_ms: u64) -> Self {
|
||||
let max_backoff_time_in_ms = warmup_time_ms - 1000;
|
||||
let randomised_backoff_time =
|
||||
Duration::from_millis(cha_rng.gen_range(0..max_backoff_time_in_ms));
|
||||
Duration::from_millis(cha_rng.random_range(0..max_backoff_time_in_ms));
|
||||
ActorReader {
|
||||
state: State::Unauthenticated,
|
||||
randomised_backoff_time,
|
||||
|
|
|
@ -26,7 +26,7 @@ impl ActorWriter {
|
|||
pub fn new(mut cha_rng: ChaCha8Rng, warmup_time_ms: u64) -> Self {
|
||||
let max_backoff_time_in_ms = 2 * warmup_time_ms / 3;
|
||||
let randomised_backoff_time =
|
||||
Duration::from_millis(cha_rng.gen_range(0..max_backoff_time_in_ms));
|
||||
Duration::from_millis(cha_rng.random_range(0..max_backoff_time_in_ms));
|
||||
ActorWriter {
|
||||
state: State::Unauthenticated,
|
||||
randomised_backoff_time,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::error::Error;
|
||||
use crate::state::{GroupName, Model};
|
||||
use rand::{thread_rng, Rng};
|
||||
use rand::{rng, Rng};
|
||||
use serde::de::{value, IntoDeserializer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -200,8 +200,8 @@ impl ProfileBuilder {
|
|||
} = self;
|
||||
|
||||
let seed: u64 = seed.unwrap_or_else(|| {
|
||||
let mut rng = thread_rng();
|
||||
rng.gen()
|
||||
let mut rng = rng();
|
||||
rng.random()
|
||||
});
|
||||
|
||||
//TODO: Allow to specify group properties from the CLI
|
||||
|
|
|
@ -187,7 +187,7 @@ pub async fn execute(state: State, control_rx: broadcast::Receiver<Signal>) -> R
|
|||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let main_client_index = seeded_rng.gen_range(0..cloned_clients.len());
|
||||
let main_client_index = seeded_rng.random_range(0..cloned_clients.len());
|
||||
let main_client = cloned_clients.remove(main_client_index);
|
||||
//note that cloned_clients now contains all other clients except the first one
|
||||
|
||||
|
|
|
@ -694,7 +694,7 @@ mod tests {
|
|||
|
||||
for file in PathBuf::from(&examples_dir)
|
||||
.canonicalize()
|
||||
.expect(&format!("Can't find examples dir at {}", examples_dir))
|
||||
.unwrap_or_else(|_| panic!("Can't find examples dir at {}", examples_dir))
|
||||
.read_dir()
|
||||
.expect("Can't read examples dir!")
|
||||
{
|
||||
|
|
|
@ -71,32 +71,32 @@ impl RequestOptions {
|
|||
fn nss_fallback_unavail() {
|
||||
let req_opt = RequestOptions::fallback_unavail();
|
||||
let Response::Unavail = core::get_all_user_entries(req_opt) else {
|
||||
unreachable!();
|
||||
panic!("unrecoverable");
|
||||
};
|
||||
|
||||
let req_opt = RequestOptions::fallback_unavail();
|
||||
let Response::Unavail = core::get_user_entry_by_uid(0, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("unrecoverable");
|
||||
};
|
||||
|
||||
let req_opt = RequestOptions::fallback_unavail();
|
||||
let Response::Unavail = core::get_user_entry_by_name("root".to_string(), req_opt) else {
|
||||
unreachable!();
|
||||
panic!("unrecoverable");
|
||||
};
|
||||
|
||||
let req_opt = RequestOptions::fallback_unavail();
|
||||
let Response::Unavail = core::get_all_group_entries(req_opt) else {
|
||||
unreachable!();
|
||||
panic!("unrecoverable");
|
||||
};
|
||||
|
||||
let req_opt = RequestOptions::fallback_unavail();
|
||||
let Response::Unavail = core::get_group_entry_by_gid(0, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("unrecoverable");
|
||||
};
|
||||
|
||||
let req_opt = RequestOptions::fallback_unavail();
|
||||
let Response::Unavail = core::get_group_entry_by_name("root".to_string(), req_opt) else {
|
||||
unreachable!();
|
||||
panic!("unrecoverable");
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ fn nss_fallback_all_user_entries() {
|
|||
let req_opt = RequestOptions::fallback_fixture();
|
||||
|
||||
let Response::Success(users) = core::get_all_user_entries(req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get all user entries");
|
||||
};
|
||||
|
||||
assert_eq!(users.len(), 3);
|
||||
|
@ -129,7 +129,7 @@ fn nss_fallback_all_user_entries() {
|
|||
fn nss_fallback_user_entry_by_uid() {
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(user) = core::get_user_entry_by_uid(0, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get user entry by uid");
|
||||
};
|
||||
|
||||
assert_eq!(user.name, "root");
|
||||
|
@ -139,7 +139,7 @@ fn nss_fallback_user_entry_by_uid() {
|
|||
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(user) = core::get_user_entry_by_uid(1000, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get user entry by uid");
|
||||
};
|
||||
|
||||
assert_eq!(user.name, "tobias");
|
||||
|
@ -149,7 +149,7 @@ fn nss_fallback_user_entry_by_uid() {
|
|||
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::NotFound = core::get_user_entry_by_uid(10, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Wrong result");
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ fn nss_fallback_user_entry_by_uid() {
|
|||
fn nss_fallback_user_entry_by_name() {
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(user) = core::get_user_entry_by_name("root".to_string(), req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get user entry by name");
|
||||
};
|
||||
|
||||
assert_eq!(user.name, "root");
|
||||
|
@ -167,7 +167,7 @@ fn nss_fallback_user_entry_by_name() {
|
|||
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(user) = core::get_user_entry_by_name("ellie".to_string(), req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get user entry by name");
|
||||
};
|
||||
|
||||
assert_eq!(user.name, "ellie");
|
||||
|
@ -177,7 +177,7 @@ fn nss_fallback_user_entry_by_name() {
|
|||
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::NotFound = core::get_user_entry_by_name("william".to_string(), req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Wrong result");
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ fn nss_fallback_all_group_entries() {
|
|||
let req_opt = RequestOptions::fallback_fixture();
|
||||
|
||||
let Response::Success(groups) = core::get_all_group_entries(req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get all group entries");
|
||||
};
|
||||
|
||||
assert_eq!(groups.len(), 3);
|
||||
|
@ -207,7 +207,7 @@ fn nss_fallback_all_group_entries() {
|
|||
fn nss_fallback_group_entry_by_uid() {
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(group) = core::get_group_entry_by_gid(0, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get group entry by gid");
|
||||
};
|
||||
|
||||
assert_eq!(group.name, "root");
|
||||
|
@ -216,7 +216,7 @@ fn nss_fallback_group_entry_by_uid() {
|
|||
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(group) = core::get_group_entry_by_gid(1000, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Failed to get group entry by gid");
|
||||
};
|
||||
|
||||
assert_eq!(group.name, "tobias");
|
||||
|
@ -225,7 +225,7 @@ fn nss_fallback_group_entry_by_uid() {
|
|||
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::NotFound = core::get_group_entry_by_gid(10, req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Wrong result");
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ fn nss_fallback_group_entry_by_name() {
|
|||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(group) = core::get_group_entry_by_name("root".to_string(), req_opt)
|
||||
else {
|
||||
unreachable!();
|
||||
panic!("Failed to get group entry by name");
|
||||
};
|
||||
|
||||
assert_eq!(group.name, "root");
|
||||
|
@ -244,7 +244,7 @@ fn nss_fallback_group_entry_by_name() {
|
|||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::Success(group) = core::get_group_entry_by_name("ellie".to_string(), req_opt)
|
||||
else {
|
||||
unreachable!();
|
||||
panic!("Failed to get group entry by name");
|
||||
};
|
||||
|
||||
assert_eq!(group.name, "ellie");
|
||||
|
@ -253,6 +253,6 @@ fn nss_fallback_group_entry_by_name() {
|
|||
|
||||
let req_opt = RequestOptions::fallback_fixture();
|
||||
let Response::NotFound = core::get_group_entry_by_name("william".to_string(), req_opt) else {
|
||||
unreachable!();
|
||||
panic!("Wrong result");
|
||||
};
|
||||
}
|
||||
|
|
|
@ -121,23 +121,17 @@ impl PamHandler for TestHandler {
|
|||
/// Display a message to the user.
|
||||
fn message(&self, _prompt: &str) -> PamResult<()> {
|
||||
let mut q = self.response_queue.lock().unwrap();
|
||||
match q.pop_front() {
|
||||
e => {
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition");
|
||||
}
|
||||
}
|
||||
let e = q.pop_front();
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition message");
|
||||
}
|
||||
|
||||
/// Display a device grant request to the user.
|
||||
fn message_device_grant(&self, _data: &DeviceAuthorizationResponse) -> PamResult<()> {
|
||||
let mut q = self.response_queue.lock().unwrap();
|
||||
match q.pop_front() {
|
||||
e => {
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition");
|
||||
}
|
||||
}
|
||||
let e = q.pop_front();
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition message_device_grant");
|
||||
}
|
||||
|
||||
/// Request a password from the user.
|
||||
|
@ -154,22 +148,16 @@ impl PamHandler for TestHandler {
|
|||
|
||||
fn prompt_for_pin(&self, _msg: Option<&str>) -> PamResult<Option<String>> {
|
||||
let mut q = self.response_queue.lock().unwrap();
|
||||
match q.pop_front() {
|
||||
e => {
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition");
|
||||
}
|
||||
}
|
||||
let e = q.pop_front();
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition prompt_for_pin");
|
||||
}
|
||||
|
||||
fn prompt_for_mfacode(&self) -> PamResult<Option<String>> {
|
||||
let mut q = self.response_queue.lock().unwrap();
|
||||
match q.pop_front() {
|
||||
e => {
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition");
|
||||
}
|
||||
}
|
||||
let mut q = self.response_queue.lock().expect("Failed to lock mutex");
|
||||
let e = q.pop_front();
|
||||
eprintln!("{:?}", e);
|
||||
panic!("Invalid event transition prompt_for_mfacode");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1189,7 +1189,7 @@ async fn test_cache_extend_group_members() {
|
|||
assert!(groups.iter().any(|group| {
|
||||
group.name == "extensible_group"
|
||||
&& group.members.as_slice()
|
||||
== &[
|
||||
== [
|
||||
"local_account".to_string(),
|
||||
"testaccount1@idm.example.com".to_string(),
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue