browse-everything 0.16.1 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +3 -0
- data/CODE_OF_CONDUCT.md +36 -0
- data/CONTRIBUTING.md +21 -19
- data/Gemfile +1 -0
- data/README.md +29 -9
- data/SUPPORT.md +5 -0
- data/app/controllers/browse_everything_controller.rb +7 -3
- data/app/views/browse_everything/_files.html.erb +14 -6
- data/app/views/browse_everything/index.html.erb +7 -1
- data/browse-everything.gemspec +5 -5
- data/lib/browse_everything/driver/base.rb +1 -1
- data/lib/browse_everything/driver/box.rb +4 -14
- data/lib/browse_everything/driver/dropbox.rb +34 -11
- data/lib/browse_everything/driver/google_drive.rb +2 -2
- data/lib/browse_everything/driver/s3.rb +8 -14
- data/lib/browse_everything/retriever.rb +4 -5
- data/lib/browse_everything/version.rb +1 -1
- data/lib/generators/browse_everything/templates/browse_everything_providers.yml.example +2 -2
- data/spec/controllers/browse_everything_controller_spec.rb +8 -1
- data/spec/lib/browse_everything/driver/box_spec.rb +114 -34
- data/spec/lib/browse_everything/driver/dropbox_spec.rb +53 -5
- data/spec/lib/browse_everything/driver/google_drive_spec.rb +41 -4
- data/spec/lib/browse_everything/driver/s3_spec.rb +27 -18
- data/spec/lib/browse_everything/retriever_spec.rb +65 -2
- data/spec/spec_helper.rb +4 -9
- data/spec/support/capybara.rb +14 -10
- metadata +31 -37
- data/spec/fixtures/vcr_cassettes/box.yml +0 -498
- data/spec/fixtures/vcr_cassettes/dropbox.yml +0 -282
- data/spec/fixtures/vcr_cassettes/google_drive.yml +0 -331
- data/spec/fixtures/vcr_cassettes/retriever.yml +0 -170
@@ -120,7 +120,7 @@ module BrowseEverything
|
|
120
120
|
|
121
121
|
# Provides a URL for authorizing against Google Drive
|
122
122
|
# @return [String] the URL
|
123
|
-
def auth_link
|
123
|
+
def auth_link(*_args)
|
124
124
|
Addressable::URI.parse(authorizer.get_authorization_url)
|
125
125
|
end
|
126
126
|
|
@@ -175,7 +175,7 @@ module BrowseEverything
|
|
175
175
|
# @param params [Hash] HTTP response passed to the OAuth callback
|
176
176
|
# @param _data [Object,nil] an unused parameter
|
177
177
|
# @return [String] a new access token
|
178
|
-
def connect(params, _data)
|
178
|
+
def connect(params, _data, _url_options)
|
179
179
|
@code = params[:code]
|
180
180
|
authorize!
|
181
181
|
end
|
@@ -8,7 +8,7 @@ module BrowseEverything
|
|
8
8
|
class S3 < Base
|
9
9
|
DEFAULTS = { response_type: :signed_url, expires_in: 14400 }.freeze
|
10
10
|
RESPONSE_TYPES = %i[signed_url public_url s3_uri].freeze
|
11
|
-
CONFIG_KEYS = %i[bucket].freeze
|
11
|
+
CONFIG_KEYS = %i[bucket region].freeze
|
12
12
|
|
13
13
|
class << self
|
14
14
|
attr_accessor :authentication_klass
|
@@ -21,9 +21,10 @@ module BrowseEverything
|
|
21
21
|
attr_reader :entries
|
22
22
|
|
23
23
|
def initialize(config, *args)
|
24
|
-
if config.key?(:signed_url)
|
25
|
-
warn '[DEPRECATION] Amazon S3 driver: `:signed_url` is deprecated. Please use
|
26
|
-
|
24
|
+
if config.key?(:signed_url)
|
25
|
+
warn '[DEPRECATION] Amazon S3 driver: `:signed_url` is deprecated. Please use `response_type :signed_url` instead.'
|
26
|
+
response_type = config.delete(:signed_url) ? :signed_url : :public_url
|
27
|
+
config[:response_type] = response_type
|
27
28
|
end
|
28
29
|
merged_config = DEFAULTS.merge(config)
|
29
30
|
self.class.authentication_klass ||= self.class.default_authentication_klass
|
@@ -45,7 +46,8 @@ module BrowseEverything
|
|
45
46
|
# @return [Array<BrowseEverything::FileEntry>]
|
46
47
|
def contents(path = '')
|
47
48
|
path = File.join(path, '') unless path.empty?
|
48
|
-
|
49
|
+
@entries = []
|
50
|
+
|
49
51
|
generate_listing(path)
|
50
52
|
@sorter.call(@entries)
|
51
53
|
end
|
@@ -111,15 +113,6 @@ module BrowseEverything
|
|
111
113
|
@client ||= authenticate
|
112
114
|
end
|
113
115
|
|
114
|
-
def init_entries(path)
|
115
|
-
@entries = if path.empty?
|
116
|
-
[]
|
117
|
-
else
|
118
|
-
[BrowseEverything::FileEntry.new(Pathname(path).join('..').to_s, '', '..',
|
119
|
-
0, Time.current, true)]
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
116
|
def entry_for(name, size, date, dir)
|
124
117
|
BrowseEverything::FileEntry.new(name, [key, name].join(':'), File.basename(name), size, date, dir)
|
125
118
|
end
|
@@ -138,6 +131,7 @@ module BrowseEverything
|
|
138
131
|
end
|
139
132
|
|
140
133
|
def generate_listing(path)
|
134
|
+
client
|
141
135
|
listing = client.list_objects(bucket: config[:bucket], delimiter: '/', prefix: full_path(path))
|
142
136
|
add_directories(listing)
|
143
137
|
add_files(listing, path)
|
@@ -70,7 +70,7 @@ module BrowseEverything
|
|
70
70
|
end
|
71
71
|
|
72
72
|
download_options = extract_download_options(options)
|
73
|
-
url = download_options
|
73
|
+
url = download_options[:url]
|
74
74
|
|
75
75
|
case url.scheme
|
76
76
|
when 'file'
|
@@ -91,8 +91,7 @@ module BrowseEverything
|
|
91
91
|
url = options.fetch('url')
|
92
92
|
|
93
93
|
# This avoids the potential for a KeyError
|
94
|
-
headers = options.fetch('
|
95
|
-
headers.each_pair { |k, v| headers[k] = v.tr('+', ' ') }
|
94
|
+
headers = options.fetch('headers', {}) || {}
|
96
95
|
|
97
96
|
file_size_value = options.fetch('file_size', 0)
|
98
97
|
file_size = file_size_value.to_i
|
@@ -131,9 +130,9 @@ module BrowseEverything
|
|
131
130
|
url = options.fetch(:url)
|
132
131
|
retrieved = 0
|
133
132
|
|
134
|
-
request = Typhoeus::Request.new(url.to_s, headers: headers)
|
133
|
+
request = Typhoeus::Request.new(url.to_s, method: :get, headers: headers)
|
135
134
|
request.on_headers do |response|
|
136
|
-
raise DownloadError.new("#{self.class}: Failed to download #{url}", response) unless response.code == 200
|
135
|
+
raise DownloadError.new("#{self.class}: Failed to download #{url}: Status Code: #{response.code}", response) unless response.code == 200
|
137
136
|
end
|
138
137
|
request.on_body do |chunk|
|
139
138
|
retrieved += chunk.bytesize
|
@@ -3,8 +3,8 @@
|
|
3
3
|
# The file_system provider can be a path to any directory on the server where your application is running.
|
4
4
|
#
|
5
5
|
# dropbox:
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# client_id: YOUR_DROPBOX_APP_KEY
|
7
|
+
# client_secret: YOUR_DROPBOX_APP_SECRET
|
8
8
|
# box:
|
9
9
|
# client_id: YOUR_BOX_CLIENT_ID
|
10
10
|
# client_secret: YOUR_BOX_CLIENT_SECRET
|
@@ -15,6 +15,13 @@ RSpec.describe BrowseEverythingController, type: :controller do
|
|
15
15
|
|
16
16
|
describe '#auth' do
|
17
17
|
let(:provider_session) { instance_double(BrowseEverythingSession::ProviderSession) }
|
18
|
+
let(:connector_response_url_options) do
|
19
|
+
{
|
20
|
+
protocol: 'http://',
|
21
|
+
host: 'test.host',
|
22
|
+
port: 80
|
23
|
+
}
|
24
|
+
end
|
18
25
|
|
19
26
|
before do
|
20
27
|
allow(controller).to receive(:params).and_return('code' => 'test-code')
|
@@ -24,7 +31,7 @@ RSpec.describe BrowseEverythingController, type: :controller do
|
|
24
31
|
end
|
25
32
|
|
26
33
|
it 'retrieves the authorization code from the parameters' do
|
27
|
-
expect(provider).to have_received(:connect).with({ 'code' => 'test-code' }, nil)
|
34
|
+
expect(provider).to have_received(:connect).with({ 'code' => 'test-code' }, nil, connector_response_url_options)
|
28
35
|
end
|
29
36
|
end
|
30
37
|
|
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
include BrowserConfigHelper
|
4
4
|
|
5
|
-
describe BrowseEverything::Driver::Box
|
5
|
+
describe BrowseEverything::Driver::Box do
|
6
|
+
subject { provider }
|
7
|
+
|
6
8
|
let(:browser) { BrowseEverything::Browser.new(url_options) }
|
7
9
|
let(:provider) { browser.providers['box'] }
|
8
10
|
let(:auth_params) do
|
@@ -11,31 +13,27 @@ describe BrowseEverything::Driver::Box, vcr: { cassette_name: 'box', record: :no
|
|
11
13
|
'state' => 'box'
|
12
14
|
}
|
13
15
|
end
|
14
|
-
|
15
|
-
# To re-record the VCR responses, you will need to substitute the 'token' and 'refresh_token' values with the
|
16
|
-
# actual tokens returned from Box.
|
17
|
-
#
|
18
|
-
# The easiest way to do this is output @token to the Rails log from the box_client method:
|
19
|
-
#
|
20
|
-
# def box_client
|
21
|
-
# Rails.logger.info(@token)
|
22
|
-
# [...]
|
23
|
-
#
|
24
|
-
# Make sure you have the internal_test_app built and have copied your client id and secret to the yaml config file.
|
25
|
-
# With the test app running, you can authenticate to your Box account to browse files, and should see the
|
26
|
-
# tokens listed in the Rails log. Once you have copied the new tokens, the spec test will run and use your tokens
|
27
|
-
# to authenticate to Box. To record the new responses replace `record: :none` with `record: :all`.
|
28
16
|
let(:token) do
|
29
17
|
{
|
30
18
|
'token' => 'TOKEN',
|
31
19
|
'refresh_token' => 'REFRESH_TOKEN'
|
32
20
|
}
|
33
21
|
end
|
34
|
-
|
35
|
-
subject { provider }
|
22
|
+
let(:oauth_response_body) { '{"access_token":"TOKEN","expires_in":3762,"restricted_to":[],"refresh_token":"REFRESH_TOKEN","token_type":"bearer"}' }
|
36
23
|
|
37
24
|
before do
|
38
25
|
stub_configuration
|
26
|
+
|
27
|
+
stub_request(
|
28
|
+
:post,
|
29
|
+
'https://www.box.com/api/oauth2/token'
|
30
|
+
).to_return(
|
31
|
+
body: oauth_response_body,
|
32
|
+
status: 200,
|
33
|
+
headers: {
|
34
|
+
'Content-Type' => 'application/json'
|
35
|
+
}
|
36
|
+
)
|
39
37
|
end
|
40
38
|
|
41
39
|
after do
|
@@ -48,7 +46,7 @@ describe BrowseEverything::Driver::Box, vcr: { cassette_name: 'box', record: :no
|
|
48
46
|
|
49
47
|
describe '#validate_config' do
|
50
48
|
it 'raises and error with an incomplete configuration' do
|
51
|
-
expect {
|
49
|
+
expect { described_class.new({}) }.to raise_error(BrowseEverything::InitializationError)
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
@@ -92,14 +90,42 @@ describe BrowseEverything::Driver::Box, vcr: { cassette_name: 'box', record: :no
|
|
92
90
|
end
|
93
91
|
|
94
92
|
it 'registers new tokens' do
|
95
|
-
provider.connect(auth_params, 'data')
|
93
|
+
provider.connect(auth_params, 'data', nil)
|
96
94
|
expect(provider).to have_received(:register_access_token).with(kind_of(OAuth2::AccessToken))
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
98
|
describe '#contents' do
|
101
|
-
|
99
|
+
let(:folders_response_body) do
|
100
|
+
'{"type":"folder","id":"0","sequence_id":null,"etag":null,"name":"All Files","created_at":null,"modified_at":null,"description":"","size":28747877,"path_collection":{"total_count":0,"entries":[]},"created_by":{"type":"user","id":"","name":"","login":""},"modified_by":{"type":"user","id":"225383863","name":"ADAM GARNER WEAD","login":"agw13@psu.edu"},"trashed_at":null,"purged_at":null,"content_created_at":null,"content_modified_at":null,"owned_by":{"type":"user","id":"225383863","name":"ADAM GARNER WEAD","login":"agw13@psu.edu"},"shared_link":null,"folder_upload_email":null,"parent":null,"item_status":"active","item_collection":{"total_count":13,"entries":[{"type":"folder","id":"20375782799","sequence_id":"0","etag":"0","name":"A very looooooooooooong box folder, why so loooooooong Lets make it even longer to show how far it gets sent to the side"},{"type":"folder","id":"2571160559","sequence_id":"0","etag":"0","name":"Apps Team - Shared"},{"type":"folder","id":"20194542723","sequence_id":"0","etag":"0","name":"DSRD - W Pattee 3"},{"type":"folder","id":"20284062015","sequence_id":"0","etag":"0","name":"My Box Notes"},{"type":"folder","id":"11305958926","sequence_id":"0","etag":"0","name":"PCDM-Sufia"},{"type":"folder","id":"4227519189","sequence_id":"0","etag":"0","name":"refactor"},{"type":"folder","id":"2459961273","sequence_id":"0","etag":"0","name":"SaS - Development Team"},{"type":"folder","id":"3399219062","sequence_id":"0","etag":"0","name":"Scholarsphere - Migration"},{"type":"folder","id":"1168461187","sequence_id":"0","etag":"0","name":"test"},{"type":"folder","id":"3055812547","sequence_id":"0","etag":"0","name":"UX Artifacts"},{"type":"file","id":"25581309763","file_version":{"type":"file_version","id":"23869158869","sha1":"4604bbe44fdcdd4afef3c666cf582e3773960954"},"sequence_id":"1","etag":"1","sha1":"4604bbe44fdcdd4afef3c666cf582e3773960954","name":"failed.tar.gz"},{"type":"file","id":"25588823531","file_version":{"type":"file_version","id":"23877641673","sha1":"abd18ce0a685a27b464fb05f27af5a84f9ec9be7"},"sequence_id":"1","etag":"1","sha1":"abd18ce0a685a27b464fb05f27af5a84f9ec9be7","name":"scholarsphere_5712md360.xml"},{"type":"file","id":"113711622968","file_version":{"type":"file_version","id":"122136107320","sha1":"da39a3ee5e6b4b0d3255bfef95601890afd80709"},"sequence_id":"0","etag":"0","sha1":"da39a3ee5e6b4b0d3255bfef95601890afd80709","name":"test.txt"}],"offset":0,"limit":100,"order":[{"by":"type","direction":"ASC"},{"by":"name","direction":"ASC"}]}}'
|
101
|
+
end
|
102
|
+
let(:folders_items_response_body) do
|
103
|
+
'{"total_count":13,"entries":[{"type":"folder","id":"20375782799","etag":"0","name":"A very looooooooooooong box folder, why so loooooooong Lets make it even longer to show how far it gets sent to the side","size":0,"created_at":"2017-03-01T04:15:15-08:00"},{"type":"folder","id":"2571160559","etag":"0","name":"Apps Team - Shared","size":1249,"created_at":"2014-10-15T13:00:29-07:00"},{"type":"folder","id":"20194542723","etag":"0","name":"DSRD - W Pattee 3","size":2949416,"created_at":"2017-02-27T08:17:21-08:00"},{"type":"folder","id":"20284062015","etag":"0","name":"My Box Notes","size":0,"created_at":"2017-02-28T08:52:26-08:00"},{"type":"folder","id":"11305958926","etag":"0","name":"PCDM-Sufia","size":650658,"created_at":"2016-09-14T09:14:25-07:00"},{"type":"folder","id":"4227519189","etag":"0","name":"refactor","size":8766,"created_at":"2015-08-14T07:53:56-07:00"},{"type":"folder","id":"2459961273","etag":"0","name":"SaS - Development Team","size":152720753,"created_at":"2014-09-17T13:39:31-07:00"},{"type":"folder","id":"3399219062","etag":"0","name":"Scholarsphere - Migration","size":270984,"created_at":"2015-04-07T13:17:51-07:00"},{"type":"folder","id":"1168461187","etag":"0","name":"test","size":20625445557,"created_at":"2013-09-19T12:57:59-07:00"},{"type":"folder","id":"3055812547","etag":"0","name":"UX Artifacts","size":3801994,"created_at":"2015-02-04T08:21:16-08:00"},{"type":"file","id":"25581309763","etag":"1","name":"failed.tar.gz","size":28650839,"created_at":"2015-01-29T05:18:43-08:00"},{"type":"file","id":"25588823531","etag":"1","name":"scholarsphere_5712md360.xml","size":97038,"created_at":"2015-01-29T08:38:44-08:00"},{"type":"file","id":"113711622968","etag":"0","name":"test.txt","size":0,"created_at":"2016-12-20T07:50:30-08:00"}],"offset":0,"limit":1000,"order":[{"by":"type","direction":"ASC"},{"by":"name","direction":"ASC"}]}'
|
104
|
+
end
|
105
|
+
before do
|
106
|
+
provider.token = token
|
107
|
+
|
108
|
+
stub_request(
|
109
|
+
:get, "https://api.box.com/2.0/folders/0"
|
110
|
+
).to_return(
|
111
|
+
body: folders_response_body,
|
112
|
+
status: 200,
|
113
|
+
headers: {
|
114
|
+
'Content-Type' => 'application/json'
|
115
|
+
}
|
116
|
+
)
|
117
|
+
stub_request(
|
118
|
+
:get, "https://api.box.com/2.0/folders/0/items?fields=name,size,created_at&limit=99999&offset=0"
|
119
|
+
).to_return(
|
120
|
+
body: folders_items_response_body,
|
121
|
+
status: 200,
|
122
|
+
headers: {
|
123
|
+
'Content-Type' => 'application/json'
|
124
|
+
}
|
125
|
+
)
|
126
|
+
end
|
102
127
|
|
128
|
+
# HERE
|
103
129
|
context 'with files and folders in the root directory' do
|
104
130
|
let(:root_directory) { provider.contents('') }
|
105
131
|
let(:long_file) { root_directory[0] }
|
@@ -136,18 +162,36 @@ describe BrowseEverything::Driver::Box, vcr: { cassette_name: 'box', record: :no
|
|
136
162
|
end
|
137
163
|
|
138
164
|
context 'with files and folders in the SaS - Development Team directory' do
|
139
|
-
let(:
|
140
|
-
let(:
|
141
|
-
let(:apps_dir) { sas_directory[
|
142
|
-
let(:equipment) { sas_directory[
|
143
|
-
|
144
|
-
|
145
|
-
|
165
|
+
let(:folder_id) { '2459961273' }
|
166
|
+
let(:sas_directory) { provider.contents(folder_id) }
|
167
|
+
let(:apps_dir) { sas_directory[0] }
|
168
|
+
let(:equipment) { sas_directory[11] }
|
169
|
+
let(:folders_response_body) do
|
170
|
+
'{"type":"folder","id":"2459961273","sequence_id":"0","etag":"0","name":"SaS - Development Team","created_at":"2014-09-17T13:39:31-07:00","modified_at":"2017-03-17T08:41:40-07:00","description":"","size":152720753,"path_collection":{"total_count":1,"entries":[{"type":"folder","id":"0","sequence_id":null,"etag":null,"name":"All Files"}]},"created_by":{"type":"user","id":"191882215","name":"Daniel Coughlin","login":"dmc186@psu.edu"},"modified_by":{"type":"user","id":"190902775","name":"CAROLYN A COLE","login":"cam156@psu.edu"},"trashed_at":null,"purged_at":null,"content_created_at":"2014-09-17T13:39:31-07:00","content_modified_at":"2017-03-17T08:41:40-07:00","owned_by":{"type":"user","id":"191882215","name":"Daniel Coughlin","login":"dmc186@psu.edu"},"shared_link":{"url":"https:\/\/psu.box.com\/s\/8hb3e06nthwld39ehlg5","download_url":null,"vanity_url":null,"effective_access":"collaborators","is_password_enabled":false,"unshared_at":null,"download_count":0,"preview_count":0,"access":"collaborators","permissions":{"can_download":true,"can_preview":true}},"folder_upload_email":null,"parent":null,"item_status":"active","item_collection":{"total_count":17,"entries":[{"type":"folder","id":"2459974427","sequence_id":"0","etag":"0","name":"Apps&Int"},{"type":"folder","id":"11217040834","sequence_id":"0","etag":"0","name":"Credentials"},{"type":"folder","id":"5662231069","sequence_id":"0","etag":"0","name":"DevOps Presentation"},{"type":"folder","id":"8648394509","sequence_id":"0","etag":"0","name":"old"},{"type":"folder","id":"12445061821","sequence_id":"0","etag":"0","name":"Ops Plan"},{"type":"file","id":"136917954839","file_version":{"type":"file_version","id":"158227338595","sha1":"2e2124c0d6589dd05d03a854b9c5c3a68bbc4501"},"sequence_id":"17","etag":"17","sha1":"2e2124c0d6589dd05d03a854b9c5c3a68bbc4501","name":"2-17 Upcoming ScholarSphere changes.boxnote"},{"type":"file","id":"75228871930","file_version":{"type":"file_version","id":"79668751214","sha1":"43cd4ac728cef7767dc132c26b181133d867d78f"},"sequence_id":"1","etag":"1","sha1":"43cd4ac728cef7767dc132c26b181133d867d78f","name":"99bottles (1).epub"},{"type":"file","id":"72329914177","file_version":{"type":"file_version","id":"76429987577","sha1":"a3310fdad0e6c9654b19d88b35318b8cdc246379"},"sequence_id":"2","etag":"2","sha1":"a3310fdad0e6c9654b19d88b35318b8cdc246379","name":"Development Team Projects and Milestones (not downloaded).xlsx"},{"type":"file","id":"74507436394","file_version":{"type":"file_version","id":"78854145518","sha1":"589ab64efb1ba49537074fd2c56e1570a24a47b5"},"sequence_id":"7","etag":"7","sha1":"589ab64efb1ba49537074fd2c56e1570a24a47b5","name":"Development Team Projects and Milestones - Editable.xlsx"},{"type":"file","id":"72324078305","file_version":{"type":"file_version","id":"76423451525","sha1":"42c0a5a34717cd17e315653643b61d23e94b7cd7"},"sequence_id":"3","etag":"3","sha1":"42c0a5a34717cd17e315653643b61d23e94b7cd7","name":"Development Team Projects and Milestones.xlsx"},{"type":"file","id":"106651625938","file_version":{"type":"file_version","id":"114805197783","sha1":"0c1c90a0186bd3934ce3877e092a228dc1568e93"},"sequence_id":"2","etag":"2","sha1":"0c1c90a0186bd3934ce3877e092a228dc1568e93","name":"Digital Scholarship and Repository Development (DSRD) Org Chart 2016.pdf"},{"type":"file","id":"76960974625","file_version":{"type":"file_version","id":"106919307872","sha1":"74608bfb532feff774502c6132eafe9acb1e5217"},"sequence_id":"162","etag":"162","sha1":"74608bfb532feff774502c6132eafe9acb1e5217","name":"Equipment.boxnote"},{"type":"file","id":"68362464289","file_version":{"type":"file_version","id":"101137863811","sha1":"40a0a3f98926874f1ee62fd522621a4408e0058c"},"sequence_id":"8","etag":"8","sha1":"40a0a3f98926874f1ee62fd522621a4408e0058c","name":"migrationDesign.pptx"},{"type":"file","id":"99028795390","file_version":{"type":"file_version","id":"107183805224","sha1":"7044bd7f0892f915b77b914430c2915161f942d9"},"sequence_id":"37","etag":"37","sha1":"7044bd7f0892f915b77b914430c2915161f942d9","name":"Onboarding.boxnote"},{"type":"file","id":"134865535934","file_version":{"type":"file_version","id":"143971901576","sha1":"32cc33b2cd5cc46f0a3fb924b4779cc387a81018"},"sequence_id":"1","etag":"1","sha1":"32cc33b2cd5cc46f0a3fb924b4779cc387a81018","name":"passenger-test.boxnote"},{"type":"file","id":"92102699797","file_version":{"type":"file_version","id":"98754405909","sha1":"053b762f6d5752c261ef7ff6a3d776853cdb2ca3"},"sequence_id":"1","etag":"1","sha1":"053b762f6d5752c261ef7ff6a3d776853cdb2ca3","name":"sas_development_libraries_mou_2016_08_01.docx"},{"type":"file","id":"22182934895","file_version":{"type":"file_version","id":"50126669941","sha1":"8ca396b5b26ff90d625ea3a49f0cc69ad844476b"},"sequence_id":"41","etag":"41","sha1":"8ca396b5b26ff90d625ea3a49f0cc69ad844476b","name":"TimeBox.xlsx"}],"offset":0,"limit":100,"order":[{"by":"type","direction":"ASC"},{"by":"name","direction":"ASC"}]}}'
|
171
|
+
end
|
172
|
+
let(:folders_items_response_body) do
|
173
|
+
'{"total_count":17,"entries":[{"type":"folder","id":"2459974427","etag":"0","name":"Apps&Int","size":14341346,"created_at":"2014-09-17T13:42:30-07:00"},{"type":"folder","id":"11217040834","etag":"0","name":"Credentials","size":12603,"created_at":"2016-09-07T08:37:23-07:00"},{"type":"folder","id":"5662231069","etag":"0","name":"DevOps Presentation","size":128158633,"created_at":"2015-12-07T05:51:08-08:00"},{"type":"folder","id":"8648394509","etag":"0","name":"old","size":117232,"created_at":"2016-06-30T08:03:46-07:00"},{"type":"folder","id":"12445061821","etag":"0","name":"Ops Plan","size":6181924,"created_at":"2016-11-17T06:52:58-08:00"},{"type":"file","id":"136917954839","etag":"17","name":"2-17 Upcoming ScholarSphere changes.boxnote","size":1768,"created_at":"2017-02-17T09:27:57-08:00"},{"type":"file","id":"75228871930","etag":"1","name":"99bottles (1).epub","size":1013573,"created_at":"2016-07-21T03:53:01-07:00"},{"type":"file","id":"72329914177","etag":"2","name":"Development Team Projects and Milestones (not downloaded).xlsx","size":20812,"created_at":"2016-06-30T09:10:36-07:00"},{"type":"file","id":"74507436394","etag":"7","name":"Development Team Projects and Milestones - Editable.xlsx","size":21001,"created_at":"2016-07-15T11:08:54-07:00"},{"type":"file","id":"72324078305","etag":"3","name":"Development Team Projects and Milestones.xlsx","size":22410,"created_at":"2016-06-30T08:31:56-07:00"},{"type":"file","id":"106651625938","etag":"2","name":"Digital Scholarship and Repository Development (DSRD) Org Chart 2016.pdf","size":17677,"created_at":"2016-11-30T08:27:58-08:00"},{"type":"file","id":"76960974625","etag":"162","name":"Equipment.boxnote","size":10140,"created_at":"2016-08-03T12:22:39-07:00"},{"type":"file","id":"68362464289","etag":"8","name":"migrationDesign.pptx","size":47751,"created_at":"2016-06-03T03:56:54-07:00"},{"type":"file","id":"99028795390","etag":"37","name":"Onboarding.boxnote","size":4465,"created_at":"2016-10-24T11:41:47-07:00"},{"type":"file","id":"134865535934","etag":"1","name":"passenger-test.boxnote","size":4988,"created_at":"2017-02-13T10:47:38-08:00"},{"type":"file","id":"92102699797","etag":"1","name":"sas_development_libraries_mou_2016_08_01.docx","size":134018,"created_at":"2016-08-16T07:32:53-07:00"},{"type":"file","id":"22182934895","etag":"41","name":"TimeBox.xlsx","size":21864,"created_at":"2014-10-23T08:22:16-07:00"}],"offset":0,"limit":1000,"order":[{"by":"type","direction":"ASC"},{"by":"name","direction":"ASC"}]}'
|
174
|
+
end
|
146
175
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
176
|
+
before do
|
177
|
+
stub_request(
|
178
|
+
:get, "https://api.box.com/2.0/folders/#{folder_id}"
|
179
|
+
).to_return(
|
180
|
+
body: folders_response_body,
|
181
|
+
status: 200,
|
182
|
+
headers: {
|
183
|
+
'Content-Type' => 'application/json'
|
184
|
+
}
|
185
|
+
)
|
186
|
+
stub_request(
|
187
|
+
:get, "https://api.box.com/2.0/folders/#{folder_id}/items?fields=name,size,created_at&limit=99999&offset=0"
|
188
|
+
).to_return(
|
189
|
+
body: folders_items_response_body,
|
190
|
+
status: 200,
|
191
|
+
headers: {
|
192
|
+
'Content-Type' => 'application/json'
|
193
|
+
}
|
194
|
+
)
|
151
195
|
end
|
152
196
|
|
153
197
|
describe 'the second item' do
|
@@ -172,17 +216,53 @@ describe BrowseEverything::Driver::Box, vcr: { cassette_name: 'box', record: :no
|
|
172
216
|
end
|
173
217
|
|
174
218
|
describe '#link_for' do
|
175
|
-
before
|
219
|
+
before do
|
220
|
+
provider.token = token
|
221
|
+
|
222
|
+
# Initial request for metadata
|
223
|
+
stub_request(
|
224
|
+
:get, "https://api.box.com/2.0/files/#{file_id}"
|
225
|
+
).to_return(
|
226
|
+
body: files_response_body,
|
227
|
+
status: 200,
|
228
|
+
headers: {
|
229
|
+
'Content-Type' => 'application/json'
|
230
|
+
}
|
231
|
+
)
|
232
|
+
|
233
|
+
# Request for the content
|
234
|
+
stub_request(
|
235
|
+
:get, "https://api.box.com/2.0/files/#{file_id}/content"
|
236
|
+
).to_return(
|
237
|
+
status: 302,
|
238
|
+
headers: {
|
239
|
+
'location' => files_response_location
|
240
|
+
}
|
241
|
+
)
|
242
|
+
end
|
243
|
+
let(:link) { provider.link_for(file_id) }
|
176
244
|
|
177
245
|
context 'with a file from the root directory' do
|
178
|
-
let(:
|
246
|
+
let(:files_response_location) do
|
247
|
+
'https://dl.boxcloud.com/d/1/B7Qd7B_iwPHTU4-71W2qYoTbvAaHCPzNsy5WTFHj5XpbmydlF8ud_0n7Ji7zswdU3Kg0patL8EUXCR3cpPw1PZjp-_a1t6MoH-tX3eQeCAR080Hr-yQaEmLQ8dULnnlOhYHeYwPuRp-0gCcXCF5w3O3bE6ZHgML3SCQchPoJQlsfvcYwXZyPRFEVRNUo7qou5X9dbkMCJGmB0CsvqKTXfEs8bqbmRV4hZ5qpJbD0Jer1m4vsqu8h5VkBdMIcgFMn_D9TheZOrmQdg8ExZZVPJ7X8QjFjI707WwIl7CNYkmocCdAJnbYQljFMiQsp0wF0etUqoiskNnaJBS3NagvtvSKaX3TVfiXa87CHDwPiQ3PNJE32d49eKcBK9nLLigoX3SJOkJqMqUSXO_UAxl0bO0EszCNpaWsiQwWiG2jjB5YBfDwQbmfuSTCBPkhDjIH3S3n5cadk4H_8rvgHshYBXNJd2NshgPsYt1XIkE8qj4WznzwayZoi_2k5x4liFvs2F91anj0bPAW2Mzeyz0Pi49mythoH7Rrq_i0sbYDt3VJNyCB0wqs8xUCa38Z6NocTKrKtFHrNSyM2-g5nWsAIwGeG4L4kZ_qIq8nNL49LsntvpFmhogONBozQQCvoEj0WXqhLCxxwT4U-pZ5rCYDt6dpoNlmYv962wXUzg_s21CO96J1o9-_xKl9JxmbWPf0DDJ35gCBFWMhL6BTaLckbBrybx41luHjjDuv72CxfsqsabdyW2yDN3uoBAcXIXD7QUOACPXKHvC98kL9aXL9o9X-zt89vUP61ijizsjtoI9RQc4CrjerfnxC7jS-ER3w2nwkgOEr1wkdEvq4QabcVlyixgrRxKTmzHXa0JGfmpLdEQ821Sgi7QHOpa0l5CSZTQycnWHoMKn4f_xJo5WZLmkmNgkE2DRsok0xGVUK_lNKjrt_N9mPVAdeeXLjSyoSol2_ugU79ELQSHJKKyTFAEJOscUSseg5MtWrIOLKQY6NlAaE0Ckn7c_LX4MYaSj83F-sZouvwSRNVbTklMNkC6j2fy4kr8_T3eb_9-Df94B1867kSJzt7TjXSAxz_p9PbRuj7eY1NW15zjxtOPQpk/download'
|
248
|
+
end
|
249
|
+
let(:files_response_body) do
|
250
|
+
'{"type":"file","id":"25581309763","file_version":{"type":"file_version","id":"23869158869","sha1":"4604bbe44fdcdd4afef3c666cf582e3773960954"},"sequence_id":"1","etag":"1","sha1":"4604bbe44fdcdd4afef3c666cf582e3773960954","name":"failed.tar.gz","description":"","size":28650839,"path_collection":{"total_count":1,"entries":[{"type":"folder","id":"0","sequence_id":null,"etag":null,"name":"All Files"}]},"created_at":"2015-01-29T05:18:43-08:00","modified_at":"2015-01-29T05:18:43-08:00","trashed_at":null,"purged_at":null,"content_created_at":"2015-01-17T05:59:48-08:00","content_modified_at":"2015-01-17T06:00:03-08:00","created_by":{"type":"user","id":"225383863","name":"ADAM GARNER WEAD","login":"agw13@psu.edu"},"modified_by":{"type":"user","id":"225383863","name":"ADAM GARNER WEAD","login":"agw13@psu.edu"},"owned_by":{"type":"user","id":"225383863","name":"ADAM GARNER WEAD","login":"agw13@psu.edu"},"shared_link":{"url":"https:\/\/psu.box.com\/s\/w89hg6kf73q8fn1ww51cj92ohb6piyet","download_url":"https:\/\/psu.box.com\/shared\/static\/w89hg6kf73q8fn1ww51cj92ohb6piyet.gz","vanity_url":null,"effective_access":"open","is_password_enabled":false,"unshared_at":null,"download_count":1,"preview_count":0,"access":"open","permissions":{"can_download":true,"can_preview":true}},"parent":{"type":"folder","id":"0","sequence_id":null,"etag":null,"name":"All Files"},"item_status":"active"}'
|
251
|
+
end
|
252
|
+
let(:file_id) { '25581309763' }
|
179
253
|
|
180
254
|
specify { expect(link[0]).to start_with('https://dl.boxcloud.com/d/1') }
|
181
255
|
specify { expect(link[1]).to have_key(:expires) }
|
182
256
|
end
|
183
257
|
|
184
258
|
context 'with a file from the SaS - Development Team directory' do
|
185
|
-
let(:
|
259
|
+
let(:files_response_location) do
|
260
|
+
'https://dl.boxcloud.com/d/1/lCA2dDrIV1QAvpQLU7_mkJ0bt2Soa1dLRT6FOzmF37EfJgjRmCO-rZ0VFyKCtoHgPzRoCIHgx-IWCoV8cvtfTX4Yw--RmBLBV9f4JsK6i3LMRKQzgDMxsMu97RSmuMagV-GayR8uO6NGFBtoX81yujebVY-JRB7cxhPU0fbCxAzAnv1711_IUs6YXwhWc-rNFHrNjPsUnJLqw0soQPZqF3Q5irxJLu7traVIeoeuGSfhw-7G-qfqu4CIFonC4ktwwh8jMgN9KW712kRg61moLG6Aa6FTbdCCSt_jCwvQFVGqCz_VivfzG2_BHBqh4IhIB76DmF1ISM-jD9VToUwYfscg6BgC2fqGj6OycsuYr3v3EE0gHlPw_X2rJnq9J2M9plnnhqBvXEwoUXDqyGPvSqWBeQvrrTYfvqj7fG48tUr7RKOytc_K0B4aw9hgGUk3EaifSVWzYvXzoXBp27HFHPsssvIK8fXoSU2J3HCEsGhIDFzu3cvXyPZJV_Co1_LvivWM0AGjXhyoC8PNO5qmtrZFgCob3KlZ8BEI1yJfX_0K8wpocUJP95eBNutBhWa2DEvCK6R5OG-Z0XwrJu8XFRwPcIl3_7lSsIhsQlYA7MoJer7hhwVGAl3kPP-bFsw1et66UM6KHG2FdN2xKP10DYFqR_JrShPP8DQ-ik9-lKej_8LTfiHdf0YbkdMNKzBYlXZsiQNwd3VXdRo1Z4Uhza_XtTDcfH0uxRQyYRecHr-5lEn5iUfV1199GrTsLkcOb9ONNSTFPKW15XCLpgJm6ylSpG2JSZ6zWsGL5hUzdvMytwBCMpIj84UZuwo2RTH1ZDUJYjmHRX11rDnwe2zKMz4woYIA8RjhnYEj6d13BeBz9Fy4GgR90jmM5xHIv9fiAG_b99fpDuYvT-tccN4pdrxPf0P-kCjYAHBt7kY7ToaMWcnOf1nGdLP0oaCGHhAzN0iurjRTLRi2S4N1hsWxjoMuQqayEq15QhRujy2lTZX_XyBgrU2ZodkNsQUlaWcJ6aFT8bh48DtyQvt_xfm4jqmStageFKbydyoB8BpP6oYFAMeFlkS4A6LnXJCzpO8Q../download'
|
261
|
+
end
|
262
|
+
let(:files_response_body) do
|
263
|
+
'{"type":"file","id":"76960974625","file_version":{"type":"file_version","id":"106919307872","sha1":"74608bfb532feff774502c6132eafe9acb1e5217"},"sequence_id":"162","etag":"162","sha1":"74608bfb532feff774502c6132eafe9acb1e5217","name":"Equipment.boxnote","description":"Listing equipment we currently have","size":10140,"path_collection":{"total_count":2,"entries":[{"type":"folder","id":"0","sequence_id":null,"etag":null,"name":"All Files"},{"type":"folder","id":"2459961273","sequence_id":"0","etag":"0","name":"SaS - Development Team"}]},"created_at":"2016-08-03T12:22:39-07:00","modified_at":"2016-10-26T12:40:09-07:00","trashed_at":null,"purged_at":null,"content_created_at":"2016-08-03T12:22:39-07:00","content_modified_at":"2016-10-26T12:40:09-07:00","created_by":{"type":"user","id":"212771336","name":"NICOLE M. GAMPE","login":"nmg110@psu.edu"},"modified_by":{"type":"user","id":"208208274","name":"JUSTIN R PATTERSON","login":"jrp22@psu.edu"},"owned_by":{"type":"user","id":"191882215","name":"Daniel Coughlin","login":"dmc186@psu.edu"},"shared_link":{"url":"https:\/\/psu.box.com\/s\/uolieeszpwglsv0ipwij9ws36rrepvba","download_url":"https:\/\/psu.box.com\/shared\/static\/uolieeszpwglsv0ipwij9ws36rrepvba.boxnote","vanity_url":null,"effective_access":"open","is_password_enabled":false,"unshared_at":null,"download_count":24,"preview_count":0,"access":"open","permissions":{"can_download":true,"can_preview":true}},"parent":{"type":"folder","id":"2459961273","sequence_id":"0","etag":"0","name":"SaS - Development Team"},"item_status":"active"}'
|
264
|
+
end
|
265
|
+
let(:file_id) { '76960974625' }
|
186
266
|
|
187
267
|
specify { expect(link[0]).to start_with('https://dl.boxcloud.com/d/1') }
|
188
268
|
specify { expect(link[1]).to have_key(:expires) }
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
include BrowserConfigHelper
|
4
4
|
|
5
|
-
describe BrowseEverything::Driver::Dropbox
|
5
|
+
describe BrowseEverything::Driver::Dropbox do
|
6
6
|
let(:browser) { BrowseEverything::Browser.new(url_options) }
|
7
7
|
let(:provider) { browser.providers['dropbox'] }
|
8
8
|
let(:provider_yml) do
|
@@ -11,9 +11,22 @@ describe BrowseEverything::Driver::Dropbox, vcr: { cassette_name: 'dropbox', rec
|
|
11
11
|
client_secret: 'client-secret'
|
12
12
|
}
|
13
13
|
end
|
14
|
+
let(:oauth_response_body) do
|
15
|
+
'{"access_token": "test-access-token", "token_type": "bearer", "uid": "test-user-id", "account_id": "dbid:id"}'
|
16
|
+
end
|
14
17
|
|
15
18
|
before do
|
16
19
|
stub_configuration
|
20
|
+
|
21
|
+
stub_request(
|
22
|
+
:post, 'https://api.dropboxapi.com/oauth2/token'
|
23
|
+
).to_return(
|
24
|
+
body: oauth_response_body,
|
25
|
+
status: 200,
|
26
|
+
headers: {
|
27
|
+
'Content-Type' => 'text/javascript'
|
28
|
+
}
|
29
|
+
)
|
17
30
|
end
|
18
31
|
|
19
32
|
after do
|
@@ -22,11 +35,11 @@ describe BrowseEverything::Driver::Dropbox, vcr: { cassette_name: 'dropbox', rec
|
|
22
35
|
|
23
36
|
describe '#validate_config' do
|
24
37
|
it 'raises and error with an incomplete configuration' do
|
25
|
-
expect {
|
38
|
+
expect { described_class.new({}) }.to raise_error(BrowseEverything::InitializationError)
|
26
39
|
end
|
27
40
|
|
28
41
|
it 'raises and error with a configuration without a client secret' do
|
29
|
-
expect {
|
42
|
+
expect { described_class.new(client_id: 'test-client-id') }.to raise_error(BrowseEverything::InitializationError)
|
30
43
|
end
|
31
44
|
end
|
32
45
|
|
@@ -40,11 +53,18 @@ describe BrowseEverything::Driver::Dropbox, vcr: { cassette_name: 'dropbox', rec
|
|
40
53
|
|
41
54
|
context 'with a valid configuration' do
|
42
55
|
let(:driver) { described_class.new(provider_yml) }
|
56
|
+
let(:connector_response_url_options) do
|
57
|
+
{
|
58
|
+
protocol: 'http://',
|
59
|
+
host: 'test.host',
|
60
|
+
port: 80
|
61
|
+
}
|
62
|
+
end
|
43
63
|
|
44
|
-
before { driver.connect({ code: 'code' }, {}) }
|
64
|
+
before { driver.connect({ code: 'code' }, {}, connector_response_url_options) }
|
45
65
|
|
46
66
|
describe '#auth_link' do
|
47
|
-
subject { driver.auth_link }
|
67
|
+
subject { driver.auth_link(connector_response_url_options) }
|
48
68
|
|
49
69
|
it { is_expected.to start_with('https://www.dropbox.com/oauth2/authorize') }
|
50
70
|
end
|
@@ -58,6 +78,23 @@ describe BrowseEverything::Driver::Dropbox, vcr: { cassette_name: 'dropbox', rec
|
|
58
78
|
describe '#contents' do
|
59
79
|
context 'when in the root folder' do
|
60
80
|
let(:contents) { driver.contents }
|
81
|
+
let(:list_folder_response) do
|
82
|
+
'{"entries": [{".tag": "folder", "name": "Photos", "path_lower": "/photos", "path_display": "/Photos", "id": "id:XAAAAAAAAAALA"}, {".tag": "file", "name": "Getting Started.pdf", "path_lower": "/getting started.pdf", "path_display": "/Getting Started.pdf", "id": "id:XAAAAAAAAAAKg", "client_modified": "2012-11-10T18:33:28Z", "server_modified": "2012-11-10T18:33:27Z", "rev": "60b9427f2", "size": 249159, "content_hash": "c3dfdd86981548e48bc8efb6c4162c76ba961ec92e60f6ba26189068a41fcaf2"}], "cursor": "AAFu-_dOPQTQnqOIb9JklCPYSxWtNRrBBOU4nNkY78wTCc-ktCP4MtIoN1nmOESizkoue2dpu3FbMwDM6BQbgkLObH_Ge-H0BYaPwjfLk5cUHZHd1swkMYGLWELfX_PIHH9hCmU0C8sUL2EJ-7y6BcRFpdOvPmxiu6azVyCx_Il7kA", "has_more": false}'
|
83
|
+
end
|
84
|
+
|
85
|
+
before do
|
86
|
+
stub_request(
|
87
|
+
:post, 'https://api.dropboxapi.com/2/files/list_folder'
|
88
|
+
).with(
|
89
|
+
body: '{"recursive":false,"include_media_info":false,"include_deleted":false,"path":""}'
|
90
|
+
).to_return(
|
91
|
+
body: list_folder_response,
|
92
|
+
status: 200,
|
93
|
+
headers: {
|
94
|
+
'Content-Type' => 'application/json'
|
95
|
+
}
|
96
|
+
)
|
97
|
+
end
|
61
98
|
|
62
99
|
it 'retrieves all folders the root folders' do
|
63
100
|
expect(contents).not_to be_empty
|
@@ -75,6 +112,17 @@ describe BrowseEverything::Driver::Dropbox, vcr: { cassette_name: 'dropbox', rec
|
|
75
112
|
|
76
113
|
describe '#link_for' do
|
77
114
|
subject(:link_args) { driver.link_for('/Getting Started.pdf') }
|
115
|
+
before do
|
116
|
+
stub_request(
|
117
|
+
:post, 'https://content.dropboxapi.com/2/files/download'
|
118
|
+
).to_return(
|
119
|
+
body: '{"name": "Getting Started.pdf", "path_lower": "/getting started.pdf", "path_display": "/Getting Started.pdf", "id": "id:XAAAAAAAAAAKg", "client_modified": "2012-11-10T18:33:28Z", "server_modified": "2012-11-10T18:33:27Z", "rev": "60b9427f2", "size": 249159, "content_hash": "c3dfdd86981548e48bc8efb6c4162c76ba961ec92e60f6ba26189068a41fcaf2"}',
|
120
|
+
status: 200,
|
121
|
+
headers: {
|
122
|
+
'Content-Type' => 'application/json'
|
123
|
+
}
|
124
|
+
)
|
125
|
+
end
|
78
126
|
|
79
127
|
it 'provides link arguments for accessing the file' do
|
80
128
|
expect(link_args.first).to be_a String
|