s3browser 0.1.0 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2af7ec1f09ccd3a5a9108b4db4cd02fff8d55bc
4
- data.tar.gz: 37bc0b82fc54b2716711388437e688d32db12e06
3
+ metadata.gz: 2f0b52f998b7d61530d1781fa9fde463d59aa1bc
4
+ data.tar.gz: ecafe26c558b8dfece67e41abd119855627667fe
5
5
  SHA512:
6
- metadata.gz: bfe118747868fdb3e74470a4b9d9551c97a988fc2efbb1f3b038d3c8604053384fb1df67e701b013a64d674605370acec46c53049463566e7d1bf2edbda4d664
7
- data.tar.gz: 0b807d66b7fa7dc2f97cf2ba658d1dcb9a643c9c1cf0c91a6d965314032652c7548f93210a2fcbbdae7b26cbad6d5dc0e4c0e12cee016773f939a9a5273521e4
6
+ metadata.gz: 83213e2b455ea473babb63dfd34e035563554dbeb8451671e5c7b69a3729722802aeec80db15bbdfe5b2ca4761c3e18abbde63a370630b940eeb9ba0f939007c
7
+ data.tar.gz: ecd3b4f3905cec378da87d8204d88695c0c2b3699960f1841c54f8435700de3e61d261697ad7d3036288cccbbb4013014a8f89a96efc485b06ce228fe6dca109
data/.gitignore CHANGED
File without changes
@@ -1 +1 @@
1
- 2.3.0
1
+ 2.3.1
data/Gemfile CHANGED
File without changes
File without changes
data/README.md CHANGED
@@ -10,6 +10,7 @@ This wrapper gives you a couple of killer functions:
10
10
  * [x] Automatically update file information
11
11
  * [x] Upload files
12
12
  * [x] Download files
13
+ * [x] Delete files
13
14
 
14
15
  ## Installation
15
16
 
@@ -33,6 +34,7 @@ Here's an example config.ru for booting S3Browser::Server in your choice of Rack
33
34
 
34
35
  ```ruby
35
36
  # config.ru
37
+ #\-o 0.0.0.0 -p 9292
36
38
  require 's3browser/server'
37
39
  run S3Browser::Server
38
40
  ```
@@ -147,6 +149,23 @@ After setting up the queue and the bucket, a policy **without** the following ac
147
149
  * sqs:GetQueueAttributes
148
150
  * sqs:SetQueueAttributes
149
151
 
152
+ ## S3Proxy
153
+
154
+ You might not want to allow public access to your S3 bucket. To work around this, the gem provides a proxy with which the server will fetch the file from S3 and serve it to the client, caching it in between.
155
+
156
+ It's a simple Sinatra app, so can be mounted on a Rack endpoint as well:
157
+
158
+ ```
159
+ # config.ru
160
+ #\-o 0.0.0.0 -p 9292
161
+ require 's3browser/server'
162
+ require 's3browser/s3proxy'
163
+
164
+ run Rack::URLMap.new('/s3' => S3Browser::S3Proxy, '/' => S3Browser::Server)
165
+ ```
166
+
167
+ The above example allows you to set the `S3BROWSER_THUMBNAIL_URL` and `S3BROWSER_OBJECT_URL` environmental variables to `/s3` so that you can download and view the files from the browser.
168
+
150
169
  ## Development
151
170
 
152
171
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/Rakefile CHANGED
File without changes
@@ -29,6 +29,7 @@ Vagrant.configure(2) do |config|
29
29
  sudo apt-get install -y elasticsearch
30
30
  sudo service elasticsearch stop
31
31
  echo "ES_HEAP_SIZE=1g" | sudo tee -a /etc/default/elasticsearch
32
+ echo "network.host: 0.0.0.0" | sudo tee -a /etc/elasticsearch/elasticsearch.yml
32
33
 
33
34
  # Dependencies / Utilities
34
35
  sudo apt-get install -y screen curl git build-essential
File without changes
@@ -4,6 +4,8 @@ require 's3browser/store'
4
4
 
5
5
  module S3Browser
6
6
  class Fetch
7
+ raise 'Unconfigured' unless ENV['AWS_REGION']
8
+
7
9
  class Store < S3Browser::Store
8
10
  plugin :es
9
11
  plugin :images
File without changes
@@ -21,27 +21,28 @@ module S3Browser
21
21
  # TODO Can be optimized to do a bulk index every X requests
22
22
  object[:bucket] = bucket
23
23
  object[:last_modified] = object[:last_modified].to_i
24
- object[:url] = "http://#{bucket}.s3.amazonaws.com/#{object[:key]}"
24
+ object[:url] = "#{object_url}/#{bucket}/#{object[:key]}"
25
25
  client.index(index: index, type: 'objects', id: object[:key], body: object)
26
26
  super(bucket, object)
27
27
  end
28
28
 
29
+ def remove(bucket, key)
30
+ client.delete(index: index, type: 'objects', id: key, ignore: [404])
31
+ super(bucket, key)
32
+ end
33
+
29
34
  def objects(bucket, options)
30
- body = get_body(bucket, options)
31
- if options[:key]
32
- raise 'Not implemented yet'
33
- else
34
- result = client.search(index: index, type: 'objects', body: body)
35
- result['hits']['hits'].map {|val| val['_source'].inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} }
36
- end
35
+ result = client.search(index: index, type: 'objects', body: search_body(bucket, options))
36
+ result['hits']['hits'].map {|val| val['_source'].inject({}){|memo,(k,v)| memo[k.downcase.to_sym] = v; memo} }
37
37
  end
38
38
 
39
- def search(bucket, term, options = {})
40
- get(bucket, {term: term}.merge(options))
39
+ def object(bucket, key)
40
+ result = client.get(index: index, type: 'objects', id: key)
41
+ result['_source'].inject({}){|memo,(k,v)| memo[k.downcase.to_sym] = v; memo}
41
42
  end
42
43
 
43
44
  def buckets
44
- client.search(index: index, type: 'objects', body: {
45
+ buckets = client.search(index: index, type: 'objects', body: {
45
46
  query: { match_all: {} },
46
47
  size: 0,
47
48
  aggregations: {
@@ -54,6 +55,8 @@ module S3Browser
54
55
  }
55
56
  }
56
57
  })['aggregations']['buckets']['buckets'].map {|val| val['key'] }
58
+ return buckets unless buckets.empty?
59
+ super
57
60
  end
58
61
 
59
62
  def indices
@@ -78,7 +81,7 @@ module S3Browser
78
81
  end
79
82
 
80
83
  private
81
- def get_body(bucket, options = {})
84
+ def search_body(bucket, options = {})
82
85
  body = {
83
86
  query: {
84
87
  bool: {
@@ -3,26 +3,36 @@ module S3Browser
3
3
  module StorePlugins
4
4
  module Images
5
5
  module InstanceMethods
6
- def add(bucket, object)
7
- return super(bucket, object) unless handle?(object)
8
- # TODO Create a thumbnail and make it available
9
-
10
- super(bucket, object)
11
- end
12
-
13
6
  def objects(bucket, options)
14
- result = super(bucket, options)
15
- result.map do |elm|
16
- elm[:thumbnail] = {
17
- url: "http://#{bucket}.s3.amazonaws.com/#{elm[:key]}",
7
+ super(bucket, options).map do |object|
8
+ object[:thumbnail] = {
9
+ url: "#{thumbnail_url}/#{bucket}/#{object[:key]}",
18
10
  width: 200
19
- } if handle?(elm)
20
- elm
11
+ } if handle?(object)
12
+ object
21
13
  end
22
14
  end
23
15
 
16
+ def object(bucket, key)
17
+ object = super(bucket, key)
18
+ object[:thumbnail] = {
19
+ url: "#{thumbnail_url}/#{bucket}/#{object[:key]}",
20
+ width: 200
21
+ } if handle?(object)
22
+ object
23
+ end
24
+
24
25
  def handle?(object)
25
- object[:content_type] =~ /^image\/.*/
26
+ return (object[:content_type] =~ /^image\/.*/) unless (object[:content_type].nil? || object[:content_type] == '')
27
+ return (object[:type] =~ /^image\/.*/) unless (object[:type].nil? || object[:type] == '')
28
+ object[:key] =~ /(jpg|jpeg|png|gif|bmp)$/
29
+ end
30
+
31
+ def thumbnail_url
32
+ @thumbnail_url ||= begin
33
+ return ENV['S3BROWSER_THUMBNAIL_URL'] if ENV['S3BROWSER_THUMBNAIL_URL']
34
+ "http://s3-#{ENV['AWS_REGION']}.amazonaws.com"
35
+ end
26
36
  end
27
37
  end
28
38
  end
@@ -0,0 +1,30 @@
1
+ require 'aws-sdk'
2
+
3
+ module S3Browser
4
+ class Store
5
+ module StorePlugins
6
+ module Manager
7
+ module InstanceMethods
8
+ def upload(bucket, file)
9
+ filename = file[:filename]
10
+ tempfile = file[:tempfile]
11
+
12
+ s3 = Aws::S3::Resource.new
13
+ s3.bucket(bucket).object(filename).upload_file(tempfile.path)
14
+
15
+ super(bucket, file)
16
+ end
17
+
18
+ def delete(bucket, file)
19
+ s3 = Aws::S3::Client.new
20
+ s3.delete_object(bucket: bucket, key: file)
21
+
22
+ super(bucket, file)
23
+ end
24
+ end
25
+ end
26
+
27
+ register_plugin(:manager, Manager)
28
+ end
29
+ end
30
+ end
@@ -2,7 +2,7 @@
2
2
  "Version": "2012-10-17",
3
3
  "Statement": [
4
4
  {
5
- "Sid": "example-statement-ID",
5
+ "Sid": "S3BrowserGenerateSQS",
6
6
  "Effect": "Allow",
7
7
  "Principal": { "AWS": "*" },
8
8
  "Action": [
@@ -10,8 +10,8 @@
10
10
  ],
11
11
  "Resource": "SQS-queue-ARN",
12
12
  "Condition": {
13
- "ArnLike": {
14
- "aws:SourceArn": "arn:aws:s3:*:*:bucket-name"
13
+ "ArnLike": {
14
+ "aws:SourceArn": "arn:aws:s3:*:*:bucket-name"
15
15
  }
16
16
  }
17
17
  }
@@ -0,0 +1,55 @@
1
+ require 'sinatra/base'
2
+
3
+ module S3Browser
4
+ class S3Proxy < Sinatra::Base
5
+ raise 'Unconfigured' unless ENV['AWS_REGION']
6
+
7
+ configure :development do
8
+ enable :logging
9
+ end
10
+
11
+ get %r{(.+)} do |filename|
12
+ read_file filename
13
+ end
14
+
15
+ helpers do
16
+ def read_file(file)
17
+ cached_file = cache_location(file)
18
+
19
+ matches = file.match(/([^\/]+)\/(.*)/)
20
+ options = {
21
+ bucket: matches[1],
22
+ key: matches[2],
23
+ }
24
+ options[:if_modified_since] = File.mtime(cached_file) if File.exists?(cached_file)
25
+
26
+ begin
27
+ s3object = s3.get_object(options, target: cached_file)
28
+ rescue Aws::S3::Errors::NotModified
29
+ options.delete(:if_modified_since)
30
+ s3object = s3.head_object(options)
31
+ rescue
32
+ halt(404)
33
+ end
34
+ send_file cached_file, file_name: File.basename(file), type: s3object.content_type
35
+ end
36
+
37
+ def cache_location(file)
38
+ matches = file.match(/([^\/]+)\/(.*)/)
39
+ "#{cache_folder}/#{matches[2]}"
40
+ end
41
+
42
+ def cache_folder
43
+ path = '/tmp/s3proxy'
44
+ Dir.mkdir(path) unless File.exists?(path)
45
+ path
46
+ end
47
+
48
+ def s3
49
+ @s3 ||= Aws::S3::Client.new
50
+ end
51
+ end
52
+
53
+ run! if app_file == $0
54
+ end
55
+ end
@@ -5,20 +5,24 @@ require 's3browser/store'
5
5
 
6
6
  module S3Browser
7
7
  class Server < Sinatra::Base
8
- enable :sessions
8
+ raise 'Unconfigured' unless ENV['AWS_REGION']
9
+
9
10
  use Rack::Flash
10
11
 
11
12
  class Store < S3Browser::Store
12
13
  plugin :es
13
14
  plugin :images
14
- plugin :upload
15
+ plugin :manager
16
+ end
17
+
18
+ configure do
19
+ enable :sessions
20
+ enable :method_override
21
+ set :store, Store.new('s3browser')
15
22
  end
16
23
 
17
24
  configure :development do
18
- set :port, 9292
19
- set :bind, '0.0.0.0'
20
25
  enable :logging
21
- set :store, Store.new('s3browser')
22
26
  end
23
27
 
24
28
  get '/' do
@@ -26,19 +30,38 @@ module S3Browser
26
30
  haml :index, locals: { title: 'S3Browser', buckets: buckets }
27
31
  end
28
32
 
29
- get '/:bucket' do |bucket|
33
+ get '/:bucket/?' do |bucket|
30
34
  params['q'] = nil if params['q'] == ''
31
35
  objects = settings.store.objects(bucket, term: params['q'], sort: params['s'], direction: params['d'])
32
36
  haml :bucket, locals: { title: bucket, bucket: bucket, objects: objects, q: params['q'] }
33
37
  end
34
38
 
35
- post '/upload' do
39
+ get '/:bucket/:key/?' do |bucket, key|
40
+ begin
41
+ object = settings.store.object(bucket, key)
42
+ rescue
43
+ halt(404)
44
+ end
45
+ haml :object, locals: { title: key, bucket: bucket, key: key, object: object }
46
+ end
47
+
48
+ delete '/:bucket/:key/?' do |bucket, key|
49
+ begin
50
+ settings.store.delete(bucket, key)
51
+ flash[:success] = 'File deleted'
52
+ rescue StandardError => e
53
+ flash[:error] = 'Could not remove the file: ' + e.message
54
+ end
55
+ redirect back
56
+ end
57
+
58
+ post '/upload/:bucket/?' do |bucket|
36
59
  if params['upload']
37
60
  begin
38
- settings.store.upload params['upload']
61
+ settings.store.upload bucket, params['upload']
39
62
  flash[:success] = 'File uploaded'
40
- rescue
41
- flash[:error] = 'Could not upload the file'
63
+ rescue StandardError => e
64
+ flash[:error] = 'Could not upload the file: ' + e.message
42
65
  end
43
66
  end
44
67
  redirect back
@@ -71,25 +71,39 @@ module S3Browser
71
71
  end
72
72
 
73
73
  module InstanceMethods
74
- def initialize(bucket)
74
+ def add(bucket, object)
75
+ nil
75
76
  end
76
77
 
77
- def add(bucket, object)
78
+ def remove(bucket, key)
78
79
  nil
79
80
  end
80
81
 
82
+ def upload(bucket, file)
83
+ end
84
+
85
+ def delete(bucket, file)
86
+ end
87
+
81
88
  def objects(bucket, options)
82
89
  s3.list_objects(bucket: bucket).contents.map do |object|
83
- object.to_h.merge(bucket: bucket, url: "http://#{bucket}.s3.amazonaws.com/#{object[:key]}")
90
+ object.to_h.merge(bucket: bucket, url: "#{object_url}/#{bucket}/#{object[:key]}")
84
91
  end
85
92
  end
86
93
 
87
- def search(bucket, term, options = {})
88
- []
94
+ def object(bucket, key)
95
+ s3.head_object(bucket: bucket, key: key)
89
96
  end
90
97
 
91
98
  def buckets
92
- s3.list_buckets.buckets
99
+ s3.list_buckets.buckets.map {|val| val['name'] }
100
+ end
101
+
102
+ def object_url
103
+ @object_url ||= begin
104
+ return ENV['S3BROWSER_OBJECT_URL'] if ENV['S3BROWSER_OBJECT_URL']
105
+ "http://s3-#{ENV['AWS_REGION']}.amazonaws.com"
106
+ end
93
107
  end
94
108
 
95
109
  private
@@ -1,3 +1,3 @@
1
1
  module S3Browser
2
- VERSION = "0.1.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -5,7 +5,7 @@
5
5
  = bucket
6
6
  .panel-body
7
7
  .col-md-10
8
- %form.form-horizontal{method: 'get', action: "/#{bucket}"}
8
+ %form.form-horizontal{method: 'get', action: url("/#{bucket}")}
9
9
  .form-group
10
10
  .input-group
11
11
  %input.form-control{ type: 'text', name: 'q', placeholder: 'Search', value: q }
@@ -22,6 +22,7 @@
22
22
  = haml :column_header, locals: { field: :key }
23
23
  = haml :column_header, locals: { field: :size }
24
24
  = haml :column_header, locals: { field: :content_type, field_name: 'Type' }
25
+ %th Download
25
26
  = haml :column_header, locals: { field: :last_modified }
26
27
  %th
27
28
  Thumbnail
@@ -29,17 +30,18 @@
29
30
  -objects.each do |obj|
30
31
  %tr
31
32
  %td
32
- %a{ target: '_blank', href: obj[:url] }
33
- = obj[:key]
33
+ %a{ href: url("/#{bucket}/#{obj[:key]}") }= obj[:key]
34
34
  %td= obj[:size]
35
35
  %td= obj[:content_type]
36
+ %td
37
+ %a.btn.btn-default{ target: '_blank', href: obj[:url] } Download
36
38
  %td= Time.at(obj[:last_modified]).strftime('%Y-%m-%d %H:%M:%S')
37
39
  %td
38
40
  -if obj[:thumbnail]
39
- %img{ src: obj[:thumbnail][:url], width: obj[:thumbnail][:width]}
41
+ %img.img-response.center-block.img-thumbnail{ src: obj[:thumbnail][:url], width: obj[:thumbnail][:width]}
40
42
 
41
43
  - if settings.store.respond_to? :upload
42
- %form{ enctype: 'multipart/form-data', method: 'post', action: '/upload' }
44
+ %form{ enctype: 'multipart/form-data', method: 'post', action: '/upload/' + bucket }
43
45
  #upload-modal.modal.fade{ tabindex: -1, role: 'dialog' }
44
46
  .modal-dialog
45
47
  .modal-content
File without changes
File without changes
@@ -9,4 +9,4 @@
9
9
  -buckets.each do |bucket|
10
10
  %tr
11
11
  %td
12
- %a{ href: "/#{bucket}" }= bucket
12
+ %a{ href: url("/#{bucket}") }= bucket
@@ -3,7 +3,7 @@
3
3
  %head
4
4
  %meta{:charset => 'utf-8'}
5
5
  %title
6
- S3Browser
6
+ S3Browser
7
7
  - if defined? title
8
8
  = "- #{title}"
9
9
  %meta{:name => "description", :content => ""}
@@ -34,6 +34,5 @@
34
34
 
35
35
  / Placed at the end of the document so the pages load faster
36
36
  %script{ type: 'text/javascript', src: '//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js' }
37
- %script{ type: 'text/javascript', src: '//maps.googleapis.com/maps/api/js?libraries=places' }
38
37
  %script{ type: 'text/javascript', src: '//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js' }
39
38
 
@@ -0,0 +1,39 @@
1
+ .row
2
+ .col-md-12
3
+ .panel.panel-primary
4
+ .panel-heading
5
+ = "#{bucket} / #{key}"
6
+
7
+ %table.table.table-hover
8
+ %tr
9
+ %th Key
10
+ %td= object[:key]
11
+ %tr
12
+ %th Bucket
13
+ %td= object[:bucket]
14
+ %tr
15
+ %th eTag
16
+ %td= object[:etag]
17
+ %tr
18
+ %th Size
19
+ %td= object[:size]
20
+ %tr
21
+ %th Type
22
+ %td= object[:content_type]
23
+ %tr
24
+ %th Last Modified
25
+ %td= Time.at(object[:last_modified]).strftime('%Y-%m-%d %H:%M:%S')
26
+ %tr
27
+ %th Storage Class
28
+ %td= object[:storage_class]
29
+ %tr
30
+ %td.text-left
31
+ %a.btn.btn-default{ target: '_base', href: object[:url] } Download
32
+ %td.text-right
33
+ %form{ method: 'post', action: url("/#{bucket}/#{object[:key]}") }
34
+ %input{ type: 'hidden', name: '_method', value: 'delete'}
35
+ %button.btn.btn-warning{ type: 'submit', onclick: 'return confirm("This will completely remove the file.");' } Delete
36
+ -if object[:thumbnail]
37
+ .row
38
+ .col-md-12
39
+ %img.img-response.img-thumbnail.center-block{ src: object[:url] }
@@ -5,6 +5,8 @@ module S3Browser
5
5
  class Worker
6
6
  include Shoryuken::Worker
7
7
 
8
+ raise 'Unconfigured' unless ENV['AWS_REGION']
9
+
8
10
  shoryuken_options queue: ENV['AWS_SQS_QUEUE'], body_parser: :json, auto_delete: true
9
11
 
10
12
  class Store < S3Browser::Store
@@ -12,22 +14,44 @@ module S3Browser
12
14
  plugin :images
13
15
  end
14
16
 
17
+ def initialize
18
+ Shoryuken.logger.level = ::Logger::DEBUG if ENV['RACK_ENV'] != 'production'
19
+ end
20
+
15
21
  def perform(sqs_msg, body)
22
+ Shoryuken.logger.debug body
23
+
16
24
  if body['Records']
17
25
  body['Records'].each do |record|
18
- bucket = record['s3']['bucket']['name']
19
- key = record['s3']['object']['key']
20
-
21
- info = s3.head_object({ bucket: bucket, key: key })
22
- info = info.to_h.merge(record['s3']['object'])
23
-
24
- store.add bucket, info
26
+ case record['eventName']
27
+ when 'ObjectRemoved:Delete'
28
+ remove record
29
+ when 'ObjectCreated:Put'
30
+ add record
31
+ end
25
32
  end
26
33
  else
27
34
  raise unless body['Event'] == 's3:TestEvent'
28
35
  end
29
36
  end
30
37
 
38
+ def add(record)
39
+ bucket = record['s3']['bucket']['name']
40
+ key = record['s3']['object']['key']
41
+
42
+ info = s3.head_object({ bucket: bucket, key: key })
43
+ info = info.to_h.merge(record['s3']['object'].inject({}){|memo,(k,v)| memo[k.downcase.to_sym] = v; memo})
44
+
45
+ store.add bucket, info
46
+ end
47
+
48
+ def remove(record)
49
+ bucket = record['s3']['bucket']['name']
50
+ key = record['s3']['object']['key']
51
+
52
+ store.remove bucket, key
53
+ end
54
+
31
55
  private
32
56
  def store
33
57
  @store ||= Store.new('s3browser')
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3browser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jurgens du Toit
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-20 00:00:00.000000000 Z
11
+ date: 2016-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -173,8 +173,9 @@ files:
173
173
  - lib/s3browser/gem_tasks.rb
174
174
  - lib/s3browser/plugins/es.rb
175
175
  - lib/s3browser/plugins/images.rb
176
- - lib/s3browser/plugins/upload.rb
176
+ - lib/s3browser/plugins/manager.rb
177
177
  - lib/s3browser/policy.json
178
+ - lib/s3browser/s3proxy.rb
178
179
  - lib/s3browser/server.rb
179
180
  - lib/s3browser/store.rb
180
181
  - lib/s3browser/version.rb
@@ -183,6 +184,7 @@ files:
183
184
  - lib/s3browser/views/flash_messages.haml
184
185
  - lib/s3browser/views/index.haml
185
186
  - lib/s3browser/views/layout.haml
187
+ - lib/s3browser/views/object.haml
186
188
  - lib/s3browser/worker.rb
187
189
  - s3browser.gemspec
188
190
  homepage: https://github.com/jrgns/s3browser
@@ -1,22 +0,0 @@
1
- require 'aws-sdk'
2
-
3
- module S3Browser
4
- class Store
5
- module StorePlugins
6
- module Upload
7
- module InstanceMethods
8
- def upload(file)
9
- filename = file[:filename]
10
- file = file[:tempfile]
11
- bucket = 's3browser'
12
-
13
- s3 = Aws::S3::Resource.new
14
- s3.bucket(bucket).object(filename).upload_file(file.path)
15
- end
16
- end
17
- end
18
-
19
- register_plugin(:upload, Upload)
20
- end
21
- end
22
- end