cloud_storage/resources/
bucket_access_control.rs

1pub use crate::resources::common::{Entity, ProjectTeam, Role};
2
3/// The BucketAccessControl resource represents the Access Control Lists (ACLs) for buckets within
4/// Google Cloud Storage. ACLs let you specify who has access to your data and to what extent.
5///
6/// ```text,ignore
7/// Important: This method fails with a 400 Bad Request response for buckets with uniform
8/// bucket-level access enabled. Use `Bucket::get_iam_policy` and `Bucket::set_iam_policy` to
9/// control access instead.
10/// ```
11///
12/// There are three roles that can be assigned to an entity:
13///
14/// * READERs can get the bucket, though no acl property will be returned, and list the bucket's
15/// objects.
16/// * WRITERs are READERs, and they can insert objects into the bucket and delete the bucket's
17/// objects.
18/// * OWNERs are WRITERs, and they can get the acl property of a bucket, update a bucket, and call
19/// all BucketAccessControl methods on the bucket.
20#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
21#[serde(rename_all = "camelCase")]
22pub struct BucketAccessControl {
23    /// The kind of item this is. For bucket access control entries, this is always
24    /// `storage#bucketAccessControl`.
25    pub kind: String,
26    /// The ID of the access-control entry.
27    pub id: String,
28    /// The link to this access-control entry.
29    pub self_link: String,
30    /// The name of the bucket.
31    pub bucket: String,
32    /// The entity holding the permission, in one of the following forms:
33    ///
34    /// * `user-userId`
35    /// * `user-email`
36    /// * `group-groupId`
37    /// * `group-email`
38    /// * `domain-domain`
39    /// * `project-team-projectId`
40    /// * `allUsers`
41    /// * `allAuthenticatedUsers`
42    ///
43    /// Examples:
44    ///
45    /// * The user liz@example.com would be user-liz@example.com.
46    /// * The group example@googlegroups.com would be group-example@googlegroups.com.
47    /// * To refer to all members of the G Suite for Business domain example.com, the entity would
48    /// be domain-example.com.
49    pub entity: Entity,
50    /// The access permission for the entity.
51    pub role: Role,
52    /// The email address associated with the entity, if any.
53    pub email: Option<String>,
54    /// The ID for the entity, if any.
55    pub entity_id: Option<String>,
56    /// The domain associated with the entity, if any.
57    pub domain: Option<String>,
58    /// The project team associated with the entity, if any.
59    pub project_team: Option<ProjectTeam>,
60    /// HTTP 1.1 Entity tag for the access-control entry.
61    pub etag: String,
62}
63
64/// Model that can be used to create a new BucketAccessControl object.
65#[derive(Debug, PartialEq, serde::Serialize)]
66#[serde(rename_all = "camelCase")]
67pub struct NewBucketAccessControl {
68    /// The entity holding the permission, in one of the following forms:
69    ///
70    /// * `user-userId`
71    /// * `user-email`
72    /// * `group-groupId`
73    /// * `group-email`
74    /// * `domain-domain`
75    /// * `project-team-projectId`
76    /// * `allUsers`
77    /// * `allAuthenticatedUsers`
78    ///
79    /// Examples:
80    ///
81    /// * The user liz@example.com would be user-liz@example.com.
82    /// * The group example@googlegroups.com would be group-example@googlegroups.com.
83    /// * To refer to all members of the G Suite for Business domain example.com, the entity would
84    /// be domain-example.com.
85    pub entity: Entity,
86    /// The access permission for the entity.
87    pub role: Role,
88}
89
90impl BucketAccessControl {
91    /// Create a new `BucketAccessControl` using the provided `NewBucketAccessControl`, related to
92    /// the `Bucket` provided by the `bucket_name` argument.
93    ///
94    /// ### Important
95    /// Important: This method fails with a 400 Bad Request response for buckets with uniform
96    /// bucket-level access enabled. Use `Bucket::get_iam_policy` and `Bucket::set_iam_policy` to
97    /// control access instead.
98    /// ### Example
99    /// ```rust,no_run
100    /// # #[tokio::main]
101    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
102    /// use cloud_storage::bucket_access_control::{BucketAccessControl, NewBucketAccessControl};
103    /// use cloud_storage::bucket_access_control::{Role, Entity};
104    ///
105    /// let new_bucket_access_control = NewBucketAccessControl {
106    ///     entity: Entity::AllUsers,
107    ///     role: Role::Reader,
108    /// };
109    /// BucketAccessControl::create("mybucket", &new_bucket_access_control).await?;
110    /// # Ok(())
111    /// # }
112    /// ```
113    #[cfg(feature = "global-client")]
114    pub async fn create(
115        bucket: &str,
116        new_bucket_access_control: &NewBucketAccessControl,
117    ) -> crate::Result<Self> {
118        crate::CLOUD_CLIENT
119            .bucket_access_control()
120            .create(bucket, new_bucket_access_control)
121            .await
122    }
123
124    /// The synchronous equivalent of `BucketAccessControl::create`.
125    ///
126    /// ### Features
127    /// This function requires that the feature flag `sync` is enabled in `Cargo.toml`.
128    #[cfg(all(feature = "global-client", feature = "sync"))]
129    pub fn create_sync(
130        bucket: &str,
131        new_bucket_access_control: &NewBucketAccessControl,
132    ) -> crate::Result<Self> {
133        crate::runtime()?.block_on(Self::create(bucket, new_bucket_access_control))
134    }
135
136    /// Returns all `BucketAccessControl`s related to this bucket.
137    ///
138    /// ### Important
139    /// Important: This method fails with a 400 Bad Request response for buckets with uniform
140    /// bucket-level access enabled. Use `Bucket::get_iam_policy` and `Bucket::set_iam_policy` to
141    /// control access instead.
142    /// ### Example
143    /// ```rust,no_run
144    /// # #[tokio::main]
145    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
146    /// use cloud_storage::bucket_access_control::BucketAccessControl;
147    ///
148    /// let acls = BucketAccessControl::list("mybucket").await?;
149    /// # Ok(())
150    /// # }
151    /// ```
152    #[cfg(feature = "global-client")]
153    pub async fn list(bucket: &str) -> crate::Result<Vec<Self>> {
154        crate::CLOUD_CLIENT
155            .bucket_access_control()
156            .list(bucket)
157            .await
158    }
159
160    /// The synchronous equivalent of `BucketAccessControl::list`.
161    ///
162    /// ### Features
163    /// This function requires that the feature flag `sync` is enabled in `Cargo.toml`.
164    #[cfg(all(feature = "global-client", feature = "sync"))]
165    pub fn list_sync(bucket: &str) -> crate::Result<Vec<Self>> {
166        crate::runtime()?.block_on(Self::list(bucket))
167    }
168
169    /// Returns the ACL entry for the specified entity on the specified bucket.
170    ///
171    /// ### Important
172    /// Important: This method fails with a 400 Bad Request response for buckets with uniform
173    /// bucket-level access enabled. Use `Bucket::get_iam_policy` and `Bucket::set_iam_policy` to
174    /// control access instead.
175    /// ### Example
176    /// ```rust,no_run
177    /// # #[tokio::main]
178    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
179    /// use cloud_storage::bucket_access_control::{BucketAccessControl, Entity};
180    ///
181    /// let controls = BucketAccessControl::read("mybucket", &Entity::AllUsers).await?;
182    /// # Ok(())
183    /// # }
184    /// ```
185    #[cfg(feature = "global-client")]
186    pub async fn read(bucket: &str, entity: &Entity) -> crate::Result<Self> {
187        crate::CLOUD_CLIENT
188            .bucket_access_control()
189            .read(bucket, entity)
190            .await
191    }
192
193    /// The synchronous equivalent of `BucketAccessControl::read`.
194    ///
195    /// ### Features
196    /// This function requires that the feature flag `sync` is enabled in `Cargo.toml`.
197    #[cfg(all(feature = "global-client", feature = "sync"))]
198    pub fn read_sync(bucket: &str, entity: &Entity) -> crate::Result<Self> {
199        crate::runtime()?.block_on(Self::read(bucket, entity))
200    }
201
202    /// Update this `BucketAccessControl`.
203    ///
204    /// ### Important
205    /// Important: This method fails with a 400 Bad Request response for buckets with uniform
206    /// bucket-level access enabled. Use `Bucket::get_iam_policy` and `Bucket::set_iam_policy` to
207    /// control access instead.
208    /// ### Example
209    /// ```rust,no_run
210    /// # #[tokio::main]
211    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
212    /// use cloud_storage::bucket_access_control::{BucketAccessControl, Entity};
213    ///
214    /// let mut acl = BucketAccessControl::read("mybucket", &Entity::AllUsers).await?;
215    /// acl.entity = Entity::AllAuthenticatedUsers;
216    /// acl.update().await?;
217    /// # Ok(())
218    /// # }
219    /// ```
220    #[cfg(feature = "global-client")]
221    pub async fn update(&self) -> crate::Result<Self> {
222        crate::CLOUD_CLIENT
223            .bucket_access_control()
224            .update(self)
225            .await
226    }
227
228    /// The synchronous equivalent of `BucketAccessControl::update`.
229    ///
230    /// ### Features
231    /// This function requires that the feature flag `sync` is enabled in `Cargo.toml`.
232    #[cfg(all(feature = "global-client", feature = "sync"))]
233    pub fn update_sync(&self) -> crate::Result<Self> {
234        crate::runtime()?.block_on(self.update())
235    }
236
237    /// Permanently deletes the ACL entry for the specified entity on the specified bucket.
238    ///
239    /// ### Important
240    /// Important: This method fails with a 400 Bad Request response for buckets with uniform
241    /// bucket-level access enabled. Use `Bucket::get_iam_policy` and `Bucket::set_iam_policy` to
242    /// control access instead.
243    /// ### Example
244    /// ```rust,no_run
245    /// # #[tokio::main]
246    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
247    /// use cloud_storage::bucket_access_control::{BucketAccessControl, Entity};
248    ///
249    /// let controls = BucketAccessControl::read("mybucket", &Entity::AllUsers).await?;
250    /// controls.delete().await?;
251    /// # Ok(())
252    /// # }
253    /// ```
254    #[cfg(feature = "global-client")]
255    pub async fn delete(self) -> crate::Result<()> {
256        crate::CLOUD_CLIENT
257            .bucket_access_control()
258            .delete(self)
259            .await
260    }
261
262    /// The synchronous equivalent of `BucketAccessControl::delete`.
263    ///
264    /// ### Features
265    /// This function requires that the feature flag `sync` is enabled in `Cargo.toml`.
266    #[cfg(all(feature = "global-client", feature = "sync"))]
267    pub fn delete_sync(self) -> crate::Result<()> {
268        crate::runtime()?.block_on(self.delete())
269    }
270}
271
272#[cfg(all(test, feature = "global-client"))]
273mod tests {
274    use super::*;
275
276    #[tokio::test]
277    async fn create() -> Result<(), Box<dyn std::error::Error>> {
278        let bucket = crate::read_test_bucket().await;
279        let new_bucket_access_control = NewBucketAccessControl {
280            entity: Entity::AllUsers,
281            role: Role::Reader,
282        };
283        BucketAccessControl::create(&bucket.name, &new_bucket_access_control)
284            .await
285            .unwrap();
286        Ok(())
287    }
288
289    #[tokio::test]
290    async fn list() -> Result<(), Box<dyn std::error::Error>> {
291        let bucket = crate::read_test_bucket().await;
292        BucketAccessControl::list(&bucket.name).await?;
293        Ok(())
294    }
295
296    #[tokio::test]
297    async fn read() -> Result<(), Box<dyn std::error::Error>> {
298        let bucket = crate::read_test_bucket().await;
299        BucketAccessControl::read(&bucket.name, &Entity::AllUsers).await?;
300        Ok(())
301    }
302
303    #[tokio::test]
304    async fn update() -> Result<(), Box<dyn std::error::Error>> {
305        // use a seperate bucket to prevent synchronization issues
306        let bucket = crate::create_test_bucket("test-update-bucket-access-controls").await;
307        let new_bucket_access_control = NewBucketAccessControl {
308            entity: Entity::AllUsers,
309            role: Role::Reader,
310        };
311        BucketAccessControl::create(&bucket.name, &new_bucket_access_control).await?;
312        let mut acl = BucketAccessControl::read(&bucket.name, &Entity::AllUsers).await?;
313        acl.entity = Entity::AllAuthenticatedUsers;
314        acl.update().await?;
315        bucket.delete().await?;
316        Ok(())
317    }
318
319    #[tokio::test]
320    async fn delete() -> Result<(), Box<dyn std::error::Error>> {
321        // use a seperate bucket to prevent synchronization issues
322        let bucket = crate::create_test_bucket("test-delete-bucket-access-controls").await;
323        let new_bucket_access_control = NewBucketAccessControl {
324            entity: Entity::AllUsers,
325            role: Role::Reader,
326        };
327        BucketAccessControl::create(&bucket.name, &new_bucket_access_control).await?;
328        let acl = BucketAccessControl::read(&bucket.name, &Entity::AllUsers).await?;
329        acl.delete().await?;
330        bucket.delete().await?;
331        Ok(())
332    }
333
334    #[cfg(all(feature = "global-client", feature = "sync"))]
335    mod sync {
336        use super::*;
337
338        #[test]
339        fn create() -> Result<(), Box<dyn std::error::Error>> {
340            let bucket = crate::read_test_bucket_sync();
341            let new_bucket_access_control = NewBucketAccessControl {
342                entity: Entity::AllUsers,
343                role: Role::Reader,
344            };
345            BucketAccessControl::create_sync(&bucket.name, &new_bucket_access_control)?;
346            Ok(())
347        }
348
349        #[test]
350        fn list() -> Result<(), Box<dyn std::error::Error>> {
351            let bucket = crate::read_test_bucket_sync();
352            BucketAccessControl::list_sync(&bucket.name)?;
353            Ok(())
354        }
355
356        #[test]
357        fn read() -> Result<(), Box<dyn std::error::Error>> {
358            let bucket = crate::read_test_bucket_sync();
359            BucketAccessControl::read_sync(&bucket.name, &Entity::AllUsers)?;
360            Ok(())
361        }
362
363        #[test]
364        fn update() -> Result<(), Box<dyn std::error::Error>> {
365            // use a seperate bucket to prevent synchronization issues
366            let bucket = crate::create_test_bucket_sync("test-update-bucket-access-controls");
367            let new_bucket_access_control = NewBucketAccessControl {
368                entity: Entity::AllUsers,
369                role: Role::Reader,
370            };
371            BucketAccessControl::create_sync(&bucket.name, &new_bucket_access_control)?;
372            let mut acl = BucketAccessControl::read_sync(&bucket.name, &Entity::AllUsers)?;
373            acl.entity = Entity::AllAuthenticatedUsers;
374            acl.update_sync()?;
375            bucket.delete_sync()?;
376            Ok(())
377        }
378
379        #[test]
380        fn delete() -> Result<(), Box<dyn std::error::Error>> {
381            // use a seperate bucket to prevent synchronization issues
382            let bucket = crate::create_test_bucket_sync("test-delete-bucket-access-controls");
383            let new_bucket_access_control = NewBucketAccessControl {
384                entity: Entity::AllUsers,
385                role: Role::Reader,
386            };
387            BucketAccessControl::create_sync(&bucket.name, &new_bucket_access_control)?;
388            let acl = BucketAccessControl::read_sync(&bucket.name, &Entity::AllUsers)?;
389            acl.delete_sync()?;
390            bucket.delete_sync()?;
391            Ok(())
392        }
393    }
394}