google-api-client 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +13 -5
  2. data/CHANGELOG.md +14 -0
  3. data/Gemfile +0 -36
  4. data/README.md +12 -1
  5. data/Rakefile +1 -8
  6. data/google-api-client.gemspec +40 -0
  7. data/lib/google/api_client.rb +98 -30
  8. data/lib/google/api_client/auth/compute_service_account.rb +1 -1
  9. data/lib/google/api_client/auth/file_storage.rb +19 -44
  10. data/lib/google/api_client/auth/installed_app.rb +11 -7
  11. data/lib/google/api_client/auth/storage.rb +101 -0
  12. data/lib/google/api_client/auth/storages/file_store.rb +58 -0
  13. data/lib/google/api_client/auth/storages/redis_store.rb +54 -0
  14. data/lib/google/api_client/batch.rb +13 -11
  15. data/lib/google/api_client/charset.rb +33 -0
  16. data/lib/google/api_client/client_secrets.rb +9 -6
  17. data/lib/google/api_client/discovery/api.rb +3 -3
  18. data/lib/google/api_client/discovery/resource.rb +3 -3
  19. data/lib/google/api_client/discovery/schema.rb +3 -5
  20. data/lib/google/api_client/errors.rb +5 -0
  21. data/lib/google/api_client/railtie.rb +2 -1
  22. data/lib/google/api_client/request.rb +1 -2
  23. data/lib/google/api_client/result.rb +4 -2
  24. data/lib/google/api_client/service.rb +2 -2
  25. data/lib/google/api_client/service/batch.rb +7 -0
  26. data/lib/google/api_client/service/stub_generator.rb +4 -2
  27. data/lib/google/api_client/service_account.rb +3 -0
  28. data/lib/google/api_client/version.rb +8 -13
  29. data/spec/google/api_client/auth/storage_spec.rb +122 -0
  30. data/spec/google/api_client/auth/storages/file_store_spec.rb +40 -0
  31. data/spec/google/api_client/auth/storages/redis_store_spec.rb +70 -0
  32. data/spec/google/api_client/batch_spec.rb +29 -30
  33. data/spec/google/api_client/client_secrets_spec.rb +53 -0
  34. data/spec/google/api_client/discovery_spec.rb +101 -91
  35. data/spec/google/api_client/gzip_spec.rb +21 -9
  36. data/spec/google/api_client/media_spec.rb +31 -32
  37. data/spec/google/api_client/request_spec.rb +3 -4
  38. data/spec/google/api_client/result_spec.rb +51 -47
  39. data/spec/google/api_client/service_account_spec.rb +40 -35
  40. data/spec/google/api_client/service_spec.rb +144 -112
  41. data/spec/google/api_client/simple_file_store_spec.rb +30 -34
  42. data/spec/google/api_client_spec.rb +139 -40
  43. data/spec/spec_helper.rb +9 -1
  44. metadata +111 -88
  45. data/CONTRIBUTING.md +0 -32
  46. data/lib/cacerts.pem +0 -2183
  47. data/lib/google/inflection.rb +0 -28
  48. data/spec/fixtures/files/privatekey.p12 +0 -0
  49. data/spec/fixtures/files/sample.txt +0 -33
  50. data/spec/fixtures/files/secret.pem +0 -19
  51. data/tasks/gem.rake +0 -97
  52. data/tasks/git.rake +0 -45
  53. data/tasks/metrics.rake +0 -22
  54. data/tasks/spec.rake +0 -57
  55. data/tasks/wiki.rake +0 -82
  56. data/tasks/yard.rake +0 -29
@@ -26,7 +26,7 @@ module Google
26
26
  # client = Google::APIClient.new
27
27
  # flow = Google::APIClient::InstalledAppFlow.new(
28
28
  # :client_id => '691380668085.apps.googleusercontent.com',
29
- # :client_secret => '...,
29
+ # :client_secret => '...',
30
30
  # :scope => 'https://www.googleapis.com/auth/drive'
31
31
  # )
32
32
  # client.authorization = flow.authorize
@@ -92,9 +92,10 @@ module Google
92
92
  :Logger => WEBrick::Log.new(STDOUT, 0),
93
93
  :AccessLog => []
94
94
  )
95
- trap("INT") { server.shutdown }
96
-
97
- server.mount_proc '/' do |req, res|
95
+ begin
96
+ trap("INT") { server.shutdown }
97
+
98
+ server.mount_proc '/' do |req, res|
98
99
  auth.code = req.query['code']
99
100
  if auth.code
100
101
  auth.fetch_access_token!
@@ -102,10 +103,13 @@ module Google
102
103
  res.status = WEBrick::HTTPStatus::RC_ACCEPTED
103
104
  res.body = RESPONSE_BODY
104
105
  server.stop
105
- end
106
+ end
106
107
 
107
- Launchy.open(auth.authorization_uri.to_s)
108
- server.start
108
+ Launchy.open(auth.authorization_uri.to_s)
109
+ server.start
110
+ ensure
111
+ server.shutdown
112
+ end
109
113
  if @authorization.access_token
110
114
  if storage.respond_to?(:write_credentials)
111
115
  storage.write_credentials(@authorization)
@@ -0,0 +1,101 @@
1
+ # Copyright 2013 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'signet/oauth_2/client'
16
+
17
+ module Google
18
+ class APIClient
19
+ ##
20
+ # Represents cached OAuth 2 tokens stored on local disk in a
21
+ # JSON serialized file. Meant to resemble the serialized format
22
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
23
+ #
24
+ class Storage
25
+
26
+ AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'
27
+ TOKEN_CREDENTIAL_URI = 'https://accounts.google.com/o/oauth2/token'
28
+
29
+ # @return [Object] Storage object.
30
+ attr_accessor :store
31
+
32
+ # @return [Signet::OAuth2::Client]
33
+ attr_reader :authorization
34
+
35
+ ##
36
+ # Initializes the Storage object.
37
+ #
38
+ # @params [Object] Storage object
39
+ def initialize(store)
40
+ @store= store
41
+ end
42
+
43
+ ##
44
+ # Write the credentials to the specified store.
45
+ #
46
+ # @params [Signet::OAuth2::Client] authorization
47
+ # Optional authorization instance. If not provided, the authorization
48
+ # already associated with this instance will be written.
49
+ def write_credentials(authorization=nil)
50
+ @authorization = authorization if authorization
51
+ if @authorization.respond_to?(:refresh_token) && @authorization.refresh_token
52
+ store.write_credentials(credentials_hash)
53
+ end
54
+ end
55
+
56
+ ##
57
+ # Loads credentials and authorizes an client.
58
+ # @return [Object] Signet::OAuth2::Client or NIL
59
+ def authorize
60
+ @authorization = nil
61
+ cached_credentials = load_credentials
62
+ if cached_credentials && cached_credentials.size > 0
63
+ @authorization = Signet::OAuth2::Client.new(cached_credentials)
64
+ @authorization.issued_at = Time.at(cached_credentials['issued_at'].to_i)
65
+ self.refresh_authorization if @authorization.expired?
66
+ end
67
+ return @authorization
68
+ end
69
+
70
+ ##
71
+ # refresh credentials and save them to store
72
+ def refresh_authorization
73
+ authorization.refresh!
74
+ self.write_credentials
75
+ end
76
+
77
+ private
78
+
79
+ ##
80
+ # Attempt to read in credentials from the specified store.
81
+ def load_credentials
82
+ store.load_credentials
83
+ end
84
+
85
+ ##
86
+ # @return [Hash] with credentials
87
+ def credentials_hash
88
+ {
89
+ :access_token => authorization.access_token,
90
+ :authorization_uri => AUTHORIZATION_URI,
91
+ :client_id => authorization.client_id,
92
+ :client_secret => authorization.client_secret,
93
+ :expires_in => authorization.expires_in,
94
+ :refresh_token => authorization.refresh_token,
95
+ :token_credential_uri => TOKEN_CREDENTIAL_URI,
96
+ :issued_at => authorization.issued_at.to_i
97
+ }
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,58 @@
1
+ # Copyright 2013 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'json'
16
+
17
+ module Google
18
+ class APIClient
19
+ ##
20
+ # Represents cached OAuth 2 tokens stored on local disk in a
21
+ # JSON serialized file. Meant to resemble the serialized format
22
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
23
+ #
24
+ class FileStore
25
+
26
+ attr_accessor :path
27
+
28
+ ##
29
+ # Initializes the FileStorage object.
30
+ #
31
+ # @param [String] path
32
+ # Path to the credentials file.
33
+ def initialize(path)
34
+ @path= path
35
+ end
36
+
37
+ ##
38
+ # Attempt to read in credentials from the specified file.
39
+ def load_credentials
40
+ open(path, 'r') { |f| JSON.parse(f.read) }
41
+ rescue
42
+ nil
43
+ end
44
+
45
+ ##
46
+ # Write the credentials to the specified file.
47
+ #
48
+ # @param [Signet::OAuth2::Client] authorization
49
+ # Optional authorization instance. If not provided, the authorization
50
+ # already associated with this instance will be written.
51
+ def write_credentials(credentials_hash)
52
+ open(self.path, 'w+') do |f|
53
+ f.write(credentials_hash.to_json)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright 2013 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'json'
16
+
17
+ module Google
18
+ class APIClient
19
+ class RedisStore
20
+
21
+ DEFAULT_REDIS_CREDENTIALS_KEY = "google_api_credentials"
22
+
23
+ attr_accessor :redis
24
+
25
+ ##
26
+ # Initializes the RedisStore object.
27
+ #
28
+ # @params [Object] Redis instance
29
+ def initialize(redis, key = nil)
30
+ @redis= redis
31
+ @redis_credentials_key = key
32
+ end
33
+
34
+ ##
35
+ # Attempt to read in credentials from redis.
36
+ def load_credentials
37
+ credentials = redis.get redis_credentials_key
38
+ JSON.parse(credentials) if credentials
39
+ end
40
+
41
+ def redis_credentials_key
42
+ @redis_credentials_key || DEFAULT_REDIS_CREDENTIALS_KEY
43
+ end
44
+
45
+ ##
46
+ # Write the credentials to redis.
47
+ #
48
+ # @params [Hash] credentials
49
+ def write_credentials(credentials_hash)
50
+ redis.set(redis_credentials_key, credentials_hash.to_json)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -14,7 +14,7 @@
14
14
 
15
15
  require 'addressable/uri'
16
16
  require 'google/api_client/reference'
17
- require 'uuidtools'
17
+ require 'securerandom'
18
18
 
19
19
  module Google
20
20
  class APIClient
@@ -90,8 +90,7 @@ module Google
90
90
  @global_callback = block if block_given?
91
91
  @last_auto_id = 0
92
92
 
93
- # TODO(sgomes): Use SecureRandom.uuid, drop UUIDTools when we drop 1.8
94
- @base_id = UUIDTools::UUID.random_create.to_s
93
+ @base_id = SecureRandom.uuid
95
94
 
96
95
  options[:uri] ||= 'https://www.googleapis.com/batch'
97
96
  options[:http_method] ||= 'POST'
@@ -140,14 +139,17 @@ module Google
140
139
  # the HTTP response.
141
140
  def process_http_response(response)
142
141
  content_type = find_header('Content-Type', response.headers)
143
- boundary = /.*boundary=(.+)/.match(content_type)[1]
144
- parts = response.body.split(/--#{Regexp.escape(boundary)}/)
145
- parts = parts[1...-1]
146
- parts.each do |part|
147
- call_response = deserialize_call_response(part)
148
- _, call, callback = @calls.assoc(call_response.call_id)
149
- result = Google::APIClient::Result.new(call, call_response)
150
- callback.call(result) if callback
142
+ m = /.*boundary=(.+)/.match(content_type)
143
+ if m
144
+ boundary = m[1]
145
+ parts = response.body.split(/--#{Regexp.escape(boundary)}/)
146
+ parts = parts[1...-1]
147
+ parts.each do |part|
148
+ call_response = deserialize_call_response(part)
149
+ _, call, callback = @calls.assoc(call_response.call_id)
150
+ result = Google::APIClient::Result.new(call, call_response)
151
+ callback.call(result) if callback
152
+ end
151
153
  end
152
154
  Google::APIClient::Result.new(self, response)
153
155
  end
@@ -0,0 +1,33 @@
1
+ require 'faraday'
2
+ require 'zlib'
3
+
4
+ module Google
5
+ class APIClient
6
+ class Charset < Faraday::Response::Middleware
7
+ include Google::APIClient::Logging
8
+
9
+ def charset_for_content_type(type)
10
+ if type
11
+ m = type.match(/(?:charset|encoding)="?([a-z0-9-]+)"?/i)
12
+ if m
13
+ return Encoding.find(m[1])
14
+ end
15
+ end
16
+ nil
17
+ end
18
+
19
+ def adjust_encoding(env)
20
+ charset = charset_for_content_type(env[:response_headers]['content-type'])
21
+ if charset && env[:body].encoding != charset
22
+ env[:body].force_encoding(charset)
23
+ end
24
+ end
25
+
26
+ def on_complete(env)
27
+ adjust_encoding(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ Faraday::Response.register_middleware :charset => Google::APIClient::Charset
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
 
15
15
 
16
- require 'multi_json'
17
16
  require 'compat/multi_json'
18
17
 
19
18
 
@@ -63,7 +62,7 @@ module Google
63
62
  end
64
63
  while filename == nil
65
64
  search_path ||= File.expand_path('.')
66
- if File.exist?(File.join(search_path, 'client_secrets.json'))
65
+ if File.exists?(File.join(search_path, 'client_secrets.json'))
67
66
  filename = File.join(search_path, 'client_secrets.json')
68
67
  elsif search_path == '/' || search_path =~ /[a-zA-Z]:[\/\\]/
69
68
  raise ArgumentError,
@@ -89,12 +88,12 @@ module Google
89
88
  @client_id = fdata[:client_id] || fdata["client_id"]
90
89
  @client_secret = fdata[:client_secret] || fdata["client_secret"]
91
90
  @redirect_uris = fdata[:redirect_uris] || fdata["redirect_uris"]
92
- @redirect_uris ||= [fdata[:redirect_uri]]
91
+ @redirect_uris ||= [fdata[:redirect_uri] || fdata["redirect_uri"]].compact
93
92
  @javascript_origins = (
94
93
  fdata[:javascript_origins] ||
95
94
  fdata["javascript_origins"]
96
95
  )
97
- @javascript_origins ||= [fdata[:javascript_origin]]
96
+ @javascript_origins ||= [fdata[:javascript_origin] || fdata["javascript_origin"]].compact
98
97
  @authorization_uri = fdata[:auth_uri] || fdata["auth_uri"]
99
98
  @authorization_uri ||= fdata[:authorization_uri]
100
99
  @token_credential_uri = fdata[:token_uri] || fdata["token_uri"]
@@ -121,7 +120,11 @@ module Google
121
120
  # @return [String]
122
121
  # JSON
123
122
  def to_json
124
- return MultiJson.dump({
123
+ return MultiJson.dump(to_hash)
124
+ end
125
+
126
+ def to_hash
127
+ {
125
128
  self.flow => ({
126
129
  'client_id' => self.client_id,
127
130
  'client_secret' => self.client_secret,
@@ -142,7 +145,7 @@ module Google
142
145
  end
143
146
  accu
144
147
  end
145
- })
148
+ }
146
149
  end
147
150
 
148
151
  def to_authorization
@@ -15,7 +15,7 @@
15
15
 
16
16
  require 'addressable/uri'
17
17
  require 'multi_json'
18
- require 'google/inflection'
18
+ require 'active_support/inflector'
19
19
  require 'google/api_client/discovery/resource'
20
20
  require 'google/api_client/discovery/method'
21
21
  require 'google/api_client/discovery/media'
@@ -41,13 +41,13 @@ module Google
41
41
  @discovery_document = discovery_document
42
42
  metaclass = (class << self; self; end)
43
43
  self.discovered_resources.each do |resource|
44
- method_name = Google::INFLECTOR.underscore(resource.name).to_sym
44
+ method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
45
45
  if !self.respond_to?(method_name)
46
46
  metaclass.send(:define_method, method_name) { resource }
47
47
  end
48
48
  end
49
49
  self.discovered_methods.each do |method|
50
- method_name = Google::INFLECTOR.underscore(method.name).to_sym
50
+ method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
51
51
  if !self.respond_to?(method_name)
52
52
  metaclass.send(:define_method, method_name) { method }
53
53
  end
@@ -15,7 +15,7 @@
15
15
 
16
16
  require 'addressable/uri'
17
17
 
18
- require 'google/inflection'
18
+ require 'active_support/inflector'
19
19
  require 'google/api_client/discovery/method'
20
20
 
21
21
 
@@ -45,13 +45,13 @@ module Google
45
45
  @discovery_document = discovery_document
46
46
  metaclass = (class <<self; self; end)
47
47
  self.discovered_resources.each do |resource|
48
- method_name = Google::INFLECTOR.underscore(resource.name).to_sym
48
+ method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
49
49
  if !self.respond_to?(method_name)
50
50
  metaclass.send(:define_method, method_name) { resource }
51
51
  end
52
52
  end
53
53
  self.discovered_methods.each do |method|
54
- method_name = Google::INFLECTOR.underscore(method.name).to_sym
54
+ method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
55
55
  if !self.respond_to?(method_name)
56
56
  metaclass.send(:define_method, method_name) { method }
57
57
  end
@@ -21,7 +21,7 @@ require 'autoparse'
21
21
  require 'addressable/uri'
22
22
  require 'addressable/template'
23
23
 
24
- require 'google/inflection'
24
+ require 'active_support/inflector'
25
25
  require 'google/api_client/errors'
26
26
 
27
27
 
@@ -78,10 +78,8 @@ module Google
78
78
  # puts schema_data.inspect
79
79
 
80
80
  if schema_name
81
- api_name_string =
82
- Google::INFLECTOR.camelize(api.name)
83
- api_version_string =
84
- Google::INFLECTOR.camelize(api.version).gsub('.', '_')
81
+ api_name_string = ActiveSupport::Inflector.camelize(api.name)
82
+ api_version_string = ActiveSupport::Inflector.camelize(api.version).gsub('.', '_')
85
83
  # This is for compatibility with Ruby 1.8.7.
86
84
  # TODO(bobaman) Remove this when we eventually stop supporting 1.8.7.
87
85
  args = []