bg_s3uploadable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c10753fe8c1404bbb2816a0e96fcbdf391901560
4
+ data.tar.gz: 16412f90de3d1d9290b7ac53c79e719c55da20a8
5
+ SHA512:
6
+ metadata.gz: 14e4b3612de21c1aa986339b9c11eb04314f680d49df75703695dbc9f12e203fc82b6671982915eeaa4747d3814a19e86a9c71a9c212680faadbabe01526a43d
7
+ data.tar.gz: 1c6a25806d8f5ef0d1fc337f6b2741ea0ed583c947b54e288e881bf64362e75829f86a5bf611871c871085c9c18a4de95237fcfa61f54d7c0f2bc60c642f1f26
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bg_s3uploadable.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Keitaroh Kobayashi
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,31 @@
1
+ # BgS3uploadable
2
+
3
+ Extracted from a couple of my projects. The code is still really messy.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'bg_s3uploadable'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install bg_s3uploadable
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/bg_s3uploadable/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,129 @@
1
+ #= require jquery.fileupload
2
+
3
+ draganddrop = () ->
4
+ if @draggable == undefined
5
+ div = document.createElement 'div'
6
+ @draggable = ('draggable' of div) or ('ondragstart' of div and 'ondrop' of div)
7
+ else
8
+ @draggable
9
+
10
+ window.s3uploaderInstall = () ->
11
+ $('.file-upload').each () ->
12
+ form = $ this
13
+
14
+ return if form.data('s3uploader-installed') == true
15
+ form.data 's3uploader-installed', true
16
+
17
+ if draganddrop()
18
+ installDragAndDrop this
19
+
20
+ bar = form.find '.progress-bar'
21
+
22
+ setProgress = (val) ->
23
+ bar.css 'width', "#{val}%"
24
+ bar.attr 'aria-valuenow', val
25
+
26
+ $s3key_field = $ form.data('s3key-field')
27
+ $image_holder = $ form.data('image-holder')
28
+
29
+ setImageURI = (uri) ->
30
+ image = $image_holder.find('> img')
31
+ if image.length == 0
32
+ $("<img src='#{uri}'>").appendTo $image_holder
33
+ else
34
+ image.attr 'src', uri
35
+
36
+ form.fileupload
37
+ url: form.data 'action'
38
+ type: 'POST'
39
+ autoUpload: true
40
+ dataType: 'xml'
41
+ add: (event, data) ->
42
+ reader = new FileReader
43
+ reader.onload = (e) ->
44
+ setImageURI e.target.result
45
+ reader.readAsDataURL data.files[0]
46
+
47
+ $.ajax
48
+ url: '/s3/signed_url'
49
+ type: 'GET'
50
+ dataType: 'json'
51
+ data:
52
+ doc:
53
+ title: data.files[0].name
54
+ success: (signature) ->
55
+ data.formData =
56
+ key: signature.key
57
+ policy: signature.policy
58
+ signature: signature.signature
59
+ AWSAccessKeyId: form.data 'accesskeyid'
60
+ acl: 'private'
61
+ success_action_status: '201'
62
+ 'x-amz-server-side-encryption': 'AES256'
63
+
64
+ data.submit()
65
+
66
+ send: (e, data) ->
67
+ form.find('.progress').fadeIn()
68
+
69
+ progress: (e, data) ->
70
+ percent = parseInt data.loaded / data.total * 100, 10
71
+ setProgress percent
72
+
73
+ fail: (e, data) ->
74
+ console.log "Failure."
75
+
76
+ success: (data) ->
77
+ key = $(data).find('Key').text()
78
+ $s3key_field.val key
79
+
80
+ # uri = "/s3/uploaded_image?key=#{key}"
81
+ # setImageURI uri
82
+
83
+ # form.parents('form').submit()
84
+ form.hide()
85
+ done: (e, data) ->
86
+ form.find('.progress').fadeOut 300, () ->
87
+ setProgress 0
88
+
89
+ installDragAndDrop = (container) ->
90
+ counter = 0
91
+ $container = $ container
92
+
93
+ container.addEventListener 'dragover', (e) ->
94
+ e.preventDefault()
95
+
96
+ container.addEventListener 'dragenter', (e) ->
97
+ counter += 1
98
+
99
+ if counter == 1
100
+ $container.addClass 'filedrag'
101
+
102
+ container.addEventListener 'dragleave', (e) ->
103
+ counter -= 1
104
+
105
+ if counter == 0
106
+ $container.removeClass 'filedrag'
107
+
108
+ container.addEventListener 'drop', (e) ->
109
+ e.preventDefault()
110
+
111
+ counter = 0
112
+ $container.removeClass 'filedrag'
113
+
114
+ $(document).on 'ready page:load', window.s3uploaderInstall
115
+ $(document).on 'page:load', ->
116
+ $('.filestyle').each ->
117
+ $this = $ this
118
+ options =
119
+ 'input' : if $this.attr('data-input') == 'false' then false else true,
120
+ 'icon' : if $this.attr('data-icon') == 'false' then false else true,
121
+ 'buttonBefore' : if $this.attr('data-buttonBefore') == 'true' then true else false,
122
+ 'disabled' : if $this.attr('data-disabled') == 'true' then true else false,
123
+ 'size' : $this.attr('data-size'),
124
+ 'buttonText' : $this.attr('data-buttonText'),
125
+ 'buttonName' : $this.attr('data-buttonName'),
126
+ 'iconName' : $this.attr('data-iconName'),
127
+ 'badge' : if $this.attr('data-badge') == 'false' then false else true
128
+
129
+ $this.filestyle options
@@ -0,0 +1,60 @@
1
+ module BgS3uploadable
2
+ class SignedUrlsController < ApplicationController
3
+ def show
4
+ policy = s3_upload_policy_document
5
+
6
+ render json: {
7
+ policy: policy,
8
+ signature: s3_upload_signature(policy),
9
+ key: "uploads/#{SecureRandom.uuid}/#{params[:doc][:title]}",
10
+ success_action_redirect: "/",
11
+ upload_endpoint: "https://#{ENV['S3_BUCKET']}.s3.amazonaws.com",
12
+ :AWSAccessKeyID => ENV['AWS_ACCESS_KEY_ID'],
13
+ }
14
+ end
15
+
16
+ def uploaded_image
17
+ unless params[:key] =~ /\Auploads\//
18
+ render json: { error: 'Access denied' }, status: 403
19
+ return
20
+ end
21
+
22
+ s3 = AWS::S3.new
23
+ bucket = s3.buckets[ENV['S3_BUCKET']]
24
+ obj = bucket.objects[params[:key]]
25
+
26
+ presign = AWS::S3::PresignV4.new obj
27
+
28
+ redirect_to presign.presign(:get, expires: 5.minutes.from_now.to_i, secure: true).to_s
29
+ end
30
+
31
+ private
32
+
33
+ # generate the policy document that amazon is expecting.
34
+ def s3_upload_policy_document
35
+ Base64.strict_encode64(
36
+ {
37
+ expiration: 30.minutes.from_now.utc.strftime('%Y-%m-%dT%H:%M:%S.000Z'),
38
+ conditions: [
39
+ { bucket: ENV['S3_BUCKET'] },
40
+ { acl: 'private' },
41
+ ["starts-with", "$key", "uploads/"],
42
+ { success_action_status: '201' },
43
+ { :'x-amz-server-side-encryption' => 'AES256' }
44
+ ]
45
+ }.to_json
46
+ ).gsub(/\n|\r/, '')
47
+ end
48
+
49
+ # sign our request by Base64 encoding the policy document.
50
+ def s3_upload_signature(policy)
51
+ Base64.strict_encode64(
52
+ OpenSSL::HMAC.digest(
53
+ OpenSSL::Digest::SHA1.new,
54
+ ENV['AWS_SECRET_ACCESS_KEY'],
55
+ policy
56
+ )
57
+ ).gsub(/\n/, '')
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ module BgS3uploadable
2
+ class UploaderJob < ::ActiveJob::Base
3
+ def perform(record, attachment)
4
+ key = record.send :"#{attachment}_s3key"
5
+ return if key.blank?
6
+
7
+ f = Tempfile.new(SecureRandom.uuid, encoding: 'binary')
8
+
9
+ s3 = AWS::S3.new
10
+ bucket = s3.buckets[ENV['S3_BUCKET']]
11
+ obj = bucket.objects[key]
12
+ obj.read do |chunk|
13
+ f.write chunk
14
+ end
15
+ f.flush
16
+
17
+ record.class.transaction do
18
+ record.send(:"#{attachment}=", f)
19
+ record.send(:write_attribute, :"#{attachment}_s3key", nil)
20
+
21
+ record.save validate: false
22
+ end
23
+ ensure
24
+ f.close
25
+ f.unlink
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bg_s3uploadable/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "bg_s3uploadable"
8
+ spec.version = BgS3uploadable::VERSION
9
+ spec.authors = ["Keitaroh Kobayashi"]
10
+ spec.email = ["keita@kkob.us"]
11
+ spec.summary = %q{Extension for direct and background S3 uploading to Paperclip}
12
+ spec.description = %q{}
13
+ spec.homepage = "https://github.com/keichan34/bg_s3uploadable"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
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_runtime_dependency "rails", "~> 4.2"
22
+ spec.add_runtime_dependency "aws-sdk", "< 2.0"
23
+ spec.add_runtime_dependency "jquery.fileupload-rails", "~> 1.11"
24
+ spec.add_runtime_dependency "paperclip", ">= 4.2"
25
+ spec.add_runtime_dependency "coffee-rails", "~> 4.0"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.7"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rspec", "~> 3.1"
30
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ BgS3uploadable::Engine.routes.draw do
2
+ get '/signed_url' => 'signed_urls#show'
3
+ get '/uploaded_image' => 'signed_urls#uploaded_image'
4
+ get '/uploaded_image/*key' => 'signed_urls#uploaded_image',
5
+ format: false, as: :uploaded_image_with_key
6
+ end
@@ -0,0 +1,11 @@
1
+ module BgS3uploadable
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace BgS3uploadable
4
+
5
+ initializer "bg_s3uploadable.activerecord_ext" do
6
+ ActiveSupport.on_load(:active_record) do
7
+ ActiveRecord::Base.send :include, Uploadable
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,58 @@
1
+ module BgS3uploadable
2
+ module Uploadable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ after_commit :queue_s3key_notifications
7
+ end
8
+
9
+ private
10
+
11
+ def set_s3key(attachment, key)
12
+ return if key.blank?
13
+
14
+ fail ArgumentError, 'Invalid key' unless key =~ /\Auploads\//
15
+
16
+ write_attribute :"#{attachment}_s3key", key
17
+
18
+ @s3key_notifications_required ||= []
19
+ @s3key_notifications_required << attachment
20
+
21
+ # Clear the old attachment out while processing.
22
+ send(:"#{attachment}=", nil)
23
+ end
24
+
25
+ def queue_s3key_notifications
26
+ return if @s3key_notifications_required.blank?
27
+
28
+ @s3key_notifications_required.each do |attachment|
29
+ UploaderJob.perform_later self, attachment.to_s
30
+ end
31
+
32
+ @s3key_notifications_required = nil
33
+ end
34
+
35
+ module ClassMethods
36
+ def s3_uploadable(*attachments)
37
+ attachments.each { |e| _s3_uploadable e }
38
+ end
39
+
40
+ private
41
+
42
+ def _s3_uploadable(attachment)
43
+ define_method :"#{attachment}_s3key=" do |key|
44
+ set_s3key attachment, key
45
+ end
46
+
47
+ attr_reader :"remove_#{attachment}"
48
+
49
+ define_method :"remove_#{attachment}=" do |value|
50
+ instance_variable_set :"@remove_#{attachment}", value
51
+ if value == '1' or value == 1
52
+ send(:"#{attachment}=", nil)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module BgS3uploadable
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "jquery.fileupload-rails"
2
+
3
+ require "bg_s3uploadable/version"
4
+
5
+ module BgS3uploadable
6
+ end
7
+
8
+ require "bg_s3uploadable/uploadable"
9
+ require "bg_s3uploadable/engine"
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bg_s3uploadable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Keitaroh Kobayashi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "<"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jquery.fileupload-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.11'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: paperclip
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '4.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '4.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coffee-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.7'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.7'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.1'
125
+ description: ''
126
+ email:
127
+ - keita@kkob.us
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - Gemfile
134
+ - LICENSE.txt
135
+ - README.md
136
+ - Rakefile
137
+ - app/assets/javascripts/bg_s3uploadable/s3uploader.js.coffee
138
+ - app/controllers/bg_s3uploadable/signed_urls_controller.rb
139
+ - app/jobs/bg_s3uploadable/uploader_job.rb
140
+ - bg_s3uploadable.gemspec
141
+ - config/routes.rb
142
+ - lib/bg_s3uploadable.rb
143
+ - lib/bg_s3uploadable/engine.rb
144
+ - lib/bg_s3uploadable/uploadable.rb
145
+ - lib/bg_s3uploadable/version.rb
146
+ homepage: https://github.com/keichan34/bg_s3uploadable
147
+ licenses:
148
+ - MIT
149
+ metadata: {}
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ requirements: []
165
+ rubyforge_project:
166
+ rubygems_version: 2.4.5
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: Extension for direct and background S3 uploading to Paperclip
170
+ test_files: []