cloud_storage/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] => {
138                Project(Team::from_str(team).unwrap(), project_id.to_string())
139            }
140            ["allUsers"] => AllUsers,
141            ["allAuthenticatedUsers"] => AllAuthenticatedUsers,
142            _ => return Err(E::custom(format!("Unexpected `Entity`: {}", value))),
143        };
144        Ok(result)
145    }
146}
147
148fn is_email(pattern: &[&str]) -> bool {
149    pattern.iter().any(|s| s.contains('@'))
150}
151
152impl<'de> serde::Deserialize<'de> for Entity {
153    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
154    where
155        D: serde::Deserializer<'de>,
156    {
157        deserializer.deserialize_str(EntityVisitor)
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn serialize() {
167        let entity1 = UserId("some id".to_string());
168        assert_eq!(serde_json::to_string(&entity1).unwrap(), "\"user-some id\"");
169
170        let entity2 = UserEmail("some@email".to_string());
171        assert_eq!(
172            serde_json::to_string(&entity2).unwrap(),
173            "\"user-some@email\""
174        );
175
176        let entity3 = GroupId("some group id".to_string());
177        assert_eq!(
178            serde_json::to_string(&entity3).unwrap(),
179            "\"group-some group id\""
180        );
181
182        let entity4 = GroupEmail("some@group.email".to_string());
183        assert_eq!(
184            serde_json::to_string(&entity4).unwrap(),
185            "\"group-some@group.email\""
186        );
187
188        let entity5 = Domain("example.com".to_string());
189        assert_eq!(
190            serde_json::to_string(&entity5).unwrap(),
191            "\"domain-example.com\""
192        );
193
194        let entity6 = Project(Team::Viewers, "project id".to_string());
195        assert_eq!(
196            serde_json::to_string(&entity6).unwrap(),
197            "\"project-viewers-project id\""
198        );
199
200        let entity7 = AllUsers;
201        assert_eq!(serde_json::to_string(&entity7).unwrap(), "\"allUsers\"");
202
203        let entity8 = AllAuthenticatedUsers;
204        assert_eq!(
205            serde_json::to_string(&entity8).unwrap(),
206            "\"allAuthenticatedUsers\""
207        );
208    }
209
210    #[test]
211    fn deserialize() {
212        let str1 = "\"user-some id\"";
213        assert_eq!(
214            serde_json::from_str::<Entity>(str1).unwrap(),
215            UserId("some id".to_string())
216        );
217
218        let str2 = "\"user-some@email\"";
219        assert_eq!(
220            serde_json::from_str::<Entity>(str2).unwrap(),
221            UserEmail("some@email".to_string())
222        );
223
224        let str3 = "\"group-some group id\"";
225        assert_eq!(
226            serde_json::from_str::<Entity>(str3).unwrap(),
227            GroupId("some group id".to_string())
228        );
229
230        let str4 = "\"group-some@group.email\"";
231        assert_eq!(
232            serde_json::from_str::<Entity>(str4).unwrap(),
233            GroupEmail("some@group.email".to_string())
234        );
235
236        let str5 = "\"domain-example.com\"";
237        assert_eq!(
238            serde_json::from_str::<Entity>(str5).unwrap(),
239            Domain("example.com".to_string())
240        );
241
242        let str6 = "\"project-viewers-project id\"";
243        assert_eq!(
244            serde_json::from_str::<Entity>(str6).unwrap(),
245            Project(Team::Viewers, "project id".to_string())
246        );
247
248        let str7 = "\"allUsers\"";
249        assert_eq!(serde_json::from_str::<Entity>(str7).unwrap(), AllUsers);
250
251        let str8 = "\"allAuthenticatedUsers\"";
252        assert_eq!(
253            serde_json::from_str::<Entity>(str8).unwrap(),
254            AllAuthenticatedUsers
255        );
256    }
257}