carrierwave-aws 1.0.0.pre.rc.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -3
- data/CHANGELOG.md +7 -0
- data/README.md +4 -0
- data/Rakefile +10 -1
- data/carrierwave-aws.gemspec +1 -1
- data/lib/carrierwave-aws.rb +57 -1
- data/lib/carrierwave/aws/version.rb +1 -1
- data/lib/carrierwave/storage/aws_file.rb +11 -1
- data/spec/carrierwave-aws_spec.rb +130 -3
- data/spec/carrierwave/storage/aws_file_spec.rb +11 -0
- data/spec/features/storing_files_spec.rb +4 -0
- data/spec/spec_helper.rb +2 -2
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0daf2d106b4a0d27f423cfbaa8745fa019d5f840
|
4
|
+
data.tar.gz: 2213c9acca949bd4d1608a0fd08cbd96ed12b64b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa5b275f21820fb4fed97d1cd183a3f1ae909de304e1dd6616d64d4a047fa9d285b340a66fea9ad4a720df9ee6bf8e2ee3eb485277d58974fb22cde1b185ec7b
|
7
|
+
data.tar.gz: abffdcdca5ee8d72c7daf90f4e6fc9ee18df1b3c30cc4e0a4e692214ea02b851254449364155b1b020f4a205e3f1f6ea20cb20bef6f264cb92318ffa803ff9f2
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## Version 1.0.0 2015-09-18
|
2
|
+
|
3
|
+
* Added: ACL options are verified when they are set, and coerced into usable
|
4
|
+
values when possible.
|
5
|
+
* Added: Specify an `aws_signer` lambda for use signing authenticated content
|
6
|
+
served through services like CloudFront.
|
7
|
+
|
1
8
|
## Version 1.0.0-rc.1 2015-07-02
|
2
9
|
|
3
10
|
* Continues where 0.6.0 left off. This wraps AWS-SDK v2 and all of the breaking
|
data/README.md
CHANGED
@@ -58,6 +58,10 @@ CarrierWave.configure do |config|
|
|
58
58
|
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
|
59
59
|
region: ENV.fetch('AWS_REGION') # Required
|
60
60
|
}
|
61
|
+
|
62
|
+
# Optional: Signing of download urls, e.g. for serving private
|
63
|
+
# content through CloudFront.
|
64
|
+
config.aws_signer = -> (unsigned_url, options) { Aws::CF::Signer.sign_url unsigned_url, options }
|
61
65
|
end
|
62
66
|
```
|
63
67
|
|
data/Rakefile
CHANGED
data/carrierwave-aws.gemspec
CHANGED
data/lib/carrierwave-aws.rb
CHANGED
@@ -6,15 +6,71 @@ require 'carrierwave/storage/aws_options'
|
|
6
6
|
require 'carrierwave/support/uri_filename'
|
7
7
|
|
8
8
|
class CarrierWave::Uploader::Base
|
9
|
+
ACCEPTED_ACL = %w[
|
10
|
+
private
|
11
|
+
public-read
|
12
|
+
public-read-write
|
13
|
+
authenticated-read
|
14
|
+
bucket-owner-read
|
15
|
+
bucket-owner-full-control
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
ConfigurationError = Class.new(StandardError)
|
19
|
+
|
9
20
|
add_config :aws_attributes
|
10
21
|
add_config :aws_authenticated_url_expiration
|
11
22
|
add_config :aws_credentials
|
12
23
|
add_config :aws_bucket
|
13
|
-
add_config :aws_acl
|
14
24
|
add_config :aws_read_options
|
15
25
|
add_config :aws_write_options
|
26
|
+
add_config :aws_acl
|
27
|
+
add_config :aws_signer
|
16
28
|
|
17
29
|
configure do |config|
|
18
30
|
config.storage_engines[:aws] = 'CarrierWave::Storage::AWS'
|
19
31
|
end
|
32
|
+
|
33
|
+
def self.aws_acl=(acl)
|
34
|
+
@aws_acl = normalized_acl(acl)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.normalized_acl(acl)
|
38
|
+
normalized = acl.to_s.downcase.sub('_', '-')
|
39
|
+
|
40
|
+
unless ACCEPTED_ACL.include?(normalized)
|
41
|
+
raise ConfigurationError.new("Invalid ACL option: #{normalized}")
|
42
|
+
end
|
43
|
+
|
44
|
+
normalized
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.aws_signer(value = nil)
|
48
|
+
self.aws_signer = value if value
|
49
|
+
|
50
|
+
if instance_variable_defined?('@aws_signer')
|
51
|
+
@aws_signer
|
52
|
+
elsif superclass.respond_to? :aws_signer
|
53
|
+
superclass.aws_signer
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.aws_signer=(signer)
|
58
|
+
@aws_signer = validated_signer(signer)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.validated_signer(signer)
|
62
|
+
unless signer.nil? || signer.instance_of?(Proc) && signer.arity == 2
|
63
|
+
raise ConfigurationError.new("Invalid signer option. Signer proc has to respond to '.call(unsigned_url, options)'")
|
64
|
+
end
|
65
|
+
|
66
|
+
signer
|
67
|
+
end
|
68
|
+
|
69
|
+
def aws_acl=(acl)
|
70
|
+
@aws_acl = self.class.normalized_acl(acl)
|
71
|
+
end
|
72
|
+
|
73
|
+
def aws_signer
|
74
|
+
instance_variable_defined?('@aws_signer') ? @aws_signer : self.class.aws_signer
|
75
|
+
end
|
20
76
|
end
|
@@ -60,6 +60,10 @@ module CarrierWave
|
|
60
60
|
bucket.object(new_path).copy_from(copy_source: "#{bucket.name}/#{file.key}")
|
61
61
|
end
|
62
62
|
|
63
|
+
def signed_url(options = {})
|
64
|
+
signer.call(public_url, options)
|
65
|
+
end
|
66
|
+
|
63
67
|
def authenticated_url(options = {})
|
64
68
|
file.presigned_url(:get, aws_options.expiration_options(options))
|
65
69
|
end
|
@@ -73,7 +77,9 @@ module CarrierWave
|
|
73
77
|
end
|
74
78
|
|
75
79
|
def url(options = {})
|
76
|
-
if
|
80
|
+
if signer
|
81
|
+
signed_url(options)
|
82
|
+
elsif uploader.aws_acl.to_s != 'public-read'
|
77
83
|
authenticated_url(options)
|
78
84
|
else
|
79
85
|
public_url
|
@@ -85,6 +91,10 @@ module CarrierWave
|
|
85
91
|
def bucket
|
86
92
|
@bucket ||= connection.bucket(uploader.aws_bucket)
|
87
93
|
end
|
94
|
+
|
95
|
+
def signer
|
96
|
+
uploader.aws_signer
|
97
|
+
end
|
88
98
|
end
|
89
99
|
end
|
90
100
|
end
|
@@ -1,13 +1,140 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CarrierWave::Uploader::Base do
|
4
|
-
|
5
|
-
|
4
|
+
let(:uploader) do
|
5
|
+
Class.new(CarrierWave::Uploader::Base)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:derived_uploader) do
|
9
|
+
Class.new(uploader)
|
6
10
|
end
|
7
11
|
|
8
12
|
it 'inserts aws as a known storage engine' do
|
9
|
-
|
13
|
+
uploader.configure do |config|
|
10
14
|
expect(config.storage_engines).to have_key(:aws)
|
11
15
|
end
|
12
16
|
end
|
17
|
+
|
18
|
+
it 'defines aws specific storage options' do
|
19
|
+
expect(uploader).to respond_to(:aws_attributes)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#aws_acl' do
|
23
|
+
it 'allows known acess control values' do
|
24
|
+
expect {
|
25
|
+
uploader.aws_acl = 'private'
|
26
|
+
uploader.aws_acl = 'public-read'
|
27
|
+
uploader.aws_acl = 'authenticated-read'
|
28
|
+
}.not_to raise_exception
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'does not allow unknown control values' do
|
32
|
+
expect {
|
33
|
+
uploader.aws_acl = 'everybody'
|
34
|
+
}.to raise_exception(CarrierWave::Uploader::Base::ConfigurationError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'normalizes the set value' do
|
38
|
+
uploader.aws_acl = :'public-read'
|
39
|
+
expect(uploader.aws_acl).to eq('public-read')
|
40
|
+
|
41
|
+
uploader.aws_acl = 'PUBLIC_READ'
|
42
|
+
expect(uploader.aws_acl).to eq('public-read')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'can be overridden on an instance level' do
|
46
|
+
instance = uploader.new
|
47
|
+
|
48
|
+
uploader.aws_acl = 'private'
|
49
|
+
instance.aws_acl = 'public-read'
|
50
|
+
|
51
|
+
expect(uploader.aws_acl).to eq('private')
|
52
|
+
expect(instance.aws_acl).to eq('public-read')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can be looked up from superclass' do
|
56
|
+
uploader.aws_acl = 'private'
|
57
|
+
instance = derived_uploader.new
|
58
|
+
|
59
|
+
expect(derived_uploader.aws_acl).to eq('private')
|
60
|
+
expect(instance.aws_acl).to eq('private')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can be overridden on a class level' do
|
64
|
+
uploader.aws_acl = 'public-read'
|
65
|
+
derived_uploader.aws_acl = 'private'
|
66
|
+
|
67
|
+
base = uploader.new
|
68
|
+
expect(base.aws_acl).to eq('public-read')
|
69
|
+
|
70
|
+
instance = derived_uploader.new
|
71
|
+
expect(instance.aws_acl).to eq('private')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'can be set with the configure block' do
|
75
|
+
uploader.configure do |config|
|
76
|
+
config.aws_acl = 'public-read'
|
77
|
+
end
|
78
|
+
|
79
|
+
expect(uploader.aws_acl).to eq('public-read')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#aws_signer' do
|
84
|
+
let(:signer_proc) { -> (unsigned_url, options) { } }
|
85
|
+
let(:other_signer) { -> (unsigned_url, options) { } }
|
86
|
+
|
87
|
+
it 'allows proper signer object' do
|
88
|
+
expect { uploader.aws_signer = signer_proc }.not_to raise_exception
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'does not allow signer with unknown api' do
|
92
|
+
signer_proc = -> (unsigned_url) { }
|
93
|
+
|
94
|
+
expect { uploader.aws_signer = signer_proc }.to raise_exception(CarrierWave::Uploader::Base::ConfigurationError)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'can be overridden on an instance level' do
|
98
|
+
instance = uploader.new
|
99
|
+
|
100
|
+
uploader.aws_signer = signer_proc
|
101
|
+
instance.aws_signer = other_signer
|
102
|
+
|
103
|
+
expect(uploader.aws_signer).to eql(signer_proc)
|
104
|
+
expect(instance.aws_signer).to eql(other_signer)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'can be overridden on a class level' do
|
108
|
+
uploader.aws_signer = signer_proc
|
109
|
+
derived_uploader.aws_signer = other_signer
|
110
|
+
|
111
|
+
base = uploader.new
|
112
|
+
expect(base.aws_signer).to eq(signer_proc)
|
113
|
+
|
114
|
+
instance = derived_uploader.new
|
115
|
+
expect(instance.aws_signer).to eql(other_signer)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'can be looked up from superclass' do
|
119
|
+
uploader.aws_signer = signer_proc
|
120
|
+
instance = derived_uploader.new
|
121
|
+
|
122
|
+
expect(derived_uploader.aws_signer).to eq(signer_proc)
|
123
|
+
expect(instance.aws_signer).to eql(signer_proc)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'can be set with the configure block' do
|
127
|
+
uploader.configure do |config|
|
128
|
+
config.aws_signer = signer_proc
|
129
|
+
end
|
130
|
+
|
131
|
+
expect(uploader.aws_signer).to eql(signer_proc)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'can be set when passed as argument to the class getter method' do
|
135
|
+
uploader.aws_signer signer_proc
|
136
|
+
|
137
|
+
expect(uploader.aws_signer).to eql(signer_proc)
|
138
|
+
end
|
139
|
+
end
|
13
140
|
end
|
@@ -12,6 +12,7 @@ describe CarrierWave::Storage::AWSFile do
|
|
12
12
|
aws_acl: :'public-read',
|
13
13
|
aws_attributes: {},
|
14
14
|
asset_host: nil,
|
15
|
+
aws_signer: nil,
|
15
16
|
aws_read_options: { encryption_key: 'abc' },
|
16
17
|
aws_write_options: { encryption_key: 'def' }
|
17
18
|
)
|
@@ -62,6 +63,16 @@ describe CarrierWave::Storage::AWSFile do
|
|
62
63
|
aws_file.url
|
63
64
|
end
|
64
65
|
|
66
|
+
it 'requests an signed url if url signing is configured' do
|
67
|
+
signature = 'Signature=QWERTZ&Key-Pair-Id=XYZ'
|
68
|
+
cloudfront_signer = -> (unsigned_url, options) { [unsigned_url, signature].join('?') }
|
69
|
+
|
70
|
+
allow(uploader).to receive(:aws_signer) { cloudfront_signer }
|
71
|
+
expect(file).to receive(:public_url) { 'http://example.com' }
|
72
|
+
|
73
|
+
expect(aws_file.url).to eq "http://example.com?#{signature}"
|
74
|
+
end
|
75
|
+
|
65
76
|
it 'uses the asset_host and file path if asset_host is set' do
|
66
77
|
allow(uploader).to receive(:aws_acl) { :'public-read' }
|
67
78
|
allow(uploader).to receive(:asset_host) { 'http://example.com' }
|
@@ -4,6 +4,10 @@ describe 'Storing Files', type: :feature do
|
|
4
4
|
let(:image) { File.open('spec/fixtures/image.png', 'r') }
|
5
5
|
let(:instance) { FeatureUploader.new }
|
6
6
|
|
7
|
+
before do
|
8
|
+
instance.aws_acl = 'public-read'
|
9
|
+
end
|
10
|
+
|
7
11
|
it 'uploads the file to the configured bucket' do
|
8
12
|
instance.store!(image)
|
9
13
|
instance.retrieve_from_store!('image.png')
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: carrierwave-aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Parker Selbert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: carrierwave
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.0
|
33
|
+
version: '2.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 2.0
|
40
|
+
version: '2.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,12 +98,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
98
|
version: '0'
|
99
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: '0'
|
104
104
|
requirements: []
|
105
105
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.4.5
|
106
|
+
rubygems_version: 2.4.5.1
|
107
107
|
signing_key:
|
108
108
|
specification_version: 4
|
109
109
|
summary: A slimmer alternative to using Fog for S3 support in CarrierWave
|