From 86804cd1b00dd9accb49198ee45cbcb2b842f888 Mon Sep 17 00:00:00 2001 From: Wayne Date: Sat, 29 Sep 2012 12:36:08 -0500 Subject: [PATCH] init commit --- .gitignore | 18 +++++++ .rspec | 2 + Gemfile | 6 +++ LICENSE | 22 ++++++++ README.md | 58 ++++++++++++++++++++ Rakefile | 2 + lib/s3_direct_upload.rb | 11 ++++ lib/s3_direct_upload/config_aws.rb | 18 +++++++ lib/s3_direct_upload/engine.rb | 4 ++ lib/s3_direct_upload/form_helper.rb | 84 +++++++++++++++++++++++++++++ lib/s3_direct_upload/version.rb | 3 ++ s3_direct_upload.gemspec | 20 +++++++ spec/existance_spec.rb | 18 +++++++ spec/spec_helper.rb | 9 ++++ 14 files changed, 275 insertions(+) create mode 100644 .gitignore create mode 100644 .rspec create mode 100644 Gemfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Rakefile create mode 100644 lib/s3_direct_upload.rb create mode 100644 lib/s3_direct_upload/config_aws.rb create mode 100644 lib/s3_direct_upload/engine.rb create mode 100644 lib/s3_direct_upload/form_helper.rb create mode 100644 lib/s3_direct_upload/version.rb create mode 100644 s3_direct_upload.gemspec create mode 100644 spec/existance_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c1ecbde --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +.DS_Store +*.gem +*.rbc +.bundle +.config +.yardoc +Gemfile.lock +InstalledFiles +_yardoc +coverage +doc/ +lib/bundler/man +pkg +rdoc +spec/reports +test/tmp +test/version_tmp +tmp diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..b3eb8b4 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format documentation \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..17dce36 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in s3_direct_upload.gemspec +gemspec +gem 'rspec' +gem 'jquery-fileupload-rails' \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..47ba1b8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012 Wayne + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e8600ae --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# S3DirectUpload + +TODO: Write a gem description + +## Installation + +Add this line to your application's Gemfile: + + gem 's3_direct_upload' + +Then add a new initalizer with this code: +``` +S3DirectUpload.config do |c| + c.access_key_id = "" # your access key id + c.secret_access_key = "" # your secret access key + c.bucket = "" # your bucket name +end +``` + +S3 Cors Config should look like this: +``` + + + http://0.0.0.0:3000 + GET + POST + PUT + 3000 + * + + +``` + +This gem requires the gem "jquery-fileupload-rails", which is already included by the gem. + +You will need to add the following jquery-fileupload assets to your asset pipeline: + +application.js +``` +//= require jquery-fileupload/basic +//= require jquery-fileupload/vendor/tmpl +``` +## Usage + +Create a new view that uses the helper: +``` +<%= s3_uploader_form post: paintings_url, as: "painting[image_url]" do %> + <%= file_field_tag :file, multiple: true %> +<% end %> +``` + +## Contributing + +1. Fork it +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Added some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create new Pull Request diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..f57ae68 --- /dev/null +++ b/Rakefile @@ -0,0 +1,2 @@ +#!/usr/bin/env rake +require "bundler/gem_tasks" diff --git a/lib/s3_direct_upload.rb b/lib/s3_direct_upload.rb new file mode 100644 index 0000000..17cd4a8 --- /dev/null +++ b/lib/s3_direct_upload.rb @@ -0,0 +1,11 @@ +require "s3_direct_upload/version" + +require 'base64' +require 'openssl' +require 'digest/sha1' + +require 's3_direct_upload/config_aws' +require 's3_direct_upload/form_helper' +require 's3_direct_upload/engine' + +ActionView::Base.send(:include, S3DirectUpload::UploadHelper) if defined?(ActionView::Base) diff --git a/lib/s3_direct_upload/config_aws.rb b/lib/s3_direct_upload/config_aws.rb new file mode 100644 index 0000000..1571bc4 --- /dev/null +++ b/lib/s3_direct_upload/config_aws.rb @@ -0,0 +1,18 @@ +require "singleton" + +module S3DirectUpload + class Config + include Singleton + + ATTRIBUTES = [:access_key_id, :secret_access_key, :bucket] + + attr_accessor *ATTRIBUTES + end + + def self.config + if block_given? + yield Config.instance + end + Config.instance + end +end \ No newline at end of file diff --git a/lib/s3_direct_upload/engine.rb b/lib/s3_direct_upload/engine.rb new file mode 100644 index 0000000..11bb6a2 --- /dev/null +++ b/lib/s3_direct_upload/engine.rb @@ -0,0 +1,4 @@ +module S3DirectUpload + class Engine < ::Rails::Engine + end +end \ No newline at end of file diff --git a/lib/s3_direct_upload/form_helper.rb b/lib/s3_direct_upload/form_helper.rb new file mode 100644 index 0000000..31c140d --- /dev/null +++ b/lib/s3_direct_upload/form_helper.rb @@ -0,0 +1,84 @@ +module S3DirectUpload + module UploadHelper + def s3_uploader_form(options = {}, &block) + uploader = S3Uploader.new(options) + form_tag(uploader.url, uploader.form_options) do + uploader.fields.map do |name, value| + hidden_field_tag(name, value) + end.join.html_safe + capture(&block) + end + end + + class S3Uploader + def initialize(options) + @options = options.reverse_merge( + id: "fileupload", + aws_access_key_id: S3DirectUpload.config.access_key_id, + aws_secret_access_key: S3DirectUpload.config.secret_access_key, + bucket: S3DirectUpload.config.bucket, + acl: "public-read", + expiration: 10.hours.from_now, + max_file_size: 500.megabytes, + as: "file" + ) + end + + def form_options + { + id: @options[:id], + method: "post", + authenticity_token: false, + multipart: true, + data: { + post: @options[:post], + as: @options[:as] + } + } + end + + def fields + { + :key => key, + :acl => @options[:acl], + :policy => policy, + :signature => signature, + "AWSAccessKeyId" => @options[:aws_access_key_id], + } + end + + def key + @key ||= "uploads/#{SecureRandom.hex}/${filename}" + end + + def url + "https://#{@options[:bucket]}.s3.amazonaws.com/" + end + + def policy + Base64.encode64(policy_data.to_json).gsub("\n", "") + end + + def policy_data + { + expiration: @options[:expiration], + conditions: [ + ["starts-with", "$utf8", ""], + ["starts-with", "$key", ""], + ["content-length-range", 0, @options[:max_file_size]], + {bucket: @options[:bucket]}, + {acl: @options[:acl]} + ] + } + end + + def signature + Base64.encode64( + OpenSSL::HMAC.digest( + OpenSSL::Digest::Digest.new('sha1'), + @options[:aws_secret_access_key], policy + ) + ).gsub("\n", "") + end + end + end +end \ No newline at end of file diff --git a/lib/s3_direct_upload/version.rb b/lib/s3_direct_upload/version.rb new file mode 100644 index 0000000..38d88ce --- /dev/null +++ b/lib/s3_direct_upload/version.rb @@ -0,0 +1,3 @@ +module S3DirectUpload + VERSION = "0.0.1" +end diff --git a/s3_direct_upload.gemspec b/s3_direct_upload.gemspec new file mode 100644 index 0000000..c71cd33 --- /dev/null +++ b/s3_direct_upload.gemspec @@ -0,0 +1,20 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../lib/s3_direct_upload/version', __FILE__) + +Gem::Specification.new do |gem| + gem.authors = ["Wayne"] + gem.email = ["wayne@blissofbeing.com"] + gem.description = %q{Direct Upload to Amazon S3 With CORS} + gem.summary = %q{Gives a form helper for Rails which allows direct uploads to s3} + gem.homepage = "" + + gem.files = `git ls-files`.split($\) + gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } + gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) + gem.name = "s3_direct_upload" + gem.require_paths = ["lib"] + gem.version = S3DirectUpload::VERSION + + gem.add_dependency 'rails', '~> 3.2' + gem.add_dependency 'jquery-fileupload-rails', '~> 0.3.4' +end diff --git a/spec/existance_spec.rb b/spec/existance_spec.rb new file mode 100644 index 0000000..0b4d3c6 --- /dev/null +++ b/spec/existance_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' +describe S3DirectUpload do + it "version must be defined" do + S3DirectUpload::VERSION.should be_true + end + + it "config must be defined" do + S3DirectUpload.config.should be_true + end + + it "engine must be defined" + pending + end + + it "form helper must be defined" + pending + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..e4e3119 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,9 @@ +require 's3_direct_upload' + +RSpec.configure do |config| + config.treat_symbols_as_metadata_keys_with_true_values = true + config.run_all_when_everything_filtered = true + config.filter_run :focus + + config.order = 'random' +end