browse-everything 1.6.0 → 1.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eedf3447096af5429b239653b707bf23e881fcd43a097cbe25804c7d48bc16e2
4
- data.tar.gz: 1ccf9adb1e189a413ae6ceb9a4e67bccfae3a5179c84f583c1b165f4e051cf00
3
+ metadata.gz: faa729e0e6ae6d2ae76c0c9364b44017d689bbb89153b3c1e98bde8c17fa1427
4
+ data.tar.gz: 7a29fe7df1a1dd5bdd309e23e4edc22af28d3fb618bceaf01d852537d37fdb3b
5
5
  SHA512:
6
- metadata.gz: 58511d9c04085a4a9d72246c906bb20cb46bac2e980d17bf90276807b67fe4c38eab79dbae89c10a69e735da6ee2e0acffe0399fe7993526a0454886cc3555ee
7
- data.tar.gz: 5484761c6ed0b148ba8a10852dea363a1c6860b146271dd0b8bedbad65f37dfb50b0644f3da2ae533c0b84c782fadea9d808f8d1f2d10d1acb00e3ee8f9d6b34
6
+ metadata.gz: 4a97f843dafad43ddb8a58cf30f663d586dcdecaec0ba1fde64f38c2189c6a3c731d9fd0e1c9c39437ce63f8ad294ded4befac02d651b9de2063eedf3b13311b
7
+ data.tar.gz: 487830c4ba65dbd1810774a87fef7ecd4202e805a4153bbfdb4c333e9c833afdcfaab24de26e285c198e2bc29d1ea944f387bf1011cb21c76e697da88a23e2d3
data/Gemfile CHANGED
@@ -25,6 +25,12 @@ end
25
25
 
26
26
  ENV['RAILS_VERSION'] ||= "8.0.0"
27
27
 
28
+ # json 3 dropped the quirks_mode option that ActiveSupport before 8.1 passes
29
+ # when encoding, so Hash#to_json raises ArgumentError under it.
30
+ if ENV['RAILS_VERSION'] != 'edge' && Gem::Version.new(ENV['RAILS_VERSION']) < Gem::Version.new('8.1')
31
+ gem 'json', '< 3'
32
+ end
33
+
28
34
  if ENV['RAILS_VERSION']
29
35
  if ENV['RAILS_VERSION'] == 'edge'
30
36
  gem 'rails', github: 'rails/rails'
@@ -323,7 +323,12 @@ $(function () {
323
323
 
324
324
  $(document).on('click', 'button.ev-submit', function (event) {
325
325
  event.preventDefault();
326
- $(this).button('loading');
326
+ // button('loading') is Bootstrap 3's button plugin. When jQuery UI's
327
+ // button widget owns $.fn.button instead, it throws on the call and the
328
+ // selection is never submitted. startWait() disables the button either way.
329
+ if ($.fn.button && $.fn.button.Constructor) {
330
+ $(this).button('loading');
331
+ }
327
332
  startWait();
328
333
  $('form.ev-submit-form').append(Array.from(selected_files.values()));
329
334
  var main_form = $(this).closest('form');
@@ -55,17 +55,19 @@ module BrowseEverything
55
55
  def link_for(path)
56
56
  obj = bucket.object(full_path(path))
57
57
 
58
- extras = {
59
- file_name: File.basename(path),
60
- expires: (config[:expires_in] if config[:response_type] == :signed_url)
61
- }.compact
62
-
63
- url = case config[:response_type].to_sym
58
+ response_type = config[:response_type].to_sym
59
+ url = case response_type
64
60
  when :signed_url then obj.presigned_url(:get, expires_in: config[:expires_in])
65
61
  when :public_url then obj.public_url
66
62
  when :s3_uri then "s3://#{obj.bucket_name}/#{obj.key}"
67
63
  end
68
64
 
65
+ extras = {
66
+ file_name: File.basename(path),
67
+ file_size: object_size(obj),
68
+ expires: (signed_url_expiry(url) if response_type == :signed_url)
69
+ }.compact
70
+
69
71
  [url, extras]
70
72
  end
71
73
 
@@ -79,6 +81,26 @@ module BrowseEverything
79
81
 
80
82
  private
81
83
 
84
+ # The size is a convenience for consumers, so credentials that can list
85
+ # but not read an object (enough for an :s3_uri link) leave it out
86
+ # rather than fail the link.
87
+ def object_size(obj)
88
+ obj.content_length
89
+ rescue Aws::S3::Errors::ServiceError, Seahorse::Client::NetworkingError
90
+ nil
91
+ end
92
+
93
+ # Retriever#retrieve parses `expires` as a time, so send when the link
94
+ # expires, as the Box and Google Drive drivers do. It is read from the
95
+ # signed URL itself because the SDK can sign for less than expires_in,
96
+ # for example when the signing credentials are temporary.
97
+ def signed_url_expiry(url)
98
+ params = Rack::Utils.parse_query(URI(url).query)
99
+ return unless params['X-Amz-Date'] && params['X-Amz-Expires']
100
+
101
+ Time.strptime(params['X-Amz-Date'], '%Y%m%dT%H%M%S%z') + params['X-Amz-Expires'].to_i
102
+ end
103
+
82
104
  def strip(path)
83
105
  path.sub %r{^/?(.+?)/?$}, '\1'
84
106
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BrowseEverything
4
- VERSION = '1.6.0'
4
+ VERSION = '1.6.1'
5
5
  end
@@ -134,28 +134,68 @@ describe BrowseEverything::Driver::S3 do
134
134
  context 'when retrieving the link for an asset' do
135
135
  subject { contents[2] }
136
136
 
137
+ let(:signed_at) { Time.now.utc.change(usec: 0) }
138
+ let(:presigned_url) do
139
+ "https://s3.amazonaws.com/presigned_url?X-Amz-Date=#{signed_at.strftime('%Y%m%dT%H%M%SZ')}&X-Amz-Expires=3600"
140
+ end
141
+
137
142
  before do
138
143
  object = instance_double(Aws::S3::Object)
139
- allow(object).to receive(:presigned_url).and_return('https://s3.amazonaws.com/presigned_url')
144
+ allow(object).to receive(:presigned_url).and_return(presigned_url)
140
145
  allow(object).to receive(:public_url).and_return('https://s3.amazonaws.com/public_url')
141
146
  allow(object).to receive(:bucket_name).and_return('s3.bucket')
142
147
  allow(object).to receive(:key).and_return('foo/quux.png')
148
+ allow(object).to receive(:content_length).and_return(1_511_860)
143
149
  allow(provider.bucket).to receive(:object).and_return(object)
144
150
  end
145
151
 
146
152
  it ':signed_url' do
147
153
  provider.config[:response_type] = :signed_url
148
- expect(provider.link_for('foo/quux.png')).to eq ['https://s3.amazonaws.com/presigned_url', { file_name: 'quux.png', expires: 14400 }]
154
+ expect(provider.link_for('foo/quux.png')).to eq [presigned_url, { file_name: 'quux.png', file_size: 1_511_860, expires: signed_at + 3600 }]
155
+ end
156
+
157
+ it ':signed_url reports the lifetime the URL was signed for, not expires_in' do
158
+ provider.config[:response_type] = :signed_url
159
+ provider.config[:expires_in] = 14400
160
+ expect(provider.link_for('foo/quux.png').last[:expires]).to eq signed_at + 3600
161
+ end
162
+
163
+ it ':signed_url configured as a string still sends the expiry' do
164
+ provider.config[:response_type] = 'signed_url'
165
+ expect(provider.link_for('foo/quux.png').last[:expires]).to eq signed_at + 3600
166
+ end
167
+
168
+ [Aws::S3::Errors::Forbidden.new(nil, 'Forbidden'), Seahorse::Client::NetworkingError.new(Errno::ECONNRESET.new)].each do |error|
169
+ it "leaves out the size when reading it raises #{error.class}" do
170
+ provider.config[:response_type] = :s3_uri
171
+ allow(provider.bucket.object('foo/quux.png')).to receive(:content_length).and_raise(error)
172
+ expect(provider.link_for('foo/quux.png')).to eq ['s3://s3.bucket/foo/quux.png', { file_name: 'quux.png' }]
173
+ end
174
+ end
175
+
176
+ it ':s3_uri keeps a key that is not a valid URI' do
177
+ provider.config[:response_type] = :s3_uri
178
+ allow(provider.bucket.object('foo/quux.png')).to receive(:key).and_return('foo/résumé file.pdf')
179
+ expect(provider.link_for('foo/quux.png').first).to eq 's3://s3.bucket/foo/résumé file.pdf'
180
+ end
181
+
182
+ it ':signed_url gives an expiry the retriever accepts' do
183
+ provider.config[:response_type] = :signed_url
184
+ url, extras = provider.link_for('foo/quux.png')
185
+ spec = { 'url' => url, 'expires' => extras[:expires].to_s, 'file_size' => extras[:file_size] }
186
+ retriever = BrowseEverything::Retriever.new
187
+ allow(retriever).to receive(:retrieve_http)
188
+ expect { retriever.retrieve(spec) }.not_to raise_error
149
189
  end
150
190
 
151
191
  it ':public_url' do
152
192
  provider.config[:response_type] = :public_url
153
- expect(provider.link_for('foo/quux.png')).to eq ['https://s3.amazonaws.com/public_url', { file_name: 'quux.png' }]
193
+ expect(provider.link_for('foo/quux.png')).to eq ['https://s3.amazonaws.com/public_url', { file_name: 'quux.png', file_size: 1_511_860 }]
154
194
  end
155
195
 
156
196
  it ':s3_uri' do
157
197
  provider.config[:response_type] = :s3_uri
158
- expect(provider.link_for('foo/quux.png')).to eq ['s3://s3.bucket/foo/quux.png', { file_name: 'quux.png' }]
198
+ expect(provider.link_for('foo/quux.png')).to eq ['s3://s3.bucket/foo/quux.png', { file_name: 'quux.png', file_size: 1_511_860 }]
159
199
  end
160
200
  end
161
201
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: browse-everything
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carolyn Cole
@@ -629,7 +629,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
629
629
  - !ruby/object:Gem::Version
630
630
  version: '0'
631
631
  requirements: []
632
- rubygems_version: 3.7.1
632
+ rubygems_version: 4.0.22
633
633
  specification_version: 4
634
634
  summary: AJAX/Rails engine file browser for cloud storage services
635
635
  test_files: