Be non empty vec (#1501)

This commit is contained in:
MinhPhan8803 2023-03-29 20:41:52 -05:00 committed by GitHub
parent c1f62674f5
commit f5fbf43991
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 310 additions and 321 deletions

10
Cargo.lock generated
View file

@ -2429,6 +2429,7 @@ dependencies = [
"ldap3_proto", "ldap3_proto",
"libc", "libc",
"libsqlite3-sys", "libsqlite3-sys",
"nonempty",
"num_enum", "num_enum",
"openssl", "openssl",
"openssl-sys", "openssl-sys",
@ -2888,6 +2889,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "nonempty"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aeaf4ad7403de93e699c191202f017118df734d3850b01e13a3a8b2e6953d3c9"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "nss_kanidm" name = "nss_kanidm"
version = "1.1.0-alpha.12-dev" version = "1.1.0-alpha.12-dev"

View file

@ -179,6 +179,8 @@ yew = "^0.20.0"
yew-router = "^0.17.0" yew-router = "^0.17.0"
zxcvbn = "^2.2.2" zxcvbn = "^2.2.2"
nonempty = "0.8.1"
# enshrinken the WASMs # enshrinken the WASMs
[profile.release.package.kanidmd_web_ui] [profile.release.package.kanidmd_web_ui]
# optimization over all codebase ( better optimization, slower build ) # optimization over all codebase ( better optimization, slower build )

View file

@ -59,6 +59,7 @@ tokio = { workspace = true, features = ["net", "sync", "time", "rt"] }
tokio-util = { workspace = true, features = ["codec"] } tokio-util = { workspace = true, features = ["codec"] }
toml.workspace = true toml.workspace = true
touch.workspace = true touch.workspace = true
nonempty = { workspace = true, features = ["serialize"] }
tracing = { workspace = true, features = ["attributes"] } tracing = { workspace = true, features = ["attributes"] }

View file

@ -1,6 +1,7 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::time::Duration; use std::time::Duration;
use nonempty::NonEmpty;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smartstring::alias::String as AttrString; use smartstring::alias::String as AttrString;
use uuid::Uuid; use uuid::Uuid;
@ -10,7 +11,7 @@ use crate::prelude::OperationError;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct DbEntryV1 { pub struct DbEntryV1 {
pub attrs: BTreeMap<AttrString, Vec<DbValueV1>>, pub attrs: BTreeMap<AttrString, NonEmpty<DbValueV1>>,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -57,219 +58,199 @@ pub enum DbBackup {
}, },
} }
fn from_vec_dbval1(attr_val: Vec<DbValueV1>) -> Result<DbValueSetV2, OperationError> { fn from_vec_dbval1(attr_val: NonEmpty<DbValueV1>) -> Result<DbValueSetV2, OperationError> {
// ======================== match attr_val.first() {
// DbValueV1::Utf8(_) => attr_val
let mut viter = attr_val.into_iter().peekable(); .into_iter()
.map(|dbv| {
match viter.peek() { if let DbValueV1::Utf8(s) = dbv {
Some(DbValueV1::Utf8(_)) => { Ok(s)
let vs: Result<Vec<_>, _> = viter } else {
.map(|dbv| { Err(OperationError::InvalidValueState)
if let DbValueV1::Utf8(s) = dbv { }
Ok(s) })
} else { .collect::<Result<Vec<_>, _>>()
Err(OperationError::InvalidValueState) .map(DbValueSetV2::Utf8),
} DbValueV1::Iutf8(_) => attr_val
}) .into_iter()
.collect(); .map(|dbv| {
vs.map(DbValueSetV2::Utf8) if let DbValueV1::Iutf8(s) = dbv {
} Ok(s)
Some(DbValueV1::Iutf8(_)) => { } else {
let vs: Result<Vec<_>, _> = viter Err(OperationError::InvalidValueState)
.map(|dbv| { }
if let DbValueV1::Iutf8(s) = dbv { })
Ok(s) .collect::<Result<Vec<_>, _>>()
} else { .map(DbValueSetV2::Iutf8),
Err(OperationError::InvalidValueState) DbValueV1::Iname(_) => attr_val
} .into_iter()
}) .map(|dbv| {
.collect(); if let DbValueV1::Iname(s) = dbv {
vs.map(DbValueSetV2::Iutf8) Ok(s)
} } else {
Some(DbValueV1::Iname(_)) => { Err(OperationError::InvalidValueState)
let vs: Result<Vec<_>, _> = viter }
.map(|dbv| { })
if let DbValueV1::Iname(s) = dbv { .collect::<Result<Vec<_>, _>>()
Ok(s) .map(DbValueSetV2::Iname),
} else { DbValueV1::Uuid(_) => attr_val
Err(OperationError::InvalidValueState) .into_iter()
} .map(|dbv| {
}) if let DbValueV1::Uuid(s) = dbv {
.collect(); Ok(s)
vs.map(DbValueSetV2::Iname) } else {
} Err(OperationError::InvalidValueState)
Some(DbValueV1::Uuid(_)) => { }
let vs: Result<Vec<_>, _> = viter })
.map(|dbv| { .collect::<Result<Vec<_>, _>>()
if let DbValueV1::Uuid(s) = dbv { .map(DbValueSetV2::Uuid),
Ok(s) DbValueV1::Bool(_) => attr_val
} else { .into_iter()
Err(OperationError::InvalidValueState) .map(|dbv| {
} if let DbValueV1::Bool(s) = dbv {
}) Ok(s)
.collect(); } else {
vs.map(DbValueSetV2::Uuid) Err(OperationError::InvalidValueState)
} }
Some(DbValueV1::Bool(_)) => { })
let vs: Result<Vec<_>, _> = viter .collect::<Result<Vec<_>, _>>()
.map(|dbv| { .map(DbValueSetV2::Bool),
if let DbValueV1::Bool(s) = dbv { DbValueV1::SyntaxType(_) => attr_val
Ok(s) .into_iter()
} else { .map(|dbv| {
Err(OperationError::InvalidValueState) if let DbValueV1::SyntaxType(s) = dbv {
} Ok(s)
}) } else {
.collect(); Err(OperationError::InvalidValueState)
vs.map(DbValueSetV2::Bool) }
} })
Some(DbValueV1::SyntaxType(_)) => { .collect::<Result<Vec<_>, _>>()
let vs: Result<Vec<_>, _> = viter .map(DbValueSetV2::SyntaxType),
.map(|dbv| { DbValueV1::IndexType(_) => attr_val
if let DbValueV1::SyntaxType(s) = dbv { .into_iter()
Ok(s) .map(|dbv| {
} else { if let DbValueV1::IndexType(s) = dbv {
Err(OperationError::InvalidValueState) u16::try_from(s).map_err(|_| OperationError::InvalidValueState)
} } else {
}) Err(OperationError::InvalidValueState)
.collect(); }
vs.map(DbValueSetV2::SyntaxType) })
} .collect::<Result<Vec<_>, _>>()
Some(DbValueV1::IndexType(_)) => { .map(DbValueSetV2::IndexType),
let vs: Result<Vec<_>, _> = viter DbValueV1::Reference(_) => attr_val
.map(|dbv| { .into_iter()
if let DbValueV1::IndexType(s) = dbv { .map(|dbv| {
u16::try_from(s).map_err(|_| OperationError::InvalidValueState) if let DbValueV1::Reference(s) = dbv {
} else { Ok(s)
Err(OperationError::InvalidValueState) } else {
} Err(OperationError::InvalidValueState)
}) }
.collect(); })
vs.map(DbValueSetV2::IndexType) .collect::<Result<Vec<_>, _>>()
} .map(DbValueSetV2::Reference),
Some(DbValueV1::Reference(_)) => { DbValueV1::JsonFilter(_) => attr_val
let vs: Result<Vec<_>, _> = viter .into_iter()
.map(|dbv| { .map(|dbv| {
if let DbValueV1::Reference(s) = dbv { if let DbValueV1::JsonFilter(s) = dbv {
Ok(s) Ok(s)
} else { } else {
Err(OperationError::InvalidValueState) Err(OperationError::InvalidValueState)
} }
}) })
.collect(); .collect::<Result<Vec<_>, _>>()
vs.map(DbValueSetV2::Reference) .map(DbValueSetV2::JsonFilter),
} DbValueV1::Credential(_) => attr_val
Some(DbValueV1::JsonFilter(_)) => { .into_iter()
let vs: Result<Vec<_>, _> = viter .map(|dbv| {
.map(|dbv| { if let DbValueV1::Credential(s) = dbv {
if let DbValueV1::JsonFilter(s) = dbv { Ok(s)
Ok(s) } else {
} else { Err(OperationError::InvalidValueState)
Err(OperationError::InvalidValueState) }
} })
}) .collect::<Result<Vec<_>, _>>()
.collect(); .map(DbValueSetV2::Credential),
vs.map(DbValueSetV2::JsonFilter) DbValueV1::SecretValue(_) => attr_val
} .into_iter()
Some(DbValueV1::Credential(_)) => { .map(|dbv| {
let vs: Result<Vec<_>, _> = viter if let DbValueV1::SecretValue(s) = dbv {
.map(|dbv| { Ok(s)
if let DbValueV1::Credential(s) = dbv { } else {
Ok(s) Err(OperationError::InvalidValueState)
} else { }
Err(OperationError::InvalidValueState) })
} .collect::<Result<Vec<_>, _>>()
}) .map(DbValueSetV2::SecretValue),
.collect(); DbValueV1::SshKey(_) => attr_val
vs.map(DbValueSetV2::Credential) .into_iter()
} .map(|dbv| {
Some(DbValueV1::SecretValue(_)) => { if let DbValueV1::SshKey(s) = dbv {
let vs: Result<Vec<_>, _> = viter Ok(s)
.map(|dbv| { } else {
if let DbValueV1::SecretValue(s) = dbv { Err(OperationError::InvalidValueState)
Ok(s) }
} else { })
Err(OperationError::InvalidValueState) .collect::<Result<Vec<_>, _>>()
} .map(DbValueSetV2::SshKey),
}) DbValueV1::Spn(_, _) => attr_val
.collect(); .into_iter()
vs.map(DbValueSetV2::SecretValue) .map(|dbv| {
} if let DbValueV1::Spn(n, d) = dbv {
Some(DbValueV1::SshKey(_)) => { Ok((n, d))
let vs: Result<Vec<_>, _> = viter } else {
.map(|dbv| { Err(OperationError::InvalidValueState)
if let DbValueV1::SshKey(s) = dbv { }
Ok(s) })
} else { .collect::<Result<Vec<_>, _>>()
Err(OperationError::InvalidValueState) .map(DbValueSetV2::Spn),
} DbValueV1::Uint32(_) => attr_val
}) .into_iter()
.collect(); .map(|dbv| {
vs.map(DbValueSetV2::SshKey) if let DbValueV1::Uint32(s) = dbv {
} Ok(s)
Some(DbValueV1::Spn(_, _)) => { } else {
let vs: Result<Vec<_>, _> = viter Err(OperationError::InvalidValueState)
.map(|dbv| { }
if let DbValueV1::Spn(n, d) = dbv { })
Ok((n, d)) .collect::<Result<Vec<_>, _>>()
} else { .map(DbValueSetV2::Uint32),
Err(OperationError::InvalidValueState) DbValueV1::Cid(_) => attr_val
} .into_iter()
}) .map(|dbv| {
.collect(); if let DbValueV1::Cid(s) = dbv {
vs.map(DbValueSetV2::Spn) Ok(s)
} } else {
Some(DbValueV1::Uint32(_)) => { Err(OperationError::InvalidValueState)
let vs: Result<Vec<_>, _> = viter }
.map(|dbv| { })
if let DbValueV1::Uint32(s) = dbv { .collect::<Result<Vec<_>, _>>()
Ok(s) .map(DbValueSetV2::Cid),
} else { DbValueV1::NsUniqueId(_) => attr_val
Err(OperationError::InvalidValueState) .into_iter()
} .map(|dbv| {
}) if let DbValueV1::NsUniqueId(s) = dbv {
.collect(); Ok(s)
vs.map(DbValueSetV2::Uint32) } else {
} Err(OperationError::InvalidValueState)
Some(DbValueV1::Cid(_)) => { }
let vs: Result<Vec<_>, _> = viter })
.map(|dbv| { .collect::<Result<Vec<_>, _>>()
if let DbValueV1::Cid(s) = dbv { .map(DbValueSetV2::NsUniqueId),
Ok(s) DbValueV1::DateTime(_) => attr_val
} else { .into_iter()
Err(OperationError::InvalidValueState) .map(|dbv| {
} if let DbValueV1::DateTime(s) = dbv {
}) Ok(s)
.collect(); } else {
vs.map(DbValueSetV2::Cid) Err(OperationError::InvalidValueState)
} }
Some(DbValueV1::NsUniqueId(_)) => { })
let vs: Result<Vec<_>, _> = viter .collect::<Result<Vec<_>, _>>()
.map(|dbv| { .map(DbValueSetV2::DateTime),
if let DbValueV1::NsUniqueId(s) = dbv { DbValueV1::EmailAddress(_) => {
Ok(s)
} else {
Err(OperationError::InvalidValueState)
}
})
.collect();
vs.map(DbValueSetV2::NsUniqueId)
}
Some(DbValueV1::DateTime(_)) => {
let vs: Result<Vec<_>, _> = viter
.map(|dbv| {
if let DbValueV1::DateTime(s) = dbv {
Ok(s)
} else {
Err(OperationError::InvalidValueState)
}
})
.collect();
vs.map(DbValueSetV2::DateTime)
}
Some(DbValueV1::EmailAddress(_)) => {
let mut primary = None; let mut primary = None;
let vs: Result<Vec<_>, _> = viter let vs: Result<Vec<_>, _> = attr_val
.into_iter()
.map(|dbv| { .map(|dbv| {
if let DbValueV1::EmailAddress(DbValueEmailAddressV1 { d, p }) = dbv { if let DbValueV1::EmailAddress(DbValueEmailAddressV1 { d, p }) = dbv {
if p { if p {
@ -284,9 +265,10 @@ fn from_vec_dbval1(attr_val: Vec<DbValueV1>) -> Result<DbValueSetV2, OperationEr
let primary = primary.ok_or(OperationError::InvalidValueState)?; let primary = primary.ok_or(OperationError::InvalidValueState)?;
vs.map(|vs| DbValueSetV2::EmailAddress(primary, vs)) vs.map(|vs| DbValueSetV2::EmailAddress(primary, vs))
} }
Some(DbValueV1::PhoneNumber(_)) => { DbValueV1::PhoneNumber(_) => {
let mut primary = None; let mut primary = None;
let vs: Result<Vec<_>, _> = viter let vs: Result<Vec<_>, _> = attr_val
.into_iter()
.map(|dbv| { .map(|dbv| {
if let DbValueV1::PhoneNumber(DbValuePhoneNumberV1 { d, p }) = dbv { if let DbValueV1::PhoneNumber(DbValuePhoneNumberV1 { d, p }) = dbv {
if p { if p {
@ -301,107 +283,106 @@ fn from_vec_dbval1(attr_val: Vec<DbValueV1>) -> Result<DbValueSetV2, OperationEr
let primary = primary.ok_or(OperationError::InvalidValueState)?; let primary = primary.ok_or(OperationError::InvalidValueState)?;
vs.map(|vs| DbValueSetV2::PhoneNumber(primary, vs)) vs.map(|vs| DbValueSetV2::PhoneNumber(primary, vs))
} }
Some(DbValueV1::Address(_)) => { DbValueV1::Address(_) => attr_val
let vs: Result<Vec<_>, _> = viter .into_iter()
.map(|dbv| { .map(|dbv| {
if let DbValueV1::Address(s) = dbv { if let DbValueV1::Address(s) = dbv {
Ok(s) Ok(s)
} else { } else {
Err(OperationError::InvalidValueState) Err(OperationError::InvalidValueState)
} }
}) })
.collect(); .collect::<Result<Vec<_>, _>>()
vs.map(DbValueSetV2::Address) .map(DbValueSetV2::Address),
} DbValueV1::Url(_) => attr_val
Some(DbValueV1::Url(_)) => { .into_iter()
let vs: Result<Vec<_>, _> = viter .map(|dbv| {
.map(|dbv| { if let DbValueV1::Url(s) = dbv {
if let DbValueV1::Url(s) = dbv { Ok(s)
Ok(s) } else {
} else { Err(OperationError::InvalidValueState)
Err(OperationError::InvalidValueState) }
} })
}) .collect::<Result<Vec<_>, _>>()
.collect(); .map(DbValueSetV2::Url),
vs.map(DbValueSetV2::Url) DbValueV1::OauthScope(_) => attr_val
} .into_iter()
Some(DbValueV1::OauthScope(_)) => { .map(|dbv| {
let vs: Result<Vec<_>, _> = viter if let DbValueV1::OauthScope(s) = dbv {
.map(|dbv| { Ok(s)
if let DbValueV1::OauthScope(s) = dbv { } else {
Ok(s) Err(OperationError::InvalidValueState)
} else { }
Err(OperationError::InvalidValueState) })
} .collect::<Result<Vec<_>, _>>()
}) .map(DbValueSetV2::OauthScope),
.collect(); DbValueV1::OauthScopeMap(_) => attr_val
vs.map(DbValueSetV2::OauthScope) .into_iter()
} .map(|dbv| {
Some(DbValueV1::OauthScopeMap(_)) => { if let DbValueV1::OauthScopeMap(s) = dbv {
let vs: Result<Vec<_>, _> = viter Ok(s)
.map(|dbv| { } else {
if let DbValueV1::OauthScopeMap(s) = dbv { Err(OperationError::InvalidValueState)
Ok(s) }
} else { })
Err(OperationError::InvalidValueState) .collect::<Result<Vec<_>, _>>()
} .map(DbValueSetV2::OauthScopeMap),
}) DbValueV1::PrivateBinary(_) => attr_val
.collect(); .into_iter()
vs.map(DbValueSetV2::OauthScopeMap) .map(|dbv| {
} if let DbValueV1::PrivateBinary(s) = dbv {
Some(DbValueV1::PrivateBinary(_)) => { Ok(s)
let vs: Result<Vec<_>, _> = viter } else {
.map(|dbv| { Err(OperationError::InvalidValueState)
if let DbValueV1::PrivateBinary(s) = dbv { }
Ok(s) })
} else { .collect::<Result<Vec<_>, _>>()
Err(OperationError::InvalidValueState) .map(DbValueSetV2::PrivateBinary),
} DbValueV1::PublicBinary(_, _) => attr_val
}) .into_iter()
.collect(); .map(|dbv| {
vs.map(DbValueSetV2::PrivateBinary) if let DbValueV1::PublicBinary(t, s) = dbv {
} Ok((t, s))
Some(DbValueV1::PublicBinary(_, _)) => { } else {
let vs: Result<Vec<_>, _> = viter Err(OperationError::InvalidValueState)
.map(|dbv| { }
if let DbValueV1::PublicBinary(t, s) = dbv { })
Ok((t, s)) .collect::<Result<Vec<_>, _>>()
} else { .map(DbValueSetV2::PublicBinary),
Err(OperationError::InvalidValueState) DbValueV1::RestrictedString(_) => attr_val
} .into_iter()
}) .map(|dbv| {
.collect(); if let DbValueV1::RestrictedString(s) = dbv {
vs.map(DbValueSetV2::PublicBinary) Ok(s)
} } else {
Some(DbValueV1::RestrictedString(_)) => { Err(OperationError::InvalidValueState)
let vs: Result<Vec<_>, _> = viter }
.map(|dbv| { })
if let DbValueV1::RestrictedString(s) = dbv { .collect::<Result<Vec<_>, _>>()
Ok(s) .map(DbValueSetV2::RestrictedString),
} else { DbValueV1::IntentToken { u: _, s: _ } => attr_val
Err(OperationError::InvalidValueState) .into_iter()
} .map(|dbv| {
}) if let DbValueV1::IntentToken { u, s } = dbv {
.collect(); Ok((u.as_hyphenated().to_string(), s))
vs.map(DbValueSetV2::RestrictedString) } else {
} Err(OperationError::InvalidValueState)
Some(DbValueV1::IntentToken { u: _, s: _ }) => { }
let vs: Result<Vec<_>, _> = viter })
.map(|dbv| { .collect::<Result<Vec<_>, _>>()
if let DbValueV1::IntentToken { u, s } = dbv { .map(DbValueSetV2::IntentToken),
Ok((u.as_hyphenated().to_string(), s)) DbValueV1::TrustedDeviceEnrollment { u: _ } => attr_val
} else { .into_iter()
Err(OperationError::InvalidValueState) .map(|dbv| {
} if let DbValueV1::TrustedDeviceEnrollment { u } = dbv {
}) Ok(u)
.collect(); } else {
vs.map(DbValueSetV2::IntentToken) Err(OperationError::InvalidValueState)
} }
// Neither of these should exist yet. })
Some(DbValueV1::TrustedDeviceEnrollment { u: _ }) .collect::<Result<Vec<_>, _>>()
| Some(DbValueV1::Session { u: _ }) .map(DbValueSetV2::TrustedDeviceEnrollment),
| None => { DbValueV1::Session { u: _ } => {
// Shiiiiii
debug_assert!(false); debug_assert!(false);
Err(OperationError::InvalidState) Err(OperationError::InvalidState)
} }
@ -413,11 +394,6 @@ impl DbEntry {
if let DbEntryVers::V1(dbe) = self.ent { if let DbEntryVers::V1(dbe) = self.ent {
dbe.attrs dbe.attrs
.into_iter() .into_iter()
.filter(|(_attr_name, attr_val)| {
// Skip anything that is empty, because our from impl
// can't handle it, neither can our dbvaluesetv2
!attr_val.is_empty()
})
.map(|(attr_name, attr_val)| { .map(|(attr_name, attr_val)| {
from_vec_dbval1(attr_val).map(|attr_val_2| (attr_name, attr_val_2)) from_vec_dbval1(attr_val).map(|attr_val_2| (attr_name, attr_val_2))
}) })