directlytos3 0.1.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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +40 -0
- data/Rakefile +1 -0
- data/directlytos3.gemspec +26 -0
- data/lib/directlytos3.rb +11 -0
- data/lib/directlytos3/exceptions.rb +18 -0
- data/lib/directlytos3/form_builders.rb +27 -0
- data/lib/directlytos3/form_helpers.rb +78 -0
- data/lib/directlytos3/railtie.rb +13 -0
- data/lib/directlytos3/s3.rb +29 -0
- data/lib/directlytos3/snowman_patch.rb +14 -0
- data/lib/directlytos3/version.rb +3 -0
- metadata +80 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Directly To S3
|
2
|
+
|
3
|
+
## Requirements
|
4
|
+
|
5
|
+
- Rails 3.1
|
6
|
+
|
7
|
+
## Purpose
|
8
|
+
|
9
|
+
Inserts an S3 upload field anywhere in a document
|
10
|
+
|
11
|
+
## Installing
|
12
|
+
|
13
|
+
gem install directlytos3
|
14
|
+
export S3_KEY="<your key>"
|
15
|
+
export S3_SECRET_KEY="<your secret key>"
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
= s3_form_for Article.new, :id => "tester3", :bucket => 'thisismybucket', :builder => TwitterBootstrapFormFor::FormBuilder do |f|
|
20
|
+
= f.file_field :hello
|
21
|
+
= s3_field_tag 'name', :bucket => 'thisismybucket', :key => "test", :randomize => true, :redirect => "http://localhost", :remote => true
|
22
|
+
|
23
|
+
You can use either helper, though if you do use `s3_form_for` and you add any other input fields it will fail. This was mainly implemented so you could use builders and adjust the style easily. In addition, if you use `s3_form_for` you have to add the `file_field`. This was done for the reasons above as well.
|
24
|
+
|
25
|
+
## Options
|
26
|
+
|
27
|
+
A full list of options that can be passed to the helpers are listed below
|
28
|
+
|
29
|
+
- bucket: The name of the bucket
|
30
|
+
- secret_key: The secret key, though you could probably put this in the environment variables
|
31
|
+
- public_key: The public access key, likewise with this as well
|
32
|
+
- key: The path (not excluding the final '/')
|
33
|
+
- redirect: Where to redirect
|
34
|
+
- acl: public-read|public|private
|
35
|
+
- max_filesize: The maximum file size
|
36
|
+
- randomize: Add a leading random string to avoid collisions
|
37
|
+
|
38
|
+
## TODO
|
39
|
+
|
40
|
+
- Specs
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "directlytos3/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "directlytos3"
|
7
|
+
s.version = Directlytos3::VERSION
|
8
|
+
s.authors = ["Scott Tesoriere"]
|
9
|
+
s.email = ["scott@tesoriere.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A rails helper to create an S3 upload form}
|
12
|
+
s.description = %q{A rails helper to create an S3 upload form}
|
13
|
+
|
14
|
+
s.rubyforge_project = "directlytos3"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# s.add_development_dependency "rspec", "~> 2.6"
|
22
|
+
s.add_dependency 'railties', '~> 3'
|
23
|
+
s.add_dependency 'actionpack', '~> 3'
|
24
|
+
|
25
|
+
|
26
|
+
end
|
data/lib/directlytos3.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
|
3
|
+
module Directlytos3
|
4
|
+
autoload :VERSION, 'directlytos3/version'
|
5
|
+
autoload :Railtie, 'directlytos3/railtie'
|
6
|
+
autoload :FormHelpers, 'directlytos3/form_helpers'
|
7
|
+
autoload :S3, 'directlytos3/s3'
|
8
|
+
autoload :Exceptions, 'directlytos3/exceptions'
|
9
|
+
end
|
10
|
+
|
11
|
+
Directlytos3::Railtie
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Directlytos3::Exceptions
|
2
|
+
class S3Exception < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class MissingAccessKey < S3Exception
|
6
|
+
def initialize(key)
|
7
|
+
super("You did not provide both required access keys. Please provide the #{key} key.")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class NoBucketSpecified < S3Exception
|
12
|
+
def initialize
|
13
|
+
super("You did not specify a bucket.")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'action_view/helpers'
|
2
|
+
|
3
|
+
class ActionView::Helpers::FormBuilder
|
4
|
+
def s3_file_field(method, options = {})
|
5
|
+
parent_form_options = @parent_builder.instance_variable_get("@options")
|
6
|
+
self.multipart = true
|
7
|
+
if parent_form_options.has_key?(:html) && parent_form_options[:html].has_key?(:id) && parent_form_options[:html][:id] == 's3-upload-form'
|
8
|
+
# file_field(method, options.merge(:name => "file"))
|
9
|
+
@template.file_field(@object_name, method, objectify_options(options.merge(:name=>"file")))
|
10
|
+
else
|
11
|
+
# file_field(method, options)
|
12
|
+
@template.file_field(@object_name, method, objectify_options(options))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
alias_method :file_field, :s3_file_field
|
16
|
+
|
17
|
+
# def extra_tags_for_form_with_snowman_excluded_from_gets(html_options)
|
18
|
+
# old = extra_tags_for_form_without_snowman_excluded_from_gets(html_options)
|
19
|
+
# if html_options.has_key?("id") && html_options["id"] == 's3-upload-form' && !old.include?("_method")
|
20
|
+
# content_tag(:div, '', :style => 'margin:0;padding:0;display:inline')
|
21
|
+
# else
|
22
|
+
# old
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# alias_method_chain :extra_tags_for_form, :snowman_excluded_from_gets
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'mime/types'
|
2
|
+
require 'action_view/helpers'
|
3
|
+
require 'base64'
|
4
|
+
require 'directlytos3'
|
5
|
+
require 'digest'
|
6
|
+
|
7
|
+
|
8
|
+
module Directlytos3
|
9
|
+
|
10
|
+
def self.configure(options)
|
11
|
+
options[:bucket] ||= ENV['S3_BUCKET']
|
12
|
+
options[:secret_key] ||= ENV['S3_SECRET_KEY']
|
13
|
+
options[:access_key] ||= ENV['S3_KEY']
|
14
|
+
options[:key] ||= ''
|
15
|
+
options[:key].gsub!(/(\/)$/, '')
|
16
|
+
options[:content_type] ||= MIME::Types.type_for("${filename}").to_s
|
17
|
+
options[:redirect] ||= '/'
|
18
|
+
options[:acl] ||= 'public-read'
|
19
|
+
options[:expiration_date] ||= 10.hours.from_now.utc.xmlschema
|
20
|
+
options[:max_filesize] ||= 1.megabyte
|
21
|
+
options[:randomize] ||= false
|
22
|
+
raise Directlytos3::Exceptions::NoBucketSpecified if !options[:bucket]
|
23
|
+
raise Directlytos3::Exceptions::MissingAccessKey, "secret" if !options[:secret_key]
|
24
|
+
raise Directlytos3::Exceptions::MissingAccessKey, "public" if !options[:access_key]
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def self.random_string
|
29
|
+
Digest::SHA1.hexdigest Time.now.utc.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
module FormHelpers
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
def s3_field_tag(name, options = {})
|
37
|
+
Directlytos3::configure(options)
|
38
|
+
|
39
|
+
form_tag("https://#{options[:bucket]}.s3.amazonaws.com/", :remote => options[:remote], :enctype=>"multipart/form-data",:method=>"post", :id => 's3-upload-form', :authenticity_token => false) do
|
40
|
+
s3_hidden_fields(options)
|
41
|
+
concat file_field_tag 'file'
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
def s3_form_for(record, *args, &block)
|
50
|
+
raise ArgumentError, "s3_form_for: Missing block" unless block_given?
|
51
|
+
|
52
|
+
options = args.extract_options!
|
53
|
+
args << {:url => "https://#{options[:bucket]}.s3.amazonaws.com/", :builder => options[:builder], :enctype => "multipart/form-data", :method => "post", :html => {:id => 's3-upload-form'}, :authenticity_token => false, :remote => options[:remote]}
|
54
|
+
Directlytos3::configure(options)
|
55
|
+
form_for(record, *(args)) do |f|
|
56
|
+
s3_hidden_fields(options)
|
57
|
+
block.call(f)
|
58
|
+
# f.file_field "file", :name => "file"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def s3_hidden_fields(options)
|
63
|
+
|
64
|
+
policy = Directlytos3::S3.policy(options)
|
65
|
+
signature = Directlytos3::S3.signature(options)
|
66
|
+
|
67
|
+
concat hidden_field_tag('key', "#{options[:key]}#{'/' if !options[:key].blank?}#{Directlytos3.random_string if options[:randomize]}${filename}")
|
68
|
+
concat hidden_field_tag('AWSAccessKeyId', "#{options[:access_key]}")
|
69
|
+
concat hidden_field_tag('acl', "#{options[:acl]}")
|
70
|
+
concat hidden_field_tag('success_action_redirect', "#{options[:redirect]}")
|
71
|
+
concat hidden_field_tag('policy', "#{policy}")
|
72
|
+
concat hidden_field_tag('signature', "#{signature}")
|
73
|
+
concat hidden_field_tag('Content-Type', "#{options[:content_type]}")
|
74
|
+
options.except!(:key, :access_key, :acl, :redirect, :content_type, :secret_key, :randomize, :expiration_date, :max_filesize)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails/railtie'
|
2
|
+
require 'directlytos3'
|
3
|
+
|
4
|
+
class Directlytos3::Railtie < Rails::Railtie
|
5
|
+
initializer 'directlytos3.initialize' do
|
6
|
+
ActiveSupport.on_load(:action_view) do
|
7
|
+
# require 'directlytos3/form_builders'
|
8
|
+
include Directlytos3::FormHelpers
|
9
|
+
require 'directlytos3/snowman_patch'
|
10
|
+
require 'directlytos3/form_builders'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'mime/types'
|
2
|
+
require 'base64'
|
3
|
+
require 'directlytos3'
|
4
|
+
|
5
|
+
module Directlytos3::S3
|
6
|
+
|
7
|
+
def self.signature(options)
|
8
|
+
policy = self.policy(options)
|
9
|
+
secret_key = options[:secret_key] || ENV['S3_SECRET_KEY']
|
10
|
+
Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), secret_key, policy)).gsub("\n","")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.policy(options)
|
14
|
+
|
15
|
+
|
16
|
+
policy = {"expiration" => options[:expiration_date],
|
17
|
+
"conditions" => [
|
18
|
+
{"bucket" => options[:bucket]},
|
19
|
+
["starts-with", "$key", options[:key]],
|
20
|
+
{"acl" => options[:acl]},
|
21
|
+
{"success_action_redirect" => options[:redirect]},
|
22
|
+
["starts-with", "$Content-Type", ''],
|
23
|
+
["content-length-range", 0, options[:max_filesize]]
|
24
|
+
]
|
25
|
+
}
|
26
|
+
Base64.encode64(policy.to_json).gsub(/\n/,'')
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActionView::Helpers::FormTagHelper
|
2
|
+
private
|
3
|
+
|
4
|
+
def extra_tags_for_form_with_snowman_excluded_from_gets(html_options)
|
5
|
+
old = extra_tags_for_form_without_snowman_excluded_from_gets(html_options)
|
6
|
+
if html_options.has_key?("id") && html_options["id"] == 's3-upload-form' && !old.include?("_method")
|
7
|
+
content_tag(:div, '', :style => 'margin:0;padding:0;display:inline')
|
8
|
+
else
|
9
|
+
old
|
10
|
+
end
|
11
|
+
end
|
12
|
+
alias_method_chain :extra_tags_for_form, :snowman_excluded_from_gets
|
13
|
+
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: directlytos3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Scott Tesoriere
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-08 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: railties
|
16
|
+
requirement: &70166362487740 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70166362487740
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: actionpack
|
27
|
+
requirement: &70166362486760 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70166362486760
|
36
|
+
description: A rails helper to create an S3 upload form
|
37
|
+
email:
|
38
|
+
- scott@tesoriere.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- Gemfile
|
45
|
+
- README.md
|
46
|
+
- Rakefile
|
47
|
+
- directlytos3.gemspec
|
48
|
+
- lib/directlytos3.rb
|
49
|
+
- lib/directlytos3/exceptions.rb
|
50
|
+
- lib/directlytos3/form_builders.rb
|
51
|
+
- lib/directlytos3/form_helpers.rb
|
52
|
+
- lib/directlytos3/railtie.rb
|
53
|
+
- lib/directlytos3/s3.rb
|
54
|
+
- lib/directlytos3/snowman_patch.rb
|
55
|
+
- lib/directlytos3/version.rb
|
56
|
+
homepage: ''
|
57
|
+
licenses: []
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project: directlytos3
|
76
|
+
rubygems_version: 1.8.10
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: A rails helper to create an S3 upload form
|
80
|
+
test_files: []
|