middleman-google_drive 0.2.1 → 0.2.2

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: 5bf7956b153e220ffa3c09c0aaa15a06d72683df
4
- data.tar.gz: f7b3ccb5e1bd511e070037bef2def79c27935f68
3
+ metadata.gz: 2857e937b68c10de7780fa28220f3d70e6953f29
4
+ data.tar.gz: a4c19ba124ac231e4795d86047d6c8a5aafd7786
5
5
  SHA512:
6
- metadata.gz: 6cabc9eb4a1a5b3eb1b8486df8f5a9d98c4202223efcf74c4ed85e6f93c53bb0a34dad5b0b240a1c45ec2f0bcadf5f12d85c0296d934c8b7406a0ebeba8fda6b
7
- data.tar.gz: aa172b233c0582022b8ec4233a69e8f0f4bc3e7066b1033de6632db662a79ad26ec734c1da73962268d038fe894b1c880c3313039871f51f91af3087f91a117a
6
+ metadata.gz: 27ebca38276d76f625c781204b68fed14ed387a204d1c7a9543b58bb35d020548dde02cb6d04198e90bd37d5f2dc0292ae56b4fc92008d5098cc555d52d46509
7
+ data.tar.gz: 4822b82da85d3ddc9e20d963170c5802267f54e81749acb185d0d1eb31bf8ccb5965200a3410b381e8acb4bc3cdd43884fca6fbbd1b9a048f297f34d5ec109c0
data/Rakefile CHANGED
@@ -1,2 +1,12 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'bundler/setup'
3
+ require 'rake/testtask'
4
+ require 'rake/clean'
2
5
 
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib'
8
+ t.test_files = FileList['test/*_test.rb']
9
+ end
10
+
11
+ desc 'Run tests'
12
+ task default: :test
data/lib/google_drive.rb CHANGED
@@ -5,94 +5,65 @@ require 'google/api_client/auth/file_storage'
5
5
  require 'google/api_client/auth/installed_app'
6
6
 
7
7
  class GoogleDrive
8
+ attr_reader :client
8
9
  def initialize
9
- credentials = ENV['GOOGLE_DRIVE_OAUTH'] || File.expand_path(
10
+ @credentials = ENV['GOOGLE_DRIVE_OAUTH'] || File.expand_path(
10
11
  '~/.google_drive_oauth2.json')
11
- client_secrets = ENV['GOOGLE_CLIENT_SECRETS'] || File.expand_path(
12
+ @client_secrets = ENV['GOOGLE_CLIENT_SECRETS'] || File.expand_path(
12
13
  '~/.google_client_secrets.json')
13
14
 
14
- person = ENV['GOOGLE_OAUTH_PERSON']
15
- issuer = ENV['GOOGLE_OAUTH_ISSUER']
16
- key_path = ENV['GOOGLE_OAUTH_KEYFILE']
17
- private_key = ENV['GOOGLE_OAUTH_PRIVATE_KEY']
15
+ @person = ENV['GOOGLE_OAUTH_PERSON']
16
+ @issuer = ENV['GOOGLE_OAUTH_ISSUER']
17
+ @key_path = ENV['GOOGLE_OAUTH_KEYFILE']
18
+ @private_key = ENV['GOOGLE_OAUTH_PRIVATE_KEY']
18
19
 
19
20
  # try to read the file,
20
21
  # throw errors if not readable or not found
21
- if key_path
22
- key = Google::APIClient::KeyUtils.load_from_pkcs12(
23
- key_path, 'notasecret')
22
+ if @key_path
23
+ @key = Google::APIClient::KeyUtils.load_from_pkcs12(
24
+ @key_path, 'notasecret')
24
25
  elsif @private_key
25
- key = OpenSSL::PKey::RSA.new(
26
- private_key, 'notasecret')
26
+ @key = OpenSSL::PKey::RSA.new(
27
+ @private_key, 'notasecret')
27
28
  end
28
29
 
29
- if key
30
- @client = Google::APIClient.new(
31
- application_name: 'Middleman',
32
- application_version: Middleman::GoogleDrive::VERSION,
33
- authorization: Signet::OAuth2::Client.new(
34
- token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
35
- audience: 'https://accounts.google.com/o/oauth2/token',
36
- person: person,
37
- issuer: issuer,
38
- signing_key: key,
39
- scope: ['https://www.googleapis.com/auth/drive']
40
- )
41
- )
42
- @client.authorization.fetch_access_token!
43
- else
44
- @client = Google::APIClient.new(
45
- application_name: 'Middleman',
46
- application_version: Middleman::GoogleDrive::VERSION
47
- )
48
- begin
49
- file_storage = Google::APIClient::FileStorage.new(credentials)
50
- rescue URI::InvalidURIError
51
- File.delete credentials
52
- file_storage = Google::APIClient::FileStorage.new(credentials)
53
- end
54
- if file_storage.authorization.nil?
55
- unless File.exist? client_secrets
56
- fail ConfigurationError, 'You need to create a client_secrets.json file and save it to ~/.google_client_secrets.json.'
57
- end
58
- puts 'Please login via your web browser'
59
- client_secrets = Google::APIClient::ClientSecrets.load(client_secrets)
60
- flow = Google::APIClient::InstalledAppFlow.new(
61
- client_id: client_secrets.client_id,
62
- client_secret: client_secrets.client_secret,
63
- scope: ['https://www.googleapis.com/auth/drive']
64
- )
65
- @client.authorization = flow.authorize(file_storage)
66
- else
67
- @client.authorization = file_storage.authorization
68
- end
69
- end
30
+ @_files = {}
31
+ @_spreadsheets = {}
32
+
33
+ do_auth
70
34
  end
71
35
 
72
- def get_sheet(key)
73
- require 'roo'
74
- # setup the hash that we will eventually return
75
- data = {}
36
+ def find(key)
37
+ return @_files[key] unless @_files[key].nil?
38
+
76
39
  drive = @client.discovered_api('drive', 'v2')
77
40
 
78
41
  # get the file metadata
79
- list_resp = @client.execute(
42
+ resp = @client.execute(
80
43
  api_method: drive.files.get,
81
44
  parameters: { fileId: key })
82
45
 
83
46
  # die if there's an error
84
- fail list_resp.error_message if list_resp.error?
47
+ fail GoogleDriveError, resp.error_message if resp.error?
48
+
49
+ @_files[key] = resp.data
50
+ end
51
+
52
+ def spreadsheet(key)
53
+ require 'roo'
54
+
55
+ list_resp = find(key)
85
56
 
86
57
  # Grab the export url. We're gonna request the spreadsheet
87
58
  # in excel format. Because it includes all the worksheets.
88
- uri = list_resp.data['exportLinks'][
59
+ uri = list_resp['exportLinks'][
89
60
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
90
61
 
91
62
  # get the export
92
63
  get_resp = @client.execute(uri: uri)
93
64
 
94
65
  # die if there's an error
95
- fail get_resp.error_message if get_resp.error?
66
+ fail GoogleDriveError, get_resp.error_message if get_resp.error?
96
67
 
97
68
  # get a temporary file. The export is binary, so open the tempfile in
98
69
  # write binary mode
@@ -101,10 +72,17 @@ class GoogleDrive
101
72
  fp.write get_resp.body
102
73
  fp.close
103
74
 
104
- # now open the file with Roo. (Roo can't handle an IO
105
- # object, it will only take filenames or urls, coulda done this all
106
- # in memory, but alas...)
107
- xls = Roo::Spreadsheet.open(filename)
75
+ # now open the file with Roo
76
+ ret = Roo::Spreadsheet.open(filename)
77
+
78
+ fp.unlink # delete our tempfile
79
+
80
+ ret
81
+ end
82
+
83
+ def prepared_spreadsheet(key)
84
+ xls = spreadsheet(key)
85
+ data = {}
108
86
  xls.each_with_pagename do |title, sheet|
109
87
  # if the sheet is called microcopy, copy or ends with copy, we assume
110
88
  # the first column contains keys and the second contains values.
@@ -126,15 +104,33 @@ class GoogleDrive
126
104
  end
127
105
  else
128
106
  # otherwise parse the sheet into a hash
129
- sheet.header_line = 2 # this is stupid. theres a bug in Roo.
107
+ sheet.header_line = 2 # a bug in Roo.
130
108
  data[title] = sheet.parse(headers: true)
131
109
  end
132
110
  end
133
- fp.unlink # delete our tempfile
134
111
  data
135
112
  end
136
113
 
137
- def copy_doc(file_id, title=nil)
114
+ def doc(key, format = 'html')
115
+ doc = find(key)
116
+
117
+ # Grab the export url.
118
+ if format.to_s == 'html'
119
+ uri = doc['exportLinks']['text/html']
120
+ else
121
+ uri = doc['exportLinks']['text/plain']
122
+ end
123
+
124
+ # get the export
125
+ resp = @client.execute(uri: uri)
126
+
127
+ # die if there's an error
128
+ fail GoogleDriveError, resp.error_message if resp.error?
129
+
130
+ resp.body
131
+ end
132
+
133
+ def copy(file_id, title = nil)
138
134
  drive = @client.discovered_api('drive', 'v2')
139
135
 
140
136
  if title.nil?
@@ -153,7 +149,74 @@ class GoogleDrive
153
149
  return { id: cp_resp.data['id'], url: cp_resp.data['alternateLink'] }
154
150
  end
155
151
  end
152
+ alias_method :copy_doc, :copy
153
+
154
+ def redo_auth
155
+ File.delete @credentials if @key.nil?
156
+ do_auth
157
+ end
158
+
159
+ def do_auth
160
+ if local?
161
+ @client = Google::APIClient.new(
162
+ application_name: 'Middleman',
163
+ application_version: Middleman::GoogleDrive::VERSION
164
+ )
165
+ begin
166
+ file_storage = Google::APIClient::FileStorage.new(@credentials)
167
+ rescue URI::InvalidURIError
168
+ File.delete @credentials
169
+ file_storage = Google::APIClient::FileStorage.new(@credentials)
170
+ end
171
+ if file_storage.authorization.nil?
172
+ unless File.exist? @client_secrets
173
+ fail ConfigurationError, 'You need to create a client_secrets.json file and save it to ~/.google_client_secrets.json.'
174
+ end
175
+ puts <<-MSG
176
+
177
+ Please login via your web browser. We opened the tab for you...
178
+
179
+ MSG
180
+ client_secrets = Google::APIClient::ClientSecrets.load(@client_secrets)
181
+ flow = Google::APIClient::InstalledAppFlow.new(
182
+ client_id: client_secrets.client_id,
183
+ client_secret: client_secrets.client_secret,
184
+ scope: ['https://www.googleapis.com/auth/drive']
185
+ )
186
+ @client.authorization = flow.authorize(file_storage)
187
+ else
188
+ @client.authorization = file_storage.authorization
189
+ end
190
+ else
191
+ @client = Google::APIClient.new(
192
+ application_name: 'Middleman',
193
+ application_version: Middleman::GoogleDrive::VERSION,
194
+ authorization: Signet::OAuth2::Client.new(
195
+ token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
196
+ audience: 'https://accounts.google.com/o/oauth2/token',
197
+ person: @person,
198
+ issuer: @issuer,
199
+ signing_key: @key,
200
+ scope: ['https://www.googleapis.com/auth/drive']
201
+ )
202
+ )
203
+ @client.authorization.fetch_access_token!
204
+ end
205
+ nil
206
+ end
207
+
208
+ # Returns true if we're using a private key to autheticate (like on a server).
209
+ def server?
210
+ ! @key.nil?
211
+ end
212
+
213
+ # Returns true if we're using local oauth2 (like on your computer).
214
+ def local?
215
+ @key.nil?
216
+ end
156
217
 
157
- class CreateError < Exception; end
158
- class ConfigurationError < Exception; end
218
+ class GoogleDriveError < StandardError; end
219
+ class DoesNotExist < GoogleDriveError; end
220
+ class CreateError < GoogleDriveError; end
221
+ class ConfigurationError < GoogleDriveError; end
159
222
  end
@@ -12,9 +12,43 @@ module Middleman
12
12
 
13
13
  drive = ::GoogleDrive.new
14
14
 
15
- app = klass.inst # where would you store the app instance?
15
+ app = klass.inst
16
+ app.set :drive, drive # so you can access the drive api directly
16
17
  options.load_sheets.each do |k, v|
17
- app.data.store(k, drive.get_sheet(v))
18
+ loop do
19
+ begin
20
+ app.data.store(k, drive.prepared_spreadsheet(v))
21
+ doc = drive.find(v)
22
+ puts <<-MSG
23
+ == Loaded data.#{k} from Google Doc "#{doc['title']}"
24
+ == #{doc['alternateLink']}
25
+ MSG
26
+ break
27
+ rescue ::GoogleDrive::GoogleDriveError => exc
28
+ if drive.server?
29
+ puts "== FAILED to load Google Doc \"#{exc.message}\""
30
+ break
31
+ end
32
+
33
+ puts <<-MSG
34
+
35
+ Could not load the Google Doc.
36
+
37
+ Things to check:
38
+ - Make sure the Google Doc key is correct
39
+ - Make sure you're logging in with the correct account
40
+ - Make sure you have access to the document
41
+
42
+ Google said "#{exc.message}." It might be a lie.
43
+
44
+ Would you like to try again? [Y/n]
45
+ MSG
46
+ resp = $stdin.read 1
47
+ break unless resp.strip.empty? || resp =~ /[Yy]/
48
+
49
+ drive.redo_auth
50
+ end
51
+ end
18
52
  end
19
53
  end
20
54
  end
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  module GoogleDrive
3
- VERSION = '0.2.1'
3
+ VERSION = '0.2.2'
4
4
  end
5
5
  end
@@ -23,5 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_runtime_dependency 'google-api-client', '>= 0.7.1'
24
24
  spec.add_runtime_dependency 'roo', '~> 1.13.2'
25
25
  spec.add_development_dependency 'bundler', '~> 1.6'
26
- spec.add_development_dependency 'rake', '>= 10.3.2'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'minitest'
27
28
  end
@@ -0,0 +1,50 @@
1
+ require 'minitest/autorun'
2
+ require 'google_drive'
3
+
4
+ # Test the client lib!
5
+ class TestChorusApiClient < MiniTest::Test
6
+ def setup
7
+ @drive = ::GoogleDrive.new
8
+ end
9
+
10
+ def test_old_find
11
+ file = @drive.find '0AiOYF21HkoowdEZ4Ukkyc09nb2czQUxUYldidTB4Q1E'
12
+ assert_equal file['title'], 'Example Middleman Google Drive worksheet'
13
+ end
14
+
15
+ def test_old_prepared_spreadsheet
16
+ file = @drive.prepared_spreadsheet '0AiOYF21HkoowdEZ4Ukkyc09nb2czQUxUYldidTB4Q1E'
17
+ assert_has_key file, 'microcopy'
18
+ assert_has_key file['microcopy'], 'help'
19
+ end
20
+
21
+ def test_new_find
22
+ file = @drive.find '1vIICbbfHJ8lYSthiDWTNypZulrMResi9zPRjv4ePJJU'
23
+ assert_equal file['title'], 'Example Middleman Google Drive worksheet'
24
+ end
25
+
26
+ def test_new_prepared_spreadsheet
27
+ file = @drive.prepared_spreadsheet '1vIICbbfHJ8lYSthiDWTNypZulrMResi9zPRjv4ePJJU'
28
+ assert_has_key file, 'microcopy'
29
+ assert_has_key file['microcopy'], 'help'
30
+ end
31
+
32
+ def test_new_doc
33
+ file = @drive.doc '1lH-Nr_8UBOkvk8OdcdFoDez3OFIJxkawGVkwlMB-BjQ'
34
+ assert_not_nil file =~ /^<html>/
35
+
36
+ file = @drive.doc '1lH-Nr_8UBOkvk8OdcdFoDez3OFIJxkawGVkwlMB-BjQ', 'text'
37
+ assert_nil file =~ /^<html>/
38
+ end
39
+
40
+ def test_copy_file
41
+ end
42
+
43
+ def assert_has_key(hash, key, msg=nil)
44
+ assert hash.key?(key), msg || "The key '#{key}' is missing from #{hash}"
45
+ end
46
+
47
+ def assert_not_nil(thing, msg=nil)
48
+ assert !thing.nil?, msg
49
+ end
50
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-google_drive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Mark
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-20 00:00:00.000000000 Z
12
+ date: 2014-11-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: middleman-core
@@ -73,14 +73,28 @@ dependencies:
73
73
  requirements:
74
74
  - - '>='
75
75
  - !ruby/object:Gem::Version
76
- version: 10.3.2
76
+ version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - '>='
82
82
  - !ruby/object:Gem::Version
83
- version: 10.3.2
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: minitest
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
84
98
  description:
85
99
  email:
86
100
  - ryan@mrk.cc
@@ -100,6 +114,7 @@ files:
100
114
  - lib/middleman-google_drive/version.rb
101
115
  - lib/middleman_extension.rb
102
116
  - middleman-google_drive.gemspec
117
+ - test/google_drive_test.rb
103
118
  homepage: https://github.com/voxmedia/middleman-google_drive
104
119
  licenses:
105
120
  - BSD
@@ -120,8 +135,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
135
  version: '0'
121
136
  requirements: []
122
137
  rubyforge_project:
123
- rubygems_version: 2.2.2
138
+ rubygems_version: 2.4.1
124
139
  signing_key:
125
140
  specification_version: 4
126
141
  summary: Pull content from a google spreadsheet to use in your middleman site.
127
- test_files: []
142
+ test_files:
143
+ - test/google_drive_test.rb