s3_form_presenter 0.0.1
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/Gemfile +2 -0
- data/Gemfile.lock +14 -0
- data/LICENSE +22 -0
- data/README.md +10 -0
- data/Rakefile +25 -0
- data/lib/s3_form_presenter/version.rb +3 -0
- data/lib/s3_form_presenter.rb +84 -0
- data/s3_form_presenter.gemspec +17 -0
- data/test/form_test.rb +109 -0
- data/test/test_helper.rb +3 -0
- metadata +62 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2012 {Lance Carlson}[http://github.com/lancecarlson]
|
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,10 @@
|
|
1
|
+
= S3 Form Presenter =
|
2
|
+
|
3
|
+
Generates a simple form that is compatible with S3's form API. You can upload S3 assets directly to S3 without hitting your server.
|
4
|
+
|
5
|
+
= Usage =
|
6
|
+
|
7
|
+
<% S3FormPresenter::Form.new("some/key/path.ext") do %>
|
8
|
+
<input name="file" type="file">
|
9
|
+
<input type="submit" value="Save File">
|
10
|
+
<% end %>
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
def gemspec
|
6
|
+
$s3_form_presenter_gemspec ||= Gem::Specification.load("s3_form_presenter.gemspec")
|
7
|
+
end
|
8
|
+
|
9
|
+
task :gem => :gemspec
|
10
|
+
|
11
|
+
desc %{Validate the gemspec file.}
|
12
|
+
task :gemspec do
|
13
|
+
gemspec.validate
|
14
|
+
end
|
15
|
+
|
16
|
+
desc %{Release the gem to RubyGems.org}
|
17
|
+
task :release => :gem do
|
18
|
+
sh "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
19
|
+
end
|
20
|
+
|
21
|
+
task :build => :gemspec do
|
22
|
+
sh "mkdir -p pkg"
|
23
|
+
sh "gem build s3_form_presenter.gemspec"
|
24
|
+
sh "mv s3_form_presenter-#{S3FormPresenter::VERSION}.gem pkg"
|
25
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'base64'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
module S3FormPresenter
|
6
|
+
class Form
|
7
|
+
HIDDEN_FIELD_NAMES = :key, :access_key, :secret_key, :acl, :redirect_url, :policy, :signature
|
8
|
+
ACCESSOR_FIELDS = HIDDEN_FIELD_NAMES - [:policy, :signature]
|
9
|
+
RENAMED_FIELDS = {:redirect_url => "success_action_redirect", :access_key => "AWSAccessKeyId"}
|
10
|
+
attr_accessor :bucket, :inner_content
|
11
|
+
|
12
|
+
def initialize(key, options={}, &block)
|
13
|
+
@key = key
|
14
|
+
@access_key = options[:access_key] || ENV["AWS_ACCESS_KEY_ID"]
|
15
|
+
@secret_key = options[:secret_key] || ENV["AWS_SECRET_ACCESS_KEY"]
|
16
|
+
@bucket = options[:bucket] || ENV["AWS_S3_BUCKET"]
|
17
|
+
@acl = options[:acl]
|
18
|
+
if block_given?
|
19
|
+
@inner_content = block.call
|
20
|
+
else
|
21
|
+
@inner_content = %Q(<input name="file" type="file"><input type="submit" value="Upload File" class="btn btn-primary">)
|
22
|
+
end
|
23
|
+
generate_hidden_field_accessors
|
24
|
+
end
|
25
|
+
|
26
|
+
def header
|
27
|
+
%Q(<form action="http://#{bucket}.s3.amazonaws.com/" method="post" enctype="multipart/form-data">)
|
28
|
+
end
|
29
|
+
|
30
|
+
def footer
|
31
|
+
%Q(</form>)
|
32
|
+
end
|
33
|
+
|
34
|
+
def hidden_fields
|
35
|
+
HIDDEN_FIELD_NAMES.map do |field|
|
36
|
+
hidden_field(field, send(field))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def hidden_field(name, value)
|
41
|
+
%Q(<input type="hidden" name="#{name}" value="#{value}">)
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_html
|
45
|
+
content = ""
|
46
|
+
content += header
|
47
|
+
content += hidden_fields.join
|
48
|
+
content += inner_content
|
49
|
+
content += footer
|
50
|
+
end
|
51
|
+
|
52
|
+
def policy
|
53
|
+
Base64.encode64(policy_object.to_json).gsub(/\n|\r/, '')
|
54
|
+
end
|
55
|
+
|
56
|
+
def signature
|
57
|
+
Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), secret_key, policy)).gsub("\n","")
|
58
|
+
end
|
59
|
+
|
60
|
+
def policy_object
|
61
|
+
{
|
62
|
+
"expiration" => policy_expiration,
|
63
|
+
"conditions" => [
|
64
|
+
{"bucket" => bucket},
|
65
|
+
["starts-with", "$key", "#{key}"],
|
66
|
+
{"acl" => acl},
|
67
|
+
{"success_action_redirect" => redirect_url}
|
68
|
+
]
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def policy_expiration
|
75
|
+
(Time.now + (10*60*60)).utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_hidden_field_accessors
|
79
|
+
ACCESSOR_FIELDS.each do |field|
|
80
|
+
self.class.send(:attr_accessor, field) unless self.class.respond_to?(field)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 's3_form_presenter/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "s3_form_presenter"
|
6
|
+
gem.version = S3FormPresenter::VERSION
|
7
|
+
gem.rubyforge_project = 's3_form_presenter'
|
8
|
+
gem.summary = %Q{Generates a simple form that is compatible with S3's form API.}
|
9
|
+
gem.description = %Q{Generates a simple form that is compatible with S3's form API. You can upload S3 assets directly to S3 without hitting your server.}
|
10
|
+
gem.email = ["lancecarlson@gmail.com"]
|
11
|
+
gem.homepage = "http://github.com/lancecarlson/s3_form_presenter"
|
12
|
+
gem.authors = ["Lance Carlson"]
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split("\n")
|
15
|
+
gem.test_files = `git ls-files -- {tests}/*`.split("\n")
|
16
|
+
gem.require_paths = ['lib']
|
17
|
+
end
|
data/test/form_test.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
include S3FormPresenter
|
4
|
+
|
5
|
+
describe S3FormPresenter::Form do
|
6
|
+
before do
|
7
|
+
@form = Form.new("some/test/key.ext") do
|
8
|
+
%Q(<input name="file" type="file"><input type="submit" value="Upload File" class="btn btn-primary">)
|
9
|
+
end
|
10
|
+
@form.bucket = "test_bucket"
|
11
|
+
@form.access_key = "test_access_key"
|
12
|
+
@form.secret_key = "test_secret_key"
|
13
|
+
@form.acl = :private
|
14
|
+
@form.redirect_url = "http://www.some-test-redirect.com/some/path"
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "initializer" do
|
18
|
+
it "allows an empty block and provides a sane default" do
|
19
|
+
@form = Form.new("some/test/key.ext").inner_content.must_equal %Q(<input name="file" type="file"><input type="submit" value="Upload File" class="btn btn-primary">)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should let you override access_key, secret_key and bucket with ENV" do
|
23
|
+
ENV["AWS_ACCESS_KEY_ID"] = "overridden_env_access_key"
|
24
|
+
ENV["AWS_SECRET_ACCESS_KEY"] = "overridden_env_secret_key"
|
25
|
+
ENV["AWS_S3_BUCKET"] = "overridden_env_bucket"
|
26
|
+
@form = Form.new("some/test/key.ext").access_key.must_equal "overridden_env_access_key"
|
27
|
+
@form = Form.new("some/test/key.ext").secret_key.must_equal "overridden_env_secret_key"
|
28
|
+
@form = Form.new("some/test/key.ext").bucket.must_equal "overridden_env_bucket"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should let you override access_key, secret_key and bucket and acl with options in the initializer" do
|
32
|
+
@form = Form.new("some/test/key.ext", :access_key => "overridden_options_access_key").access_key.must_equal "overridden_options_access_key"
|
33
|
+
@form = Form.new("some/test/key.ext", :secret_key => "overridden_options_secret_key").secret_key.must_equal "overridden_options_secret_key"
|
34
|
+
@form = Form.new("some/test/key.ext", :bucket => "overridden_options_bucket").bucket.must_equal "overridden_options_bucket"
|
35
|
+
@form = Form.new("some/test/key.ext", :acl => "overridden_options_acl").acl.must_equal "overridden_options_acl"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "header" do
|
40
|
+
it "generates a multi-part post form with the correct path" do
|
41
|
+
@form.header.must_equal %Q(<form action="http://test_bucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "footer" do
|
46
|
+
it "generates an ending form tag" do
|
47
|
+
@form.footer.must_equal %Q(</form>)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "accessor_fields" do
|
52
|
+
it "generates accessors for all accessor_fields after initialize" do
|
53
|
+
Form::ACCESSOR_FIELDS.each do |field|
|
54
|
+
@form.must_respond_to(field)
|
55
|
+
@form.must_respond_to("#{field}=")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "hidden_field" do
|
61
|
+
it "generates HTML for a hidden field tag" do
|
62
|
+
@form.hidden_field("some_name", "some_value").must_equal %Q(<input type="hidden" name="some_name" value="some_value">)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "hidden_fields" do
|
67
|
+
it "generates HTML for each hidden_field" do
|
68
|
+
#@form.hidden_fields.must_equal []
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "policy_json" do
|
73
|
+
it "generates the plain json for the policy" do
|
74
|
+
obj = @form.policy_object
|
75
|
+
conditions = obj["conditions"]
|
76
|
+
obj["expiration"].must_equal (Time.now + (10*60*60)).utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
77
|
+
conditions[0]["bucket"].must_equal "test_bucket"
|
78
|
+
conditions[1].must_equal ["starts-with", "$key", "some/test/key.ext"]
|
79
|
+
conditions[2]["acl"].must_equal :private
|
80
|
+
conditions[3]["success_action_redirect"].must_equal "http://www.some-test-redirect.com/some/path"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "policy" do
|
85
|
+
it "generates the base64 encoded policy used in the form" do
|
86
|
+
@form.policy.length.must_equal 288
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "signature" do
|
91
|
+
it "generates the signature" do
|
92
|
+
@form.signature.length.must_equal 28
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "inner_content" do
|
97
|
+
it "should grab content from a block if passed" do
|
98
|
+
@form.inner_content.must_equal %Q(<input name="file" type="file"><input type="submit" value="Upload File" class="btn btn-primary">)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "to_html" do
|
103
|
+
it "generates the full html of the form" do
|
104
|
+
content = @form.header + @form.hidden_fields.join + @form.inner_content + @form.footer
|
105
|
+
#content = "" # comment out if you want to see real output
|
106
|
+
@form.to_html.must_equal content
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: s3_form_presenter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lance Carlson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-19 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Generates a simple form that is compatible with S3's form API. You can
|
15
|
+
upload S3 assets directly to S3 without hitting your server.
|
16
|
+
email:
|
17
|
+
- lancecarlson@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- Gemfile
|
23
|
+
- Gemfile.lock
|
24
|
+
- LICENSE
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- lib/s3_form_presenter.rb
|
28
|
+
- lib/s3_form_presenter/version.rb
|
29
|
+
- s3_form_presenter.gemspec
|
30
|
+
- test/form_test.rb
|
31
|
+
- test/test_helper.rb
|
32
|
+
homepage: http://github.com/lancecarlson/s3_form_presenter
|
33
|
+
licenses: []
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
hash: -1406833252476802253
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
hash: -1406833252476802253
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project: s3_form_presenter
|
58
|
+
rubygems_version: 1.8.15
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Generates a simple form that is compatible with S3's form API.
|
62
|
+
test_files: []
|