1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use kanidm_proto::v1::{Group as ProtoGroup, OperationError};
use uuid::Uuid;
use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed};
use crate::prelude::*;
use crate::value::PartialValue;
#[derive(Debug, Clone)]
pub struct Group {
spn: String,
uuid: Uuid,
}
macro_rules! try_from_account_e {
($value:expr, $qs:expr) => {{
let spn = $value.get_ava_single_proto_string("spn").ok_or(
OperationError::InvalidAccountState("Missing attribute: spn".to_string()),
)?;
let uuid = $value.get_uuid();
let upg = Group { spn, 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_uuid(u)))
.collect()
));
let ges: Vec<_> = $qs.internal_search(f).map_err(|e| {
admin_error!(?e, "internal search failed");
e
})?;
let groups: Result<Vec<_>, _> = ges
.iter()
.map(|e| Group::try_from_entry(e.as_ref()))
.collect();
groups.map_err(|e| {
admin_error!(?e, "failed to transform group entries to groups");
e
})?
}
None => {
vec![]
}
};
groups.push(upg);
Ok(groups)
}};
}
impl Group {
pub fn try_from_account_entry_red_ro(
value: &Entry<EntryReduced, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Vec<Self>, OperationError> {
try_from_account_e!(value, qs)
}
pub fn try_from_account_entry_ro(
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerReadTransaction,
) -> Result<Vec<Self>, OperationError> {
try_from_account_e!(value, qs)
}
pub fn try_from_account_entry_rw(
value: &Entry<EntrySealed, EntryCommitted>,
qs: &mut QueryServerWriteTransaction,
) -> Result<Vec<Self>, OperationError> {
try_from_account_e!(value, qs)
}
pub fn try_from_entry(
value: &Entry<EntrySealed, EntryCommitted>,
) -> Result<Self, OperationError> {
if !value.attribute_equality("class", &PVCLASS_GROUP) {
return Err(OperationError::InvalidAccountState(
"Missing class: group".to_string(),
));
}
let spn =
value
.get_ava_single_proto_string("spn")
.ok_or(OperationError::InvalidAccountState(
"Missing attribute: spn".to_string(),
))?;
let uuid = value.get_uuid();
Ok(Group { spn, uuid })
}
pub fn to_proto(&self) -> ProtoGroup {
ProtoGroup {
spn: self.spn.clone(),
uuid: self.uuid.as_hyphenated().to_string(),
}
}
}