s3lurp 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +152 -0
- data/Rakefile +1 -0
- data/lib/s3lurp.rb +51 -0
- data/lib/s3lurp/railtie.rb +8 -0
- data/lib/s3lurp/version.rb +3 -0
- data/lib/s3lurp/view_helpers.rb +126 -0
- data/s3lurp.gemspec +26 -0
- data/spec/s3lurp_spec.rb +137 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/support/config/s3.yml +4 -0
- metadata +150 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Lukas Eklund
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# s3lurp - Browser Uploads Direct to S3
|
2
|
+
|
3
|
+
direct s3 upload Rails form helper
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 's3lurp'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install s3lurp
|
18
|
+
|
19
|
+
### Configuration
|
20
|
+
|
21
|
+
S3lurp has many options that can be configured globally or passed
|
22
|
+
to the helper via a hash.
|
23
|
+
|
24
|
+
#### AWS S3 Setup
|
25
|
+
|
26
|
+
There are three options required for buckets that are not public-write:
|
27
|
+
|
28
|
+
* `s3_bucket` - The name of the bucket where files go
|
29
|
+
* `s3_access_key` - This is your AWS Access Key ID
|
30
|
+
* `s3_secret_ley` - Your AWS Secret Accss Key
|
31
|
+
|
32
|
+
|
33
|
+
These three options can be set via a yaml config file, an initializer, or ENV vars.
|
34
|
+
|
35
|
+
|
36
|
+
ENV['S3_BUCKET']
|
37
|
+
ENV['S3_ACCESS_KEY']
|
38
|
+
ENV['S3_SECRET_KEY']
|
39
|
+
|
40
|
+
Another way to set up these options is to us an initializer.
|
41
|
+
|
42
|
+
In config/initializers/s3lurp.rb
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
S3lurp.configure do |config|
|
46
|
+
config.s3_bucket = "bucket_of_holding"
|
47
|
+
config.s3_access_key = "some_acces_key"
|
48
|
+
config.s3_secret_key = "keep_it_secret"
|
49
|
+
```
|
50
|
+
|
51
|
+
Finally you can use use a yaml file to load the configuration.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
# config/initializers/s3lurp.rb
|
55
|
+
S3lurp.congigure do |config|
|
56
|
+
config.file = 's3lurp.yml'
|
57
|
+
end
|
58
|
+
# config/s3lurp.yml
|
59
|
+
development:
|
60
|
+
s3_bucket: "dev_bucket"
|
61
|
+
s3_access_key: "dev_key"
|
62
|
+
s3_secret_key: "dev_secret"
|
63
|
+
production:
|
64
|
+
s3_bucket: "prod_bucket"
|
65
|
+
s3_access_key: "prod_key"
|
66
|
+
s3_secret_key: "prod_secret"
|
67
|
+
```
|
68
|
+
|
69
|
+
Using a yaml conifg file allows you to use different settings for different
|
70
|
+
environments. Note: It's not necessary to provide environment based settings. The
|
71
|
+
yaml can just be a set of key/value pairs without any grouping by environment.
|
72
|
+
|
73
|
+
#### S3lurp Config Example
|
74
|
+
|
75
|
+
Here is an exmaple of how to configure s3lurp using Heroku.
|
76
|
+
|
77
|
+
Setup your ENV variables for heroku and for local use.
|
78
|
+
For more on Heroku config see here: https://devcenter.heroku.com/articles/config-vars
|
79
|
+
|
80
|
+
```
|
81
|
+
$ heroku config:add S3_KEY=asdfg12345 S3_SECRET=qwertyu0987622`
|
82
|
+
$ export S3_KEY=asdfg12345
|
83
|
+
$ export S3_SECRET=qwertyu0987622
|
84
|
+
```
|
85
|
+
|
86
|
+
Set up some defaults with an initialzer
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
# config/initializers/s3lurp.rb
|
90
|
+
S3lurp.congigure do |config|
|
91
|
+
config.acl = 'public-read'
|
92
|
+
config.minutes_valid = '600'
|
93
|
+
config.max_file_size = 10.megabytes
|
94
|
+
config.min_file_size = 1024
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
And now in your view you can call
|
99
|
+
|
100
|
+
s3_direct_form_tag({:key => 'photos/uuid/${filename}'})
|
101
|
+
|
102
|
+
This will generate a complete form with a file input and a submit tag. The form
|
103
|
+
will contain all the necessary hidden fields to perform a direct upload to S3.
|
104
|
+
|
105
|
+
#### Configuration Options
|
106
|
+
|
107
|
+
Many of these options correspond to the HTML form fields that AWS accepts. This documentation will
|
108
|
+
be helpful: http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTForms.html
|
109
|
+
|
110
|
+
All of these can be congured in an initializer, a yaml config file, or passed directly
|
111
|
+
to the helper in a hash.
|
112
|
+
|
113
|
+
| Option | Description |
|
114
|
+
|--------------------------|-------------|
|
115
|
+
|__:file__ | Name of yaml file located in the config directory. Contains any of the options listed in this table. Should be set inside a configuration block via an initializer. |
|
116
|
+
|__:s3\_bucket__ | AWS S3 bucket name where files will stored. Can also be configured via ENV['S3_BUCKET']. __Required__|
|
117
|
+
|__:s3\_access\_key__ | AWS Access Key. Can also be configured via ENV['S3_ACCESS_KEY']. __Required for buckets that are not public-write.__|
|
118
|
+
|__:s3\_secret\_key__ | AWS AWS Secret Accss Key. Can also be configured via ENV['S3_SECRET_KEY']. __Required for buckets that are not public-write.__|
|
119
|
+
|__:key__ | This is the key for the S3 object. To use the filename of the upload, use the vairable ${filename} (see example). __Required__|
|
120
|
+
|__:acl__ | Sepecies an S3 access control list. Valid values: `private` `public-read` `public-read-write` `authenticated-read` `bucket-owner-read` `bucket-owner-full-control`. _Default_: `private` |
|
121
|
+
|__:cache\_control__ | Refer to [S3 PUT Object documentation](http://docs.aws.amazon.com/AmazonS3/2006-03-01/API/RESTObjectPUT.html)|
|
122
|
+
|__:content\_disposition__ | Refer to [S3 PUT Object documentation](http://docs.aws.amazon.com/AmazonS3/2006-03-01/API/RESTObjectPUT.html)|
|
123
|
+
|__:content\_encoding__ | Refer to [S3 PUT Object documentation](http://docs.aws.amazon.com/AmazonS3/2006-03-01/API/RESTObjectPUT.html)|
|
124
|
+
|__:expires__ | Refer to [S3 PUT Object documentation](http://docs.aws.amazon.com/AmazonS3/2006-03-01/API/RESTObjectPUT.html)|
|
125
|
+
|__:content\_type__ | A standard MIME type describing the format of the contents. _Default_: `binary/octet-stream`. Note: S3 will not automatically determine the content\_type.|
|
126
|
+
|__:success\_action\_redirect__| The URL to which a client is redirected after a successful upload. S3 will append the bucket, key, and etag as query parameters to the URL |
|
127
|
+
|__:success\_action\_status__| HTTP status code returned upon successful upload if success_action_redirect is not set. _Default:_ 204. |
|
128
|
+
|__:min\_file\_size__ | Size in bytes of minimum allowed file size _Default:_ 0 |
|
129
|
+
|__:max\_file\_size__ | Size in bytes of maximum allowed file size _Default:_ 10485760 |
|
130
|
+
|__:amz\_meta\_tags__ | Hash of additional metadata to be stored with the object. Stored on S3 as `x-amz-meta-#{key} = #{value}` |
|
131
|
+
|__:minutes\_valid__ | Length of time in minutes that the generated form is valid. _Default:_ 360 |
|
132
|
+
|__:form\_html\_options__ | Hash of additional options that is passed to the form_tag contructor. |
|
133
|
+
|__:file\_field\_tag\_accept__ | Sets the accept parameter of the file field tag. [?](http://www.w3.org/TR/html-markup/input.file.html#input.file.attrs.accept) |
|
134
|
+
|__:submit\_tag__ | HTML string containing code for the input or button that will handle form submission. This is optional and if not included a basic submit tag will be generated for the form. |
|
135
|
+
|__:submit\_tag\_value__ | Override the value of the standard generated submit tag. _Default:_ "Upload" |
|
136
|
+
|__:submit\_tag\_options__ | Hash of options passed to the submit_tag generator. |
|
137
|
+
|
138
|
+
|
139
|
+
### Examples
|
140
|
+
|
141
|
+
coming soon.
|
142
|
+
|
143
|
+
## Credits
|
144
|
+
|
145
|
+
With inspiration from:
|
146
|
+
|
147
|
+
* [d2s3](https://github.com/mwilliams/d2s3)
|
148
|
+
* [Sinatra-S3-Direct-Upload](https://github.com/waynehoover/Sinatra-S3-Direct-Upload)
|
149
|
+
|
150
|
+
## License
|
151
|
+
|
152
|
+
Copyright © 2013 Lukas Eklund, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/s3lurp.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 's3lurp/version'
|
2
|
+
require 's3lurp/view_helpers'
|
3
|
+
require 's3lurp/railtie' if defined? ::Rails::Railtie
|
4
|
+
|
5
|
+
module S3lurp
|
6
|
+
VALID_CONFIG_KEYS = [
|
7
|
+
:s3_bucket, :s3_access_key, :s3_secret_key, :acl, :cache_control,
|
8
|
+
:content_type, :content_disposition, :content_encoding, :expires,
|
9
|
+
:success_action_redirect, :success_action_status,
|
10
|
+
:min_file_size, :max_file_size,
|
11
|
+
:amz_meta_tags, :minutes_valid,
|
12
|
+
:form_html_options, :file_field_tag_accept,
|
13
|
+
:submit_tag, :submit_tag_value, :submit_tag_options,
|
14
|
+
:file, :key].freeze
|
15
|
+
class << self
|
16
|
+
attr_accessor :config
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configure
|
20
|
+
self.config ||= Configuration.new
|
21
|
+
yield(config)
|
22
|
+
if config.file
|
23
|
+
loaded_conf = YAML.load_file(Rails.root.join("config", config.file).to_s)
|
24
|
+
env_conf = loaded_conf[Rails.env] || loaded_conf
|
25
|
+
VALID_CONFIG_KEYS.each do |key|
|
26
|
+
config.send("#{key.to_s}=", env_conf[key.to_s])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.reset_config
|
32
|
+
self.config = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
class Configuration
|
36
|
+
attr_accessor *VALID_CONFIG_KEYS
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
@s3_bucket = ENV['S3_BUCKET'] || "S3_BUCKET"
|
40
|
+
@s3_access_key = ENV['S3_ACCESS_KEY'] || "S3_KEY"
|
41
|
+
@s3_secret_key = ENV['S3_SECRET_KEY'] || "S3_SECRET"
|
42
|
+
@min_file_size = 0
|
43
|
+
@max_file_size = 10485760
|
44
|
+
@minutes_valid = 360
|
45
|
+
@form_html_options = {}
|
46
|
+
@submit_tag_options = {}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
require 'digest/sha1'
|
4
|
+
|
5
|
+
module S3lurp
|
6
|
+
module ViewHelpers
|
7
|
+
HIDDEN_FIELD_MAP= {
|
8
|
+
:key => 'key',
|
9
|
+
:s3_access_key => 'AWSAccessKeyId',
|
10
|
+
:acl => 'acl',
|
11
|
+
:cache_control => 'Cache-Control',
|
12
|
+
:content_type => 'Content-Type',
|
13
|
+
:content_disposition => 'Content-Disposition',
|
14
|
+
:content_encoding => 'Content-Encoding',
|
15
|
+
:expires => 'Expires',
|
16
|
+
:success_action_redirect => 'success_action_redirect',
|
17
|
+
:success_action_status => 'success_action_status'
|
18
|
+
}
|
19
|
+
NON_FIELD_OPTIONS = %w( s3_bucket s3_secret_key
|
20
|
+
max_file_size min_file_size
|
21
|
+
amz_meta_tags minutes_valid
|
22
|
+
form_html_options file_field_tag_accept
|
23
|
+
submit_tag submit_tag_value submit_tag_options).map(&:to_sym)
|
24
|
+
|
25
|
+
def s3_direct_form_tag(opt = {})
|
26
|
+
options = (NON_FIELD_OPTIONS + HIDDEN_FIELD_MAP.keys).each_with_object({}) do |i, h|
|
27
|
+
h[i] = opt[i] || S3lurp.config.send(i)
|
28
|
+
end
|
29
|
+
|
30
|
+
# configurable fields the field map is formed as {:configuration_name => "input_field_name"}
|
31
|
+
hidden_fields = HIDDEN_FIELD_MAP.each_with_object({}) do |(k,v), h|
|
32
|
+
h[k] = options[k] unless options[k].nil? || options[k].blank?
|
33
|
+
end
|
34
|
+
|
35
|
+
amz_meta_tags = options[:amz_meta_tags].is_a?(Hash) ? s3_generate_amz_meta_tags(options[:amz_meta_tags]) : {}
|
36
|
+
|
37
|
+
# generate an expiration date for the policy
|
38
|
+
minutes = Integer(options[:minutes_valid]) rescue 360
|
39
|
+
expiration_date = minutes.minutes.from_now.utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
40
|
+
|
41
|
+
security_fields = {}
|
42
|
+
if hidden_fields[:s3_access_key] # only generate security fields when necessary
|
43
|
+
security_fields[:policy] = Base64.encode64(
|
44
|
+
s3_generate_policy(
|
45
|
+
hidden_fields.clone,
|
46
|
+
{ :meta_tags => amz_meta_tags,
|
47
|
+
:s3_bucket => options[:s3_bucket],
|
48
|
+
:expiration => expiration_date,
|
49
|
+
:min_file_size => options[:min_file_size],
|
50
|
+
:max_file_size => options[:max_file_size]
|
51
|
+
}
|
52
|
+
)).gsub(/\n/,'')
|
53
|
+
security_fields[:signature] = Base64.encode64(
|
54
|
+
OpenSSL::HMAC.digest(
|
55
|
+
OpenSSL::Digest::Digest.new('sha1'),
|
56
|
+
options[:s3_secret_key], security_fields[:policy])
|
57
|
+
).gsub(/\n/,'')
|
58
|
+
end
|
59
|
+
|
60
|
+
amz_meta_tags.merge! security_fields
|
61
|
+
submit = s3_generate_submit_tag(options)
|
62
|
+
file = s3_generate_file_field_tag(options)
|
63
|
+
form_tag("http://s3.amazonaws.com/#{options[:s3_bucket]}", {:authenticity_token => false, :method => 'POST', :multipart => true}.merge(options[:form_html_options])) do
|
64
|
+
(
|
65
|
+
hidden_fields.map{|k,v| hidden_field_tag(HIDDEN_FIELD_MAP[k],v, {:id => nil})}.join.html_safe +
|
66
|
+
amz_meta_tags.map{|k,v| hidden_field_tag(k,v,{:id => nil})}.join.html_safe +
|
67
|
+
field_set_tag(nil,:class=>"s3lurp_file") {file} +
|
68
|
+
field_set_tag(nil,:class=>"s3lurp_submit") {submit.html_safe}
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def s3_generate_policy(fields = {}, options = {})
|
74
|
+
fields.delete(:s3_access_key)
|
75
|
+
conditions = [
|
76
|
+
{ :bucket => options[:s3_bucket]},
|
77
|
+
['content-length-range', options[:min_file_size], options[:max_file_size]],
|
78
|
+
['starts-with', '$utf8', ""]
|
79
|
+
]
|
80
|
+
HIDDEN_FIELD_MAP.each do |field, field_name|
|
81
|
+
next unless fields[field]
|
82
|
+
case field
|
83
|
+
when :key
|
84
|
+
key = fields[field].gsub(/\/?\$\{filename\}\/?/,'')
|
85
|
+
conditions.push ["starts-with", "$key", key]
|
86
|
+
else
|
87
|
+
conditions.push ({ field_name => fields[field] })
|
88
|
+
end
|
89
|
+
end
|
90
|
+
if options[:meta_tags]
|
91
|
+
conditions = conditions + options[:meta_tags].map{|k,v| {k => v}}
|
92
|
+
end
|
93
|
+
policy = {
|
94
|
+
"expiration" => options[:expiration],
|
95
|
+
"conditions" => conditions
|
96
|
+
}.to_json
|
97
|
+
end
|
98
|
+
|
99
|
+
def s3_generate_amz_meta_tags(meta = {})
|
100
|
+
meta.each_with_object({}) do |(k,v), hash|
|
101
|
+
hash[%(x-amz-meta-#{k})] = v
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def s3_generate_submit_tag(opt = {})
|
106
|
+
opt[:submit_tag_options].update(:name => nil)
|
107
|
+
if opt[:submit_tag]
|
108
|
+
opt[:submit_tag]
|
109
|
+
elsif opt[:submit_tag_value]
|
110
|
+
submit_tag(opt[:submit_tag_value], opt[:submit_tag_options])
|
111
|
+
else
|
112
|
+
submit_tag("Upload", opt[:submit_tag_options])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def s3_generate_file_field_tag(opt ={})
|
117
|
+
if opt[:file_field_tag_accept]
|
118
|
+
file_field_tag('file', :accept => opt[:file_field_tag_accept], :class => 's3lurp_file_tag')
|
119
|
+
else
|
120
|
+
file_field_tag('file', :class => 's3lurp_file_tag')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
data/s3lurp.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 's3lurp/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "s3lurp"
|
8
|
+
spec.version = S3lurp::VERSION
|
9
|
+
spec.authors = ["Lukas Eklund"]
|
10
|
+
spec.email = ["leklund@gmail.com"]
|
11
|
+
spec.description = %q{s3lurp - Browser uploads direct to Amazon S3}
|
12
|
+
spec.summary = %q{ActionView::Helper to generate a form tag for direct uploads to S3. Configurable via ENV or yml}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency 'actionpack'
|
25
|
+
spec.add_development_dependency 'activesupport'
|
26
|
+
end
|
data/spec/s3lurp_spec.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 's3lurp'
|
4
|
+
|
5
|
+
ActionView::Base.send(:include, S3lurp::ViewHelpers)
|
6
|
+
|
7
|
+
|
8
|
+
describe S3lurp::ViewHelpers do
|
9
|
+
before do
|
10
|
+
ENV.clear
|
11
|
+
S3lurp.reset_config
|
12
|
+
end
|
13
|
+
view = ActionView::Base.new
|
14
|
+
|
15
|
+
it "should return a form with a minimum set of hidden fields for public buckets" do
|
16
|
+
S3lurp.configure do |config|
|
17
|
+
config.s3_access_key = nil
|
18
|
+
config.s3_secret_key = nil
|
19
|
+
end
|
20
|
+
form = view.s3_direct_form_tag({:key => '/files/s3lurp/lib/s3lurp.rb'})
|
21
|
+
(!!form.match(/<form.*?>/)).should be_true
|
22
|
+
form.should include(%(name="key"), %(type="hidden"))
|
23
|
+
form.should include(%(name="file"), %(type="file"))
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return a form with a policy and signature and my meta tags" do
|
27
|
+
S3lurp.configure do |config|
|
28
|
+
config.s3_bucket = "bucket_o_stuff"
|
29
|
+
config.s3_access_key = 'oingoboingo'
|
30
|
+
config.s3_secret_key = "qwerty5678_"
|
31
|
+
end
|
32
|
+
form = view.s3_direct_form_tag({
|
33
|
+
:key => '/some/key.pl',
|
34
|
+
:acl => 'public-read',
|
35
|
+
:success_action_redirect => 'http://foobar.com/thanks',
|
36
|
+
:success_action_status => 204,
|
37
|
+
:content_disposition => "attachment",
|
38
|
+
:min_file_size => 1024,
|
39
|
+
:max_file_size => 6291456,
|
40
|
+
:minutes_valid => 333,
|
41
|
+
:amz_meta_tags => {
|
42
|
+
:foo => "bar",
|
43
|
+
:parent_id => 42
|
44
|
+
},
|
45
|
+
:form_html_options => {:class => "myclass", :id => "s3lurp_form"}
|
46
|
+
})
|
47
|
+
(!!form.match(/<form.*?>/)).should be_true
|
48
|
+
form.should include(%(class="myclass"))
|
49
|
+
form.should include(%(id="s3lurp_form"))
|
50
|
+
form.should include(%(name="key"), %(value="/some/key.pl"))
|
51
|
+
form.should include(%(name="AWSAccessKeyId"), %(value="oingoboingo"))
|
52
|
+
form.should include(%(name="file"), %(type="file"))
|
53
|
+
form.should include(%(name="policy"), %(type="hidden"))
|
54
|
+
form.should include(%(name="x-amz-meta-foo"), %(value="bar"))
|
55
|
+
form.should include(%(name="x-amz-meta-parent_id"), %(value="42"))
|
56
|
+
form.should include(%(name="Content-Disposition"), %(type="hidden"), %(value="attachment"))
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should return valid json from the generate policy method and should have the keys I send it' do
|
61
|
+
json = view.s3_generate_policy({:key => "/foo/bar/${filename}", :acl => 'public-read'},
|
62
|
+
{:bucket => 'mybucket',
|
63
|
+
:expiration => "2013-03-14T21:16:51.000Z"})
|
64
|
+
(!!(JSON.parse(json) rescue nil)).should be_true
|
65
|
+
j = JSON.parse(json)
|
66
|
+
j["expiration"].should == "2013-03-14T21:16:51.000Z"
|
67
|
+
key_cond = j["conditions"].select{|a| a[1] == '$key'}.first
|
68
|
+
key_cond[2].should == "/foo/bar"
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should return a submit tag or return the submit tag passed' do
|
72
|
+
view.s3_generate_submit_tag({:submit_tag_value => "zootboot", :submit_tag_options => {}})\
|
73
|
+
.should == %(<input type="submit" value="zootboot" />)
|
74
|
+
view.s3_generate_submit_tag({:submit_tag_options => {:class => "noway"}})\
|
75
|
+
.should == %(<input class="noway" type="submit" value="Upload" />)
|
76
|
+
view.s3_generate_submit_tag({:submit_tag_value => "zootboot", :submit_tag_options => {:class => "noway"}})\
|
77
|
+
.should == %(<input class="noway" type="submit" value="zootboot" />)
|
78
|
+
view.s3_generate_submit_tag({:submit_tag => %(<input type=submit class="button" id="upload-button">), :submit_tag_options => {}})\
|
79
|
+
.should == %(<input type=submit class="button" id="upload-button">)
|
80
|
+
view.s3_generate_submit_tag({:submit_tag_options => {}})\
|
81
|
+
.should == %(<input type="submit" value="Upload" />)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should generate file field tag with and without accept=' do
|
85
|
+
view.s3_generate_file_field_tag().should_not include("accept")
|
86
|
+
view.s3_generate_file_field_tag({:file_field_tag_accept => "image/*"}).should include('accept="image/*"')
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
describe S3lurp do
|
93
|
+
def random_string
|
94
|
+
rand(36**8).to_s(36)
|
95
|
+
end
|
96
|
+
before do
|
97
|
+
S3lurp.reset_config
|
98
|
+
ENV.clear
|
99
|
+
@bucket = random_string
|
100
|
+
@key = random_string
|
101
|
+
@secret = random_string
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should configure with options' do
|
105
|
+
S3lurp.configure do |config|
|
106
|
+
config.s3_bucket = @bucket
|
107
|
+
config.s3_access_key = @key
|
108
|
+
config.s3_secret_key = @secret
|
109
|
+
end
|
110
|
+
S3lurp.config.s3_bucket.should == @bucket
|
111
|
+
S3lurp.config.s3_access_key.should == @key
|
112
|
+
S3lurp.config.s3_secret_key.should == @secret
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should should always use ENV first for config' do
|
116
|
+
ENV['S3_BUCKET'] = @bucket
|
117
|
+
ENV['S3_ACCESS_KEY'] = @key
|
118
|
+
ENV['S3_SECRET_KEY'] = @secret
|
119
|
+
S3lurp.configure do |config|
|
120
|
+
# nothing
|
121
|
+
end
|
122
|
+
S3lurp.config.s3_bucket.should == @bucket
|
123
|
+
S3lurp.config.s3_access_key.should == @key
|
124
|
+
S3lurp.config.s3_secret_key.should == @secret
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should configure from a yml file' do
|
129
|
+
S3lurp.configure do |config|
|
130
|
+
config.file = 's3.yml'
|
131
|
+
end
|
132
|
+
S3lurp.config.s3_bucket.should == 'yml_bucket'
|
133
|
+
S3lurp.config.s3_access_key.should == 'yml_key'
|
134
|
+
S3lurp.config.s3_secret_key.should == 'yml_secret'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_support/core_ext/numeric'
|
4
|
+
require 'action_view'
|
5
|
+
require 'pathname'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
9
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
10
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
11
|
+
# loaded once.
|
12
|
+
#
|
13
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
config.filter_run :focus
|
18
|
+
|
19
|
+
# Run specs in random order to surface order dependencies. If you find an
|
20
|
+
# order dependency and want to debug it, you can fix the order by providing
|
21
|
+
# the seed, which is printed after each run.
|
22
|
+
# --seed 1234
|
23
|
+
config.order = 'random'
|
24
|
+
end
|
25
|
+
|
26
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/s3lurp")
|
27
|
+
|
28
|
+
#some dummy Rails
|
29
|
+
class Rails
|
30
|
+
class << self
|
31
|
+
attr_accessor :env, :root
|
32
|
+
end
|
33
|
+
@env = 'development'
|
34
|
+
@root = Pathname.new(File.expand_path(File.dirname(__FILE__) + "/support"))
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: s3lurp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lukas Eklund
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: actionpack
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: activesupport
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: s3lurp - Browser uploads direct to Amazon S3
|
95
|
+
email:
|
96
|
+
- leklund@gmail.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .rspec
|
103
|
+
- Gemfile
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/s3lurp.rb
|
108
|
+
- lib/s3lurp/railtie.rb
|
109
|
+
- lib/s3lurp/version.rb
|
110
|
+
- lib/s3lurp/view_helpers.rb
|
111
|
+
- s3lurp.gemspec
|
112
|
+
- spec/s3lurp_spec.rb
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
- spec/support/config/s3.yml
|
115
|
+
homepage: ''
|
116
|
+
licenses:
|
117
|
+
- MIT
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
hash: -3173245167068990906
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
segments:
|
138
|
+
- 0
|
139
|
+
hash: -3173245167068990906
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 1.8.25
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: ActionView::Helper to generate a form tag for direct uploads to S3. Configurable
|
146
|
+
via ENV or yml
|
147
|
+
test_files:
|
148
|
+
- spec/s3lurp_spec.rb
|
149
|
+
- spec/spec_helper.rb
|
150
|
+
- spec/support/config/s3.yml
|