class Google::Cloud::Storage::File::SignerV2

@private Create a signed_url for a file.

Public Class Methods

from_bucket(bucket, path) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 39
def self.from_bucket bucket, path
  new bucket.name, path, bucket.service
end
from_file(file) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 35
def self.from_file file
  new file.bucket, file.name, file.service
end
new(bucket, path, service) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 29
def initialize bucket, path, service
  @bucket = bucket
  @path = path
  @service = service
end

Public Instance Methods

apply_option_defaults(options) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 66
def apply_option_defaults options
  adjusted_expires = (Time.now.utc + (options[:expires] || 300)).to_i
  options[:expires] = adjusted_expires
  options[:method] ||= "GET"
  options
end
determine_issuer(options = {}) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 86
def determine_issuer options = {}
  issuer = options[:issuer] || options[:client_email] || @service.credentials.issuer
  raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer
  issuer
end
determine_signing_key(options = {}) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 79
def determine_signing_key options = {}
  signing_key = options[:signing_key] || options[:private_key] ||
                options[:signer] || @service.credentials.signing_key
  raise SignedUrlUnavailable, error_msg("signing_key (private_key, signer)") unless signing_key
  signing_key
end
error_msg(attr_name) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 92
def error_msg attr_name
  "Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
  "see https://cloud.google.com/iam/docs/service-accounts"
end
ext_path() click to toggle source

The external path to the file, URI-encoded. Will not URI encode the special `${filename}` variable. “You can also use the ${filename} variable…” cloud.google.com/storage/docs/xml-api/post-object

# File lib/google/cloud/storage/file/signer_v2.rb, line 49
def ext_path
  path = "/#{@bucket}/#{@path}"
  escaped = Addressable::URI.escape path
  special_var = "${filename}"
  # Restore the unencoded `${filename}` variable, if present.
  if path.include? special_var
    return escaped.gsub "$%7Bfilename%7D", special_var
  end
  escaped
end
ext_url() click to toggle source

The external url to the file.

# File lib/google/cloud/storage/file/signer_v2.rb, line 62
def ext_url
  "#{GOOGLEAPIS_URL}#{ext_path}"
end
format_extension_headers(headers) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 157
def format_extension_headers headers
  return "" if headers.nil?
  raise "Headers must be given in a Hash" unless headers.is_a? Hash
  flatten = headers.map do |key, value|
    "#{key.to_s.downcase}:#{value.gsub(/\s+/, ' ')}\n"
  end
  flatten.reject! { |h| h.start_with? "x-goog-encryption-key" }
  flatten.sort.join
end
generate_signature(signing_key, secret) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 132
def generate_signature signing_key, secret
  unencoded_signature = ""
  if signing_key.is_a? Proc
    unencoded_signature = signing_key.call secret
  else
    unless signing_key.respond_to? :sign
      signing_key = OpenSSL::PKey::RSA.new signing_key
    end
    unencoded_signature = signing_key.sign OpenSSL::Digest::SHA256.new, secret
  end
  Base64.strict_encode64(unencoded_signature).delete "\n"
end
generate_signed_url(issuer, signed_string, expires, query) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 145
def generate_signed_url issuer, signed_string, expires, query
  url = "#{ext_url}?GoogleAccessId=#{url_escape issuer}" \
    "&Expires=#{expires}" \
    "&Signature=#{url_escape signed_string}"

  query&.each do |name, value|
    url << "&#{url_escape name}=#{url_escape value}"
  end

  url
end
post_object(options) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 97
def post_object options
  options = apply_option_defaults options

  fields = {
    key: ext_path.sub("/", "")
  }

  p = options[:policy] || {}
  raise "Policy must be given in a Hash" unless p.is_a? Hash

  i = determine_issuer options
  s = determine_signing_key options

  policy_str = p.to_json
  policy = Base64.strict_encode64(policy_str).delete "\n"

  signature = generate_signature s, policy

  fields[:GoogleAccessId] = i
  fields[:signature] = signature
  fields[:policy] = policy

  Google::Cloud::Storage::PostObject.new GOOGLEAPIS_URL, fields
end
signature_str(options) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 73
def signature_str options
  [options[:method], options[:content_md5],
   options[:content_type], options[:expires],
   format_extension_headers(options[:headers]) + ext_path].join "\n"
end
signed_url(options) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 122
def signed_url options
  options = apply_option_defaults options

  i = determine_issuer options
  s = determine_signing_key options

  sig = generate_signature s, signature_str(options)
  generate_signed_url i, sig, options[:expires], options[:query]
end
url_escape(str) click to toggle source
# File lib/google/cloud/storage/file/signer_v2.rb, line 167
def url_escape str
  CGI.escape String str
end