rustical_dav/
privileges.rs

1use quick_xml::name::Namespace;
2use rustical_xml::{XmlDeserialize, XmlSerialize};
3use std::collections::{HashMap, HashSet};
4
5// https://datatracker.ietf.org/doc/html/rfc3744
6#[derive(Debug, Clone, XmlSerialize, XmlDeserialize, Eq, Hash, PartialEq)]
7pub enum UserPrivilege {
8    Read,
9    Write,
10    WriteProperties,
11    WriteContent,
12    ReadAcl,
13    ReadCurrentUserPrivilegeSet,
14    WriteAcl,
15    All,
16}
17
18impl XmlSerialize for UserPrivilegeSet {
19    fn serialize(
20        &self,
21        ns: Option<Namespace>,
22        tag: Option<&[u8]>,
23        namespaces: &HashMap<Namespace, &[u8]>,
24        writer: &mut quick_xml::Writer<&mut Vec<u8>>,
25    ) -> std::io::Result<()> {
26        #[derive(XmlSerialize)]
27        pub struct FakeUserPrivilegeSet {
28            #[xml(rename = b"privilege", flatten)]
29            privileges: Vec<UserPrivilege>,
30        }
31
32        FakeUserPrivilegeSet {
33            privileges: self.privileges.iter().cloned().collect(),
34        }
35        .serialize(ns, tag, namespaces, writer)
36    }
37
38    fn attributes<'a>(&self) -> Option<Vec<quick_xml::events::attributes::Attribute<'a>>> {
39        None
40    }
41}
42
43#[derive(Debug, Clone, Default, PartialEq)]
44pub struct UserPrivilegeSet {
45    privileges: HashSet<UserPrivilege>,
46}
47
48impl UserPrivilegeSet {
49    pub fn has(&self, privilege: &UserPrivilege) -> bool {
50        if (privilege == &UserPrivilege::WriteProperties
51            || privilege == &UserPrivilege::WriteContent)
52            && self.privileges.contains(&UserPrivilege::Write)
53        {
54            return true;
55        }
56        self.privileges.contains(privilege) || self.privileges.contains(&UserPrivilege::All)
57    }
58
59    pub fn all() -> Self {
60        Self {
61            privileges: HashSet::from([UserPrivilege::All]),
62        }
63    }
64
65    pub fn owner_only(is_owner: bool) -> Self {
66        if is_owner {
67            Self::all()
68        } else {
69            Self::default()
70        }
71    }
72
73    pub fn owner_read(is_owner: bool) -> Self {
74        if is_owner {
75            Self::read_only()
76        } else {
77            Self::default()
78        }
79    }
80
81    pub fn owner_write_properties(is_owner: bool) -> Self {
82        // Content is read-only but we can write properties
83        if is_owner {
84            Self::write_properties()
85        } else {
86            Self::default()
87        }
88    }
89
90    pub fn read_only() -> Self {
91        Self {
92            privileges: HashSet::from([
93                UserPrivilege::Read,
94                UserPrivilege::ReadAcl,
95                UserPrivilege::ReadCurrentUserPrivilegeSet,
96            ]),
97        }
98    }
99
100    pub fn write_properties() -> Self {
101        Self {
102            privileges: HashSet::from([
103                UserPrivilege::Read,
104                UserPrivilege::WriteProperties,
105                UserPrivilege::ReadAcl,
106                UserPrivilege::ReadCurrentUserPrivilegeSet,
107            ]),
108        }
109    }
110}
111
112impl<const N: usize> From<[UserPrivilege; N]> for UserPrivilegeSet {
113    fn from(privileges: [UserPrivilege; N]) -> Self {
114        Self {
115            privileges: HashSet::from(privileges),
116        }
117    }
118}