browse-everything 0.10.5 → 0.11.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +16 -0
  4. data/.rubocop_todo.yml +149 -0
  5. data/.travis.yml +5 -6
  6. data/Rakefile +2 -2
  7. data/app/controllers/browse_everything_controller.rb +19 -22
  8. data/app/helpers/bootstrap_version_helper.rb +9 -11
  9. data/app/helpers/browse_everything_helper.rb +11 -22
  10. data/app/views/browse_everything/_file.html.erb +7 -11
  11. data/app/views/browse_everything/_files.html.erb +4 -7
  12. data/app/views/browse_everything/index.html.erb +1 -1
  13. data/browse-everything.gemspec +37 -34
  14. data/config/routes.rb +3 -3
  15. data/lib/browse-everything.rb +1 -1
  16. data/lib/browse_everything.rb +9 -8
  17. data/lib/browse_everything/browser.rb +4 -4
  18. data/lib/browse_everything/driver/base.rb +14 -14
  19. data/lib/browse_everything/driver/box.rb +48 -59
  20. data/lib/browse_everything/driver/dropbox.rb +10 -11
  21. data/lib/browse_everything/driver/file_system.rb +19 -24
  22. data/lib/browse_everything/driver/google_drive.rb +58 -82
  23. data/lib/browse_everything/driver/s3.rb +87 -0
  24. data/lib/browse_everything/driver/sky_drive.rb +41 -47
  25. data/lib/browse_everything/engine.rb +2 -2
  26. data/lib/browse_everything/file_entry.rb +3 -3
  27. data/lib/browse_everything/retriever.rb +19 -20
  28. data/lib/browse_everything/version.rb +1 -1
  29. data/lib/generators/browse_everything/assets_generator.rb +2 -4
  30. data/lib/generators/browse_everything/config_generator.rb +12 -12
  31. data/lib/generators/browse_everything/install_generator.rb +2 -4
  32. data/lib/generators/browse_everything/templates/browse_everything_providers.yml.example +6 -0
  33. data/spec/features/select_files_spec.rb +12 -12
  34. data/spec/features/test_compiling_stylesheets_spec.rb +2 -2
  35. data/spec/helper/browse_everything_controller_helper_spec.rb +8 -8
  36. data/spec/javascripts/jasmine_spec.rb +5 -5
  37. data/spec/javascripts/support/jasmine_helper.rb +9 -9
  38. data/spec/spec_helper.rb +26 -23
  39. data/spec/support/app/controllers/file_handler_controller.rb +3 -3
  40. data/spec/support/rake.rb +1 -1
  41. data/spec/test_app_templates/lib/generators/test_app_generator.rb +21 -22
  42. data/spec/unit/base_spec.rb +6 -6
  43. data/spec/unit/browse_everything_helper_spec.rb +9 -9
  44. data/spec/unit/browser_spec.rb +19 -19
  45. data/spec/unit/dropbox_spec.rb +44 -43
  46. data/spec/unit/file_entry_spec.rb +31 -31
  47. data/spec/unit/file_system_spec.rb +26 -26
  48. data/spec/unit/retriever_spec.rb +42 -43
  49. data/spec/unit/s3_spec.rb +77 -0
  50. data/spec/unit/sky_drive_spec.rb +31 -31
  51. data/spec/views/browse_everything/_file.html.erb_spec.rb +37 -37
  52. data/tasks/ci.rake +3 -3
  53. metadata +52 -7
  54. data/app/.DS_Store +0 -0
  55. data/app/views/.DS_Store +0 -0
@@ -1,30 +1,29 @@
1
1
  module BrowseEverything
2
2
  module Driver
3
3
  class FileSystem < Base
4
-
5
4
  def icon
6
5
  'file'
7
6
  end
8
-
7
+
9
8
  def validate_config
10
9
  unless config[:home]
11
- raise BrowseEverything::InitializationError, "FileSystem driver requires a :home argument"
10
+ raise BrowseEverything::InitializationError, 'FileSystem driver requires a :home argument'
12
11
  end
13
12
  end
14
13
 
15
- def contents(path='')
16
- relative_path = path.sub(%r{^[\/.]+},'')
14
+ def contents(path = '')
15
+ relative_path = path.sub(%r{^[\/.]+}, '')
17
16
  real_path = File.join(config[:home], relative_path)
18
17
  result = []
19
18
  if File.directory?(real_path)
20
19
  if relative_path.present?
21
- result << details(File.expand_path('..',real_path),'..')
20
+ result << details(File.expand_path('..', real_path), '..')
22
21
  end
23
- result += Dir[File.join(real_path,'*')].collect { |f| details(f) }
24
- elsif File.exists?(real_path)
22
+ result += Dir[File.join(real_path, '*')].collect { |f| details(f) }
23
+ elsif File.exist?(real_path)
25
24
  result += [details(real_path)]
26
25
  end
27
- result.sort do |a,b|
26
+ result.sort do |a, b|
28
27
  if b.container?
29
28
  a.container? ? a.name.downcase <=> b.name.downcase : 1
30
29
  else
@@ -33,20 +32,17 @@ module BrowseEverything
33
32
  end
34
33
  end
35
34
 
36
- def details(path,display=nil)
37
- if File.exists?(path)
38
- info = File::Stat.new(path)
39
- BrowseEverything::FileEntry.new(
40
- Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(config[:home])),
41
- [self.key,path].join(':'),
42
- display || File.basename(path),
43
- info.size,
44
- info.mtime,
45
- info.directory?
46
- )
47
- else
48
- nil
49
- end
35
+ def details(path, display = nil)
36
+ return nil unless File.exist?(path)
37
+ info = File::Stat.new(path)
38
+ BrowseEverything::FileEntry.new(
39
+ Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(config[:home])),
40
+ [key, path].join(':'),
41
+ display || File.basename(path),
42
+ info.size,
43
+ info.mtime,
44
+ info.directory?
45
+ )
50
46
  end
51
47
 
52
48
  def link_for(path)
@@ -59,6 +55,5 @@ module BrowseEverything
59
55
  true
60
56
  end
61
57
  end
62
-
63
58
  end
64
59
  end
@@ -1,8 +1,8 @@
1
1
  module BrowseEverything
2
2
  module Driver
3
3
  class GoogleDrive < Base
4
-
5
- require 'google/api_client'
4
+ require 'google/apis/drive_v3'
5
+ require 'signet'
6
6
 
7
7
  def icon
8
8
  'google-plus-sign'
@@ -10,121 +10,97 @@ module BrowseEverything
10
10
 
11
11
  def validate_config
12
12
  unless config[:client_id]
13
- raise BrowseEverything::InitializationError, "GoogleDrive driver requires a :client_id argument"
13
+ raise BrowseEverything::InitializationError, 'GoogleDrive driver requires a :client_id argument'
14
14
  end
15
15
  unless config[:client_secret]
16
- raise BrowseEverything::InitializationError, "GoogleDrive driver requires a :client_secret argument"
16
+ raise BrowseEverything::InitializationError, 'GoogleDrive driver requires a :client_secret argument'
17
17
  end
18
18
  end
19
19
 
20
- def contents(path='')
21
- default_params = { }
20
+ def contents(path = '')
21
+ return to_enum(:contents, path) unless block_given?
22
+ default_params = {
23
+ order_by: 'folder,modifiedTime desc,name',
24
+ fields: 'nextPageToken,files(name,id,mimeType,size,modifiedTime,parents,web_content_link)'
25
+ # page_size: 100
26
+ }
22
27
  page_token = nil
23
- files = []
24
28
  begin
25
- unless path.blank?
26
- default_params[:q] = "'#{path}' in parents"
27
- end
28
- unless page_token.blank?
29
- default_params[:pageToken] = page_token
30
- end
31
- api_result = oauth_client.execute( api_method: drive.files.list, parameters: default_params )
32
- response = JSON.parse(api_result.response.body)
33
- page_token = response["nextPageToken"]
34
- response["items"].select do |file|
35
- path.blank? ? (file["parents"].blank? or file["parents"].any?{|p| p["isRoot"] }) : true
29
+ default_params[:q] = "'#{path}' in parents" unless path.blank?
30
+ default_params[:page_token] = page_token unless page_token.blank?
31
+ response = drive.list_files(default_params)
32
+ page_token = response.next_page_token
33
+ response.files.select do |file|
34
+ path.blank? ? (file.parents.blank? || file.parents.any? { |p| p == 'root' }) : true
36
35
  end.each do |file|
37
- files << details(file, path)
36
+ d = details(file, path)
37
+ yield d if d
38
38
  end
39
39
  end while !page_token.blank?
40
- files.compact
41
40
  end
42
41
 
43
- def details(file, path='')
44
- if file["downloadUrl"] or file["mimeType"] == "application/vnd.google-apps.folder"
45
- BrowseEverything::FileEntry.new(
46
- file["id"],
47
- "#{self.key}:#{file["id"]}",
48
- file["title"],
49
- (file["fileSize"] || 0),
50
- Time.parse(file["modifiedDate"]),
51
- file["mimeType"] == "application/vnd.google-apps.folder",
52
- file["mimeType"] == "application/vnd.google-apps.folder" ?
53
- "directory" :
54
- file["mimeType"]
55
- )
56
- end
42
+ def details(file, _path = '')
43
+ mime_folder = file.mime_type == 'application/vnd.google-apps.folder'
44
+ BrowseEverything::FileEntry.new(
45
+ file.id,
46
+ "#{key}:#{file.id}",
47
+ file.name,
48
+ file.size.to_i,
49
+ file.modified_time || DateTime.new,
50
+ mime_folder,
51
+ mime_folder ? 'directory' : file.mime_type
52
+ )
57
53
  end
58
54
 
59
55
  def link_for(id)
60
- api_method = drive.files.get
61
- api_result = oauth_client.execute(api_method: api_method, parameters: {fileId: id})
62
- download_url = JSON.parse(api_result.response.body)["downloadUrl"]
63
- auth_header = {'Authorization' => "Bearer #{oauth_client.authorization.access_token.to_s}"}
64
- extras = {
56
+ file = drive.get_file(id)
57
+ auth_header = { 'Authorization' => "Bearer #{auth_client.access_token}" }
58
+ extras = {
65
59
  auth_header: auth_header,
66
- expires: 1.hour.from_now,
67
- file_name: api_result.data.title,
68
- file_size: api_result.data.fileSize.to_i
60
+ expires: 1.hour.from_now,
61
+ file_name: file.name,
62
+ file_size: file.size.to_i
69
63
  }
70
- [download_url, extras]
64
+ [file.web_content_link, extras]
71
65
  end
72
66
 
73
67
  def auth_link
74
- oauth_client.authorization.authorization_uri.to_s
68
+ auth_client.authorization_uri
75
69
  end
76
70
 
77
71
  def authorized?
78
- @token.present?
72
+ token.present?
79
73
  end
80
74
 
81
- def connect(params, data)
82
- oauth_client.authorization.code = params[:code]
83
- @token = oauth_client.authorization.fetch_access_token!
75
+ def connect(params, _data)
76
+ auth_client.code = params[:code]
77
+ self.token = auth_client.fetch_access_token!
84
78
  end
85
79
 
86
80
  def drive
87
- oauth_client.discovered_api('drive', 'v2')
81
+ @drive ||= Google::Apis::DriveV3::DriveService.new.tap do |s|
82
+ s.authorization = authorization
83
+ end
88
84
  end
89
85
 
90
86
  private
91
87
 
92
- #As per issue http://stackoverflow.com/questions/12572723/rails-google-client-api-unable-to-exchange-a-refresh-token-for-access-token
93
-
94
- #patch start
95
- def token_expired?(token)
96
- client=@client
97
- result = client.execute( api_method: drive.files.list, parameters: {} )
98
- (result.status != 200)
99
- end
100
-
101
- def exchange_refresh_token( refresh_token )
102
- client=oauth_client
103
- client.authorization.grant_type = 'refresh_token'
104
- client.authorization.refresh_token = refresh_token
105
- client.authorization.fetch_access_token!
106
- client.authorization
107
- client
88
+ def authorization
89
+ return @auth_client unless @auth_client.nil?
90
+ return nil unless token.present?
91
+ auth_client.update_token!(token)
92
+ self.token = auth_client.fetch_access_token! if auth_client.expired?
93
+ auth_client
108
94
  end
109
- #patch end
110
95
 
111
- def oauth_client
112
- if @client.nil?
113
- @client = Google::APIClient.new
114
- @client.authorization.client_id = config[:client_id]
115
- @client.authorization.client_secret = config[:client_secret]
116
- @client.authorization.scope = "https://www.googleapis.com/auth/drive"
117
- @client.authorization.redirect_uri = callback
118
- @client.authorization.update_token!(@token) if @token.present?
119
- #Patch start
120
- @client = exchange_refresh_token(@token["refresh_token"]) if @token.present? && token_expired?(@token)
121
- #Patch end
122
- end
123
- #todo error checking here
124
- @client
96
+ def auth_client
97
+ @auth_client ||= Signet::OAuth2::Client.new token_credential_uri: 'https://www.googleapis.com/oauth2/v3/token',
98
+ authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
99
+ scope: 'https://www.googleapis.com/auth/drive',
100
+ client_id: config[:client_id],
101
+ client_secret: config[:client_secret],
102
+ redirect_uri: callback
125
103
  end
126
-
127
104
  end
128
-
129
105
  end
130
106
  end
@@ -0,0 +1,87 @@
1
+ require 'aws-sdk'
2
+
3
+ module BrowseEverything
4
+ module Driver
5
+ class S3 < Base
6
+ DEFAULTS = { signed_url: true, region: 'us-east-1' }
7
+
8
+ def initialize config, *args
9
+ config = DEFAULTS.merge(config)
10
+ super
11
+ end
12
+
13
+ def icon
14
+ 'amazon'
15
+ end
16
+
17
+ def validate_config
18
+ unless [:app_key, :app_secret, :bucket].all? { |key| config[key].present? }
19
+ raise BrowseEverything::InitializationError, 'Amazon S3 driver requires :bucket, :app_key and :app_secret'
20
+ end
21
+ end
22
+
23
+ def contents(path = '')
24
+ path = File.join(path,'') unless path.empty?
25
+ result = []
26
+ listing = client.list_objects(bucket: config[:bucket], delimiter: '/', prefix: path)
27
+ unless path.empty?
28
+ result << BrowseEverything::FileEntry.new(
29
+ Pathname(path).join('..'),
30
+ '', '..', 0, Time.now, true
31
+ )
32
+ end
33
+ listing.common_prefixes.each do |prefix|
34
+ result << entry_for(prefix.prefix, 0, Time.now, true)
35
+ end
36
+ listing.contents.reject { |entry| entry.key == path }.each do |entry|
37
+ result << entry_for(entry.key, entry.size, entry.last_modified, false)
38
+ end
39
+ result.sort do |a, b|
40
+ if b.container?
41
+ a.container? ? a.name.downcase <=> b.name.downcase : 1
42
+ else
43
+ a.container? ? -1 : a.name.downcase <=> b.name.downcase
44
+ end
45
+ end
46
+ end
47
+
48
+ def entry_for(name, size, date, dir)
49
+ BrowseEverything::FileEntry.new(name, [key,name].join(':'), File.basename(name), size, date, dir)
50
+ end
51
+
52
+ def details(path)
53
+ entry = client.head_object(path)
54
+ BrowseEverything::FileEntry.new(
55
+ entry.key,
56
+ [key,entry.key].join(':'),
57
+ File.basename(entry.key),
58
+ entry.size,
59
+ entry.last_modified,
60
+ false
61
+ )
62
+ end
63
+
64
+ def link_for(path)
65
+ obj = bucket.object(path)
66
+ if config[:signed_url]
67
+ obj.presigned_url(:get, expires_in: 14400)
68
+ else
69
+ obj.public_url
70
+ end
71
+ end
72
+
73
+ def authorized?
74
+ true
75
+ end
76
+
77
+ def bucket
78
+ @bucket ||= Aws::S3::Bucket.new(config[:bucket], client: client)
79
+ end
80
+
81
+ def client
82
+ @client ||= Aws::S3::Client.new(credentials: Aws::Credentials.new(config[:app_key], config[:app_secret]), region: config[:region])
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -1,7 +1,6 @@
1
1
  module BrowseEverything
2
2
  module Driver
3
3
  class SkyDrive < Base
4
-
5
4
  require 'skydrive'
6
5
 
7
6
  def icon
@@ -9,27 +8,27 @@ module BrowseEverything
9
8
  end
10
9
 
11
10
  def container_items
12
- ["folder","album"]
11
+ %w(folder album)
13
12
  end
14
13
 
15
14
  def validate_config
16
15
  unless config[:client_id]
17
- raise BrowseEverything::InitializationError, "SkyDrive driver requires a :client_id argument"
16
+ raise BrowseEverything::InitializationError, 'SkyDrive driver requires a :client_id argument'
18
17
  end
19
18
  unless config[:client_secret]
20
- raise BrowseEverything::InitializationError, "SkyDrive driver requires a :client_secret argument"
19
+ raise BrowseEverything::InitializationError, 'SkyDrive driver requires a :client_secret argument'
21
20
  end
22
21
  end
23
22
 
24
- def contents(path='')
23
+ def contents(path = '')
25
24
  result = []
26
25
  token_obj = rehydrate_token
27
26
  client = Skydrive::Client.new(token_obj)
28
- if (path == '')
27
+ if path == ''
29
28
  folder = client.my_skydrive
30
- #todo do some loop to get down to my path
29
+ # TODO: do some loop to get down to my path
31
30
  else
32
- folder = client.get("/#{path.gsub("-",".")}/")
31
+ folder = client.get("/#{path.tr('-', '.')}/")
33
32
  result += [parent_folder_details(folder)] if folder.parent_id
34
33
  end
35
34
 
@@ -47,68 +46,63 @@ module BrowseEverything
47
46
 
48
47
  def link_for(path)
49
48
  response = Skydrive::Client.new(rehydrate_token).get("/#{real_id(path)}/")
50
- [response.download_link, {expires: 1.hour.from_now, file_name: File.basename(path), file_size: response.size.to_i}]
49
+ [response.download_link, { expires: 1.hour.from_now, file_name: File.basename(path), file_size: response.size.to_i }]
51
50
  end
52
51
 
53
-
54
-
55
52
  def file_details(file)
56
- BrowseEverything::FileEntry.new(
57
- safe_id(file.id),
58
- "#{key}:#{safe_id(file.id)}",
59
- file.name,
60
- file.size,
61
- file.updated_time,
62
- false
63
- )
53
+ BrowseEverything::FileEntry.new(
54
+ safe_id(file.id),
55
+ "#{key}:#{safe_id(file.id)}",
56
+ file.name,
57
+ file.size,
58
+ file.updated_time,
59
+ false
60
+ )
64
61
  end
65
62
 
66
- def parent_folder_details(file)
67
- BrowseEverything::FileEntry.new(
68
- safe_id(file.parent_id),
69
- "#{key}:#{safe_id(file.parent_id)}",
70
- "..",
71
- 0,
72
- Time.now,
73
- true
74
- )
63
+ def parent_folder_details(file)
64
+ BrowseEverything::FileEntry.new(
65
+ safe_id(file.parent_id),
66
+ "#{key}:#{safe_id(file.parent_id)}",
67
+ '..',
68
+ 0,
69
+ Time.now,
70
+ true
71
+ )
75
72
  end
76
73
 
77
-
78
-
79
-
80
74
  def folder_details(folder)
81
75
  BrowseEverything::FileEntry.new(
82
- safe_id(folder.id),
83
- "#{key}:#{safe_id(folder.id)}",
84
- folder.name,
85
- 0,
86
- folder.updated_time,
87
- true,
88
- 'directory'#todo how are we getting mime type
76
+ safe_id(folder.id),
77
+ "#{key}:#{safe_id(folder.id)}",
78
+ folder.name,
79
+ 0,
80
+ folder.updated_time,
81
+ true,
82
+ 'directory' # TODO: how are we getting mime type
89
83
  )
90
84
  end
91
85
 
92
-
93
86
  def auth_link
94
87
  oauth_client.authorize_url
95
88
  end
96
89
 
97
90
  def authorized?
98
91
  return false unless @token.present?
99
- return !rehydrate_token.expired?
92
+ !rehydrate_token.expired?
100
93
  end
101
94
 
102
- def connect(params,data)
95
+ def connect(params, _data)
103
96
  Rails.logger.warn "params #{params.inspect}"
104
97
  token = oauth_client.get_access_token(params[:code])
105
- @token = {token:token.token, expires_at:token.expires_at}
98
+ @token = { token: token.token, expires_at: token.expires_at }
106
99
  end
107
100
 
108
101
  private
102
+
109
103
  def oauth_client
110
- Skydrive::Oauth::Client.new(config[:client_id], config[:client_secret], callback.to_s,"wl.skydrive")
111
- #todo error checking here
104
+ Skydrive::Oauth::Client.new(config[:client_id], config[:client_secret], callback.to_s, 'wl.skydrive')
105
+ # TODO: error checking here
112
106
  end
113
107
 
114
108
  def rehydrate_token
@@ -116,15 +110,15 @@ module BrowseEverything
116
110
  token_str = @token[:token]
117
111
  token_expires = @token[:expires_at]
118
112
  Rails.logger.warn "\n\n Rehydrating: #{@token} #{token_str} #{token_expires}"
119
- @rehydrate_token = oauth_client.get_access_token_from_hash(token_str,{expires_at:token_expires})
113
+ @rehydrate_token = oauth_client.get_access_token_from_hash(token_str, expires_at: token_expires)
120
114
  end
121
115
 
122
116
  def safe_id(id)
123
- id.gsub(".","-")
117
+ id.tr('.', '-')
124
118
  end
125
119
 
126
120
  def real_id(id)
127
- id.gsub("-",".")
121
+ id.tr('-', '.')
128
122
  end
129
123
  end
130
124
  end