cloud_storage_rs/resources/
common.rs

1use serde::Serializer;
2use std::str::FromStr;
3
4/// Contains information about the team related to this `DefaultObjectAccessControls`
5#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub struct ProjectTeam {
8    /// The project number.
9    project_number: String,
10    /// The team.
11    team: Team,
12}
13
14/// Any type of team we can encounter.
15#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
16#[serde(rename_all = "lowercase")]
17pub enum Team {
18    /// The team consists of `Editors`.
19    Editors,
20    /// The team consists of `Owners`.
21    Owners,
22    /// The team consists of `Viewers`.
23    Viewers,
24}
25
26impl std::fmt::Display for Team {
27    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
28        match self {
29            Team::Editors => write!(f, "{}", "editors"),
30            Team::Owners => write!(f, "{}", "owners"),
31            Team::Viewers => write!(f, "{}", "viewers"),
32        }
33    }
34}
35
36impl FromStr for Team {
37    type Err = String;
38
39    fn from_str(s: &str) -> Result<Self, Self::Err> {
40        match s {
41            "editors" => Ok(Self::Editors),
42            "owners" => Ok(Self::Owners),
43            "viewers" => Ok(Self::Viewers),
44            _ => Err(format!("Invalid `Team`: {}", s)),
45        }
46    }
47}
48
49/// Any type of role we can encounter.
50#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
51#[serde(rename_all = "UPPERCASE")]
52pub enum Role {
53    /// Full access.
54    Owner,
55    /// Write, but not administer.
56    Writer,
57    /// Only read access.
58    Reader,
59}
60
61#[derive(Debug, serde::Deserialize)]
62#[serde(rename_all = "camelCase")]
63pub(crate) struct ListResponse<T> {
64    #[serde(default = "Vec::new")]
65    pub items: Vec<T>,
66    pub next_page_token: Option<String>,
67}
68
69/// An entity is used to represent a user or group of users that often have some kind of permission.
70#[derive(Debug, PartialEq, Clone)]
71pub enum Entity {
72    /// A single user, identified by its id.
73    UserId(String),
74    /// A single user, identified by its email address.
75    UserEmail(String),
76    /// A group of users, identified by its id.
77    GroupId(String),
78    /// A group of users, identified by its email address.
79    GroupEmail(String),
80    /// All users identifed by an email that ends with the domain, for example `mydomain.rs` in
81    /// `me@mydomain.rs`.
82    Domain(String),
83    /// All users within a project, identified by the `team` name and `project` id.
84    Project(Team, String),
85    /// All users.
86    AllUsers,
87    /// All users that are logged in.
88    AllAuthenticatedUsers,
89}
90
91use Entity::*;
92
93impl std::fmt::Display for Entity {
94    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
95        match self {
96            UserId(s) => write!(f, "user-{}", s),
97            UserEmail(s) => write!(f, "user-{}", s),
98            GroupId(s) => write!(f, "group-{}", s),
99            GroupEmail(s) => write!(f, "group-{}", s),
100            Domain(s) => write!(f, "domain-{}", s),
101            Project(team, project_id) => write!(f, "project-{}-{}", team, project_id),
102            AllUsers => write!(f, "allUsers"),
103            AllAuthenticatedUsers => write!(f, "allAuthenticatedUsers"),
104        }
105    }
106}
107
108impl serde::Serialize for Entity {
109    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110    where
111        S: Serializer,
112    {
113        serializer.serialize_str(&format!("{}", self))
114    }
115}
116
117struct EntityVisitor;
118
119impl<'de> serde::de::Visitor<'de> for EntityVisitor {
120    type Value = Entity;
121
122    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
123        f.write_str("an `Entity` resource")
124    }
125
126    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
127    where
128        E: serde::de::Error,
129    {
130        let parts: Vec<&str> = value.split('-').collect();
131        let result = match &parts[..] {
132            ["user", rest @ ..] if is_email(rest) => UserEmail(rest.join("-")),
133            ["user", rest @ ..] => UserId(rest.join("-")),
134            ["group", rest @ ..] if is_email(rest) => GroupEmail(rest.join("-")),
135            ["group", rest @ ..] => GroupId(rest.join("-")),
136            ["domain", rest @ ..] => Domain(rest.join("-")),
137            ["project", team, project_id] => Project(Team::from_str(team).unwrap(), project_id.to_string()),
138            ["allUsers"] => AllUsers,
139            ["allAuthenticatedUsers"] => AllAuthenticatedUsers,
140            _ => return Err(E::custom(format!("Unexpected `Entity`: {}", value))),
141        };
142        Ok(result)
143    }
144}
145
146fn is_email(pattern: &[&str]) -> bool {
147    pattern.iter().any(|s| s.contains('@'))
148}
149
150impl<'de> serde::Deserialize<'de> for Entity {
151    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
152    where
153        D: serde::Deserializer<'de>,
154    {
155        deserializer.deserialize_str(EntityVisitor)
156    }
157}
158
159#[cfg(test)]
160mod tests {
161    use super::*;
162
163    #[test]
164    fn serialize() {
165        let entity1 = UserId("some id".to_string());
166        assert_eq!(serde_json::to_string(&entity1).unwrap(), "\"user-some id\"");
167
168        let entity2 = UserEmail("some@email".to_string());
169        assert_eq!(
170            serde_json::to_string(&entity2).unwrap(),
171            "\"user-some@email\""
172        );
173
174        let entity3 = GroupId("some group id".to_string());
175        assert_eq!(
176            serde_json::to_string(&entity3).unwrap(),
177            "\"group-some group id\""
178        );
179
180        let entity4 = GroupEmail("some@group.email".to_string());
181        assert_eq!(
182            serde_json::to_string(&entity4).unwrap(),
183            "\"group-some@group.email\""
184        );
185
186        let entity5 = Domain("example.com".to_string());
187        assert_eq!(
188            serde_json::to_string(&entity5).unwrap(),
189            "\"domain-example.com\""
190        );
191
192        let entity6 = Project(Team::Viewers, "project id".to_string());
193        assert_eq!(
194            serde_json::to_string(&entity6).unwrap(),
195            "\"project-viewers-project id\""
196        );
197
198        let entity7 = AllUsers;
199        assert_eq!(serde_json::to_string(&entity7).unwrap(), "\"allUsers\"");
200
201        let entity8 = AllAuthenticatedUsers;
202        assert_eq!(
203            serde_json::to_string(&entity8).unwrap(),
204            "\"allAuthenticatedUsers\""
205        );
206    }
207
208    #[test]
209    fn deserialize() {
210        let str1 = "\"user-some id\"";
211        assert_eq!(
212            serde_json::from_str::<Entity>(str1).unwrap(),
213            UserId("some id".to_string())
214        );
215
216        let str2 = "\"user-some@email\"";
217        assert_eq!(
218            serde_json::from_str::<Entity>(str2).unwrap(),
219            UserEmail("some@email".to_string())
220        );
221
222        let str3 = "\"group-some group id\"";
223        assert_eq!(
224            serde_json::from_str::<Entity>(str3).unwrap(),
225            GroupId("some group id".to_string())
226        );
227
228        let str4 = "\"group-some@group.email\"";
229        assert_eq!(
230            serde_json::from_str::<Entity>(str4).unwrap(),
231            GroupEmail("some@group.email".to_string())
232        );
233
234        let str5 = "\"domain-example.com\"";
235        assert_eq!(
236            serde_json::from_str::<Entity>(str5).unwrap(),
237            Domain("example.com".to_string())
238        );
239
240        let str6 = "\"project-viewers-project id\"";
241        assert_eq!(
242            serde_json::from_str::<Entity>(str6).unwrap(),
243            Project(Team::Viewers, "project id".to_string())
244        );
245
246        let str7 = "\"allUsers\"";
247        assert_eq!(serde_json::from_str::<Entity>(str7).unwrap(), AllUsers);
248
249        let str8 = "\"allAuthenticatedUsers\"";
250        assert_eq!(
251            serde_json::from_str::<Entity>(str8).unwrap(),
252            AllAuthenticatedUsers
253        );
254    }
255}