# Copyright 2014 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require "google/cloud/storage/errors"
require "google/cloud/storage/service"
require "google/cloud/storage/convert"
require "google/cloud/storage/credentials"
require "google/cloud/storage/bucket"
require "google/cloud/storage/bucket/cors"
require "google/cloud/storage/bucket/lifecycle"
require "google/cloud/storage/file"
require "google/cloud/storage/hmac_key"
module Google
module Cloud
module Storage
##
# # Project
#
# Represents the project that storage buckets and files belong to.
# All data in Google Cloud Storage belongs inside a project.
# A project consists of a set of users, a set of APIs, billing,
# authentication, and monitoring settings for those APIs.
#
# Google::Cloud::Storage::Project is the main object for interacting with
# Google Storage. {Google::Cloud::Storage::Bucket} objects are created,
# read, updated, and deleted by Google::Cloud::Storage::Project.
#
# See {Google::Cloud#storage}
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.bucket "my-bucket"
# file = bucket.file "path/to/my-file.ext"
#
class Project
include Convert
##
# @private The Service object.
attr_accessor :service
##
# @private Creates a new Project instance.
#
# See {Google::Cloud#storage}
def initialize service
@service = service
end
##
# The universe domain the client is connected to
#
# @return [String]
#
def universe_domain
service.universe_domain
end
##
# The Storage project connected to.
#
# @return [String]
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new(
# project_id: "my-project",
# credentials: "/path/to/keyfile.json"
# )
#
# storage.project_id #=> "my-project"
#
def project_id
service.project
end
alias project project_id
##
# The Google Cloud Storage managed service account created for the
# project used to initialize the client library. (See also
# {#project_id}.)
#
# @return [String] The service account email address.
#
def service_account_email
@service_account_email ||= service.project_service_account.email_address
end
##
# Add custom Google extension headers to the requests that use the signed URLs.
#
# @param [Hash] headers Google extension headers (custom HTTP headers that
# begin with `x-goog-`) to be included in requests that use the signed URLs.
# Provide headers as a key/value array, where the key is
# the header name, and the value is an array of header values.
# For headers with multiple values, provide values as a simple
# array, or a comma-separated string. For a reference of allowed
# headers, see [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers).
#
# @return [Google::Cloud::Storage::Project] Returns the Project for method chaining
#
def add_custom_headers headers
@service.add_custom_headers headers
self
end
##
# Add custom Google extension header to the requests that use the signed URLs.
#
# @param [String] header_name Name of Google extension header (custom HTTP header that
# begin with `x-goog-`) to be included in requests that use the signed URLs.
# For a reference of allowed headers, see
# [Reference Headers](https://cloud.google.com/storage/docs/xml-api/reference-headers).
# @param [Object] header_value Valid value of the Google extension header being added.
# For headers with multiple values, provide values as a simple array, or a comma-separated string.
#
# @return [Google::Cloud::Storage::Project] Returns the Project for method chaining
#
def add_custom_header header_name, header_value
@service.add_custom_header header_name, header_value
self
end
##
# Retrieves a list of buckets for the given project.
#
# @param [String] prefix Filter results to buckets whose names begin
# with this prefix.
# @param [String] token A previously-returned page token representing
# part of the larger set of results to view.
# @param [Integer] max Maximum number of buckets to return.
# @param [Boolean, String] user_project If this parameter is set to
# `true`, transit costs for operations on the enabled buckets or their
# files will be billed to the current project for this client. (See
# {#project} for the ID of the current project.) If this parameter is
# set to a project ID other than the current project, and that project
# is authorized for the currently authenticated service account,
# transit costs will be billed to the given project. This parameter is
# required with requester pays-enabled buckets. The default is `nil`.
#
# The value provided will be applied to all operations on the returned
# bucket instances and their files.
#
# See also {Bucket#requester_pays=} and {Bucket#requester_pays}.
#
# @return [Array<Google::Cloud::Storage::Bucket>] (See
# {Google::Cloud::Storage::Bucket::List})
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# buckets = storage.buckets
# buckets.each do |bucket|
# puts bucket.name
# end
#
# @example Retrieve buckets with names that begin with a given prefix:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# user_buckets = storage.buckets prefix: "user-"
# user_buckets.each do |bucket|
# puts bucket.name
# end
#
# @example Retrieve all buckets: (See {Bucket::List#all})
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# buckets = storage.buckets
# buckets.all do |bucket|
# puts bucket.name
# end
#
# @example Retrieve soft deleted buckets
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# soft_deleted_buckets = storage.buckets soft_deleted: true
# soft_deleted_buckets.each do |bucket|
# puts bucket.name
# end
def buckets prefix: nil, token: nil, max: nil, user_project: nil, soft_deleted: nil
gapi = service.list_buckets \
prefix: prefix, token: token, max: max, user_project: user_project, soft_deleted: soft_deleted
Bucket::List.from_gapi \
gapi, service, prefix, max, user_project: user_project, soft_deleted: soft_deleted
end
alias find_buckets buckets
##
# Retrieves bucket by name.
#
# @param [String] bucket_name Name of a bucket.
# @param [Boolean] skip_lookup Optionally create a Bucket object
# without verifying the bucket resource exists on the Storage service.
# Calls made on this object will raise errors if the bucket resource
# does not exist. Default is `false`.
# @param [Integer] if_metageneration_match Makes the operation conditional
# on whether the bucket's current metageneration matches the given value.
# @param [Integer] if_metageneration_not_match Makes the operation
# conditional on whether the bucket's current metageneration does not
# match the given value.
# @param [Boolean, String] user_project If this parameter is set to
# `true`, transit costs for operations on the requested bucket or a
# file it contains will be billed to the current project for this
# client. (See {#project} for the ID of the current project.) If this
# parameter is set to a project ID other than the current project, and
# that project is authorized for the currently authenticated service
# account, transit costs will be billed to the given project. This
# parameter is required with requester pays-enabled buckets. The
# default is `nil`.
# @param [Integer] generation generation no of bucket
# on whether the bucket's current metageneration matches the given value.
# @param [Boolean] soft_deleted If true, returns the soft-deleted bucket.
# This parameter is required if generation is specified.
#
# The value provided will be applied to all operations on the returned
# bucket instance and its files.
#
# See also {Bucket#requester_pays=} and {Bucket#requester_pays}.
#
# @return [Google::Cloud::Storage::Bucket, nil] Returns nil if bucket
# does not exist
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.bucket "my-bucket"
# puts bucket.name
#
# @example With `user_project` set to bill costs to the default project:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.bucket "other-project-bucket", user_project: true
# files = bucket.files # Billed to current project
#
# @example With `user_project` set to a project other than the default:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.bucket "other-project-bucket",
# user_project: "my-other-project"
# files = bucket.files # Billed to "my-other-project"
# @example With `soft_deleted` set to true and generation specified:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.bucket "my-bucket",
# soft_deleted: true,
# generation: 1234567889
# puts bucket.name
#
def bucket bucket_name,
skip_lookup: false,
generation: nil,
soft_deleted: nil,
if_metageneration_match: nil,
if_metageneration_not_match: nil,
user_project: nil
if skip_lookup
return Bucket.new_lazy bucket_name, service,
user_project: user_project
end
gapi = service.get_bucket bucket_name,
if_metageneration_match: if_metageneration_match,
if_metageneration_not_match: if_metageneration_not_match,
user_project: user_project,
soft_deleted: soft_deleted,
generation: generation
Bucket.from_gapi gapi, service, user_project: user_project
rescue Google::Cloud::NotFoundError
nil
end
alias find_bucket bucket
##
# Creates a new bucket with optional attributes. Also accepts a block
# for defining the CORS configuration for a static website served from
# the bucket. See {Bucket::Cors} for details.
#
# The API call to create the bucket may be retried under certain
# conditions. See {Google::Cloud#storage} to control this behavior.
#
# You can pass [website
# settings](https://cloud.google.com/storage/docs/website-configuration)
# for the bucket, including a block that defines CORS rule. See
# {Bucket::Cors} for details.
#
# Before enabling uniform bucket-level access (see
# {Bucket#uniform_bucket_level_access=}) please review [uniform bucket-level
# access](https://cloud.google.com/storage/docs/uniform-bucket-level-access).
#
# @see https://cloud.google.com/storage/docs/cross-origin Cross-Origin
# Resource Sharing (CORS)
# @see https://cloud.google.com/storage/docs/website-configuration How
# to Host a Static Website
#
# @param [String] bucket_name Name of a bucket.
# @param [String] acl Apply a predefined set of access controls to this
# bucket.
#
# Acceptable values are:
#
# * `auth`, `auth_read`, `authenticated`, `authenticated_read`,
# `authenticatedRead` - Project team owners get OWNER access, and
# allAuthenticatedUsers get READER access.
# * `private` - Project team owners get OWNER access.
# * `project_private`, `projectPrivate` - Project team members get
# access according to their roles.
# * `public`, `public_read`, `publicRead` - Project team owners get
# OWNER access, and allUsers get READER access.
# * `public_write`, `publicReadWrite` - Project team owners get OWNER
# access, and allUsers get WRITER access.
# @param [String] default_acl Apply a predefined set of default object
# access controls to this bucket.
#
# Acceptable values are:
#
# * `auth`, `auth_read`, `authenticated`, `authenticated_read`,
# `authenticatedRead` - File owner gets OWNER access, and
# allAuthenticatedUsers get READER access.
# * `owner_full`, `bucketOwnerFullControl` - File owner gets OWNER
# access, and project team owners get OWNER access.
# * `owner_read`, `bucketOwnerRead` - File owner gets OWNER access,
# and project team owners get READER access.
# * `private` - File owner gets OWNER access.
# * `project_private`, `projectPrivate` - File owner gets OWNER
# access, and project team members get access according to their
# roles.
# * `public`, `public_read`, `publicRead` - File owner gets OWNER
# access, and allUsers get READER access.
# @param [String] location The location of the bucket. Optional.
# If not passed, the default location, 'US', will be used.
# If specifying a dual-region location, the `customPlacementConfig`
# property should be set in conjunction. See:
# [Storage Locations](https://cloud.google.com/storage/docs/locations).
# @param [String] logging_bucket The destination bucket for the bucket's
# logs. For more information, see [Access
# Logs](https://cloud.google.com/storage/docs/access-logs).
# @param [String] logging_prefix The prefix used to create log object
# names for the bucket. It can be at most 900 characters and must be a
# [valid object
# name](https://cloud.google.com/storage/docs/bucket-naming#objectnames)
# . By default, the object prefix is the name of the bucket for which
# the logs are enabled. For more information, see [Access
# Logs](https://cloud.google.com/storage/docs/access-logs).
# @param [Symbol, String] storage_class Defines how objects in the
# bucket are stored and determines the SLA and the cost of storage.
# Accepted values include `:standard`, `:nearline`, `:coldline`, and
# `:archive`, as well as the equivalent strings returned by
# {Bucket#storage_class}. For more information, see [Storage
# Classes](https://cloud.google.com/storage/docs/storage-classes). The
# default value is the `:standard` storage class.
# @param [Boolean] versioning Whether [Object
# Versioning](https://cloud.google.com/storage/docs/object-versioning)
# is to be enabled for the bucket. The default value is `false`.
# @param [String] website_main The index page returned from a static
# website served from the bucket when a site visitor requests the top
# level directory. For more information, see [How to Host a Static
# Website
# ](https://cloud.google.com/storage/docs/website-configuration#step4).
# @param [String] website_404 The page returned from a static website
# served from the bucket when a site visitor requests a resource that
# does not exist. For more information, see [How to Host a Static
# Website
# ](https://cloud.google.com/storage/docs/website-configuration#step4).
# @param [String] user_project If this parameter is set to a project ID
# other than the current project, and that project is authorized for
# the currently authenticated service account, transit costs will be
# billed to the given project. The default is `nil`.
# @param [Boolean] autoclass_enabled The bucket's autoclass configuration.
# Buckets can have either StorageClass OLM rules or Autoclass, but
# not both. When Autoclass is enabled on a bucket, adding StorageClass
# OLM rules will result in failure. For more information, see
# [Autoclass](https://cloud.google.com/storage/docs/autoclass).
#
# The value provided will be applied to all operations on the returned
# bucket instance and its files.
#
# See also {Bucket#requester_pays=} and {Bucket#requester_pays}.
# @param [Boolean] enable_object_retention
# When set to true, object retention is enabled for this bucket.
#
# @yield [bucket] a block for configuring the bucket before it is
# created
# @yieldparam [Bucket] bucket the bucket object to be configured
#
# @return [Google::Cloud::Storage::Bucket]
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.create_bucket "my-bucket"
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.create_bucket "my-bucket", enable_object_retention: true
#
# @example Configure the bucket in a block:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket = storage.create_bucket "my-bucket" do |b|
# b.website_main = "index.html"
# b.website_404 = "not_found.html"
# b.requester_pays = true
# b.cors.add_rule ["http://example.org", "https://example.org"],
# "*",
# headers: ["X-My-Custom-Header"],
# max_age: 300
#
# b.lifecycle.add_set_storage_class_rule "COLDLINE", age: 10
# end
#
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def create_bucket bucket_name,
acl: nil,
default_acl: nil,
location: nil,
custom_placement_config: nil,
storage_class: nil,
logging_bucket: nil,
logging_prefix: nil,
website_main: nil,
website_404: nil,
versioning: nil,
requester_pays: nil,
user_project: nil,
autoclass_enabled: false,
enable_object_retention: nil,
hierarchical_namespace: nil
params = {
name: bucket_name,
location: location,
custom_placement_config: custom_placement_config,
hierarchical_namespace: hierarchical_namespace
}.delete_if { |_, v| v.nil? }
new_bucket = Google::Apis::StorageV1::Bucket.new(**params)
storage_class = storage_class_for storage_class
updater = Bucket::Updater.new(new_bucket).tap do |b|
b.logging_bucket = logging_bucket unless logging_bucket.nil?
b.logging_prefix = logging_prefix unless logging_prefix.nil?
b.autoclass_enabled = autoclass_enabled
b.storage_class = storage_class unless storage_class.nil?
b.website_main = website_main unless website_main.nil?
b.website_404 = website_404 unless website_404.nil?
b.versioning = versioning unless versioning.nil?
b.requester_pays = requester_pays unless requester_pays.nil?
b.hierarchical_namespace = hierarchical_namespace unless hierarchical_namespace.nil?
end
yield updater if block_given?
updater.check_for_changed_labels!
updater.check_for_mutable_cors!
updater.check_for_mutable_lifecycle!
gapi = service.insert_bucket \
new_bucket, acl: acl_rule(acl), default_acl: acl_rule(default_acl),
user_project: user_project,
enable_object_retention: enable_object_retention
Bucket.from_gapi gapi, service, user_project: user_project
end
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
##
# Creates a new HMAC key.
#
# @param [String] service_account_email The email address of the service
# account. Used to create the HMAC key.
# @param [String] project_id The project ID associated with
# `service_account_email`, if `service_account_email` belongs to a
# project other than the currently authenticated project. Optional. If
# not provided, the project ID for the current project will be used.
# @param [String] user_project If this parameter is set to a project ID
# other than the current project, and that project is authorized for
# the currently authenticated service account, transit costs will be
# billed to the given project. The default is `nil`.
#
# @return [Google::Cloud::Storage::HmacKey]
#
def create_hmac_key service_account_email, project_id: nil,
user_project: nil
gapi = service.create_hmac_key service_account_email,
project_id: project_id,
user_project: user_project
HmacKey.from_gapi gapi, service, user_project: user_project
end
##
# Retrieves an HMAC key's metadata; the key's secret is not included in
# the representation.
#
# @param [String] project_id The project ID associated with the
# `service_account_email` used to create the HMAC key, if the
# service account email belongs to a project other than the
# currently authenticated project. Optional. If not provided, the
# project ID for current project will be used.
# @param [String] user_project If this parameter is set to a project ID
# other than the current project, and that project is authorized for
# the currently authenticated service account, transit costs will be
# billed to the given project. The default is `nil`.
#
# @return [Google::Cloud::Storage::HmacKey]
#
def hmac_key access_id, project_id: nil, user_project: nil
gapi = service.get_hmac_key \
access_id, project_id: project_id, user_project: user_project
HmacKey.from_gapi_metadata gapi, service, user_project: user_project
end
##
# Retrieves a list of HMAC key metadata matching the criteria; the keys'
# secrets are not included.
#
# @param [String] service_account_email
# If present, only keys for the given service account are returned.
# @param [String] project_id The project ID associated with the
# `service_account_email` used to create the HMAC keys, if the
# service account email belongs to a project other than the
# currently authenticated project. Optional. If not provided, the
# project ID for current project will be used.
# @param [Boolean] show_deleted_keys
# Whether to include keys in the `DELETED` state. The default value is
# false.
# @param [String] token A previously-returned page token representing
# part of the larger set of results to view.
# @param [Integer] max Maximum number of keys to return.
# @param [String] user_project If this parameter is set to a project ID
# other than the current project, and that project is authorized for
# the currently authenticated service account, transit costs will be
# billed to the given project. The default is `nil`.
#
# @return [Google::Cloud::Storage::HmacKey]
#
def hmac_keys service_account_email: nil, project_id: nil,
show_deleted_keys: nil, token: nil, max: nil,
user_project: nil
gapi = service.list_hmac_keys \
max: max, token: token,
service_account_email: service_account_email,
project_id: project_id, show_deleted_keys: show_deleted_keys,
user_project: user_project
HmacKey::List.from_gapi \
gapi, service,
service_account_email: nil, show_deleted_keys: nil,
max: max, user_project: user_project
end
##
# Restores a soft deleted bucket with bucket name and generation.
#
# @param [String] bucket_name Name of the bucket.
# @param [Fixnum] generation Generation of the bucket.
#
# @return [Google::Cloud::Storage::Bucket, nil] Returns nil if bucket
# does not exist
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
# generation= 123
#
# bucket = storage.restore_bucket "my-bucket", generation
# puts bucket.name
#
def restore_bucket bucket_name,
generation,
options: {}
gapi = service.restore_bucket bucket_name, generation,
options: options
Bucket.from_gapi gapi, service
end
##
# Generates a signed URL. See [Signed
# URLs](https://cloud.google.com/storage/docs/access-control/signed-urls)
# for more information.
#
# Generating a URL requires service account credentials, either by
# connecting with a service account when calling
# {Google::Cloud.storage}, or by passing in the service account `issuer`
# and `signing_key` values. Although the private key can be passed as a
# string for convenience, creating and storing an instance of
# `OpenSSL::PKey::RSA` is more efficient when making multiple calls to
# `signed_url`.
#
# A {SignedUrlUnavailable} is raised if the service account credentials
# are missing. Service account credentials are acquired by following the
# steps in [Service Account Authentication](
# https://cloud.google.com/iam/docs/service-accounts).
#
# @see https://cloud.google.com/storage/docs/access-control/signed-urls
# Signed URLs guide
# @see https://cloud.google.com/storage/docs/access-control/signed-urls#signing-resumable
# Using signed URLs with resumable uploads
#
# @param [String, nil] bucket Name of the bucket, or nil if URL for all
# buckets is desired.
# @param [String] path Path to the file in Google Cloud Storage.
# @param [String] method The HTTP verb to be used with the signed URL.
# Signed URLs can be used
# with `GET`, `HEAD`, `PUT`, and `DELETE` requests. Default is `GET`.
# @param [Integer] expires The number of seconds until the URL expires.
# If the `version` is `:v2`, the default is 300 (5 minutes). If the
# `version` is `:v4`, the default is 604800 (7 days).
# @param [String] content_type When provided, the client (browser) must
# send this value in the HTTP header. e.g. `text/plain`. This param is
# not used if the `version` is `:v4`.
# @param [String] content_md5 The MD5 digest value in base64. If you
# provide this in the string, the client (usually a browser) must
# provide this HTTP header with this same value in its request. This
# param is not used if the `version` is `:v4`.
# @param [Hash] headers Google extension headers (custom HTTP headers
# that begin with `x-goog-`) that must be included in requests that
# use the signed URL.
# @param [String] issuer Service Account's Client Email.
# @param [String] client_email Service Account's Client Email.
# @param [OpenSSL::PKey::RSA, String, Proc] signing_key Service Account's
# Private Key or a Proc that accepts a single String parameter and returns a
# RSA SHA256 signature using a valid Google Service Account Private Key.
# @param [OpenSSL::PKey::RSA, String, Proc] private_key Service Account's
# Private Key or a Proc that accepts a single String parameter and returns a
# RSA SHA256 signature using a valid Google Service Account Private Key.
# @param [OpenSSL::PKey::RSA, String, Proc] signer Service Account's
# Private Key or a Proc that accepts a single String parameter and returns a
# RSA SHA256 signature using a valid Google Service Account Private Key.
#
# When using this method in environments such as GAE Flexible Environment,
# GKE, or Cloud Functions where the private key is unavailable, it may be
# necessary to provide a Proc (or lambda) via the signer parameter. This
# Proc should return a signature created using a RPC call to the
# [Service Account Credentials signBlob](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob)
# method as shown in the example below.
# @param [Hash] query Query string parameters to include in the signed
# URL. The given parameters are not verified by the signature.
#
# Parameters such as `response-content-disposition` and
# `response-content-type` can alter the behavior of the response when
# using the URL, but only when the file resource is missing the
# corresponding values. (These values can be permanently set using
# {File#content_disposition=} and {File#content_type=}.)
# @param [String] scheme The URL scheme. The default value is `HTTPS`.
# @param [Boolean] virtual_hosted_style Whether to use a virtual hosted-style
# hostname, which adds the bucket into the host portion of the URI rather
# than the path, e.g. `https://mybucket.storage.googleapis.com/...`.
# For V4 signing, this also sets the `host` header in the canonicalized
# extension headers to the virtual hosted-style host, unless that header is
# supplied via the `headers` param. The default value of `false` uses the
# form of `https://storage.googleapis.com/mybucket`.
# @param [String] bucket_bound_hostname Use a bucket-bound hostname, which
# replaces the `storage.googleapis.com` host with the name of a `CNAME`
# bucket, e.g. a bucket named `gcs-subdomain.my.domain.tld`, or a Google
# Cloud Load Balancer which routes to a bucket you own, e.g.
# `my-load-balancer-domain.tld`.
# @param [Symbol, String] version The version of the signed credential
# to create. Must be one of `:v2` or `:v4`. The default value is
# `:v2`.
#
# @return [String] The signed URL.
#
# @raise [SignedUrlUnavailable] If the service account credentials
# are missing. Service account credentials are acquired by following the
# steps in [Service Account Authentication](
# https://cloud.google.com/iam/docs/service-accounts).
#
# @example
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket_name = "my-todo-app"
# file_path = "avatars/heidi/400x400.png"
# shared_url = storage.signed_url bucket_name, file_path
#
# @example Using the `expires` and `version` options:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket_name = "my-todo-app"
# file_path = "avatars/heidi/400x400.png"
# shared_url = storage.signed_url bucket_name, file_path,
# expires: 300, # 5 minutes from now
# version: :v4
#
# @example Using the `issuer` and `signing_key` options:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket_name = "my-todo-app"
# file_path = "avatars/heidi/400x400.png"
# issuer_email = "service-account@gcloud.com"
# key = OpenSSL::PKey::RSA.new "-----BEGIN PRIVATE KEY-----\n..."
# shared_url = storage.signed_url bucket_name, file_path,
# issuer: issuer_email,
# signing_key: key
#
# @example Using Cloud IAMCredentials signBlob to create the signature:
# require "google/cloud/storage"
# require "google/apis/iamcredentials_v1"
# require "googleauth"
#
# # Issuer is the service account email that the Signed URL will be signed with
# # and any permission granted in the Signed URL must be granted to the
# # Google Service Account.
# issuer = "service-account@project-id.iam.gserviceaccount.com"
#
# # Create a lambda that accepts the string_to_sign
# signer = lambda do |string_to_sign|
# IAMCredentials = Google::Apis::IamcredentialsV1
# iam_client = IAMCredentials::IAMCredentialsService.new
#
# # Get the environment configured authorization
# scopes = ["https://www.googleapis.com/auth/iam"]
# iam_client.authorization = Google::Auth.get_application_default scopes
#
# request = Google::Apis::IamcredentialsV1::SignBlobRequest.new(
# payload: string_to_sign
# )
# resource = "projects/-/serviceAccounts/#{issuer}"
# response = iam_client.sign_service_account_blob resource, request
# response.signed_blob
# end
#
# storage = Google::Cloud::Storage.new
#
# bucket_name = "my-todo-app"
# file_path = "avatars/heidi/400x400.png"
# url = storage.signed_url bucket_name, file_path,
# method: "GET", issuer: issuer,
# signer: signer
#
# @example Using the `headers` option:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket_name = "my-todo-app"
# file_path = "avatars/heidi/400x400.png"
# shared_url = storage.signed_url bucket_name, file_path,
# headers: {
# "x-goog-acl" => "private",
# "x-goog-meta-foo" => "bar,baz"
# }
#
# @example Generating a signed URL for resumable upload:
# require "google/cloud/storage"
#
# storage = Google::Cloud::Storage.new
#
# bucket_name = "my-todo-app"
# file_path = "avatars/heidi/400x400.png"
#
# url = storage.signed_url bucket_name, file_path,
# method: "POST",
# content_type: "image/png",
# headers: {
# "x-goog-resumable" => "start"
# }
# # Send the `x-goog-resumable:start` header and the content type
# # with the resumable upload POST request.
#
def signed_url bucket,
path,
method: "GET",
expires: nil,
content_type: nil,
content_md5: nil,
headers: nil,
issuer: nil,
client_email: nil,
signing_key: nil,
private_key: nil,
signer: nil,
query: nil,
scheme: "HTTPS",
virtual_hosted_style: nil,
bucket_bound_hostname: nil,
version: nil
version ||= :v2
case version.to_sym
when :v2
sign = File::SignerV2.new bucket, path, service
sign.signed_url method: method,
expires: expires,
headers: headers,
content_type: content_type,
content_md5: content_md5,
issuer: issuer,
client_email: client_email,
signing_key: signing_key,
private_key: private_key,
signer: signer,
query: query
when :v4
sign = File::SignerV4.new bucket, path, service
sign.signed_url method: method,
expires: expires,
headers: headers,
issuer: issuer,
client_email: client_email,
signing_key: signing_key,
private_key: private_key,
signer: signer,
query: query,
scheme: scheme,
virtual_hosted_style: virtual_hosted_style,
bucket_bound_hostname: bucket_bound_hostname
else
raise ArgumentError, "version '#{version}' not supported"
end
end
protected
def acl_rule option_name
Bucket::Acl.predefined_rule_for option_name
end
end
end
end
end