google-ads-common 0.9.9 → 0.10.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
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODExZjI0NTAwNDdmOWY2NzcxNGMwZmJlNDc1ZTg4YmRkYWVmM2VlMg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YzdhOWY3OGMxMjYxMzJjYTZhY2YwNTMyY2YwZmU4YmVkZjAxMzM5OA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTllZWU2NDdhOWU1YzExNTYxM2ZjNTI5MzA1OTY5NzgwNDBiYzRmMTFiNDQ0
|
10
|
+
NmVhMWQ0NmJiNjY0MjFlNzFmYmRiNjNlYzdhNjgyMjIxN2E5Njc1Zjk3NTVl
|
11
|
+
MTdiMjhkZWQ1YTJjMmQzOTU5YWUwN2U0YjAzNGY5MmYxOWE1N2U=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjZkNTA3MWE0ZTJlY2U2ODM0OGM2MTg2NGIyYzY5ZDE4MDM3NWEzYjM3Yjk5
|
14
|
+
MmM0ODQ3NDdhNjI5MjE2YWQ1ZGFjMDI0NDViMmEwNzdhY2UxOTIwOTNiZjc0
|
15
|
+
ZTIwNjFmOGQ1YWExNTM2OWM4NjAyNmE2MzY1YTI4YWI4NTM3OTc=
|
data/ChangeLog
CHANGED
data/lib/ads_common/api.rb
CHANGED
@@ -25,7 +25,7 @@ require 'ads_common/config'
|
|
25
25
|
require 'ads_common/errors'
|
26
26
|
require 'ads_common/utils'
|
27
27
|
require 'ads_common/auth/oauth2_handler'
|
28
|
-
require 'ads_common/auth/
|
28
|
+
require 'ads_common/auth/oauth2_service_account_handler'
|
29
29
|
|
30
30
|
module AdsCommon
|
31
31
|
class Api
|
@@ -201,10 +201,10 @@ module AdsCommon
|
|
201
201
|
@config,
|
202
202
|
api_config.environment_config(environment, :oauth_scope)
|
203
203
|
)
|
204
|
-
when :
|
204
|
+
when :OAUTH2_SERVICE_ACCOUNT_
|
205
205
|
environment = @config.read('service.environment',
|
206
206
|
api_config.default_environment())
|
207
|
-
AdsCommon::Auth::
|
207
|
+
AdsCommon::Auth::OAuth2ServiceAccountHandler.new(
|
208
208
|
@config,
|
209
209
|
api_config.environment_config(environment, :oauth_scope)
|
210
210
|
)
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# See the License for the specific language governing permissions and
|
18
18
|
# limitations under the License.
|
19
19
|
#
|
20
|
-
# This module manages OAuth2.0
|
20
|
+
# This module manages OAuth2.0 service account authentication.
|
21
21
|
|
22
22
|
require 'faraday'
|
23
23
|
require 'signet/oauth_2/client'
|
@@ -29,7 +29,7 @@ module AdsCommon
|
|
29
29
|
module Auth
|
30
30
|
|
31
31
|
# Credentials class to handle OAuth2.0 authentication.
|
32
|
-
class
|
32
|
+
class OAuth2ServiceAccountHandler < AdsCommon::Auth::BaseHandler
|
33
33
|
|
34
34
|
OAUTH2_CONFIG = {
|
35
35
|
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
|
@@ -60,7 +60,8 @@ module AdsCommon
|
|
60
60
|
raise error
|
61
61
|
end
|
62
62
|
|
63
|
-
# Generates auth string for OAuth2.0
|
63
|
+
# Generates auth string for OAuth2.0 service account method of
|
64
|
+
# authentication.
|
64
65
|
#
|
65
66
|
# Args:
|
66
67
|
# - credentials: credentials set for authorization
|
@@ -91,7 +92,8 @@ module AdsCommon
|
|
91
92
|
|
92
93
|
private
|
93
94
|
|
94
|
-
# Auxiliary method to validate the credentials for
|
95
|
+
# Auxiliary method to validate the credentials for service account
|
96
|
+
# authentication.
|
95
97
|
#
|
96
98
|
# Args:
|
97
99
|
# - credentials: a hash with the credentials for the account being
|
@@ -121,18 +123,18 @@ module AdsCommon
|
|
121
123
|
|
122
124
|
if credentials[:oauth2_key].nil? && credentials[:oauth2_keyfile].nil?
|
123
125
|
raise AdsCommon::Errors::AuthError,
|
124
|
-
'Either key or key file must be provided for OAuth2
|
126
|
+
'Either key or key file must be provided for OAuth2 service account.'
|
125
127
|
end
|
126
128
|
|
127
129
|
if credentials[:oauth2_key] && credentials[:oauth2_keyfile]
|
128
130
|
raise AdsCommon::Errors::AuthError,
|
129
|
-
'Both
|
131
|
+
'Both service account key and key file provided, only one can be used.'
|
130
132
|
end
|
131
133
|
|
132
134
|
if credentials[:oauth2_key] &&
|
133
135
|
!credentials[:oauth2_key].kind_of?(OpenSSL::PKey::RSA)
|
134
136
|
raise AdsCommon::Errors::AuthError,
|
135
|
-
'OAuth2
|
137
|
+
'OAuth2 service account key provided must be of type OpenSSL::PKey::RSA.'
|
136
138
|
end
|
137
139
|
|
138
140
|
if credentials[:oauth2_keyfile] &&
|
@@ -167,7 +169,7 @@ module AdsCommon
|
|
167
169
|
|
168
170
|
# Creates a Signet client based on credentials.
|
169
171
|
def create_client(credentials)
|
170
|
-
credentials =
|
172
|
+
credentials = load_oauth2_service_account_credentials(credentials)
|
171
173
|
oauth_options = OAUTH2_CONFIG.merge({
|
172
174
|
:issuer => credentials[:oauth2_issuer],
|
173
175
|
:signing_key => credentials[:oauth2_key],
|
@@ -177,8 +179,8 @@ module AdsCommon
|
|
177
179
|
return Signet::OAuth2::Client.new(oauth_options)
|
178
180
|
end
|
179
181
|
|
180
|
-
# Loads
|
181
|
-
def
|
182
|
+
# Loads service account key if configured with a filename.
|
183
|
+
def load_oauth2_service_account_credentials(credentials)
|
182
184
|
return credentials unless credentials.include?(:oauth2_keyfile)
|
183
185
|
key_file = File.read(credentials[:oauth2_keyfile])
|
184
186
|
key_secret = credentials[:oauth2_secret]
|
data/lib/ads_common/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-ads-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergio Gomes
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-07-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: savon
|
@@ -66,9 +66,8 @@ files:
|
|
66
66
|
- lib/ads_common/api.rb
|
67
67
|
- lib/ads_common/api_config.rb
|
68
68
|
- lib/ads_common/auth/base_handler.rb
|
69
|
-
- lib/ads_common/auth/client_login_handler.rb
|
70
69
|
- lib/ads_common/auth/oauth2_handler.rb
|
71
|
-
- lib/ads_common/auth/
|
70
|
+
- lib/ads_common/auth/oauth2_service_account_handler.rb
|
72
71
|
- lib/ads_common/build/savon_abstract_generator.rb
|
73
72
|
- lib/ads_common/build/savon_generator.rb
|
74
73
|
- lib/ads_common/build/savon_registry.rb
|
@@ -1,198 +0,0 @@
|
|
1
|
-
# Encoding: utf-8
|
2
|
-
#
|
3
|
-
# Authors:: api.dklimkin@gmail.com (Danial Klimkin)
|
4
|
-
#
|
5
|
-
# Copyright:: Copyright 2010, Google Inc. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# License:: Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
-
# you may not use this file except in compliance with the License.
|
9
|
-
# You may obtain a copy of the License at
|
10
|
-
#
|
11
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
-
#
|
13
|
-
# Unless required by applicable law or agreed to in writing, software
|
14
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
16
|
-
# implied.
|
17
|
-
# See the License for the specific language governing permissions and
|
18
|
-
# limitations under the License.
|
19
|
-
#
|
20
|
-
# This module manages ClientLogin authentication. It either uses a user-provided
|
21
|
-
# auth token, or automatically connects to Google's ClientLogin service and
|
22
|
-
# generates an auth token that can be used to login to an API.
|
23
|
-
|
24
|
-
require 'cgi'
|
25
|
-
require 'ads_common/http'
|
26
|
-
require 'ads_common/auth/base_handler'
|
27
|
-
require 'ads_common/errors'
|
28
|
-
|
29
|
-
module AdsCommon
|
30
|
-
module Auth
|
31
|
-
|
32
|
-
# Credentials class to handle ClientLogin authentication.
|
33
|
-
class ClientLoginHandler < AdsCommon::Auth::BaseHandler
|
34
|
-
ACCOUNT_TYPE = 'GOOGLE'
|
35
|
-
AUTH_PATH = '/accounts/ClientLogin'
|
36
|
-
AUTH_PREFIX = 'GoogleLogin auth='
|
37
|
-
CAPTCHA_PATH = '/accounts/'
|
38
|
-
|
39
|
-
# Initializes the ClientLoginHandler with all the necessary details.
|
40
|
-
def initialize(config, auth_server, service_name)
|
41
|
-
super(config)
|
42
|
-
@server = auth_server
|
43
|
-
@service_name = service_name
|
44
|
-
end
|
45
|
-
|
46
|
-
# Invalidates the stored token if the email, password or provided auth
|
47
|
-
# token have changed.
|
48
|
-
def property_changed(prop, value)
|
49
|
-
if [:email, :password].include?(prop)
|
50
|
-
@token = nil
|
51
|
-
end
|
52
|
-
if :auth_token.eql?(prop)
|
53
|
-
@token = create_token_from_string(value)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Handle specific ClientLogin errors.
|
58
|
-
def handle_error(error)
|
59
|
-
# TODO: Add support for automatically regenerating auth tokens when they
|
60
|
-
# expire.
|
61
|
-
get_logger().error(error)
|
62
|
-
raise error
|
63
|
-
end
|
64
|
-
|
65
|
-
# Returns authorization string.
|
66
|
-
def auth_string(credentials)
|
67
|
-
return [AUTH_PREFIX, get_token(credentials)].join
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
# Auxiliary method to validate the credentials for token generation.
|
73
|
-
#
|
74
|
-
# Args:
|
75
|
-
# - credentials: a hash with the credentials for the account being
|
76
|
-
# accessed
|
77
|
-
#
|
78
|
-
# Raises:
|
79
|
-
# - AdsCommon::Errors::AuthError if validation fails
|
80
|
-
#
|
81
|
-
def validate_credentials(credentials)
|
82
|
-
if credentials.nil?
|
83
|
-
raise AdsCommon::Errors::AuthError, 'No credentials supplied.'
|
84
|
-
end
|
85
|
-
|
86
|
-
if credentials[:auth_token].nil?
|
87
|
-
if credentials[:email].nil?
|
88
|
-
raise AdsCommon::Errors::AuthError,
|
89
|
-
'Email address not included in credentials.'
|
90
|
-
end
|
91
|
-
if credentials[:password].nil?
|
92
|
-
raise AdsCommon::Errors::AuthError,
|
93
|
-
'Password not included in credentials.'
|
94
|
-
end
|
95
|
-
else
|
96
|
-
if credentials[:email] and credentials[:password]
|
97
|
-
get_logger().warn('Both auth_token and login credentials present' +
|
98
|
-
', preferring auth_token.')
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# Auxiliary method to generate an authentication token for login in via
|
104
|
-
# the ClientLogin API.
|
105
|
-
#
|
106
|
-
# Args:
|
107
|
-
# - credentials: a hash with the credentials for the account being
|
108
|
-
# accessed
|
109
|
-
#
|
110
|
-
# Returns:
|
111
|
-
# - The auth token for the account
|
112
|
-
#
|
113
|
-
# Raises:
|
114
|
-
# - AdsCommon::Errors::AuthError if authentication fails
|
115
|
-
#
|
116
|
-
def create_token(credentials)
|
117
|
-
token = credentials.include?(:auth_token) ?
|
118
|
-
create_token_from_string(credentials[:auth_token]) :
|
119
|
-
generate_token(credentials)
|
120
|
-
return token
|
121
|
-
end
|
122
|
-
|
123
|
-
# Creates token for provided auth string. Trivial for this handler.
|
124
|
-
def create_token_from_string(token_string)
|
125
|
-
return token_string
|
126
|
-
end
|
127
|
-
|
128
|
-
# Prepares POST data for ClientLogin request.
|
129
|
-
def get_login_data(credentials)
|
130
|
-
email = CGI.escape(credentials[:email])
|
131
|
-
password = CGI.escape(credentials[:password])
|
132
|
-
service_name = @service_name
|
133
|
-
data = "accountType=%s&Email=%s&Passwd=%s&service=%s" %
|
134
|
-
[ACCOUNT_TYPE, email, password, service_name]
|
135
|
-
if credentials[:logintoken] and credentials[:logincaptcha]
|
136
|
-
data += "&logintoken=%s&logincaptcha=%s" %
|
137
|
-
[CGI.escape(credentials[:logintoken]),
|
138
|
-
CGI.escape(credentials[:logincaptcha])]
|
139
|
-
end
|
140
|
-
return data
|
141
|
-
end
|
142
|
-
|
143
|
-
# Generates new client login token based on credentials.
|
144
|
-
def generate_token(credentials)
|
145
|
-
validate_credentials(credentials)
|
146
|
-
|
147
|
-
url = @server + AUTH_PATH
|
148
|
-
data = get_login_data(credentials)
|
149
|
-
headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
|
150
|
-
|
151
|
-
response = AdsCommon::Http.post_response(url, data, @config, headers)
|
152
|
-
results = parse_token_text(response.body)
|
153
|
-
|
154
|
-
if response.code == 200 and results.include?('Auth')
|
155
|
-
return results['Auth']
|
156
|
-
else
|
157
|
-
handle_login_error(credentials, response, results)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# Raises relevant error based on response and parsed results.
|
162
|
-
def handle_login_error(credentials, response, results)
|
163
|
-
# Handling for known errors.
|
164
|
-
if 'CaptchaRequired'.eql?(results['Error'])
|
165
|
-
captcha_url = @server + CAPTCHA_PATH + results['CaptchaUrl']
|
166
|
-
raise AdsCommon::Errors::CaptchaRequiredError.new(results['Error'],
|
167
|
-
results['CaptchaToken'], captcha_url, results['Url'])
|
168
|
-
end
|
169
|
-
# For other errors throwing a generic error.
|
170
|
-
error_message = "ClientLogin failed for email '%s': HTTP code %d." %
|
171
|
-
[credentials[:email], response.code]
|
172
|
-
error_str = results['Error'] || response.body
|
173
|
-
error_message += " Error: %s." % error_str if error_str
|
174
|
-
if results.include?('Info')
|
175
|
-
error_message += " Info: %s." % results['Info']
|
176
|
-
end
|
177
|
-
raise AdsCommon::Errors::AuthError.new(error_message, error_str,
|
178
|
-
results['Info'])
|
179
|
-
end
|
180
|
-
|
181
|
-
# Extracts key-value pairs from ClientLogin server response.
|
182
|
-
#
|
183
|
-
# Args:
|
184
|
-
# - text: server response string
|
185
|
-
#
|
186
|
-
# Returns:
|
187
|
-
# Hash of key-value pairs
|
188
|
-
#
|
189
|
-
def parse_token_text(text)
|
190
|
-
return text.split("\n").inject({}) do |result, line|
|
191
|
-
key, *values = line.split('=')
|
192
|
-
result[key] = values.join('=')
|
193
|
-
result
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|