rootasrole_core/database/
actor.rs

1use 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}