Skip to content

Commit

Permalink
delegate #presign to gcs, #url will delegate to #presign if :expires …
Browse files Browse the repository at this point in the history
…is specified
  • Loading branch information
rosskevin committed Oct 12, 2017
1 parent 863450b commit 13d7b0b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 31 deletions.
33 changes: 13 additions & 20 deletions lib/shrine/storage/google_cloud_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,17 @@ def upload(io, id, shrine_metadata: {}, **_options)

# URL to the remote file, accepts options for customizing the URL
def url(id, **_options)
host = @host || "storage.googleapis.com/#{@bucket}"

"https://#{host}/#{object_name(id)}"
if(_options.key? :expires)
signed_url = presign(id, _options).url
if @host.nil?
signed_url
else
signed_url.gsub(/storage.googleapis.com\/#{@bucket}/, @host)
end
else
host = @host || "storage.googleapis.com/#{@bucket}"
"https://#{host}/#{object_name(id)}"
end
end

# Downloads the file from GCS, and returns a `Tempfile`.
Expand Down Expand Up @@ -95,24 +103,9 @@ def clear!
end

def presign(id, **options)
method = options[:method] || "GET"
content_md5 = options[:content_md5] || ""
content_type = options[:content_type] || ""
expires = (Time.now.utc + (options[:expires] || 300)).to_i
headers = nil
path = "/#{@bucket}/" + object_name(id)

to_sign = [method, content_md5, content_type, expires, headers, path].compact.join("\n")

signing_key = options[:signing_key]
signing_key = OpenSSL::PKey::RSA.new(signing_key) unless signing_key.respond_to?(:sign)
signature = Base64.strict_encode64(signing_key.sign(OpenSSL::Digest::SHA256.new, to_sign)).delete("\n")

signed_url = "https://storage.googleapis.com#{path}?GoogleAccessId=#{options[:issuer]}" \
"&Expires=#{expires}&Signature=#{CGI.escape(signature)}"

file = get_file(id)
OpenStruct.new(
url: signed_url,
url: file.signed_url(options),
fields: {},
)
end
Expand Down
69 changes: 58 additions & 11 deletions test/gcs_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def service_account
end
end

describe "clear!" do
describe "#clear!" do
it "does not empty the whole bucket when a prefix is set" do
gcs_with_prefix = gcs(prefix: 'pre')
@gcs.upload(image, 'foo')
Expand All @@ -136,24 +136,71 @@ def service_account
end
end

describe "presign" do
it "works on a GET url" do
sa = service_account

storage = Shrine::Storage::GoogleCloudStorage.new(bucket: "shrine-test")
describe "#presign" do
it "signs a GET url with a signing key and issuer" do
gcs = gcs()
gcs.upload(image, 'foo')

sa = service_account
Time.stub :now, Time.at(1486649900) do
presign = storage.presign(
'test_presign.txt',
method: "GET",
expires: 60 * 5,
presign = gcs.presign(
'foo',
signing_key: sa[:private_key],
issuer: sa[:client_email],
)

assert_equal "https://storage.googleapis.com/shrine-test/test_presign.txt?GoogleAccessId=test-shrine@test.google&Expires=1486650200&Signature=O8tYOAJCtk0fXpO9MDhRO7ikVsIRqjALK01naly2rEJBCM2uRHl7meqEaXzu%2Bl9V17zw9P2%2FGb0K2miF%2FyEuZ6mnRIiuH6aI2tg24CV%2FKtuNU5jSqwqMU83iPzuptwakgFNxMGJj73i0SGbB%2F4wodNR7DNQ6KFhSlpJJ1mgD4hI%3D", presign.url
assert_equal "https://storage.googleapis.com/#{gcs.bucket}/foo?GoogleAccessId=test-shrine%40test.google&Expires=1486650200&Signature=FkS%2Bn4C0VxnsoqQIKG2AcsK0UWMY2KzfiyEQHAAezL%2Fk9mytRx8n8p8qV1FfEFieOOPFnj9%2FroC0MzA6VOaQUpPbHJw7NfcxLXO0F4TcTqeHxpHmbSvNgm7k18Q%2FscUdop2r9aZrqFJIMfqWoBwKlyEGsKcTZ1WNzizKhDM89p8%3D", presign.url
assert_equal({}, presign.fields)
end
end

it "signs a GET url with discovered credentials" do
gcs = gcs()
gcs.upload(image, 'foo')

Time.stub :now, Time.at(1486649900) do
presign = gcs.presign('foo')
assert presign.url.include? "https://storage.googleapis.com/#{gcs.bucket}/foo?"
assert presign.url.include? "Expires=1486650200"
assert presign.url.include? "Signature=" # each tester's discovered signature will be different
assert_equal({}, presign.fields)
end
end
end

describe "#url" do
describe "signed" do
it "url with `expires` signs a GET url with discovered credentials" do
gcs = gcs()
gcs.upload(image, 'foo')

Time.stub :now, Time.at(1486649900) do
presigned_url = gcs.url('foo', expires: 300)
assert presigned_url.include? "https://storage.googleapis.com/#{gcs.bucket}/foo?"
assert presigned_url.include? "Expires=1486650200"
assert presigned_url.include? "Signature=" # each tester's discovered signature will be different
end
end

it "url with `expires` signs a GET url with discovered credentials and specified host" do
host = "123.mycdn.net"
gcs = gcs(host: host)
gcs.upload(image, 'foo')

Time.stub :now, Time.at(1486649900) do
presigned_url = gcs.url('foo', expires: 300)
assert presigned_url.include? "https://#{host}/foo?"
assert presigned_url.include? "Expires=1486650200"
assert presigned_url.include? "Signature=" # each tester's discovered signature will be different
end
end
end

it "accepts :host for specifying CDN links" do
host = "123.mycdn.net"
gcs = gcs(host: host)
url = gcs.url('foo')
assert_equal("https://123.mycdn.net/foo", url)
end
end
end

0 comments on commit 13d7b0b

Please sign in to comment.