google-apis-core 0.1.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.
- checksums.yaml +7 -0
- data/.yardopts +12 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.md +202 -0
- data/OVERVIEW.md +22 -0
- data/lib/google/api_client/auth/installed_app.rb +143 -0
- data/lib/google/api_client/auth/key_utils.rb +94 -0
- data/lib/google/api_client/auth/storage.rb +104 -0
- data/lib/google/api_client/auth/storages/file_store.rb +57 -0
- data/lib/google/api_client/auth/storages/redis_store.rb +59 -0
- data/lib/google/api_client/client_secrets.rb +176 -0
- data/lib/google/apis.rb +81 -0
- data/lib/google/apis/core.rb +20 -0
- data/lib/google/apis/core/api_command.rb +224 -0
- data/lib/google/apis/core/base_service.rb +459 -0
- data/lib/google/apis/core/batch.rb +236 -0
- data/lib/google/apis/core/composite_io.rb +97 -0
- data/lib/google/apis/core/download.rb +118 -0
- data/lib/google/apis/core/hashable.rb +44 -0
- data/lib/google/apis/core/http_command.rb +447 -0
- data/lib/google/apis/core/json_representation.rb +153 -0
- data/lib/google/apis/core/logging.rb +30 -0
- data/lib/google/apis/core/multipart.rb +135 -0
- data/lib/google/apis/core/upload.rb +273 -0
- data/lib/google/apis/core/version.rb +22 -0
- data/lib/google/apis/errors.rb +89 -0
- data/lib/google/apis/options.rb +116 -0
- metadata +202 -0
@@ -0,0 +1,104 @@
|
|
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
|
+
# @deprecated Use google-auth-library-ruby instead
|
25
|
+
class Storage
|
26
|
+
|
27
|
+
AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'
|
28
|
+
TOKEN_CREDENTIAL_URI = 'https://accounts.google.com/o/oauth2/token'
|
29
|
+
|
30
|
+
# @return [Object] Storage object.
|
31
|
+
attr_accessor :store
|
32
|
+
|
33
|
+
# @return [Signet::OAuth2::Client]
|
34
|
+
attr_reader :authorization
|
35
|
+
|
36
|
+
##
|
37
|
+
# Initializes the Storage object.
|
38
|
+
#
|
39
|
+
# @param [Object] store
|
40
|
+
# Storage object
|
41
|
+
def initialize(store)
|
42
|
+
@store= store
|
43
|
+
@authorization = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Write the credentials to the specified store.
|
48
|
+
#
|
49
|
+
# @param [Signet::OAuth2::Client] authorization
|
50
|
+
# Optional authorization instance. If not provided, the authorization
|
51
|
+
# already associated with this instance will be written.
|
52
|
+
def write_credentials(authorization=nil)
|
53
|
+
@authorization = authorization if authorization
|
54
|
+
if @authorization.respond_to?(:refresh_token) && @authorization.refresh_token
|
55
|
+
store.write_credentials(credentials_hash)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Loads credentials and authorizes an client.
|
61
|
+
# @return [Object] Signet::OAuth2::Client or NIL
|
62
|
+
def authorize
|
63
|
+
@authorization = nil
|
64
|
+
cached_credentials = load_credentials
|
65
|
+
if cached_credentials && cached_credentials.size > 0
|
66
|
+
@authorization = Signet::OAuth2::Client.new(cached_credentials)
|
67
|
+
@authorization.issued_at = Time.at(cached_credentials['issued_at'].to_i)
|
68
|
+
self.refresh_authorization if @authorization.expired?
|
69
|
+
end
|
70
|
+
return @authorization
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# refresh credentials and save them to store
|
75
|
+
def refresh_authorization
|
76
|
+
authorization.refresh!
|
77
|
+
self.write_credentials
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
##
|
83
|
+
# Attempt to read in credentials from the specified store.
|
84
|
+
def load_credentials
|
85
|
+
store.load_credentials
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# @return [Hash] with credentials
|
90
|
+
def credentials_hash
|
91
|
+
{
|
92
|
+
:access_token => authorization.access_token,
|
93
|
+
:authorization_uri => AUTHORIZATION_URI,
|
94
|
+
:client_id => authorization.client_id,
|
95
|
+
:client_secret => authorization.client_secret,
|
96
|
+
:expires_in => authorization.expires_in,
|
97
|
+
:refresh_token => authorization.refresh_token,
|
98
|
+
:token_credential_uri => TOKEN_CREDENTIAL_URI,
|
99
|
+
:issued_at => authorization.issued_at.to_i
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,57 @@
|
|
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
|
+
# @deprecated Use google-auth-library-ruby instead
|
25
|
+
class FileStore
|
26
|
+
|
27
|
+
attr_accessor :path
|
28
|
+
|
29
|
+
##
|
30
|
+
# Initializes the FileStorage object.
|
31
|
+
#
|
32
|
+
# @param [String] path
|
33
|
+
# Path to the credentials file.
|
34
|
+
def initialize(path)
|
35
|
+
@path= path
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Attempt to read in credentials from the specified file.
|
40
|
+
def load_credentials
|
41
|
+
open(path, 'r') { |f| JSON.parse(f.read) }
|
42
|
+
rescue
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Write the credentials to the specified file.
|
48
|
+
#
|
49
|
+
# @param [Hash] credentials_hash
|
50
|
+
def write_credentials(credentials_hash)
|
51
|
+
open(self.path, 'w+') do |f|
|
52
|
+
f.write(credentials_hash.to_json)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,59 @@
|
|
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
|
+
# @deprecated Use google-auth-library-ruby instead
|
20
|
+
class RedisStore
|
21
|
+
|
22
|
+
DEFAULT_REDIS_CREDENTIALS_KEY = "google_api_credentials"
|
23
|
+
|
24
|
+
attr_accessor :redis
|
25
|
+
|
26
|
+
##
|
27
|
+
# Initializes the RedisStore object.
|
28
|
+
#
|
29
|
+
# @param [Object] redis
|
30
|
+
# Redis instance
|
31
|
+
# @param [Object] key
|
32
|
+
# Optional key to store credentials under. Defaults to 'google_api_credentials'
|
33
|
+
def initialize(redis, key = nil)
|
34
|
+
@redis= redis
|
35
|
+
@redis_credentials_key = key
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Attempt to read in credentials from redis.
|
40
|
+
# @return [Hash]
|
41
|
+
def load_credentials
|
42
|
+
credentials = redis.get redis_credentials_key
|
43
|
+
JSON.parse(credentials) if credentials
|
44
|
+
end
|
45
|
+
|
46
|
+
def redis_credentials_key
|
47
|
+
@redis_credentials_key || DEFAULT_REDIS_CREDENTIALS_KEY
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Write the credentials to redis.
|
52
|
+
#
|
53
|
+
# @param [Hash] credentials_hash
|
54
|
+
def write_credentials(credentials_hash)
|
55
|
+
redis.set(redis_credentials_key, credentials_hash.to_json)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,176 @@
|
|
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
|
+
require 'json'
|
16
|
+
require 'googleauth'
|
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
|
+
# @deprecated Use google-auth-library-ruby instead
|
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
|
+
# Reads client configuration from a file
|
51
|
+
#
|
52
|
+
# @param [String] filename
|
53
|
+
# Path to file to load
|
54
|
+
#
|
55
|
+
# @return [Google::APIClient::ClientSecrets]
|
56
|
+
# OAuth client settings
|
57
|
+
def self.load(filename=nil)
|
58
|
+
if filename && File.directory?(filename)
|
59
|
+
search_path = File.expand_path(filename)
|
60
|
+
filename = nil
|
61
|
+
end
|
62
|
+
while filename == nil
|
63
|
+
search_path ||= File.expand_path('.')
|
64
|
+
if File.exists?(File.join(search_path, 'client_secrets.json'))
|
65
|
+
filename = File.join(search_path, 'client_secrets.json')
|
66
|
+
elsif search_path == File.expand_path('..', search_path)
|
67
|
+
raise ArgumentError,
|
68
|
+
'No client_secrets.json filename supplied ' +
|
69
|
+
'and/or could not be found in search path.'
|
70
|
+
else
|
71
|
+
search_path = File.expand_path(File.join(search_path, '..'))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
data = File.open(filename, 'r') { |file| JSON.load(file.read) }
|
75
|
+
return self.new(data)
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Initialize OAuth client settings.
|
80
|
+
#
|
81
|
+
# @param [Hash] options
|
82
|
+
# Parsed client secrets files
|
83
|
+
def initialize(options={})
|
84
|
+
# Client auth configuration
|
85
|
+
@flow = options[:flow] || options.keys.first.to_s || 'web'
|
86
|
+
fdata = options[@flow.to_sym] || options[@flow]
|
87
|
+
@client_id = fdata[:client_id] || fdata["client_id"]
|
88
|
+
@client_secret = fdata[:client_secret] || fdata["client_secret"]
|
89
|
+
@redirect_uris = fdata[:redirect_uris] || fdata["redirect_uris"]
|
90
|
+
@redirect_uris ||= [fdata[:redirect_uri] || fdata["redirect_uri"]].compact
|
91
|
+
@javascript_origins = (
|
92
|
+
fdata[:javascript_origins] ||
|
93
|
+
fdata["javascript_origins"]
|
94
|
+
)
|
95
|
+
@javascript_origins ||= [fdata[:javascript_origin] || fdata["javascript_origin"]].compact
|
96
|
+
@authorization_uri = fdata[:auth_uri] || fdata["auth_uri"]
|
97
|
+
@authorization_uri ||= fdata[:authorization_uri]
|
98
|
+
@token_credential_uri = fdata[:token_uri] || fdata["token_uri"]
|
99
|
+
@token_credential_uri ||= fdata[:token_credential_uri]
|
100
|
+
|
101
|
+
# Associated token info
|
102
|
+
@access_token = fdata[:access_token] || fdata["access_token"]
|
103
|
+
@refresh_token = fdata[:refresh_token] || fdata["refresh_token"]
|
104
|
+
@id_token = fdata[:id_token] || fdata["id_token"]
|
105
|
+
@expires_in = fdata[:expires_in] || fdata["expires_in"]
|
106
|
+
@expires_at = fdata[:expires_at] || fdata["expires_at"]
|
107
|
+
@issued_at = fdata[:issued_at] || fdata["issued_at"]
|
108
|
+
end
|
109
|
+
|
110
|
+
attr_reader(
|
111
|
+
:flow, :client_id, :client_secret, :redirect_uris, :javascript_origins,
|
112
|
+
:authorization_uri, :token_credential_uri, :access_token,
|
113
|
+
:refresh_token, :id_token, :expires_in, :expires_at, :issued_at
|
114
|
+
)
|
115
|
+
|
116
|
+
##
|
117
|
+
# Serialize back to the original JSON form
|
118
|
+
#
|
119
|
+
# @return [String]
|
120
|
+
# JSON
|
121
|
+
def to_json
|
122
|
+
return Json.dump(to_hash)
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_hash
|
126
|
+
{
|
127
|
+
self.flow => ({
|
128
|
+
'client_id' => self.client_id,
|
129
|
+
'client_secret' => self.client_secret,
|
130
|
+
'redirect_uris' => self.redirect_uris,
|
131
|
+
'javascript_origins' => self.javascript_origins,
|
132
|
+
'auth_uri' => self.authorization_uri,
|
133
|
+
'token_uri' => self.token_credential_uri,
|
134
|
+
'access_token' => self.access_token,
|
135
|
+
'refresh_token' => self.refresh_token,
|
136
|
+
'id_token' => self.id_token,
|
137
|
+
'expires_in' => self.expires_in,
|
138
|
+
'expires_at' => self.expires_at,
|
139
|
+
'issued_at' => self.issued_at
|
140
|
+
}).inject({}) do |accu, (k, v)|
|
141
|
+
# Prunes empty values from JSON output.
|
142
|
+
unless v == nil || (v.respond_to?(:empty?) && v.empty?)
|
143
|
+
accu[k] = v
|
144
|
+
end
|
145
|
+
accu
|
146
|
+
end
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def to_authorization
|
151
|
+
# NOTE: Do not rely on this default value, as it may change
|
152
|
+
new_authorization = Signet::OAuth2::Client.new
|
153
|
+
new_authorization.client_id = self.client_id
|
154
|
+
new_authorization.client_secret = self.client_secret
|
155
|
+
new_authorization.authorization_uri = (
|
156
|
+
self.authorization_uri ||
|
157
|
+
'https://accounts.google.com/o/oauth2/auth'
|
158
|
+
)
|
159
|
+
new_authorization.token_credential_uri = (
|
160
|
+
self.token_credential_uri ||
|
161
|
+
'https://accounts.google.com/o/oauth2/token'
|
162
|
+
)
|
163
|
+
new_authorization.redirect_uri = self.redirect_uris.first
|
164
|
+
|
165
|
+
# These are supported, but unlikely.
|
166
|
+
new_authorization.access_token = self.access_token
|
167
|
+
new_authorization.refresh_token = self.refresh_token
|
168
|
+
new_authorization.id_token = self.id_token
|
169
|
+
new_authorization.expires_in = self.expires_in
|
170
|
+
new_authorization.issued_at = self.issued_at if self.issued_at
|
171
|
+
new_authorization.expires_at = self.expires_at if self.expires_at
|
172
|
+
return new_authorization
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
data/lib/google/apis.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Copyright 2020 Google LLC
|
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 'google/apis/core/version'
|
16
|
+
require 'logger'
|
17
|
+
require 'open3'
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Apis
|
21
|
+
ROOT = File.expand_path('..', File.dirname(__dir__))
|
22
|
+
|
23
|
+
# Current operating system
|
24
|
+
# @private
|
25
|
+
OS_VERSION = begin
|
26
|
+
if RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/
|
27
|
+
output, _ = Open3.capture2('ver')
|
28
|
+
output.sub(/\s*\[Version\s*/, '/').sub(']', '')
|
29
|
+
elsif RUBY_PLATFORM =~ /darwin/i
|
30
|
+
output, _ = Open3.capture2('sw_vers', '-productVersion')
|
31
|
+
"Mac OS X/#{output}"
|
32
|
+
elsif RUBY_PLATFORM == 'java'
|
33
|
+
require 'java'
|
34
|
+
name = java.lang.System.getProperty('os.name')
|
35
|
+
version = java.lang.System.getProperty('os.version')
|
36
|
+
"#{name}/#{version}"
|
37
|
+
else
|
38
|
+
output, _ = Open3.capture2('uname', '-sr')
|
39
|
+
output.sub(' ', '/')
|
40
|
+
end.strip
|
41
|
+
rescue
|
42
|
+
RUBY_PLATFORM
|
43
|
+
end
|
44
|
+
|
45
|
+
# @!attribute [rw] logger
|
46
|
+
# @return [Logger] The logger.
|
47
|
+
def self.logger
|
48
|
+
@logger ||= rails_logger || default_logger
|
49
|
+
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
attr_writer :logger
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Create and configure a logger
|
58
|
+
# @return [Logger]
|
59
|
+
def self.default_logger
|
60
|
+
logger = Logger.new($stdout)
|
61
|
+
logger.level = Logger::WARN
|
62
|
+
logger
|
63
|
+
end
|
64
|
+
|
65
|
+
# Check to see if client is being used in a Rails environment and get the logger if present.
|
66
|
+
# Setting the ENV variable 'GOOGLE_API_USE_RAILS_LOGGER' to false will force the client
|
67
|
+
# to use its own logger.
|
68
|
+
#
|
69
|
+
# @return [Logger]
|
70
|
+
def self.rails_logger
|
71
|
+
if 'true' == ENV.fetch('GOOGLE_API_USE_RAILS_LOGGER', 'true') &&
|
72
|
+
defined?(::Rails) &&
|
73
|
+
::Rails.respond_to?(:logger) &&
|
74
|
+
!::Rails.logger.nil?
|
75
|
+
::Rails.logger
|
76
|
+
else
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|