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

View file

@ -179,6 +179,8 @@ yew = "^0.20.0"
yew-router = "^0.17.0"
zxcvbn = "^2.2.2"
nonempty = "0.8.1"
# enshrinken the WASMs
[profile.release.package.kanidmd_web_ui]
# 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"] }
toml.workspace = true
touch.workspace = true
nonempty = { workspace = true, features = ["serialize"] }
tracing = { workspace = true, features = ["attributes"] }

View file

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