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.
- checksums.yaml +13 -5
- data/CHANGELOG.md +14 -0
- data/Gemfile +0 -36
- data/README.md +12 -1
- data/Rakefile +1 -8
- data/google-api-client.gemspec +40 -0
- data/lib/google/api_client.rb +98 -30
- data/lib/google/api_client/auth/compute_service_account.rb +1 -1
- data/lib/google/api_client/auth/file_storage.rb +19 -44
- data/lib/google/api_client/auth/installed_app.rb +11 -7
- data/lib/google/api_client/auth/storage.rb +101 -0
- data/lib/google/api_client/auth/storages/file_store.rb +58 -0
- data/lib/google/api_client/auth/storages/redis_store.rb +54 -0
- data/lib/google/api_client/batch.rb +13 -11
- data/lib/google/api_client/charset.rb +33 -0
- data/lib/google/api_client/client_secrets.rb +9 -6
- data/lib/google/api_client/discovery/api.rb +3 -3
- data/lib/google/api_client/discovery/resource.rb +3 -3
- data/lib/google/api_client/discovery/schema.rb +3 -5
- data/lib/google/api_client/errors.rb +5 -0
- data/lib/google/api_client/railtie.rb +2 -1
- data/lib/google/api_client/request.rb +1 -2
- data/lib/google/api_client/result.rb +4 -2
- data/lib/google/api_client/service.rb +2 -2
- data/lib/google/api_client/service/batch.rb +7 -0
- data/lib/google/api_client/service/stub_generator.rb +4 -2
- data/lib/google/api_client/service_account.rb +3 -0
- data/lib/google/api_client/version.rb +8 -13
- data/spec/google/api_client/auth/storage_spec.rb +122 -0
- data/spec/google/api_client/auth/storages/file_store_spec.rb +40 -0
- data/spec/google/api_client/auth/storages/redis_store_spec.rb +70 -0
- data/spec/google/api_client/batch_spec.rb +29 -30
- data/spec/google/api_client/client_secrets_spec.rb +53 -0
- data/spec/google/api_client/discovery_spec.rb +101 -91
- data/spec/google/api_client/gzip_spec.rb +21 -9
- data/spec/google/api_client/media_spec.rb +31 -32
- data/spec/google/api_client/request_spec.rb +3 -4
- data/spec/google/api_client/result_spec.rb +51 -47
- data/spec/google/api_client/service_account_spec.rb +40 -35
- data/spec/google/api_client/service_spec.rb +144 -112
- data/spec/google/api_client/simple_file_store_spec.rb +30 -34
- data/spec/google/api_client_spec.rb +139 -40
- data/spec/spec_helper.rb +9 -1
- metadata +111 -88
- data/CONTRIBUTING.md +0 -32
- data/lib/cacerts.pem +0 -2183
- data/lib/google/inflection.rb +0 -28
- data/spec/fixtures/files/privatekey.p12 +0 -0
- data/spec/fixtures/files/sample.txt +0 -33
- data/spec/fixtures/files/secret.pem +0 -19
- data/tasks/gem.rake +0 -97
- data/tasks/git.rake +0 -45
- data/tasks/metrics.rake +0 -22
- data/tasks/spec.rake +0 -57
- data/tasks/wiki.rake +0 -82
- 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
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
106
|
+
end
|
106
107
|
|
107
|
-
|
108
|
-
|
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 '
|
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
|
-
|
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
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
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.
|
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 '
|
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 =
|
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 =
|
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 '
|
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 =
|
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 =
|
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 '
|
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
|
-
|
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 = []
|