cloud_storage_rs/resources/
bucket.rs

1use crate::error::{Error, GoogleResponse};
2use crate::resources::bucket_access_control::{BucketAccessControl, NewBucketAccessControl};
3pub use crate::resources::common::Entity;
4use crate::resources::common::ListResponse;
5use crate::resources::default_object_access_control::{
6    DefaultObjectAccessControl, NewDefaultObjectAccessControl,
7};
8pub use crate::resources::location::*;
9
10/// The Buckets resource represents a
11/// [bucket](https://cloud.google.com/storage/docs/key-terms#buckets) in Google Cloud Storage. There
12/// is a single global namespace shared by all buckets. For more information, see
13/// [Bucket Name Requirements](https://cloud.google.com/storage/docs/naming#requirements).
14///
15/// Buckets contain objects which can be accessed by their own methods. In addition to the 
16/// [ACL property](https://cloud.google.com/storage/docs/access-control/lists), buckets contain
17/// `BucketAccessControls`, for use in fine-grained manipulation of an existing bucket's access
18/// controls.
19///
20/// A bucket is always owned by the project team owners group.
21#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct Bucket {
24    /// The kind of item this is. For buckets, this is always `storage#bucket`.
25    pub kind: String,
26    /// The ID of the bucket. For buckets, the `id` and `name` properties are the same.
27    pub id: String, // should be u64, mumble mumble
28    /// The URI of this bucket.
29    pub self_link: String,
30    /// The project number of the project the bucket belongs to.
31    #[serde(deserialize_with = "crate::from_str")]
32    pub project_number: u64,
33    /// The name of the bucket.
34    pub name: String,
35    /// The creation time of the bucket in RFC 3339 format.
36    pub time_created: chrono::DateTime<chrono::Utc>,
37    /// The modification time of the bucket in RFC 3339 format.
38    pub updated: chrono::DateTime<chrono::Utc>,
39    /// Whether or not to automatically apply an eventBasedHold to new objects added to the bucket.
40    pub default_event_based_hold: Option<bool>,
41    /// The bucket's retention policy, which defines the minimum age an object in the bucket must
42    /// reach before it can be deleted or overwritten.
43    pub retention_policy: Option<RetentionPolicy>,
44    /// The metadata generation of this bucket.
45    #[serde(deserialize_with = "crate::from_str")]
46    pub metageneration: i64,
47    /// Access controls on the bucket, containing one or more bucketAccessControls Resources. If
48    /// iamConfiguration.uniformBucketLevelAccess.enabled is set to true, this field is omitted in
49    /// responses, and requests that specify this field fail with a 400 Bad Request response.
50    pub acl: Option<Vec<BucketAccessControl>>,
51    /// Default access controls to apply to new objects when no ACL is provided. This list contains
52    /// one or more defaultObjectAccessControls Resources. If
53    /// iamConfiguration.uniformBucketLevelAccess.enabled is set to true, this field is omitted in
54    /// responses, and requests that specify this field fail.
55    pub default_object_acl: Option<Vec<DefaultObjectAccessControl>>,
56    /// The bucket's IAM configuration.
57    pub iam_configuration: IamConfiguration,
58    /// Encryption configuration for a bucket.
59    pub encryption: Option<Encryption>,
60    /// The owner of the bucket. This is always the project team's owner group.
61    pub owner: Option<Owner>,
62    /// The location of the bucket. Object data for objects in the bucket resides in physical
63    /// storage within this region. Defaults to US. See Cloud Storage bucket locations for the
64    /// authoritative list.
65    pub location: Location,
66    /// The type of location that the bucket resides in, as determined by the location property.
67    pub location_type: String,
68    /// The bucket's website configuration, controlling how the service behaves when accessing
69    /// bucket contents as a web site. See the Static Website Examples for more information.
70    pub website: Option<Website>,
71    /// The bucket's logging configuration, which defines the destination bucket and optional name
72    /// prefix for the current bucket's logs.
73    pub logging: Option<Logging>,
74    /// The bucket's versioning configuration.
75    pub versioning: Option<Versioning>,
76    /// The bucket's Cross-Origin Resource Sharing (CORS) configuration.
77    pub cors: Option<Vec<Cors>>,
78    /// The bucket's lifecycle configuration. See
79    /// [lifecycle management](https://cloud.google.com/storage/docs/lifecycle) for more
80    /// information.
81    pub lifecycle: Option<Lifecycle>,
82    /// User-provided bucket labels, in key/value pairs.
83    pub labels: Option<std::collections::HashMap<String, String>>,
84    /// The bucket's default storage class, used whenever no storageClass is specified for a
85    /// newly-created object. If storageClass is not specified when the bucket
86    /// is created, it defaults to STANDARD. For more information, see storage classes.
87    pub storage_class: StorageClass,
88    /// The bucket's billing configuration.
89    pub billing: Option<Billing>,
90    /// HTTP 1.1 [Entity tag](https://tools.ietf.org/html/rfc7232#section-2.3) for the bucket.
91    pub etag: String,
92}
93
94/// A model that can be used to insert new buckets into Google Cloud Storage.
95#[derive(Debug, PartialEq, Default, serde::Serialize)]
96#[serde(rename_all = "camelCase")]
97pub struct NewBucket {
98    /// The name of the bucket. See the bucket naming guidelines for more information.
99    pub name: String,
100    /// Whether or not to automatically apply an eventBasedHold to new objects added to the bucket.
101    pub default_event_based_hold: Option<bool>,
102    /// Access controls on the bucket, containing one or more `BucketAccessControls` resources. If
103    /// `iamConfiguration.uniformBucketLevelAccess.enabled` is set to true, this field is omitted in
104    /// responses, and requests that specify this field fail with a `400 Bad Request` response.
105    pub acl: Option<Vec<NewBucketAccessControl>>,
106    /// Default access controls to apply to new objects when no ACL is provided. This list defines
107    /// an entity and role for one or more `DefaultObjectAccessControls` resources. If
108    /// `iamConfiguration.uniformBucketLevelAccess.enabled` is set to true, this field is omitted in
109    /// responses, and requests that specify this field fail with a `400 Bad Request` response.
110    pub default_object_acl: Option<Vec<NewDefaultObjectAccessControl>>,
111    /// The bucket's IAM configuration.
112    pub iam_configuration: Option<IamConfiguration>,
113    /// Encryption configuration for a bucket.
114    pub encryption: Option<Encryption>,
115    /// The location of the bucket. Object data for objects in the bucket resides in physical
116    /// storage within this region. Defaults to US. See Cloud Storage bucket locations for the
117    /// authoritative list.
118    pub location: Location,
119    /// The bucket's website configuration, controlling how the service behaves when accessing
120    /// bucket contents as a web site. See the Static Website Examples for more information.
121    pub website: Option<Website>,
122    /// The bucket's logging configuration, which defines the destination bucket and optional name
123    /// prefix for the current bucket's logs.
124    pub logging: Option<Logging>,
125    /// The bucket's versioning configuration.
126    pub versioning: Option<Versioning>,
127    /// The bucket's Cross-Origin Resource Sharing (CORS) configuration.
128    pub cors: Option<Vec<Cors>>,
129    /// The bucket's lifecycle configuration. See
130    /// [lifecycle management](https://cloud.google.com/storage/docs/lifecycle) for more
131    /// information.
132    pub lifecycle: Option<Lifecycle>,
133    /// User-provided bucket labels, in key/value pairs.
134    pub labels: Option<std::collections::HashMap<String, String>>,
135    /// The bucket's default storage class, used whenever no storageClass is specified for a
136    /// newly-created object. If storageClass is not specified when the bucket
137    /// is created, it defaults to STANDARD. For more information, see storage classes.
138    pub storage_class: Option<StorageClass>,
139    /// The bucket's billing configuration.
140    pub billing: Option<Billing>,
141}
142
143/// Contains information about how files are kept after deletion.
144#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
145#[serde(rename_all = "camelCase")]
146pub struct RetentionPolicy {
147    /// The period of time, in seconds, that objects in the bucket must be retained and cannot be
148    /// deleted, overwritten, or made noncurrent. The value must be greater than 0 seconds and less
149    /// than 3,155,760,000 seconds.
150    #[serde(deserialize_with = "crate::from_str")]
151    pub retention_period: u64,
152    /// The time from which the retentionPolicy was effective, in RFC 3339 format.
153    pub effective_time: chrono::DateTime<chrono::Utc>,
154    /// Whether or not the retentionPolicy is locked. If true, the retentionPolicy cannot be removed
155    /// and the retention period cannot be reduced.
156    pub is_locked: Option<bool>,
157}
158
159/// Contains information about the Buckets IAM configuration.
160#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
161#[serde(rename_all = "camelCase")]
162pub struct IamConfiguration {
163    /// The bucket's uniform bucket-level access configuration.
164    ///
165    /// Note: iamConfiguration also includes the bucketPolicyOnly field, which uses a legacy name
166    /// but has the same functionality as the uniformBucketLevelAccess field. We recommend only
167    /// using uniformBucketLevelAccess, as specifying both fields may result in unreliable behavior.
168    pub uniform_bucket_level_access: UniformBucketLevelAccess,
169}
170
171/// Access that is configured for all objects in one go.
172#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct UniformBucketLevelAccess {
175    /// Whether or not the bucket uses uniform bucket-level access. If set, access checks only use
176    /// bucket-level IAM policies or above.
177    pub enabled: bool,
178    /// The deadline time for changing iamConfiguration.uniformBucketLevelAccess.enabled from true
179    /// to false, in RFC 3339 format.
180    ///
181    /// iamConfiguration.uniformBucketLevelAccess.enabled may be changed from true to false until
182    /// the locked time, after which the field is immutable.
183    pub locked_time: Option<chrono::DateTime<chrono::Utc>>,
184}
185
186/// Contains information about the encryption used for data in this Bucket.
187#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
188#[serde(rename_all = "camelCase")]
189pub struct Encryption {
190    /// A Cloud KMS key that will be used to encrypt objects inserted into this bucket, if no
191    /// encryption method is specified.
192    pub default_kms_key_name: String,
193}
194
195/// Contains information about an entity that is able to own a `Bucket`.
196#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
197#[serde(rename_all = "camelCase")]
198pub struct Owner {
199    /// The entity, in the form project-owner-projectId.
200    pub entity: Entity,
201    /// The ID for the entity.
202    pub entity_id: Option<String>,
203}
204
205/// Contains configuration about how to visit the website linked to this Bucket.
206#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
207#[serde(rename_all = "camelCase")]
208pub struct Website {
209    /// If the requested object path is missing, the service will ensure the path has a trailing
210    /// '/', append this suffix, and attempt to retrieve the resulting object. This allows the
211    /// creation of index.html objects to represent directory pages.
212    pub main_page_suffix: String,
213    /// If the requested object path is missing, and any mainPageSuffix object is missing, if
214    /// applicable, the service will return the named object from this bucket as the content for a
215    /// 404 Not Found result.
216    pub not_found_page: String,
217}
218
219/// Contains information of where and how access logs to this bucket are maintained.
220#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
221#[serde(rename_all = "camelCase")]
222pub struct Logging {
223    /// The destination bucket where the current bucket's logs should be placed.
224    pub log_bucket: String,
225    /// A prefix for log object names. The default prefix is the bucket name.
226    pub log_object_prefix: String,
227}
228
229/// Contains information about whether a Bucket keeps track of its version.
230#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
231#[serde(rename_all = "camelCase")]
232pub struct Versioning {
233    /// While set to true, versioning is fully enabled for this bucket.
234    pub enabled: bool,
235}
236
237/// Contains information about how OPTIONS requests for this Bucket are handled.
238#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
239#[serde(rename_all = "camelCase")]
240pub struct Cors {
241    /// The list of Origins eligible to receive CORS response headers. Note: "*" is permitted in the
242    /// list of origins, and means "any Origin".
243    pub origin: Vec<String>,
244    /// The list of HTTP methods on which to include CORS response headers, (GET, OPTIONS, POST,
245    /// etc) Note: "*" is permitted in the list of methods, and means "any method".
246    pub method: Vec<String>,
247    /// The list of HTTP headers other than the simple response headers to give permission for the
248    /// user-agent to share across domains.
249    pub response_header: Vec<String>,
250    /// The value, in seconds, to return in the Access-Control-Max-Age header used in preflight
251    /// responses.
252    #[serde(deserialize_with = "crate::from_str")]
253    pub max_age_seconds: i32,
254}
255
256/// Contains a set of `Rule` Objects which together describe the way this lifecycle behaves
257#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
258#[serde(rename_all = "camelCase")]
259pub struct Lifecycle {
260    /// A lifecycle management rule, which is made of an action to take and the condition(s) under
261    /// which the action will be taken.
262    pub rule: Vec<Rule>,
263}
264
265/// An element of the lifecyle list.
266#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
267#[serde(rename_all = "camelCase")]
268pub struct Rule {
269    /// The action to take.
270    pub action: Action,
271    /// The condition(s) under which the action will be taken.
272    pub condition: Condition,
273}
274
275/// Represents an action that might be undertaken due to a `Condition`.
276#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
277#[serde(rename_all = "camelCase")]
278pub struct Action {
279    /// Type of the action.
280    pub r#type: ActionType,
281    /// Target storage class. Required iff the type of the action is SetStorageClass.
282    pub storage_class: Option<StorageClass>,
283}
284
285/// Type of the action.
286#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
287pub enum ActionType {
288    /// Deletes a Bucket.
289    Delete,
290    /// Sets the `storage_class` of a Bucket.
291    SetStorageClass,
292}
293
294/// A rule that might induce an `Action` if met.
295#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
296#[serde(rename_all = "camelCase")]
297pub struct Condition {
298    /// Age of an object (in days). This condition is satisfied when an object reaches the specified
299    /// age.
300    #[serde(deserialize_with = "crate::from_str")]
301    pub age: i32,
302    /// A date in `RFC 3339` format with only the date part (for instance, "2013-01-15"). This
303    /// condition is satisfied when an object is created before midnight of the specified date in
304    /// UTC.
305    pub created_before: chrono::DateTime<chrono::Utc>,
306    /// Relevant only for versioned objects. If the value is true, this condition matches the live
307    /// version of objects; if the value is `false`, it matches noncurrent versions of objects.
308    pub is_live: bool,
309    /// Objects having any of the storage classes specified by this condition will be matched.
310    /// Values include STANDARD, NEARLINE, COLDLINE, MULTI_REGIONAL, REGIONAL, and
311    /// DURABLE_REDUCED_AVAILABILITY.
312    pub matches_storage_class: Vec<String>,
313    /// Relevant only for versioned objects. If the value is N, this condition is satisfied when
314    /// there are at least N versions (including the live version) newer than this version of the
315    /// object.
316    #[serde(deserialize_with = "crate::from_str")]
317    pub num_newer_versions: i32,
318}
319
320/// Contains information about the payment structure of this bucket
321#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
322#[serde(rename_all = "camelCase")]
323pub struct Billing {
324    /// When set to true, Requester Pays is enabled for this bucket.
325    pub requester_pays: bool,
326}
327
328/// The type of storage that is used. Pertains to availability, performance and cost.
329#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
330#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
331pub enum StorageClass {
332    /// Standard Storage is best for data that is frequently accessed ("hot" data) and/or stored for
333    /// only brief periods of time.
334    Standard,
335    /// Nearline Storage is a low-cost, highly durable storage service for storing infrequently
336    /// accessed data.
337    Nearline,
338    /// Coldline Storage is a very-low-cost, highly durable storage service for data archiving,
339    /// online backup, and disaster recovery.
340    Coldline,
341    /// Equivalent to Standard Storage, except Multi-Regional Storage can only be used for objects
342    /// stored in multi-regions or dual-regions.
343    MultiRegional,
344    /// Equivalent to Standard Storage, except Regional Storage can only be used for objects stored
345    /// in regions.
346    Regional,
347    /// Similar to Standard Storage except:
348    ///
349    /// DRA has higher pricing for operations.
350    /// DRA has lower performance, particularly in terms of availability (DRA has a 99% availability
351    /// SLA).
352    ///
353    /// You can move your data from DRA to other storage classes by performing a storage transfer.
354    DurableReducedAvailability,
355}
356
357/// A representation of the IAM Policiy for a certain bucket.
358#[derive(Debug, PartialEq, Default, serde::Deserialize, serde::Serialize)]
359#[serde(rename_all = "camelCase")]
360pub struct IamPolicy {
361    /// The [Cloud IAM policy](https://cloud.google.com/iam/docs/policies#versions) version.
362    pub version: i32,
363    /// The kind of item this is. For policies, this field is ignored in a request and is
364    /// `storage#policy` in a response.
365    pub kind: Option<String>,
366    /// The ID of the resource to which this policy belongs. The response for this field is of the
367    /// form `projects/_/buckets/bucket`. This field is ignored in a request.
368    pub resource_id: Option<String>,
369    /// A list of the bindings for this policy.
370    pub bindings: Vec<Binding>,
371    /// HTTP 1.1 [Entity tag](https://tools.ietf.org/html/rfc7232#section-2.3) for this policy.
372    pub etag: String,
373}
374
375/// An association between a role, which comes with a set of permissions, and members who may assume
376/// that role.
377#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
378#[serde(rename_all = "camelCase")]
379pub struct Binding {
380    /// The role to which members belong. Two types of roles are supported: standard IAM roles,
381    /// which grant permissions that do not map directly to those provided by ACLs, and legacy IAM
382    /// roles, which do map directly to ACL permissions. All roles are of the format
383    /// `roles/storage.specificRole.`
384    ///
385    /// See
386    /// [Cloud Storage IAM Roles](https://cloud.google.com/storage/docs/access-control/iam-roles)
387    /// for a list of available roles.
388    pub role: IamRole,
389    /// A collection of identifiers for members who may assume the provided role. Recognized
390    /// identifiers are as follows:
391    ///
392    /// * `allUsers` — A special identifier that represents anyone on the internet; with or without
393    ///   a Google account.
394    /// * `allAuthenticatedUsers` — A special identifier that represents anyone who is authenticated
395    ///   with a Google account or a service account.
396    /// * `user:emailid` — An email address that represents a specific account. For example,
397    ///   user:alice@gmail.com or user:joe@example.com.
398    /// * `serviceAccount:emailid` — An email address that represents a service account. For
399    ///   example, serviceAccount:my-other-app@appspot.gserviceaccount.com .
400    /// * `group:emailid` — An email address that represents a Google group. For example,
401    ///   group:admins@example.com.
402    /// * `domain:domain` — A G Suite domain name that represents all the users of that domain. For
403    ///   example, domain:google.com or domain:example.com.
404    /// * `projectOwner:projectid` — Owners of the given project. For example,
405    ///   projectOwner:my-example-project
406    /// * `projectEditor:projectid` — Editors of the given project. For example,
407    ///   projectEditor:my-example-project
408    /// * `projectViewer:projectid` — Viewers of the given project. For example,
409    ///   projectViewer:my-example-project
410    pub members: Vec<String>,
411    /// A condition object associated with this binding. Each role binding can only contain one
412    /// condition.
413    pub condition: Option<IamCondition>,
414}
415
416/// A condition object associated with a binding.
417#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
418#[serde(rename_all = "camelCase")]
419pub struct IamCondition {
420    /// Title of the condition. For example, "expires_end_of_2018".
421    pub title: String,
422    /// Optional description of the condition. For example, "Expires at midnight on 2018-12-31".
423    pub description: Option<String>,
424    /// [Attribute-based](https://cloud.google.com/iam/docs/conditions-overview#attributes) logic
425    /// expression using a subset of the Common Expression Language (CEL). For example,
426    /// "request.time < timestamp('2019-01-01T00:00:00Z')".
427    pub expression: String,
428}
429
430/// All possible roles that can exist in the IAM system. For a more comprehensive version, check
431/// [Googles Documentation](https://cloud.google.com/storage/docs/access-control/iam-roles).
432#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
433#[serde(untagged)]
434pub enum IamRole {
435    /// Standard roles can be applied to either buckets or projects.
436    Standard(StandardIamRole),
437    /// Primitive roles are roles that must be added on a per-project basis.
438    Primitive(PrimitiveIamRole),
439    /// Legacy roles are roles that can only be added to an individual bucket.
440    Legacy(LegacyIamRole),
441}
442
443/// The following enum contains Cloud Identity and Access Management (Cloud IAM) roles that are
444/// associated with Cloud Storage and lists the permissions that are contained in each role. Unless
445/// otherwise noted, these roles can be applied either to entire projects or specific buckets.
446#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
447pub enum StandardIamRole {
448    /// Allows users to create objects. Does not give permission to view, delete, or overwrite
449    /// objects.
450    #[serde(rename = "roles/storage.objectCreator")]
451    ObjectCreator,
452    /// Grants access to view objects and their metadata, excluding ACLs.
453    ///
454    /// Can also list the objects in a bucket.
455    #[serde(rename = "roles/storage.objectViewer")]
456    ObjectViewer,
457    /// Grants full control over objects, including listing, creating, viewing, and deleting
458    /// objects.
459    #[serde(rename = "roles/storage.objectAdmin")]
460    ObjectAdmin,
461    /// Full control over HMAC keys in a project.
462    #[serde(rename = "roles/storage.hmacKeyAdmin")]
463    HmacKeyAdmin,
464    /// Grants full control of buckets and objects.
465    ///
466    /// When applied to an individual bucket, control applies only to the specified bucket and
467    /// objects within the bucket.
468    #[serde(rename = "roles/storage.admin")]
469    Admin,
470}
471
472/// The following enum contains primitive roles and the Cloud Storage permissions that these roles
473/// contain. Primitive roles cannot be added at the bucket-level.
474#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
475pub enum PrimitiveIamRole {
476    /// Grants permission to list buckets as well as view bucket metadata, excluding ACLs, when
477    /// listing. Also grants permission to list and get HMAC keys in the project.
478    #[serde(rename = "role/viewer")]
479    Viewer,
480    /// Grants permission to create, list, and delete buckets. Grants permission to view bucket
481    /// metadata, excluding ACLs, when listing. Grants full control over HMAC keys in a project.
482    #[serde(rename = "role/editor")]
483    Editor,
484    /// Grants permission to create, list, and delete buckets. Also grants permission to view bucket
485    /// metadata, excluding ACLs, when listing. Grants full control over HMAC keys in a project.
486    #[serde(rename = "role/owner")]
487    Owner,
488}
489
490/// The following enum contains Cloud IAM roles that are equivalent to Access Control List (ACL)
491/// permissions. These Cloud IAM roles can only be applied to a bucket, not a project.
492#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
493pub enum LegacyIamRole {
494    /// Grants permission to view objects and their metadata, excluding ACLs.
495    #[serde(rename = "roles/storage.legacyObjectReader")]
496    LegacyObjectReader,
497    /// Grants permission to view and edit objects and their metadata, including ACLs.
498    #[serde(rename = "roles/storage.legacyObjectOwner")]
499    LegacyObjectOwner,
500    /// Grants permission to list a bucket's contents and read bucket metadata, excluding Cloud IAM
501    /// policies. Also grants permission to read object metadata, excluding Cloud IAM policies, when
502    /// listing objects.
503    ///
504    /// Use of this role is also reflected in the bucket's ACLs. See
505    /// [Cloud IAM relation to ACLs](https://cloud.google.com/storage/docs/access-control/iam#acls)
506    /// for  more information.
507    #[serde(rename = "roles/storage.legacyBucketReader")]
508    LegacyBucketReader,
509    /// Grants permission to create, overwrite, and delete objects; list objects in a bucket and
510    /// read object metadata, excluding Cloud IAM policies, when listing; and read bucket metadata,
511    /// excluding Cloud IAM policies.
512    ///
513    /// Use of this role is also reflected in the bucket's ACLs. See
514    /// [Cloud IAM relation to ACLs](https://cloud.google.com/storage/docs/access-control/iam#acls)
515    /// for  more information.
516    #[serde(rename = "roles/storage.legacyBucketWriter")]
517    LegacyBucketWriter,
518    /// Grants permission to create, overwrite, and delete objects; list objects in a bucket and
519    /// read object metadata, excluding Cloud IAM policies, when listing; and read and edit bucket
520    /// metadata, including Cloud IAM policies.
521    ///
522    /// Use of this role is also reflected in the bucket's ACLs. See
523    /// [Cloud IAM relation to ACLs](https://cloud.google.com/storage/docs/access-control/iam#acls)
524    /// for  more information.
525    #[serde(rename = "roles/storage.legacyBucketOwner")]
526    LegacyBucketOwner,
527}
528
529/// The request needed to perform the Object::test_iam_permission function.
530#[derive(Debug, PartialEq, serde::Deserialize)]
531#[serde(rename_all = "camelCase")]
532pub struct TestIamPermission {
533    /// The kind of item this is.
534    kind: String,
535    /// The permissions held by the caller. Permissions are always of the format
536    /// `storage.resource.capability`, where resource is one of buckets or objects. See
537    /// [Cloud Storage IAM Permissions]
538    /// (https://cloud.google.com/storage/docs/access-control/iam-permissions) for a list of
539    /// supported permissions.
540    permissions: Vec<String>,
541}
542
543impl Bucket {
544    /// Creates a new `Bucket`. There are many options that you can provide for creating a new
545    /// bucket, so the `NewBucket` resource contains all of them. Note that `NewBucket` implements
546    /// `Default`, so you don't have to specify the fields you're not using. And error is returned
547    /// if that bucket name is already taken.
548    /// ### Example
549    /// ```
550    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
551    /// use cloud_storage::bucket::{Bucket, NewBucket};
552    /// use cloud_storage::bucket::{Location, MultiRegion};
553    ///
554    /// let new_bucket = NewBucket {
555    ///    name: "cloud-storage-rs-doc-1".to_string(), // this is the only mandatory field
556    ///    location: Location::Multi(MultiRegion::Eu),
557    ///    ..Default::default()
558    /// };
559    /// let bucket = Bucket::create(&new_bucket)?;
560    /// # bucket.delete();
561    /// # Ok(())
562    /// # }
563    /// ```
564    pub fn create(new_bucket: &NewBucket) -> Result<Self, Error> {
565        let url = format!("{}/b/", crate::BASE_URL);
566        let project = crate::SERVICE_ACCOUNT.project_id.clone();
567        let query = [("project", project)];
568        let client = reqwest::blocking::Client::new();
569        let result: GoogleResponse<Self> = client
570            .post(&url)
571            .headers(crate::get_headers()?)
572            .query(&query)
573            .json(new_bucket)
574            .send()?
575            .json()?;
576        match result {
577            GoogleResponse::Success(s) => Ok(s),
578            GoogleResponse::Error(e) => Err(e.into()),
579        }
580    }
581
582    /// Returns all `Bucket`s within this project.
583    /// ### Example
584    /// ```
585    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
586    /// use cloud_storage::Bucket;
587    ///
588    /// let buckets = Bucket::list()?;
589    /// # Ok(())
590    /// # }
591    /// ```
592    pub fn list() -> Result<Vec<Self>, Error> {
593        let url = format!("{}/b/", crate::BASE_URL);
594        let project = crate::SERVICE_ACCOUNT.project_id.clone();
595        let query = [("project", project)];
596        let client = reqwest::blocking::Client::new();
597        let result: GoogleResponse<ListResponse<Self>> = client
598            .get(&url)
599            .headers(crate::get_headers()?)
600            .query(&query)
601            .send()?
602            .json()?;
603        match result {
604            GoogleResponse::Success(s) => Ok(s.items),
605            GoogleResponse::Error(e) => Err(e.into()),
606        }
607    }
608
609    /// Returns a single `Bucket` by its name. If the Bucket does not exist, an error is returned.
610    /// ### Example
611    /// ```
612    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
613    /// use cloud_storage::Bucket;
614    /// # use cloud_storage::bucket::NewBucket;
615    /// # let new_bucket = NewBucket {
616    /// #   name: "cloud-storage-rs-doc-2".to_string(),
617    /// #    ..Default::default()
618    /// # };
619    /// # let _ = Bucket::create(&new_bucket)?;
620    ///
621    /// let bucket = Bucket::read("cloud-storage-rs-doc-2")?;
622    /// # bucket.delete()?;
623    /// # Ok(())
624    /// # }
625    /// ```
626    pub fn read(name: &str) -> Result<Self, Error> {
627        let url = format!("{}/b/{}", crate::BASE_URL, name);
628        let client = reqwest::blocking::Client::new();
629        let result: GoogleResponse<Self> = client
630            .get(&url)
631            .headers(crate::get_headers()?)
632            .send()?
633            .json()?;
634        match result {
635            GoogleResponse::Success(s) => Ok(s),
636            GoogleResponse::Error(e) => Err(e.into()),
637        }
638    }
639
640    /// Update an existing `Bucket`. If you declare you bucket as mutable, you can edit its fields.
641    /// You can then flush your changes to Google Cloud Storage using this method.
642    /// ### Example
643    /// ```
644    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
645    /// use cloud_storage::bucket::{Bucket, RetentionPolicy};
646    /// # use cloud_storage::bucket::NewBucket;
647    /// # let new_bucket = NewBucket {
648    /// #   name: "cloud-storage-rs-doc-3".to_string(),
649    /// #    ..Default::default()
650    /// # };
651    /// # let _ = Bucket::create(&new_bucket)?;
652    ///
653    /// let mut bucket = Bucket::read("cloud-storage-rs-doc-3")?;
654    /// bucket.retention_policy = Some(RetentionPolicy {
655    ///     retention_period: 50,
656    ///     effective_time: chrono::Utc::now() + chrono::Duration::seconds(50),
657    ///     is_locked: Some(false),
658    /// });
659    /// bucket.update()?;
660    /// # bucket.delete()?;
661    /// # Ok(())
662    /// # }
663    /// ```
664    pub fn update(&self) -> Result<Self, Error> {
665        let url = format!("{}/b/{}", crate::BASE_URL, self.name);
666        let client = reqwest::blocking::Client::new();
667        let result: GoogleResponse<Self> = client
668            .put(&url)
669            .headers(crate::get_headers()?)
670            .json(self)
671            .send()?
672            .json()?;
673        match result {
674            GoogleResponse::Success(s) => Ok(s),
675            GoogleResponse::Error(e) => Err(e.into()),
676        }
677    }
678
679    /// Delete an existing `Bucket`. This permanently removes a bucket from Google Cloud Storage.
680    /// An error is returned when you don't have sufficient permissions, or when the
681    /// `retention_policy` prevents you from deleting your Bucket.
682    /// ### Example
683    /// ```no_run
684    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
685    /// use cloud_storage::Bucket;
686    /// # use cloud_storage::bucket::NewBucket;
687    /// # let new_bucket = NewBucket {
688    /// #   name: "unnecessary-bucket".to_string(),
689    /// #    ..Default::default()
690    /// # };
691    /// # let _ = Bucket::create(&new_bucket)?;
692    ///
693    /// let bucket = Bucket::read("unnecessary-bucket")?;
694    /// bucket.delete()?;
695    /// # Ok(())
696    /// # }
697    /// ```
698    pub fn delete(self) -> Result<(), Error> {
699        let url = format!("{}/b/{}", crate::BASE_URL, self.name);
700        let client = reqwest::blocking::Client::new();
701        let response = client.delete(&url).headers(crate::get_headers()?).send()?;
702        if response.status().is_success() {
703            Ok(())
704        } else {
705            Err(Error::Google(response.json()?))
706        }
707    }
708
709    /// Returns the [IAM Policy](https://cloud.google.com/iam/docs/) for this bucket.
710    /// ### Example
711    /// ```
712    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
713    /// use cloud_storage::Bucket;
714    /// # use cloud_storage::bucket::NewBucket;
715    /// # let new_bucket = NewBucket {
716    /// #   name: "cloud-storage-rs-doc-4".to_string(),
717    /// #    ..Default::default()
718    /// # };
719    /// # let _ = Bucket::create(&new_bucket)?;
720    ///
721    /// let bucket = Bucket::read("cloud-storage-rs-doc-4")?;
722    /// let policy = bucket.get_iam_policy()?;
723    /// # bucket.delete()?;
724    /// # Ok(())
725    /// # }
726    /// ```
727    pub fn get_iam_policy(&self) -> Result<IamPolicy, Error> {
728        let url = format!("{}/b/{}/iam", crate::BASE_URL, self.name);
729        let client = reqwest::blocking::Client::new();
730        let result: GoogleResponse<IamPolicy> = client
731            .get(&url)
732            .headers(crate::get_headers()?)
733            .send()?
734            .json()?;
735        match result {
736            GoogleResponse::Success(s) => Ok(s),
737            GoogleResponse::Error(e) => Err(e.into()),
738        }
739    }
740
741    /// Updates the [IAM Policy](https://cloud.google.com/iam/docs/) for this bucket.
742    /// ### Example
743    /// ```
744    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
745    /// use cloud_storage::Bucket;
746    /// use cloud_storage::bucket::{IamPolicy, Binding, IamRole, StandardIamRole, Entity};
747    /// # use cloud_storage::bucket::NewBucket;
748    /// # let new_bucket = NewBucket {
749    /// #   name: "cloud-storage-rs-doc-5".to_string(),
750    /// #    ..Default::default()
751    /// # };
752    /// # let _ = Bucket::create(&new_bucket)?;
753    ///
754    /// let bucket = Bucket::read("cloud-storage-rs-doc-5")?;
755    /// let iam_policy = IamPolicy {
756    ///     version: 1,
757    ///     bindings: vec![
758    ///         Binding {
759    ///             role: IamRole::Standard(StandardIamRole::ObjectViewer),
760    ///             members: vec!["allUsers".to_string()],
761    ///             condition: None,
762    ///         }
763    ///     ],
764    ///     ..Default::default()
765    /// };
766    /// let policy = bucket.set_iam_policy(&iam_policy)?;
767    /// # bucket.delete()?;
768    /// # Ok(())
769    /// # }
770    /// ```
771    pub fn set_iam_policy(&self, iam: &IamPolicy) -> Result<IamPolicy, Error> {
772        let url = format!("{}/b/{}/iam", crate::BASE_URL, self.name);
773        let client = reqwest::blocking::Client::new();
774        let result: GoogleResponse<IamPolicy> = client
775            .put(&url)
776            .headers(crate::get_headers()?)
777            .json(iam)
778            .send()?
779            .json()?;
780        match result {
781            GoogleResponse::Success(s) => Ok(s),
782            GoogleResponse::Error(e) => Err(e.into()),
783        }
784    }
785
786    /// Checks whether the user provided in the service account has this permission.
787    /// ### Example
788    /// ```no_run
789    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
790    /// use cloud_storage::Bucket;
791    ///
792    /// let bucket = Bucket::read("my-bucket")?;
793    /// bucket.test_iam_permission("storage.buckets.get")?;
794    /// # Ok(())
795    /// # }
796    /// ```
797    pub fn test_iam_permission(&self, permission: &str) -> Result<TestIamPermission, Error> {
798        if permission == "storage.buckets.list" || permission == "storage.buckets.create" {
799            return Err(Error::new(
800                "tested permission must not be `storage.buckets.list` or `storage.buckets.create`",
801            ));
802        }
803        let url = format!("{}/b/{}/iam/testPermissions", crate::BASE_URL, self.name);
804        let client = reqwest::blocking::Client::new();
805        let result: GoogleResponse<TestIamPermission> = client
806            .get(&url)
807            .headers(crate::get_headers()?)
808            .query(&[("permissions", permission)])
809            .send()?
810            .json()?;
811        match result {
812            GoogleResponse::Success(s) => Ok(s),
813            GoogleResponse::Error(e) => Err(e.into()),
814        }
815    }
816
817    fn _lock_retention_policy() {
818        todo!()
819    }
820}
821
822#[cfg(test)]
823mod tests {
824    use super::*;
825    use crate::resources::common::Role;
826
827    #[test]
828    fn create() -> Result<(), Box<dyn std::error::Error>> {
829        dotenv::dotenv().ok();
830        let base_name = std::env::var("TEST_BUCKET")?;
831        // use a more complex bucket in this test.
832        let new_bucket = NewBucket {
833            name: format!("{}-test-create", base_name),
834            default_event_based_hold: Some(true),
835            acl: Some(vec![NewBucketAccessControl {
836                entity: Entity::AllUsers,
837                role: Role::Reader,
838            }]),
839            default_object_acl: Some(vec![NewDefaultObjectAccessControl {
840                entity: Entity::AllUsers,
841                role: Role::Reader,
842            }]),
843            iam_configuration: Some(IamConfiguration {
844                uniform_bucket_level_access: UniformBucketLevelAccess {
845                    enabled: false,
846                    locked_time: None,
847                },
848            }),
849            ..Default::default()
850        };
851        let bucket = Bucket::create(&new_bucket)?;
852        bucket.delete()?;
853        Ok(())
854    }
855
856    #[test]
857    fn list() -> Result<(), Box<dyn std::error::Error>> {
858        Bucket::list()?;
859        Ok(())
860    }
861
862    #[test]
863    fn read() -> Result<(), Box<dyn std::error::Error>> {
864        let bucket = crate::create_test_bucket("test-read");
865        let also_bucket = Bucket::read(&bucket.name)?;
866        assert_eq!(bucket, also_bucket);
867        bucket.delete()?;
868        assert!(also_bucket.delete().is_err());
869        Ok(())
870    }
871
872    #[test]
873    fn update() -> Result<(), Box<dyn std::error::Error>> {
874        let mut bucket = crate::create_test_bucket("test-update");
875        bucket.retention_policy = Some(RetentionPolicy {
876            retention_period: 50,
877            effective_time: chrono::Utc::now() + chrono::Duration::seconds(50),
878            is_locked: Some(false),
879        });
880        bucket.update()?;
881        let updated = Bucket::read(&bucket.name)?;
882        assert_eq!(updated.retention_policy.unwrap().retention_period, 50);
883        bucket.delete()?;
884        Ok(())
885    }
886
887    // used a lot throughout the other tests, but included for completeness
888    #[test]
889    fn delete() -> Result<(), Box<dyn std::error::Error>> {
890        let bucket = crate::create_test_bucket("test-delete");
891        bucket.delete()?;
892        Ok(())
893    }
894
895    #[test]
896    fn get_iam_policy() -> Result<(), Box<dyn std::error::Error>> {
897        let bucket = crate::create_test_bucket("test-get-iam-policy");
898        bucket.get_iam_policy()?;
899        bucket.delete()?;
900        Ok(())
901    }
902
903    #[test]
904    fn set_iam_policy() -> Result<(), Box<dyn std::error::Error>> {
905        // use crate::resources::iam_policy::{Binding, IamRole, StandardIamRole};
906
907        let bucket = crate::create_test_bucket("test-set-iam-policy");
908        let iam_policy = IamPolicy {
909            bindings: vec![Binding {
910                role: IamRole::Standard(StandardIamRole::ObjectViewer),
911                members: vec!["allUsers".to_string()],
912                condition: None,
913            }],
914            ..Default::default()
915        };
916        bucket.set_iam_policy(&iam_policy)?;
917        assert_eq!(
918            bucket.get_iam_policy()?.bindings,
919            iam_policy.bindings
920        );
921        bucket.delete()?;
922        Ok(())
923    }
924
925    #[test]
926    fn test_iam_permission() -> Result<(), Box<dyn std::error::Error>> {
927        let bucket = crate::create_test_bucket("test-test-ia-permission");
928        bucket.test_iam_permission("storage.buckets.get")?;
929        bucket.delete()?;
930        Ok(())
931    }
932}