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}