google-ads-common 0.9.9 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
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
|