cure-google-api-client 0.8.7.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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +178 -0
  3. data/Gemfile +9 -0
  4. data/LICENSE +202 -0
  5. data/README.md +218 -0
  6. data/Rakefile +41 -0
  7. data/google-api-client.gemspec +43 -0
  8. data/lib/cacerts.pem +2183 -0
  9. data/lib/compat/multi_json.rb +19 -0
  10. data/lib/google/api_client.rb +750 -0
  11. data/lib/google/api_client/auth/compute_service_account.rb +28 -0
  12. data/lib/google/api_client/auth/file_storage.rb +59 -0
  13. data/lib/google/api_client/auth/installed_app.rb +126 -0
  14. data/lib/google/api_client/auth/jwt_asserter.rb +126 -0
  15. data/lib/google/api_client/auth/key_utils.rb +93 -0
  16. data/lib/google/api_client/auth/pkcs12.rb +41 -0
  17. data/lib/google/api_client/auth/storage.rb +102 -0
  18. data/lib/google/api_client/auth/storages/file_store.rb +58 -0
  19. data/lib/google/api_client/auth/storages/redis_store.rb +54 -0
  20. data/lib/google/api_client/batch.rb +326 -0
  21. data/lib/google/api_client/charset.rb +33 -0
  22. data/lib/google/api_client/client_secrets.rb +179 -0
  23. data/lib/google/api_client/discovery.rb +19 -0
  24. data/lib/google/api_client/discovery/api.rb +310 -0
  25. data/lib/google/api_client/discovery/media.rb +77 -0
  26. data/lib/google/api_client/discovery/method.rb +363 -0
  27. data/lib/google/api_client/discovery/resource.rb +156 -0
  28. data/lib/google/api_client/discovery/schema.rb +117 -0
  29. data/lib/google/api_client/environment.rb +42 -0
  30. data/lib/google/api_client/errors.rb +65 -0
  31. data/lib/google/api_client/gzip.rb +28 -0
  32. data/lib/google/api_client/logging.rb +32 -0
  33. data/lib/google/api_client/media.rb +259 -0
  34. data/lib/google/api_client/railtie.rb +18 -0
  35. data/lib/google/api_client/reference.rb +27 -0
  36. data/lib/google/api_client/request.rb +350 -0
  37. data/lib/google/api_client/result.rb +255 -0
  38. data/lib/google/api_client/service.rb +233 -0
  39. data/lib/google/api_client/service/batch.rb +110 -0
  40. data/lib/google/api_client/service/request.rb +144 -0
  41. data/lib/google/api_client/service/resource.rb +40 -0
  42. data/lib/google/api_client/service/result.rb +162 -0
  43. data/lib/google/api_client/service/simple_file_store.rb +151 -0
  44. data/lib/google/api_client/service/stub_generator.rb +61 -0
  45. data/lib/google/api_client/service_account.rb +21 -0
  46. data/lib/google/api_client/version.rb +26 -0
  47. data/spec/google/api_client/auth/storage_spec.rb +122 -0
  48. data/spec/google/api_client/auth/storages/file_store_spec.rb +40 -0
  49. data/spec/google/api_client/auth/storages/redis_store_spec.rb +70 -0
  50. data/spec/google/api_client/batch_spec.rb +248 -0
  51. data/spec/google/api_client/client_secrets_spec.rb +53 -0
  52. data/spec/google/api_client/discovery_spec.rb +708 -0
  53. data/spec/google/api_client/gzip_spec.rb +98 -0
  54. data/spec/google/api_client/media_spec.rb +178 -0
  55. data/spec/google/api_client/request_spec.rb +29 -0
  56. data/spec/google/api_client/result_spec.rb +207 -0
  57. data/spec/google/api_client/service_account_spec.rb +169 -0
  58. data/spec/google/api_client/service_spec.rb +618 -0
  59. data/spec/google/api_client/simple_file_store_spec.rb +133 -0
  60. data/spec/google/api_client_spec.rb +352 -0
  61. data/spec/spec_helper.rb +66 -0
  62. metadata +339 -0
@@ -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
@@ -0,0 +1,179 @@
1
+ # Copyright 2010 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
+
16
+ require 'compat/multi_json'
17
+
18
+
19
+ module Google
20
+ class APIClient
21
+ ##
22
+ # Manages the persistence of client configuration data and secrets. Format
23
+ # inspired by the Google API Python client.
24
+ #
25
+ # @see https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
26
+ #
27
+ # @example
28
+ # {
29
+ # "web": {
30
+ # "client_id": "asdfjasdljfasdkjf",
31
+ # "client_secret": "1912308409123890",
32
+ # "redirect_uris": ["https://www.example.com/oauth2callback"],
33
+ # "auth_uri": "https://accounts.google.com/o/oauth2/auth",
34
+ # "token_uri": "https://accounts.google.com/o/oauth2/token"
35
+ # }
36
+ # }
37
+ #
38
+ # @example
39
+ # {
40
+ # "installed": {
41
+ # "client_id": "837647042410-75ifg...usercontent.com",
42
+ # "client_secret":"asdlkfjaskd",
43
+ # "redirect_uris": ["http://localhost", "urn:ietf:oauth:2.0:oob"],
44
+ # "auth_uri": "https://accounts.google.com/o/oauth2/auth",
45
+ # "token_uri": "https://accounts.google.com/o/oauth2/token"
46
+ # }
47
+ # }
48
+ class ClientSecrets
49
+
50
+ ##
51
+ # Reads client configuration from a file
52
+ #
53
+ # @param [String] filename
54
+ # Path to file to load
55
+ #
56
+ # @return [Google::APIClient::ClientSecrets]
57
+ # OAuth client settings
58
+ def self.load(filename=nil)
59
+ if filename && File.directory?(filename)
60
+ search_path = File.expand_path(filename)
61
+ filename = nil
62
+ end
63
+ while filename == nil
64
+ search_path ||= File.expand_path('.')
65
+ if File.exists?(File.join(search_path, 'client_secrets.json'))
66
+ filename = File.join(search_path, 'client_secrets.json')
67
+ elsif search_path == '/' || search_path =~ /[a-zA-Z]:[\/\\]/
68
+ raise ArgumentError,
69
+ 'No client_secrets.json filename supplied ' +
70
+ 'and/or could not be found in search path.'
71
+ else
72
+ search_path = File.expand_path(File.join(search_path, '..'))
73
+ end
74
+ end
75
+ data = File.open(filename, 'r') { |file| MultiJson.load(file.read) }
76
+ return self.new(data)
77
+ end
78
+
79
+ ##
80
+ # Intialize OAuth client settings.
81
+ #
82
+ # @param [Hash] options
83
+ # Parsed client secrets files
84
+ def initialize(options={})
85
+ # Client auth configuration
86
+ @flow = options[:flow] || options.keys.first.to_s || 'web'
87
+ fdata = options[@flow]
88
+ @client_id = fdata[:client_id] || fdata["client_id"]
89
+ @client_secret = fdata[:client_secret] || fdata["client_secret"]
90
+ @redirect_uris = fdata[:redirect_uris] || fdata["redirect_uris"]
91
+ @redirect_uris ||= [fdata[:redirect_uri] || fdata["redirect_uri"]].compact
92
+ @javascript_origins = (
93
+ fdata[:javascript_origins] ||
94
+ fdata["javascript_origins"]
95
+ )
96
+ @javascript_origins ||= [fdata[:javascript_origin] || fdata["javascript_origin"]].compact
97
+ @authorization_uri = fdata[:auth_uri] || fdata["auth_uri"]
98
+ @authorization_uri ||= fdata[:authorization_uri]
99
+ @token_credential_uri = fdata[:token_uri] || fdata["token_uri"]
100
+ @token_credential_uri ||= fdata[:token_credential_uri]
101
+
102
+ # Associated token info
103
+ @access_token = fdata[:access_token] || fdata["access_token"]
104
+ @refresh_token = fdata[:refresh_token] || fdata["refresh_token"]
105
+ @id_token = fdata[:id_token] || fdata["id_token"]
106
+ @expires_in = fdata[:expires_in] || fdata["expires_in"]
107
+ @expires_at = fdata[:expires_at] || fdata["expires_at"]
108
+ @issued_at = fdata[:issued_at] || fdata["issued_at"]
109
+ end
110
+
111
+ attr_reader(
112
+ :flow, :client_id, :client_secret, :redirect_uris, :javascript_origins,
113
+ :authorization_uri, :token_credential_uri, :access_token,
114
+ :refresh_token, :id_token, :expires_in, :expires_at, :issued_at
115
+ )
116
+
117
+ ##
118
+ # Serialize back to the original JSON form
119
+ #
120
+ # @return [String]
121
+ # JSON
122
+ def to_json
123
+ return MultiJson.dump(to_hash)
124
+ end
125
+
126
+ def to_hash
127
+ {
128
+ self.flow => ({
129
+ 'client_id' => self.client_id,
130
+ 'client_secret' => self.client_secret,
131
+ 'redirect_uris' => self.redirect_uris,
132
+ 'javascript_origins' => self.javascript_origins,
133
+ 'auth_uri' => self.authorization_uri,
134
+ 'token_uri' => self.token_credential_uri,
135
+ 'access_token' => self.access_token,
136
+ 'refresh_token' => self.refresh_token,
137
+ 'id_token' => self.id_token,
138
+ 'expires_in' => self.expires_in,
139
+ 'expires_at' => self.expires_at,
140
+ 'issued_at' => self.issued_at
141
+ }).inject({}) do |accu, (k, v)|
142
+ # Prunes empty values from JSON output.
143
+ unless v == nil || (v.respond_to?(:empty?) && v.empty?)
144
+ accu[k] = v
145
+ end
146
+ accu
147
+ end
148
+ }
149
+ end
150
+
151
+ def to_authorization
152
+ gem 'signet', '>= 0.4.0'
153
+ require 'signet/oauth_2/client'
154
+ # NOTE: Do not rely on this default value, as it may change
155
+ new_authorization = Signet::OAuth2::Client.new
156
+ new_authorization.client_id = self.client_id
157
+ new_authorization.client_secret = self.client_secret
158
+ new_authorization.authorization_uri = (
159
+ self.authorization_uri ||
160
+ 'https://accounts.google.com/o/oauth2/auth'
161
+ )
162
+ new_authorization.token_credential_uri = (
163
+ self.token_credential_uri ||
164
+ 'https://accounts.google.com/o/oauth2/token'
165
+ )
166
+ new_authorization.redirect_uri = self.redirect_uris.first
167
+
168
+ # These are supported, but unlikely.
169
+ new_authorization.access_token = self.access_token
170
+ new_authorization.refresh_token = self.refresh_token
171
+ new_authorization.id_token = self.id_token
172
+ new_authorization.expires_in = self.expires_in
173
+ new_authorization.issued_at = self.issued_at if self.issued_at
174
+ new_authorization.expires_at = self.expires_at if self.expires_at
175
+ return new_authorization
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,19 @@
1
+ # Copyright 2010 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
+
16
+ require 'google/api_client/discovery/api'
17
+ require 'google/api_client/discovery/resource'
18
+ require 'google/api_client/discovery/method'
19
+ require 'google/api_client/discovery/schema'
@@ -0,0 +1,310 @@
1
+ # Copyright 2010 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
+
16
+ require 'addressable/uri'
17
+ require 'multi_json'
18
+ require 'active_support/inflector'
19
+ require 'google/api_client/discovery/resource'
20
+ require 'google/api_client/discovery/method'
21
+ require 'google/api_client/discovery/media'
22
+
23
+ module Google
24
+ class APIClient
25
+ ##
26
+ # A service that has been described by a discovery document.
27
+ class API
28
+
29
+ ##
30
+ # Creates a description of a particular version of a service.
31
+ #
32
+ # @param [String] document_base
33
+ # Base URI for the discovery document.
34
+ # @param [Hash] discovery_document
35
+ # The section of the discovery document that applies to this service
36
+ # version.
37
+ #
38
+ # @return [Google::APIClient::API] The constructed service object.
39
+ def initialize(document_base, discovery_document)
40
+ @document_base = Addressable::URI.parse(document_base)
41
+ @discovery_document = discovery_document
42
+ metaclass = (class << self; self; end)
43
+ self.discovered_resources.each do |resource|
44
+ method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
45
+ if !self.respond_to?(method_name)
46
+ metaclass.send(:define_method, method_name) { resource }
47
+ end
48
+ end
49
+ self.discovered_methods.each do |method|
50
+ method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
51
+ if !self.respond_to?(method_name)
52
+ metaclass.send(:define_method, method_name) { method }
53
+ end
54
+ end
55
+ end
56
+
57
+ # @return [String] unparsed discovery document for the API
58
+ attr_reader :discovery_document
59
+
60
+ ##
61
+ # Returns the id of the service.
62
+ #
63
+ # @return [String] The service id.
64
+ def id
65
+ return (
66
+ @discovery_document['id'] ||
67
+ "#{self.name}:#{self.version}"
68
+ )
69
+ end
70
+
71
+ ##
72
+ # Returns the identifier for the service.
73
+ #
74
+ # @return [String] The service identifier.
75
+ def name
76
+ return @discovery_document['name']
77
+ end
78
+
79
+ ##
80
+ # Returns the version of the service.
81
+ #
82
+ # @return [String] The service version.
83
+ def version
84
+ return @discovery_document['version']
85
+ end
86
+
87
+ ##
88
+ # Returns a human-readable title for the API.
89
+ #
90
+ # @return [Hash] The API title.
91
+ def title
92
+ return @discovery_document['title']
93
+ end
94
+
95
+ ##
96
+ # Returns a human-readable description of the API.
97
+ #
98
+ # @return [Hash] The API description.
99
+ def description
100
+ return @discovery_document['description']
101
+ end
102
+
103
+ ##
104
+ # Returns a URI for the API documentation.
105
+ #
106
+ # @return [Hash] The API documentation.
107
+ def documentation
108
+ return Addressable::URI.parse(@discovery_document['documentationLink'])
109
+ end
110
+
111
+ ##
112
+ # Returns true if this is the preferred version of this API.
113
+ #
114
+ # @return [TrueClass, FalseClass]
115
+ # Whether or not this is the preferred version of this API.
116
+ def preferred
117
+ return !!@discovery_document['preferred']
118
+ end
119
+
120
+ ##
121
+ # Returns the list of API features.
122
+ #
123
+ # @return [Array]
124
+ # The features supported by this API.
125
+ def features
126
+ return @discovery_document['features'] || []
127
+ end
128
+
129
+ ##
130
+ # Returns the root URI for this service.
131
+ #
132
+ # @return [Addressable::URI] The root URI.
133
+ def root_uri
134
+ return @root_uri ||= (
135
+ Addressable::URI.parse(self.discovery_document['rootUrl'])
136
+ )
137
+ end
138
+
139
+ ##
140
+ # Returns true if this API uses a data wrapper.
141
+ #
142
+ # @return [TrueClass, FalseClass]
143
+ # Whether or not this API uses a data wrapper.
144
+ def data_wrapper?
145
+ return self.features.include?('dataWrapper')
146
+ end
147
+
148
+ ##
149
+ # Returns the base URI for the discovery document.
150
+ #
151
+ # @return [Addressable::URI] The base URI.
152
+ attr_reader :document_base
153
+
154
+ ##
155
+ # Returns the base URI for this version of the service.
156
+ #
157
+ # @return [Addressable::URI] The base URI that methods are joined to.
158
+ def method_base
159
+ if @discovery_document['basePath']
160
+ return @method_base ||= (
161
+ self.root_uri.join(Addressable::URI.parse(@discovery_document['basePath']))
162
+ ).normalize
163
+ else
164
+ return nil
165
+ end
166
+ end
167
+
168
+ ##
169
+ # Updates the hierarchy of resources and methods with the new base.
170
+ #
171
+ # @param [Addressable::URI, #to_str, String] new_method_base
172
+ # The new base URI to use for the service.
173
+ def method_base=(new_method_base)
174
+ @method_base = Addressable::URI.parse(new_method_base)
175
+ self.discovered_resources.each do |resource|
176
+ resource.method_base = @method_base
177
+ end
178
+ self.discovered_methods.each do |method|
179
+ method.method_base = @method_base
180
+ end
181
+ end
182
+
183
+ ##
184
+ # Returns the base URI for batch calls to this service.
185
+ #
186
+ # @return [Addressable::URI] The base URI that methods are joined to.
187
+ def batch_path
188
+ if @discovery_document['batchPath']
189
+ return @batch_path ||= (
190
+ self.document_base.join(Addressable::URI.parse('/' +
191
+ @discovery_document['batchPath']))
192
+ ).normalize
193
+ else
194
+ return nil
195
+ end
196
+ end
197
+
198
+ ##
199
+ # A list of schemas available for this version of the API.
200
+ #
201
+ # @return [Hash] A list of {Google::APIClient::Schema} objects.
202
+ def schemas
203
+ return @schemas ||= (
204
+ (@discovery_document['schemas'] || []).inject({}) do |accu, (k, v)|
205
+ accu[k] = Google::APIClient::Schema.parse(self, v)
206
+ accu
207
+ end
208
+ )
209
+ end
210
+
211
+ ##
212
+ # Returns a schema for a kind value.
213
+ #
214
+ # @return [Google::APIClient::Schema] The associated Schema object.
215
+ def schema_for_kind(kind)
216
+ api_name, schema_name = kind.split('#', 2)
217
+ if api_name != self.name
218
+ raise ArgumentError,
219
+ "The kind does not match this API. " +
220
+ "Expected '#{self.name}', got '#{api_name}'."
221
+ end
222
+ for k, v in self.schemas
223
+ return v if k.downcase == schema_name.downcase
224
+ end
225
+ return nil
226
+ end
227
+
228
+ ##
229
+ # A list of resources available at the root level of this version of the
230
+ # API.
231
+ #
232
+ # @return [Array] A list of {Google::APIClient::Resource} objects.
233
+ def discovered_resources
234
+ return @discovered_resources ||= (
235
+ (@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
236
+ accu << Google::APIClient::Resource.new(
237
+ self, self.method_base, k, v
238
+ )
239
+ accu
240
+ end
241
+ )
242
+ end
243
+
244
+ ##
245
+ # A list of methods available at the root level of this version of the
246
+ # API.
247
+ #
248
+ # @return [Array] A list of {Google::APIClient::Method} objects.
249
+ def discovered_methods
250
+ return @discovered_methods ||= (
251
+ (@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
252
+ accu << Google::APIClient::Method.new(self, self.method_base, k, v)
253
+ accu
254
+ end
255
+ )
256
+ end
257
+
258
+ ##
259
+ # Allows deep inspection of the discovery document.
260
+ def [](key)
261
+ return @discovery_document[key]
262
+ end
263
+
264
+ ##
265
+ # Converts the service to a flat mapping of RPC names and method objects.
266
+ #
267
+ # @return [Hash] All methods available on the service.
268
+ #
269
+ # @example
270
+ # # Discover available methods
271
+ # method_names = client.discovered_api('buzz').to_h.keys
272
+ def to_h
273
+ return @hash ||= (begin
274
+ methods_hash = {}
275
+ self.discovered_methods.each do |method|
276
+ methods_hash[method.id] = method
277
+ end
278
+ self.discovered_resources.each do |resource|
279
+ methods_hash.merge!(resource.to_h)
280
+ end
281
+ methods_hash
282
+ end)
283
+ end
284
+
285
+ ##
286
+ # Returns a <code>String</code> representation of the service's state.
287
+ #
288
+ # @return [String] The service's state, as a <code>String</code>.
289
+ def inspect
290
+ sprintf(
291
+ "#<%s:%#0x ID:%s>", self.class.to_s, self.object_id, self.id
292
+ )
293
+ end
294
+
295
+ ##
296
+ # Marshalling support - serialize the API to a string (doc base + original
297
+ # discovery document).
298
+ def _dump(level)
299
+ MultiJson.dump([@document_base.to_s, @discovery_document])
300
+ end
301
+
302
+ ##
303
+ # Marshalling support - Restore an API instance from serialized form
304
+ def self._load(obj)
305
+ new(*MultiJson.load(obj))
306
+ end
307
+
308
+ end
309
+ end
310
+ end