Skip to content

Commit

Permalink
Initial implementation of passing s3 options to put, copy_from and pr…
Browse files Browse the repository at this point in the history
…esigned_post	(issue refile#3)
  • Loading branch information
kaapa committed May 24, 2015
1 parent 4208dc3 commit 95a9938
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 5 deletions.
24 changes: 20 additions & 4 deletions lib/refile/s3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class S3
def initialize(access_key_id:, secret_access_key:, region:, bucket:, max_size: nil, prefix: nil, hasher: Refile::RandomHasher.new, **s3_options)
@access_key_id = access_key_id
@secret_access_key = secret_access_key
@s3_presigned_post_options = s3_options.delete(:s3_presigned_post_options) { {} }
@s3_object_operation_options = s3_options.delete(:s3_object_operation_options) { {} }
@s3_options = { access_key_id: access_key_id, secret_access_key: secret_access_key, region: region }.merge s3_options
@s3 = Aws::S3::Resource.new @s3_options
@bucket_name = bucket
Expand All @@ -52,12 +54,14 @@ def initialize(access_key_id:, secret_access_key:, region:, bucket:, max_size: n
verify_uploadable def upload(uploadable)
id = @hasher.hash(uploadable)

if uploadable.is_a?(Refile::File) and uploadable.backend.is_a?(S3) and uploadable.backend.access_key_id == access_key_id
object(id).copy_from(copy_source: [@bucket_name, uploadable.backend.object(uploadable.id).key].join("/"))
operation, options = if upload_via_copy_operation?(uploadable)
[:copy_from, { copy_source: [@bucket_name, uploadable.backend.object(uploadable.id).key].join("/") }]
else
object(id).put(body: uploadable, content_length: uploadable.size)
[:put, { body: uploadable, content_length: uploadable.size }]
end

object(id).send(operation, s3_object_operation_options(options))

Refile::File.new(self, id)
end

Expand Down Expand Up @@ -137,11 +141,23 @@ def clear!(confirm = nil)
# @return [Refile::Signature]
def presign
id = RandomHasher.new.hash
signature = @bucket.presigned_post(key: [*@prefix, id].join("/"))
signature = @bucket.presigned_post(s3_presigned_post_options(key: [*@prefix, id].join("/")))
signature.content_length_range(0..@max_size) if @max_size
Signature.new(as: "file", id: id, url: signature.url.to_s, fields: signature.fields)
end

def s3_presigned_post_options(options)
@s3_presigned_post_options.merge(options)
end

def s3_object_operation_options(options)
@s3_object_operation_options.merge(options)
end

def upload_via_copy_operation?(uploadable)
uploadable.is_a?(Refile::File) and uploadable.backend.is_a?(S3) and uploadable.backend.access_key_id == access_key_id
end

verify_id def object(id)
@bucket.object([*@prefix, id].join("/"))
end
Expand Down
41 changes: 40 additions & 1 deletion spec/refile/s3_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,49 @@

WebMock.allow_net_connect!

config = YAML.load_file("s3.yml").map { |k, v| [k.to_sym, v] }.to_h
s3_config = YAML.load_file("s3.yml").map { |k, v| [k.to_sym, v] }.to_h

RSpec.describe Refile::S3 do
let(:config) { s3_config }
let(:backend) { Refile::S3.new(max_size: 100, **config) }

it_behaves_like :backend

describe '@s3_options' do
let(:value) { backend.instance_variable_get(:@s3_options) }

it 'is initialized' do
%i(access_key_id secret_access_key region).each do |attribute|
expect(value[attribute]).to eq(config[attribute])
end
end
end

%i(s3_object_operation_options s3_presigned_post_options).each do |option|
describe "@#{option}" do
let(:additional_config) do
{ "#{option}".to_sym => { server_side_encryption: 'aes256' } }
end

let(:config) { additional_config.merge s3_config }
let(:value) { backend.send(:instance_variable_get, "@#{option}") }

it 'is initialized' do
expect(value[:server_side_encryption]).to eq('aes256')
expect(backend.instance_variable_get(:@s3_options)).not_to have_key(option)
end
end

describe ".#{option}" do
let(:additional_config) do
{ "#{option}".to_sym => { server_side_encryption: 'aes256' } }
end

let(:config) { additional_config.merge s3_config }

it 'is merges provided options' do
expect(backend.send(option, { server_side_encryption: 'aws:kms' })[:server_side_encryption]).to eq('aws:kms')
end
end
end
end

0 comments on commit 95a9938

Please sign in to comment.