rootasrole_core/database/
actor.rs1use std::fmt::{self, Formatter};
2
3use bon::bon;
4use nix::unistd::{Group, User};
5use serde::{
6 de::{self, Visitor},
7 Deserialize, Deserializer, Serialize,
8};
9use serde_json::{Map, Value};
10use strum::EnumIs;
11
12#[derive(Serialize, Debug, EnumIs, Clone, PartialEq, Eq)]
13#[serde(untagged, rename_all = "lowercase")]
14pub enum SGenericActorType {
15 Id(u32),
16 Name(String),
17}
18
19#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
20pub struct SUserType(SGenericActorType);
21
22impl SUserType {
23 pub(super) fn fetch_id(&self) -> Option<u32> {
24 match &self.0 {
25 SGenericActorType::Id(id) => Some(*id),
26 SGenericActorType::Name(name) => match User::from_name(name) {
27 Ok(Some(user)) => Some(user.uid.as_raw()),
28 _ => None,
29 },
30 }
31 }
32 pub fn fetch_user(&self) -> Option<User> {
33 match &self.0 {
34 SGenericActorType::Id(id) => User::from_uid((*id).into()).ok().flatten(),
35 SGenericActorType::Name(name) => User::from_name(name).ok().flatten(),
36 }
37 }
38 pub fn fetch_eq(&self, other: &Self) -> bool {
39 let uid = self.fetch_id();
40 let ouid = other.fetch_id();
41 match (uid, ouid) {
42 (Some(uid), Some(ouid)) => uid == ouid,
43 _ => false,
44 }
45 }
46}
47
48impl fmt::Display for SUserType {
49 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
50 match &self.0 {
51 SGenericActorType::Id(id) => write!(f, "{}", id),
52 SGenericActorType::Name(name) => write!(f, "{}", name),
53 }
54 }
55}
56
57#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
58pub struct SGroupType(SGenericActorType);
59
60impl fmt::Display for SGroupType {
61 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
62 match &self.0 {
63 SGenericActorType::Id(id) => write!(f, "{}", id),
64 SGenericActorType::Name(name) => write!(f, "{}", name),
65 }
66 }
67}
68
69impl SGroupType {
70 pub(super) fn fetch_id(&self) -> Option<u32> {
71 match &self.0 {
72 SGenericActorType::Id(id) => Some(*id),
73 SGenericActorType::Name(name) => match Group::from_name(name) {
74 Ok(Some(group)) => Some(group.gid.as_raw()),
75 _ => None,
76 },
77 }
78 }
79 pub fn fetch_group(&self) -> Option<Group> {
80 match &self.0 {
81 SGenericActorType::Id(id) => Group::from_gid((*id).into()).ok().flatten(),
82 SGenericActorType::Name(name) => Group::from_name(name).ok().flatten(),
83 }
84 }
85}
86
87impl std::fmt::Display for SGenericActorType {
88 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
89 match self {
90 SGenericActorType::Id(id) => write!(f, "{}", id),
91 SGenericActorType::Name(name) => write!(f, "{}", name),
92 }
93 }
94}
95
96#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, EnumIs)]
97#[serde(untagged)]
98pub enum SGroups {
99 Single(SGroupType),
100 Multiple(Vec<SGroupType>),
101}
102
103impl SGroups {
104 pub fn len(&self) -> usize {
105 match self {
106 SGroups::Single(_) => 1,
107 SGroups::Multiple(groups) => groups.len(),
108 }
109 }
110 pub fn is_empty(&self) -> bool {
111 self.len() == 0
112 }
113}
114
115impl<'de> Deserialize<'de> for SGenericActorType {
116 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
117 where
118 D: Deserializer<'de>,
119 {
120 struct IdVisitor;
121
122 impl<'de> Visitor<'de> for IdVisitor {
123 type Value = SGenericActorType;
124
125 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 f.write_str("user ID as a number or string")
127 }
128
129 fn visit_u32<E>(self, id: u32) -> Result<Self::Value, E>
130 where
131 E: de::Error,
132 {
133 Ok(SGenericActorType::Id(id))
134 }
135
136 fn visit_str<E>(self, id: &str) -> Result<Self::Value, E>
137 where
138 E: de::Error,
139 {
140 let rid: Result<u32, _> = id.parse();
141 match rid {
142 Ok(id) => Ok(SGenericActorType::Id(id)),
143 Err(_) => Ok(SGenericActorType::Name(id.to_string())),
144 }
145 }
146 }
147
148 deserializer.deserialize_any(IdVisitor)
149 }
150}
151
152impl From<u32> for SUserType {
153 fn from(id: u32) -> Self {
154 SUserType(id.into())
155 }
156}
157
158impl From<u32> for SGroupType {
159 fn from(id: u32) -> Self {
160 SGroupType(id.into())
161 }
162}
163
164impl From<&str> for SUserType {
165 fn from(name: &str) -> Self {
166 SUserType(name.into())
167 }
168}
169
170impl From<&str> for SGroupType {
171 fn from(name: &str) -> Self {
172 SGroupType(name.into())
173 }
174}
175
176impl From<Group> for SGroupType {
177 fn from(group: Group) -> Self {
178 SGroupType(SGenericActorType::Id(group.gid.as_raw()))
179 }
180}
181
182impl From<&str> for SGenericActorType {
183 fn from(name: &str) -> Self {
184 SGenericActorType::Name(name.into())
185 }
186}
187
188impl From<u32> for SGenericActorType {
189 fn from(id: u32) -> Self {
190 SGenericActorType::Id(id)
191 }
192}
193
194impl PartialEq<User> for SUserType {
195 fn eq(&self, other: &User) -> bool {
196 let uid = self.fetch_id();
197 match uid {
198 Some(uid) => uid == other.uid.as_raw(),
199 None => false,
200 }
201 }
202}
203
204impl PartialEq<str> for SUserType {
205 fn eq(&self, other: &str) -> bool {
206 self.eq(&SUserType::from(other))
207 }
208}
209
210impl PartialEq<str> for SGroupType {
211 fn eq(&self, other: &str) -> bool {
212 self.eq(&SGroupType::from(other))
213 }
214}
215
216impl PartialEq<u32> for SUserType {
217 fn eq(&self, other: &u32) -> bool {
218 self.eq(&SUserType::from(*other))
219 }
220}
221
222impl PartialEq<u32> for SGroupType {
223 fn eq(&self, other: &u32) -> bool {
224 self.eq(&SGroupType::from(*other))
225 }
226}
227
228impl PartialEq<Group> for SGroupType {
229 fn eq(&self, other: &Group) -> bool {
230 let gid = self.fetch_id();
231 match gid {
232 Some(gid) => gid == other.gid.as_raw(),
233 None => false,
234 }
235 }
236}
237
238impl<const N: usize> PartialEq<[SGroupType; N]> for SGroups {
239 fn eq(&self, other: &[SGroupType; N]) -> bool {
240 match self {
241 SGroups::Single(group) => {
242 if N == 1 {
243 group == &other[0]
244 } else {
245 false
246 }
247 }
248 SGroups::Multiple(groups) => {
249 if groups.len() == N {
250 groups.iter().zip(other.iter()).all(|(a, b)| a == b)
251 } else {
252 false
253 }
254 }
255 }
256 }
257}
258
259impl<const N: usize> From<[SGroupType; N]> for SGroups {
260 fn from(groups: [SGroupType; N]) -> Self {
261 if N == 1 {
262 SGroups::Single(groups[0].to_owned())
263 } else {
264 SGroups::Multiple(groups.iter().map(|x| x.to_owned()).collect())
265 }
266 }
267}
268
269impl FromIterator<String> for SGroups {
270 fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
271 let mut iter = iter.into_iter();
272 let first = iter.next().unwrap();
273 let mut groups: Vec<SGroupType> = vec![first.as_str().into()];
274 for group in iter {
275 groups.push(group.as_str().into());
276 }
277 if groups.len() == 1 {
278 SGroups::Single(groups[0].to_owned())
279 } else {
280 SGroups::Multiple(groups)
281 }
282 }
283}
284
285impl<const N: usize> From<[&str; N]> for SGroups {
286 fn from(groups: [&str; N]) -> Self {
287 if N == 1 {
288 SGroups::Single(groups[0].into())
289 } else {
290 SGroups::Multiple(groups.iter().map(|&x| x.into()).collect())
291 }
292 }
293}
294
295impl From<Vec<u32>> for SGroups {
296 fn from(groups: Vec<u32>) -> Self {
297 if groups.len() == 1 {
298 SGroups::Single(groups[0].into())
299 } else {
300 SGroups::Multiple(groups.into_iter().map(|x| x.into()).collect())
301 }
302 }
303}
304
305impl From<Vec<SGroupType>> for SGroups {
306 fn from(groups: Vec<SGroupType>) -> Self {
307 if groups.len() == 1 {
308 SGroups::Single(groups[0].clone())
309 } else {
310 SGroups::Multiple(groups)
311 }
312 }
313}
314
315impl From<u32> for SGroups {
316 fn from(group: u32) -> Self {
317 SGroups::Single(group.into())
318 }
319}
320
321impl From<&str> for SGroups {
322 fn from(group: &str) -> Self {
323 SGroups::Single(group.into())
324 }
325}
326
327impl PartialEq<Vec<SGroupType>> for SGroups {
328 fn eq(&self, other: &Vec<SGroupType>) -> bool {
329 match self {
330 SGroups::Single(actor) => {
331 if other.len() == 1 {
332 return actor == &other[0];
333 }
334 }
335 SGroups::Multiple(actors) => {
336 if actors.len() == other.len() {
337 return actors.iter().all(|actor| other.iter().any(|x| actor == x));
338 }
339 }
340 }
341 false
342 }
343}
344
345impl core::fmt::Display for SGroups {
346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347 match self {
348 SGroups::Single(group) => {
349 write!(f, "{}", group)
350 }
351 SGroups::Multiple(groups) => {
352 write!(f, "{:?}", groups)
353 }
354 }
355 }
356}
357
358#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, EnumIs)]
359#[serde(tag = "type", rename_all = "lowercase")]
360pub enum SActor {
361 #[serde(rename = "user")]
362 User {
363 #[serde(alias = "name", skip_serializing_if = "Option::is_none")]
364 id: Option<SUserType>,
365 #[serde(default, flatten, skip_serializing_if = "Map::is_empty")]
366 _extra_fields: Map<String, Value>,
367 },
368 #[serde(rename = "group")]
369 Group {
370 #[serde(alias = "names", skip_serializing_if = "Option::is_none")]
371 groups: Option<SGroups>,
372 #[serde(default, flatten)]
373 _extra_fields: Map<String, Value>,
374 },
375 #[serde(untagged)]
376 Unknown(Value),
377}
378
379#[bon]
380impl SActor {
381 #[builder(finish_fn = build)]
382 pub fn user(
383 #[builder(start_fn, into)] id: SUserType,
384 #[builder(default, with = <_>::from_iter)] _extra_fields: Map<String, Value>,
385 ) -> Self {
386 SActor::User {
387 id: Some(id),
388 _extra_fields,
389 }
390 }
391 #[builder(finish_fn = build)]
392 pub fn group(
393 #[builder(start_fn, into)] groups: SGroups,
394 #[builder(default, with = <_>::from_iter)] _extra_fields: Map<String, Value>,
395 ) -> Self {
396 SActor::Group {
397 groups: Some(groups),
398 _extra_fields,
399 }
400 }
401}
402
403impl core::fmt::Display for SActor {
404 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
405 match self {
406 SActor::User { id, _extra_fields } => {
407 write!(f, "User: {}", id.as_ref().unwrap())
408 }
409 SActor::Group {
410 groups,
411 _extra_fields,
412 } => {
413 write!(f, "Group: {}", groups.as_ref().unwrap())
414 }
415 SActor::Unknown(unknown) => {
416 write!(f, "Unknown: {}", unknown)
417 }
418 }
419 }
420}
421#[cfg(test)]
422mod tests {
423 use super::*;
424
425 #[test]
426 fn test_suser_type_creation() {
427 let user_by_id = SUserType::from(0);
428 let user_by_name = SUserType::from("testuser");
429
430 assert_eq!(user_by_id.to_string(), "0");
431 assert_eq!(user_by_name.to_string(), "testuser");
432 }
433 #[test]
434 fn test_fetch_id() {
435 let user = SUserType::from(0);
436 assert_eq!(user.fetch_id(), Some(0));
437
438 let group = SGroupType::from(0);
439 assert_eq!(group.fetch_id(), Some(0));
440 }
441 #[test]
442 fn test_fetch_user() {
443 let user = SUserType::from("testuser");
444 assert!(user.fetch_user().is_none());
445 let user_by_id = SUserType::from(0);
446 assert!(user_by_id.fetch_user().is_some());
447 }
448
449 #[test]
450 fn test_sgroups_multiple() {
451 let groups = SGroups::from(vec![SGroupType::from(0), SGroupType::from(200)]);
452
453 assert_eq!(groups.len(), 2);
454 assert!(!groups.is_empty());
455
456 if let SGroups::Multiple(group_list) = groups {
457 assert_eq!(group_list[0].to_string(), "0");
458 assert_eq!(group_list[1].to_string(), "200");
459 } else {
460 panic!("Expected SGroups::Multiple");
461 }
462 }
463
464 #[test]
465 fn test_fech_group() {
466 let group = SGroupType::from(0);
467 assert_eq!(
468 group.fetch_group(),
469 Some(Group::from_gid(0.into()).unwrap().unwrap())
470 );
471
472 let group = SGroupType::from("root");
473 assert_eq!(
474 group.fetch_group(),
475 Some(Group::from_name("root").unwrap().unwrap())
476 );
477 }
478
479 #[test]
480 fn test_is_empty() {
481 let groups = SGroups::Multiple(vec![]);
482 assert!(groups.is_empty());
483 }
484}