use crate::audit::AuditScope;
use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed};
use crate::server::{
QueryServerReadTransaction, QueryServerTransaction, QueryServerWriteTransaction,
};
use crate::value::PartialValue;
use kanidm_proto::v1::Group as ProtoGroup;
use kanidm_proto::v1::OperationError;
use uuid::Uuid;
lazy_static! {
static ref PVCLASS_GROUP: PartialValue = PartialValue::new_class("group");
}
#[derive(Debug, Clone)]
pub struct Group {
name: String,
uuid: Uuid,
}
macro_rules! try_from_account_e {
($au:expr, $value:expr, $qs:expr) => {{
let name = $value
.get_ava_single_str("name")
.map(|s| s.to_string())
.ok_or_else(|| {
OperationError::InvalidAccountState("Missing attribute: name".to_string())
})?;
let uuid = *$value.get_uuid();
let upg = Group { name, uuid };
let mut groups: Vec<Group> = match $value.get_ava_as_refuuid("memberof") {
Some(riter) => {
let f = filter!(f_or(
riter
.map(|u| f_eq("uuid", PartialValue::new_uuidr(u)))
.collect()
));
let ges: Vec<_> = $qs.internal_search($au, f).map_err(|e| {
e
})?;
let groups: Result<Vec<_>, _> =
ges.into_iter().map(Group::try_from_entry).collect();
groups.map_err(|e| {
e
})?
}
None => {
vec![]
}
};
groups.push(upg);
Ok(groups)
}};
}
impl Group {
pub fn try_from_account_entry_red_ro(
au: &mut AuditScope,
value: &Entry<EntryReduced, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Vec<Self>, OperationError> {
try_from_account_e!(au, value, qs)
}
pub fn try_from_account_entry_ro(
au: &mut AuditScope,
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Vec<Self>, OperationError> {
try_from_account_e!(au, value, qs)
}
pub fn try_from_account_entry_rw(
au: &mut AuditScope,
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerWriteTransaction,
) -> Result<Vec<Self>, OperationError> {
try_from_account_e!(au, value, qs)
}
pub fn try_from_entry(
value: Entry<EntrySealed, EntryCommitted>,
) -> Result<Self, OperationError> {
if !value.attribute_value_pres("class", &PVCLASS_GROUP) {
return Err(OperationError::InvalidAccountState(
"Missing class: group".to_string(),
));
}
let name = value
.get_ava_single_str("name")
.map(|s| s.to_string())
.ok_or_else(|| {
OperationError::InvalidAccountState("Missing attribute: name".to_string())
})?;
let uuid = *value.get_uuid();
Ok(Group { name, uuid })
}
pub fn to_proto(&self) -> ProtoGroup {
ProtoGroup {
name: self.name.clone(),
uuid: self.uuid.to_hyphenated_ref().to_string(),
}
}
}